1.1 --- a/micropython/table.py Sun Oct 21 20:05:42 2007 +0200
1.2 +++ b/micropython/table.py Sun Oct 21 23:47:56 2007 +0200
1.3 @@ -16,14 +16,21 @@
1.4 offsets in the list.
1.5 """
1.6
1.7 - def __init__(self, displaced, offsets, names):
1.8 - self.displaced = displaced
1.9 - self.offsets = offsets
1.10 + def __init__(self, names):
1.11 self.names = names
1.12 + self.displaced = []
1.13 + self.offsets = {}
1.14 + self.offsets_used = set()
1.15 +
1.16 self.names_index = {}
1.17 for i, name in enumerate(self.names):
1.18 self.names_index[name] = i
1.19
1.20 + def __len__(self):
1.21 + return len(self.displaced)
1.22 +
1.23 + # Simulation methods.
1.24 +
1.25 def access(self, objname, attrname):
1.26 obj_offset = self.offsets.get(objname)
1.27 attr_index = self.names_index.get(attrname)
1.28 @@ -38,6 +45,77 @@
1.29
1.30 return None
1.31
1.32 + def dir(self, objname):
1.33 + attributes = {}
1.34 + for name in self.names:
1.35 + attr = self.access(objname, name)
1.36 + if attr is not None:
1.37 + attributes[name] = attr
1.38 + return attributes
1.39 +
1.40 + # Update methods.
1.41 +
1.42 + def add(self, objname, attributes):
1.43 +
1.44 + "Add an entry for 'objname' with the given 'attributes'."
1.45 +
1.46 + len_displaced = len(self.displaced)
1.47 + len_attributes = len(attributes)
1.48 +
1.49 + # Try to fit the row into the list, starting from the beginning and
1.50 + # skipping places where an existing row has been fitted.
1.51 +
1.52 + for offset in xrange(0, len_displaced):
1.53 + if offset in self.offsets_used:
1.54 + continue
1.55 + if self._fit_row(offset, attributes, len_displaced):
1.56 + self.offsets_used.add(offset)
1.57 + self.offsets[objname] = offset
1.58 + self._add_row(offset, attributes, len_displaced)
1.59 + break
1.60 +
1.61 + # Where a row could not be fitted within the list, add it to the
1.62 + # end.
1.63 +
1.64 + else:
1.65 + self.offsets_used.add(len_displaced)
1.66 + self.offsets[objname] = len_displaced
1.67 + self._add_row(len_displaced, attributes, len_displaced)
1.68 +
1.69 + def _fit_row(self, offset, attributes, len_displaced):
1.70 +
1.71 + """
1.72 + Fit, at the given 'offset', the row of 'attributes' in the displaced
1.73 + list having length 'len_displaced'.
1.74 + Return a true value if this succeeded.
1.75 + """
1.76 +
1.77 + for i, attr in enumerate(attributes):
1.78 + if i + offset >= len_displaced:
1.79 + break
1.80 + element = self.displaced[i + offset]
1.81 + if attr is not None and element is not None:
1.82 + return 0
1.83 + return 1
1.84 +
1.85 + def _add_row(self, offset, attributes, len_displaced):
1.86 +
1.87 + """
1.88 + Add, at the given 'offset', the row of 'attributes' in the displaced
1.89 + list having length 'len_displaced'.
1.90 + """
1.91 +
1.92 + # Extend the list if necessary.
1.93 +
1.94 + for i in xrange(0, offset + len(attributes) - len_displaced):
1.95 + self.displaced.append(None)
1.96 +
1.97 + # Record the offset and attribute details in the list.
1.98 +
1.99 + for i, attr in enumerate(attributes):
1.100 + if attr is not None:
1.101 + self.displaced[offset+i] = offset, attr
1.102 +
1.103 class Table:
1.104
1.105 "A lookup table."
1.106 @@ -46,6 +124,7 @@
1.107 self.attributes = set()
1.108 self.table = {}
1.109 self.names = []
1.110 + self.displaced_list = None
1.111
1.112 def add(self, objname, attributes):
1.113
1.114 @@ -55,6 +134,9 @@
1.115 for name, origin in attributes.items():
1.116 self.attributes.add(name)
1.117
1.118 + if self.displaced_list is not None:
1.119 + self.displaced_list.add(objname, self.matrix_row(attributes))
1.120 +
1.121 def attribute_names(self):
1.122
1.123 "Return the attribute names used in the table."
1.124 @@ -71,83 +153,34 @@
1.125
1.126 matrix = {}
1.127 for objname, attributes in self.table.items():
1.128 - row = []
1.129 - for name in self.attribute_names():
1.130 - row.append(attributes.get(name))
1.131 - matrix[objname] = row
1.132 + matrix[objname] = self.matrix_row(attributes)
1.133 return matrix
1.134
1.135 + def matrix_row(self, attributes):
1.136 +
1.137 + "Return a matrix row for the given 'attributes'."
1.138 +
1.139 + row = []
1.140 + for name in self.attribute_names():
1.141 + row.append(attributes.get(name))
1.142 + return row
1.143 +
1.144 def as_list(self):
1.145
1.146 """
1.147 Return a displaced list object encoding the table in a more compact form
1.148 - than that provided by the matrix representation.
1.149 + than that provided by the matrix representation. This list will be
1.150 + updated with new entries if added to this object using the 'add' method.
1.151 """
1.152
1.153 - displaced = []
1.154 - offsets = {}
1.155 - offsets_used = set()
1.156 -
1.157 - # Visit each row of the matrix.
1.158 -
1.159 - for objname, attributes in self.as_matrix().items():
1.160 - len_displaced = len(displaced)
1.161 - len_attributes = len(attributes)
1.162 -
1.163 - # Try to fit the row into the list, starting from the beginning and
1.164 - # skipping places where an existing row has been fitted.
1.165 + if self.displaced_list is None:
1.166 + self.displaced_list = List(self.attribute_names())
1.167
1.168 - for offset in xrange(0, len_displaced):
1.169 - if offset in offsets_used:
1.170 - continue
1.171 - if self._fit_row(offset, attributes, len_attributes, displaced, len_displaced):
1.172 - offsets_used.add(offset)
1.173 - offsets[objname] = offset
1.174 - self._add_row(offset, attributes, len_attributes, displaced, len_displaced)
1.175 - break
1.176 -
1.177 - # Where a row could not be fitted within the list, add it to the
1.178 - # end.
1.179 -
1.180 - else:
1.181 - offsets_used.add(len_displaced)
1.182 - offsets[objname] = len_displaced
1.183 - self._add_row(len_displaced, attributes, len_attributes, displaced, len_displaced)
1.184 -
1.185 - return List(displaced, offsets, self.names)
1.186 + # Visit each row of the matrix.
1.187
1.188 - def _fit_row(self, offset, attributes, len_attributes, displaced, len_displaced):
1.189 -
1.190 - """
1.191 - Fit, at the given 'offset', the row of 'attributes' having length
1.192 - 'len_attributes' in the 'displaced' list having length 'len_displaced'.
1.193 - Return a true value if this succeeded.
1.194 - """
1.195 -
1.196 - for i, attr in enumerate(attributes):
1.197 - if i + offset >= len_displaced:
1.198 - break
1.199 - element = displaced[i + offset]
1.200 - if attr is not None and element is not None:
1.201 - return 0
1.202 - return 1
1.203 + for objname, attributes in self.as_matrix().items():
1.204 + self.displaced_list.add(objname, attributes)
1.205
1.206 - def _add_row(self, offset, attributes, len_attributes, displaced, len_displaced):
1.207 -
1.208 - """
1.209 - Add, at the given 'offset', the row of 'attributes' having length
1.210 - 'len_attributes' in the 'displaced' list having length 'len_displaced'.
1.211 - """
1.212 -
1.213 - # Extend the list if necessary.
1.214 -
1.215 - for i in xrange(0, offset + len_attributes - len_displaced):
1.216 - displaced.append(None)
1.217 -
1.218 - # Record the offset and attribute details in the list.
1.219 -
1.220 - for i, attr in enumerate(attributes):
1.221 - if attr is not None:
1.222 - displaced[offset+i] = offset, attr
1.223 + return self.displaced_list
1.224
1.225 # vim: tabstop=4 expandtab shiftwidth=4