View Javadoc

1   /*
2    * $Id: DefaultDictionary.java,v 1.1 2005/10/14 19:02:44 weiju Exp $
3    * 
4    * Created on 14.10.2005
5    * Copyright 2005 by Wei-ju Wu
6    *
7    * This file is part of The Z-machine Preservation Project (ZMPP).
8    *
9    * ZMPP is free software; you can redistribute it and/or modify
10   * it under the terms of the GNU General Public License as published by
11   * the Free Software Foundation; either version 2 of the License, or
12   * (at your option) any later version.
13   *
14   * ZMPP is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Public License for more details.
18   *
19   * You should have received a copy of the GNU General Public License
20   * along with ZMPP; if not, write to the Free Software
21   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
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     // The lookup token can only be 6 characters long in version 3
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 }