/interpreter/tags/at2dist091109/src/edu/vub/at/objects/natives/FieldMap.java
Java | 196 lines | 79 code | 21 blank | 96 comment | 15 complexity | c052940bf686f1b057167b540c2bbeec MD5 | raw file
1/** 2 * AmbientTalk/2 Project 3 * FieldMap.java created on 7-aug-2006 at 19:42:44 4 * (c) Programming Technology Lab, 2006 - 2007 5 * Authors: Tom Van Cutsem & Stijn Mostinckx 6 * 7 * Permission is hereby granted, free of charge, to any person 8 * obtaining a copy of this software and associated documentation 9 * files (the "Software"), to deal in the Software without 10 * restriction, including without limitation the rights to use, 11 * copy, modify, merge, publish, distribute, sublicense, and/or 12 * sell copies of the Software, and to permit persons to whom the 13 * Software is furnished to do so, subject to the following 14 * conditions: 15 * 16 * The above copyright notice and this permission notice shall be 17 * included in all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 * OTHER DEALINGS IN THE SOFTWARE. 27 */ 28package edu.vub.at.objects.natives; 29 30import edu.vub.at.objects.grammar.ATSymbol; 31 32import java.io.Serializable; 33 34/** 35 * Instances of this class implement a so-called 'map' for an AmbientTalk object's fields. 36 * The terminology stems from the language Self. A 'map' maps variable names to an integer index. 37 * This index can be used to index an object's state vector to retrieve the value of a slot. 38 * 39 * The advantage of maps lies in their space effiency: clones can share maps, thereby enabling 40 * the sharing of variable names (which are immutable). 41 * 42 * We implement a custom map from symbols to Java ints ourselves, because the java.util.HashMap 43 * requires explicit boxing and unboxing of integers as java.lang.Integers, which is wasteful. 44 * 45 * @author tvc 46 */ 47public final class FieldMap implements Serializable { 48 49 private static final int _DEFAULT_SIZE_ = 5; 50 51 /* 52 * Field maps are represented as a simple array of the field's names. 53 * The indices of the fields are literally the indices of the field's names. 54 */ 55 56 private ATSymbol[] varNames_; 57 58 // next free position in the varNames_ array 59 private int free_; 60 61 /* 62 * Set when a fieldmap is extended when it was already shared to be able to 63 * track that both objects have a common heritage. 64 */ 65 private FieldMap origin_ = null; 66 67 public FieldMap() { 68 varNames_ = new ATSymbol[_DEFAULT_SIZE_]; 69 free_ = 0; 70 } 71 72 // used for internal cloning purposes only 73 private FieldMap(ATSymbol[] copiedNames, int copiedFree, FieldMap origin) { 74 varNames_ = copiedNames; 75 free_ = copiedFree; 76 origin_ = origin; 77 } 78 79 /** 80 * Add a new field to the field map. The field will be assigned 81 * the index of the map's current size. 82 * 83 * If the field already exists, it will not be added twice. 84 * 85 * @return true if the field was added successfully, false if the field already existed 86 */ 87 public boolean put(ATSymbol nam) { 88 if (findName(nam) != -1) // if the name is found... 89 return false; 90 91 if(free_ == varNames_.length) { 92 reAlloc(); 93 } 94 varNames_[free_++] = nam; // increment free pointer after access 95 return true; 96 } 97 98 /** 99 * Retrieve the index of a field given its name. 100 * @param nam the name of the field 101 * @return the index of the field or -1 if the field cannot be found. 102 */ 103 public int get(ATSymbol nam) { 104 int namIdx = findName(nam); 105 return (namIdx >= 0) ? namIdx : -1; 106 } 107 108 /** 109 * Remove the given name from the field map. 110 * @param nam the name of the field to be removed 111 * @return the index of the removed field or -1 if the field cannot be found. 112 */ 113 public int remove(ATSymbol nam) { 114 int namIdx = findName(nam); 115 if (namIdx >= 0) { 116 for (int i = namIdx; i < free_ - 1; i++) { 117 varNames_[i] = varNames_[i+1]; 118 } 119 free_--; 120 } 121 return namIdx; 122 } 123 124 /** 125 * Returns all field names. 126 * @return an array of the field names stored in the map. 127 */ 128 public ATSymbol[] listFields() { 129 ATSymbol[] varnames = new ATSymbol[free_]; 130 for (int i = 0; i < varnames.length; i++) { 131 varnames[i] = varNames_[i]; 132 } 133 return varnames; 134 } 135 136 /** 137 * Creates a shallow copy of the field map. This operation is performed when a 138 * new field is added in one object which shares its field map with others. To 139 * allow tracking the origins of the new fieldMap, we need to store this as its 140 * progenitor. 141 */ 142 FieldMap copy() { 143 // allocate a copy of the names array 144 ATSymbol[] newVarNames = new ATSymbol[varNames_.length]; 145 // copy content into new array 146 System.arraycopy(varNames_, 0, newVarNames, 0, varNames_.length); 147 return new FieldMap(newVarNames, free_, this); 148 } 149 150 /** 151 * Checks whether both FieldMaps are equal or whether the passed object is a 152 * FieldMap from which this one (indirectly) originates. 153 */ 154 public boolean isDerivedFrom(FieldMap aFieldMap) { 155 return (this == aFieldMap) || 156 ((origin_ != null) && origin_.isDerivedFrom(aFieldMap)); 157 } 158 159 /** 160 * Doubles the size of the map to make room for extra fields. 161 */ 162 private void reAlloc() { 163 // allocate the new array 164 ATSymbol[] newVarNames = new ATSymbol[free_ * 2]; 165 // copy old content into new array 166 System.arraycopy(varNames_, 0, newVarNames, 0, free_); 167 // throw away the old array and replace it by the new one 168 varNames_ = newVarNames; 169 } 170 171 /** 172 * Searches for the name of a field in the varNames_ array. 173 * Performs a simple sequential search, which is usually not a bottleneck 174 * as maps are supposed to be rather small (< 50 elements). 175 * @return the index of the field or -1 if not found. 176 */ 177 private int findName(ATSymbol nam) { 178 for (int i = 0; i < free_; i++) { 179 if (varNames_[i] == nam) 180 return i; 181 } 182 return -1; 183 } 184 185 public String toString() { 186 StringBuffer buff = new StringBuffer("FieldMap{"); 187 if (free_ > 0) { 188 buff.append(varNames_[0].toString()+":0"); 189 for (int i = 1; i < free_; i++) { 190 buff.append(",").append(varNames_[i].toString()+":"+i); 191 } 192 } 193 return buff.append("}").toString(); 194 } 195 196}