1 """Implements class for arrays."""
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 import weakref
45
46 from pyffi.utils.graph import DetailNode, EdgeFilter
47
49 """A wrapper for list, which uses get_value and set_value for
50 getting and setting items of the basic type."""
51
52 - def __init__(self, element_type, parent = None):
65
67 return self._get_item_hook(self, index)
68
71
73 return self._iter_item_hook(self)
74
76
77
78 for elem in self.__iter__():
79 if elem == value:
80 return True
81 return False
82
84 """A hook for members that are not implemented."""
85 raise NotImplementedError
86
88 """Iterator which calls C{get_value()} on all items. Applies when
89 the list has BasicBase elements."""
90 for elem in list.__iter__(self):
91 yield elem.get_value()
92
94 """Iterator over all items. Applies when the list does not have
95 BasicBase elements."""
96 for elem in list.__iter__(self):
97 yield elem
98
100 """Item getter which calls C{get_value()} on the C{index}'d item."""
101 return list.__getitem__(self, index).get_value()
102
106
108 """Regular item getter, used when the list does not have BasicBase
109 elements."""
110 return list.__getitem__(self, index)
111
112
113
115 """Yield children."""
116 return (item for item in list.__iter__(self))
117
119 """Yield child names."""
120 return ("[%i]" % row for row in xrange(list.__len__(self)))
121
123 """A general purpose class for 1 or 2 dimensional arrays consisting of
124 either BasicBase or StructBase elements."""
125
126 arg = None
127
128 - def __init__(
129 self,
130 element_type = None,
131 element_type_template = None,
132 element_type_argument = None,
133 count1 = None, count2 = None,
134 parent = None):
135 """Initialize the array type.
136
137 :param element_type: The class describing the type of each element.
138 :param element_type_template: If the class takes a template type
139 argument, then this argument describes the template type.
140 :param element_type_argument: If the class takes a type argument, then
141 it is described here.
142 :param count1: An C{Expression} describing the count (first dimension).
143 :param count2: Either ``None``, or an C{Expression} describing the
144 second dimension count.
145 :param parent: The parent of this instance, that is, the instance this
146 array is an attribute of."""
147 if count2 is None:
148 _ListWrap.__init__(self,
149 element_type = element_type, parent = parent)
150 else:
151 _ListWrap.__init__(self,
152 element_type = _ListWrap, parent = parent)
153 self._elementType = element_type
154 self._parent = weakref.ref(parent) if parent else None
155 self._elementTypeTemplate = element_type_template
156 self._elementTypeArgument = element_type_argument
157 self._count1 = count1
158 self._count2 = count2
159
160 if self._count2 == None:
161 for i in xrange(self._len1()):
162 elem_instance = self._elementType(
163 template = self._elementTypeTemplate,
164 argument = self._elementTypeArgument,
165 parent = self)
166 self.append(elem_instance)
167 else:
168 for i in xrange(self._len1()):
169 elem = _ListWrap(element_type = element_type, parent = self)
170 for j in xrange(self._len2(i)):
171 elem_instance = self._elementType(
172 template = self._elementTypeTemplate,
173 argument = self._elementTypeArgument,
174 parent = elem)
175 elem.append(elem_instance)
176 self.append(elem)
177
179 """The length the array should have, obtained by evaluating
180 the count1 expression."""
181 if self._parent is None:
182 return self._count1.eval()
183 else:
184 return self._count1.eval(self._parent())
185
186 - def _len2(self, index1):
187 """The length the array should have, obtained by evaluating
188 the count2 expression."""
189 if self._count2 == None:
190 raise ValueError('single array treated as double array (bug?)')
191 if self._parent is None:
192 expr = self._count2.eval()
193 else:
194 expr = self._count2.eval(self._parent())
195 if isinstance(expr, (int, long)):
196 return expr
197 else:
198 return expr[index1]
199
201 """Copy attributes from a given array which needs to have at least as
202 many elements (possibly more) as self."""
203 if self._count2 == None:
204 for i in xrange(self._len1()):
205 attrvalue = self[i]
206 if isinstance(attrvalue, StructBase):
207 attrvalue.deepcopy(block[i])
208 elif isinstance(attrvalue, Array):
209 attrvalue.update_size()
210 attrvalue.deepcopy(block[i])
211 else:
212 self[i] = block[i]
213 else:
214 for i in xrange(self._len1()):
215 for j in xrange(self._len2(i)):
216 attrvalue = self[i][j]
217 if isinstance(attrvalue, StructBase):
218 attrvalue.deepcopy(block[i][j])
219 elif isinstance(attrvalue, Array):
220 attrvalue.update_size()
221 attrvalue.deepcopy(block[i][j])
222 else:
223 self[i][j] = block[i][j]
224
225
227 text = '%s instance at 0x%08X\n' % (self.__class__, id(self))
228 if self._count2 == None:
229 for i, element in enumerate(list.__iter__(self)):
230 if i > 16:
231 text += "etc...\n"
232 break
233 text += "%i: %s" % (i, element)
234 if text[-1:] != "\n":
235 text += "\n"
236 else:
237 k = 0
238 for i, elemlist in enumerate(list.__iter__(self)):
239 for j, elem in enumerate(list.__iter__(elemlist)):
240 if k > 16:
241 text += "etc...\n"
242 break
243 text += "%i, %i: %s" % (i, j, elem)
244 if text[-1:] != "\n":
245 text += "\n"
246 k += 1
247 if k > 16:
248 break
249 return text
250
252 """Update the array size. Call this function whenever the size
253 parameters change in C{parent}."""
254
255 old_size = len(self)
256 new_size = self._len1()
257 if self._count2 == None:
258 if new_size < old_size:
259 del self[new_size:old_size]
260 else:
261 for i in xrange(new_size-old_size):
262 elem = self._elementType(
263 template = self._elementTypeTemplate,
264 argument = self._elementTypeArgument)
265 self.append(elem)
266 else:
267 if new_size < old_size:
268 del self[new_size:old_size]
269 else:
270 for i in xrange(new_size-old_size):
271 self.append(_ListWrap(self._elementType))
272 for i, elemlist in enumerate(list.__iter__(self)):
273 old_size_i = len(elemlist)
274 new_size_i = self._len2(i)
275 if new_size_i < old_size_i:
276 del elemlist[new_size_i:old_size_i]
277 else:
278 for j in xrange(new_size_i-old_size_i):
279 elem = self._elementType(
280 template = self._elementTypeTemplate,
281 argument = self._elementTypeArgument)
282 elemlist.append(elem)
283
284 - def read(self, stream, data):
285 """Read array from stream."""
286
287 self._elementTypeArgument = self.arg
288
289 len1 = self._len1()
290 if len1 > 2000000:
291 raise ValueError('array too long (%i)' % len1)
292 del self[0:self.__len__()]
293
294 if self._count2 == None:
295 for i in xrange(len1):
296 elem = self._elementType(
297 template = self._elementTypeTemplate,
298 argument = self._elementTypeArgument,
299 parent = self)
300 elem.read(stream, data)
301 self.append(elem)
302 else:
303 for i in xrange(len1):
304 len2i = self._len2(i)
305 if len2i > 2000000:
306 raise ValueError('array too long (%i)' % len2i)
307 elemlist = _ListWrap(self._elementType, parent = self)
308 for j in xrange(len2i):
309 elem = self._elementType(
310 template = self._elementTypeTemplate,
311 argument = self._elementTypeArgument,
312 parent = elemlist)
313 elem.read(stream, data)
314 elemlist.append(elem)
315 self.append(elemlist)
316
317 - def write(self, stream, data):
318 """Write array to stream."""
319 self._elementTypeArgument = self.arg
320 len1 = self._len1()
321 if len1 != self.__len__():
322 raise ValueError('array size (%i) different from to field \
323 describing number of elements (%i)'%(self.__len__(),len1))
324 if len1 > 2000000:
325 raise ValueError('array too long (%i)' % len1)
326 if self._count2 == None:
327 for elem in list.__iter__(self):
328 elem.write(stream, data)
329 else:
330 for i, elemlist in enumerate(list.__iter__(self)):
331 len2i = self._len2(i)
332 if len2i != elemlist.__len__():
333 raise ValueError("array size (%i) different from to field \
334 describing number of elements (%i)"%(elemlist.__len__(),len2i))
335 if len2i > 2000000:
336 raise ValueError('array too long (%i)' % len2i)
337 for elem in list.__iter__(elemlist):
338 elem.write(stream, data)
339
341 """Fix the links in the array by calling C{fix_links} on all elements
342 of the array."""
343 if not self._elementType._has_links:
344 return
345 for elem in self._elementList():
346 elem.fix_links(data)
347
349 """Return all links in the array by calling C{get_links} on all elements
350 of the array."""
351 links = []
352 if not self._elementType._has_links:
353 return links
354 for elem in self._elementList():
355 links.extend(elem.get_links(data))
356 return links
357
367
369 """Return all references in the array by calling C{get_refs} on all
370 elements of the array."""
371 links = []
372 if not self._elementType._has_links:
373 return links
374 for elem in self._elementList():
375 links.extend(elem.get_refs(data))
376 return links
377
379 """Calculate the sum of the size of all elements in the array."""
380 return sum(
381 (elem.get_size(data) for elem in self._elementList()), 0)
382
384 """Calculate a hash value for the array, as a tuple."""
385 hsh = []
386 for elem in self._elementList():
387 hsh.append(elem.get_hash(data))
388 return tuple(hsh)
389
391 """Calculate a hash value for the array, as a tuple."""
392 for elem in self._elementList():
393 elem.replace_global_node(oldbranch, newbranch, **kwargs)
394
396 """Generator for listing all elements."""
397 if self._count2 is None:
398 for elem in list.__iter__(self):
399 yield elem
400 else:
401 for elemlist in list.__iter__(self):
402 for elem in list.__iter__(elemlist):
403 yield elem
404
405 from pyffi.object_models.xml.basic import BasicBase
406 from pyffi.object_models.xml.struct_ import StructBase
407