1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.zmpp.vm;
24
25 import java.util.HashMap;
26 import java.util.Map;
27
28 import org.zmpp.base.MemoryReadAccess;
29 import org.zmpp.vmutil.ZsciiString;
30
31 /***
32 * This class implements a view on the dictionary within a memory map.
33 *
34 * @author Wei-ju Wu
35 * @version 1.0
36 */
37 public class DefaultDictionary implements Dictionary {
38
39 /***
40 * The memory map.
41 */
42 private MemoryReadAccess memaccess;
43
44 /***
45 * The dictionary start address.
46 */
47 private int address;
48
49 /***
50 * The lookup map.
51 */
52 private Map<String, Integer> lookupMap;
53
54 /***
55 * Constructor.
56 *
57 * @param map the memory map
58 * @param address the start address of the dictionary
59 */
60 public DefaultDictionary(MemoryReadAccess map, int address) {
61
62 this.memaccess = map;
63 this.address = address;
64 createLookupMap();
65 }
66
67 /***
68 * {@inheritDoc}
69 */
70 public int getNumberOfSeparators() {
71
72 return memaccess.readUnsignedByte(address);
73 }
74
75 /***
76 * {@inheritDoc}
77 */
78 public byte getSeparator(int i) {
79
80 return (byte) memaccess.readUnsignedByte(address + i + 1);
81 }
82
83 /***
84 * {@inheritDoc}
85 */
86 public int getEntryLength() {
87
88 return memaccess.readUnsignedByte(address + getNumberOfSeparators() + 1);
89 }
90
91 /***
92 * {@inheritDoc}
93 */
94 public int getNumberOfEntries() {
95
96 return memaccess.readUnsignedShort(address + getNumberOfSeparators() + 2);
97 }
98
99 /***
100 * {@inheritDoc}
101 */
102 public int getEntryAddress(int entryNum) {
103
104 int headerSize = getNumberOfSeparators() + 4;
105 return address + headerSize + entryNum * getEntryLength();
106 }
107
108 /***
109 * {@inheritDoc}
110 */
111 public int lookup(String token) {
112
113 String entry = token;
114
115
116 if (token.length() > 6) {
117
118 entry = token.substring(0, 6);
119 }
120
121 if (lookupMap.containsKey(entry)) {
122 return lookupMap.get(entry);
123 }
124 return 0;
125 }
126
127 /***
128 * Create the dictionary lookup map. The standards document suggests to
129 * convert the tokens into ZSCII strings and look them up in the dictionary
130 * by a binary search algorithm, which results in a O(log n) search algorithm,
131 * instead I convert the dictionary strings into Java strings and put them
132 * into a (entry - address) map, which is easier to handle and is O(1).
133 * Generating it once at initialization is safe because the dictionary is in
134 * static memory and does not change at runtime.
135 */
136 private void createLookupMap() {
137
138 lookupMap = new HashMap<String, Integer>();
139 ZsciiString zstr;
140 int entryAddress;
141
142 for (int i = 0, n = getNumberOfEntries(); i < n; i++) {
143
144 entryAddress = getEntryAddress(i);
145 zstr = new ZsciiString(memaccess, entryAddress);
146 lookupMap.put(zstr.toString(), entryAddress);
147 }
148 }
149 }