Merge lp:~ahayzen/htd/31.fix.1059893 into lp:htd/3.1
- 31.fix.1059893
- Merge into 3.1
Proposed by
Andrew Hayzen
Status: | Merged |
---|---|
Approved by: | Andrew Hayzen |
Approved revision: | 25 |
Merged at revision: | 25 |
Proposed branch: | lp:~ahayzen/htd/31.fix.1059893 |
Merge into: | lp:htd/3.1 |
Diff against target: |
474 lines (+307/-68) 1 file modified
htd31/_base/types.py (+307/-68) |
To merge this branch: | bzr merge lp:~ahayzen/htd/31.fix.1059893 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Andrew Hayzen | Approve | ||
Review via email: mp+127872@code.launchpad.net |
Commit message
Description of the change
Data Types retain ordering
To post a comment you must log in.
Revision history for this message
Andrew Hayzen (ahayzen) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'htd31/_base/types.py' |
2 | --- htd31/_base/types.py 2012-08-13 20:06:11 +0000 |
3 | +++ htd31/_base/types.py 2012-10-03 20:46:22 +0000 |
4 | @@ -35,6 +35,20 @@ |
5 | reg_dtype = Register.register_dtype # Register dtypes |
6 | |
7 | |
8 | +if sys.version_info < (3, 0): |
9 | + char = chr |
10 | +else: |
11 | + def char(data): |
12 | + return chr(int(data)).encode("ISO-8859-1") |
13 | + |
14 | + |
15 | +if sys.version_info < (3, 0): |
16 | + ordi = ord |
17 | +else: |
18 | + def ordi(raw): |
19 | + return raw |
20 | + |
21 | + |
22 | #--------------------------------------------------------------- Raw data types |
23 | class BOOL(DType): |
24 | idn = b"\x01" |
25 | @@ -167,80 +181,141 @@ |
26 | |
27 | |
28 | #------------------------------------------------------------ Number data types |
29 | -class NumBase(DType): |
30 | +class BYTE(DType): |
31 | can_range = True |
32 | - |
33 | - def sanitise(self, real): |
34 | - return pack(self._c, real) |
35 | - |
36 | - def unsanitise(self, raw): |
37 | - return unpack(self._c, raw)[0] |
38 | - |
39 | - |
40 | -class BYTE(NumBase): |
41 | idn = b"\x0f" |
42 | - _c = "b" |
43 | - can_range = True |
44 | size = 1 |
45 | |
46 | + def sanitise(self, real): |
47 | + return char(real + 128) |
48 | + |
49 | def type_check(self, real): |
50 | return type(real) is int |
51 | |
52 | - |
53 | -class UBYTE(NumBase): |
54 | + def unsanitise(self, raw): |
55 | + return ordi(raw) - 128 |
56 | + |
57 | + |
58 | +class UBYTE(DType): |
59 | + can_range = True |
60 | idn = b"\x10" |
61 | - _c = "B" |
62 | - can_range = True |
63 | size = 1 |
64 | |
65 | + def sanitise(self, real): |
66 | + return char(real) |
67 | + |
68 | def type_check(self, real): |
69 | return type(real) is int |
70 | |
71 | - |
72 | -class SHORT(NumBase): |
73 | + def unsanitise(self, raw): |
74 | + return ordi(raw) |
75 | + |
76 | + |
77 | +class SHORT(DType): |
78 | + can_range = True |
79 | idn = b"\x11" |
80 | - _c = "h" |
81 | - can_range = True |
82 | size = 2 |
83 | |
84 | + def sanitise(self, real): |
85 | + real += 32768 |
86 | + |
87 | + a, b = divmod(real, 256) |
88 | + |
89 | + return b"".join([char(a), char(b)]) |
90 | + |
91 | def type_check(self, real): |
92 | return type(real) is int |
93 | |
94 | - |
95 | -class USHORT(NumBase): |
96 | + def unsanitise(self, raw): |
97 | + a, b = raw |
98 | + |
99 | + return (ordi(a) * 256 + ordi(b)) - 32768 |
100 | + |
101 | + |
102 | +class USHORT(DType): |
103 | + can_range = True |
104 | idn = b"\x12" |
105 | - _c = "H" |
106 | - can_range = True |
107 | size = 2 |
108 | |
109 | + def sanitise(self, real): |
110 | + a, b = divmod(real, 256) |
111 | + |
112 | + return b"".join([char(a), char(b)]) |
113 | + |
114 | def type_check(self, real): |
115 | return type(real) is int |
116 | |
117 | - |
118 | -class INTEGER(NumBase): |
119 | + def unsanitise(self, raw): |
120 | + a, b = raw |
121 | + |
122 | + return (ordi(a) * 256) + ordi(b) |
123 | + |
124 | + |
125 | +class INTEGER(): |
126 | + can_range = True |
127 | idn = b"\x13" |
128 | - _c = "i" |
129 | - can_range = True |
130 | size = 4 |
131 | |
132 | + def sanitise(self, real): |
133 | + real += 2147483648 |
134 | + |
135 | + a, real = divmod(real, 256 ** 3) |
136 | + b, real = divmod(real, 256 ** 2) |
137 | + c, d = divmod(real, 256) |
138 | + |
139 | + return b"".join([char(a), char(b), char(c), char(d)]) |
140 | + |
141 | def type_check(self, real): |
142 | return type(real) is int |
143 | |
144 | - |
145 | -class UINTEGER(NumBase): |
146 | + def unsanitise(self, raw): |
147 | + a, b, c, d = raw |
148 | + |
149 | + return ((ordi(a) * 256 ** 3) + (ordi(b) * 256 ** 2) + |
150 | + (ordi(c) * 256) + ordi(d) - 2147483648) |
151 | + |
152 | + |
153 | +class UINTEGER(DType): |
154 | + can_range = True |
155 | idn = b"\x14" |
156 | - _c = "I" |
157 | size = 4 |
158 | |
159 | + def sanitise(self, real): |
160 | + a, real = divmod(real, 256 ** 3) |
161 | + b, real = divmod(real, 256 ** 2) |
162 | + c, d = divmod(real, 256) |
163 | + |
164 | + return b"".join([char(a), char(b), char(c), char(d)]) |
165 | + |
166 | def type_check(self, real): |
167 | return type(real) is int |
168 | |
169 | - |
170 | -class LONG(NumBase): |
171 | + def unsanitise(self, raw): |
172 | + a, b, c, d = raw |
173 | + |
174 | + return ((ordi(a) * 256 ** 3) + (ordi(b) * 256 ** 2) + |
175 | + (ordi(c) * 256) + d) |
176 | + |
177 | + |
178 | +class LONG(): |
179 | + can_range = True |
180 | idn = b"\x15" |
181 | - _c = "q" |
182 | size = 8 |
183 | |
184 | + def sanitise(self, real): |
185 | + real += 9223372036854775808 |
186 | + |
187 | + a, real = divmod(real, 256 ** 7) |
188 | + b, real = divmod(real, 256 ** 6) |
189 | + c, real = divmod(real, 256 ** 5) |
190 | + d, real = divmod(real, 256 ** 4) |
191 | + e, real = divmod(real, 256 ** 3) |
192 | + f, real = divmod(real, 256 ** 2) |
193 | + g, h = divmod(real, 256) |
194 | + |
195 | + return b"".join([char(a), char(b), char(c), char(d), char(e), char(f), |
196 | + char(g), char(h)]) |
197 | + |
198 | if sys.version_info < (3, 0): |
199 | def type_check(self, real): |
200 | return type(real) is long |
201 | @@ -248,12 +323,32 @@ |
202 | def type_check(self, real): |
203 | return type(real) is int |
204 | |
205 | - |
206 | -class ULONG(NumBase): |
207 | + def unsanitise(self, raw): |
208 | + a, b, c, d, e, f, g, h = raw |
209 | + |
210 | + return ((ordi(a) * 256 ** 7) + (ordi(b) * 256 ** 6) + |
211 | + (ordi(c) * 256 ** 5) + (ordi(d) * 256 ** 4) + |
212 | + (ordi(e) * 256 ** 3) + (ordi(f) * 256 ** 2) + |
213 | + (ordi(g) * 256) + ordi(h)) - 9223372036854775808 |
214 | + |
215 | + |
216 | +class ULONG(): |
217 | + can_range = True |
218 | idn = b"\x16" |
219 | - _c = "Q" |
220 | size = 8 |
221 | |
222 | + def sanitise(self, real): |
223 | + a, real = divmod(real, 256 ** 7) |
224 | + b, real = divmod(real, 256 ** 6) |
225 | + c, real = divmod(real, 256 ** 5) |
226 | + d, real = divmod(real, 256 ** 4) |
227 | + e, real = divmod(real, 256 ** 3) |
228 | + f, real = divmod(real, 256 ** 2) |
229 | + g, h = divmod(real, 256) |
230 | + |
231 | + return b"".join([char(a), char(b), char(c), char(d), char(e), char(f), |
232 | + char(g), char(h)]) |
233 | + |
234 | if sys.version_info < (3, 0): |
235 | def type_check(self, real): |
236 | return type(real) is long |
237 | @@ -261,24 +356,180 @@ |
238 | def type_check(self, real): |
239 | return type(real) is int |
240 | |
241 | - |
242 | -class FLOAT(NumBase): |
243 | + def unsanitise(self, raw): |
244 | + a, b, c, d, e, f, g, h = raw |
245 | + |
246 | + return ((ordi(a) * 256 ** 7) + (ordi(b) * 256 ** 6) + |
247 | + (ordi(c) * 256 ** 5) + (ordi(d) * 256 ** 4) + |
248 | + (ordi(e) * 256 ** 3) + (ordi(f) * 256 ** 2) + |
249 | + (ordi(g) * 256) + ordi(h)) |
250 | + |
251 | + |
252 | +#------------------------------------------------------- Float helper functions |
253 | +def float_sanitise(real): |
254 | + raw = str(abs(real)) |
255 | + |
256 | + if "e" in raw: |
257 | + raw, ex = raw.split("e") |
258 | + ex = char(int(ex) + 127) |
259 | + else: |
260 | + ex = False |
261 | + |
262 | + if "." in raw: |
263 | + ex = 0 |
264 | + d = False |
265 | + |
266 | + for i in raw: |
267 | + if i not in ["0", "."]: |
268 | + d = True |
269 | + |
270 | + if i != "." and d: |
271 | + ex += 1 |
272 | + |
273 | + if (i == "." or ex < 0) and d: |
274 | + break |
275 | + |
276 | + if i in [".", "0"] and not d: |
277 | + ex -= 1 |
278 | + |
279 | + if real < 0: |
280 | + if ex < 0: |
281 | + ex = 255 + ex |
282 | + else: |
283 | + ex = 127 - ex |
284 | + else: |
285 | + ex += 127 |
286 | + |
287 | + ex = char(ex) |
288 | + w, d = raw.split(".") |
289 | + else: |
290 | + w = raw |
291 | + d = "" |
292 | + |
293 | + n = "".join([w, d]).lstrip("0")[:9] |
294 | + n = n.ljust(9, "0") |
295 | + n = int(n) |
296 | + |
297 | + # Convert to negative offset |
298 | + if real < 0: |
299 | + n = -n |
300 | + neg = b"\x00" |
301 | + else: |
302 | + neg = b"\x01" |
303 | + |
304 | + return n, neg, ex |
305 | + |
306 | + |
307 | +def float_unsanitise(n, neg, ex): |
308 | + # Calc exponent |
309 | + if neg == 0: |
310 | + if ex > 128: |
311 | + ex -= 255 |
312 | + else: |
313 | + ex = 127 - ex |
314 | + else: |
315 | + ex -= 127 |
316 | + |
317 | + n = list(str(n)) |
318 | + |
319 | + # Build exp and data |
320 | + if neg == 0: |
321 | + off = 1 |
322 | + else: |
323 | + off = 0 |
324 | + |
325 | + if ex < 0: |
326 | + for _ in range(0, abs(ex)): |
327 | + n.insert(off, "0") |
328 | + |
329 | + n.insert(abs(ex) + off, ".") |
330 | + elif ex > 0: |
331 | + while len(n) + off < ex: |
332 | + n.append("0") |
333 | + |
334 | + n.insert(ex + off, ".") |
335 | + |
336 | + return float("".join(n)) |
337 | + |
338 | + |
339 | +class FLOAT(DType): |
340 | + can_range = True |
341 | idn = b"\x1e" |
342 | - _c = "f" |
343 | - size = 4 |
344 | + size = 6 |
345 | + |
346 | + def sanitise(self, real): |
347 | + if real == 0.0: |
348 | + return b"\x01\x00\x00\x00\x00\x00" |
349 | + |
350 | + # Convert to raw int |
351 | + n, neg, ex = float_sanitise(real) |
352 | + |
353 | + # Convert to hex |
354 | + n += 2147483648 |
355 | + |
356 | + a, n = divmod(n, 256 ** 3) |
357 | + b, n = divmod(n, 256 ** 2) |
358 | + c, d = divmod(n, 256) |
359 | + |
360 | + return b"".join([neg, ex, char(a), char(b), char(c), char(d)]) |
361 | |
362 | def type_check(self, real): |
363 | return type(real) is float |
364 | |
365 | - |
366 | -class DFLOAT(NumBase): |
367 | + def unsanitise(self, raw): |
368 | + if raw == b"\x01\x00\x00\x00\x00\x00": |
369 | + return 0.0 |
370 | + |
371 | + neg, ex, a, b, c, d = raw |
372 | + |
373 | + n = ((ordi(a) * 256 ** 3) + (ordi(b) * 256 ** 2) + (ordi(c) * 256) + |
374 | + ordi(d) - 2147483648) |
375 | + |
376 | + return float_unsanitise(n, ordi(neg), ordi(ex)) |
377 | + |
378 | + |
379 | +class DFLOAT(DType): |
380 | + can_range = True |
381 | idn = b"\x1f" |
382 | - _c = "d" |
383 | size = 8 |
384 | |
385 | + def sanitise(self, real): |
386 | + if real == 0.0: |
387 | + return b"\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00" |
388 | + |
389 | + # Convert to raw int |
390 | + n, neg, ex = float_sanitise(real) |
391 | + |
392 | + # Convert to hex |
393 | + n += 9223372036854775808 |
394 | + |
395 | + a, n = divmod(n, 256 ** 7) |
396 | + b, n = divmod(n, 256 ** 6) |
397 | + c, n = divmod(n, 256 ** 5) |
398 | + d, n = divmod(n, 256 ** 4) |
399 | + e, n = divmod(n, 256 ** 3) |
400 | + f, n = divmod(n, 256 ** 2) |
401 | + g, h = divmod(n, 256) |
402 | + |
403 | + return b"".join([neg, ex, char(a), char(b), char(c), char(d), char(e), |
404 | + char(f), char(g), char(h)]) |
405 | + |
406 | def type_check(self, real): |
407 | return type(real) is float |
408 | |
409 | + def unsanitise(self, raw): |
410 | + if raw == b"\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00": |
411 | + return 0.0 |
412 | + |
413 | + neg, ex, a, b, c, d, e, f, g, h = raw |
414 | + |
415 | + n = ((ordi(a) * 256 ** 7) + (ordi(b) * 256 ** 6) + |
416 | + (ordi(c) * 256 ** 5) + (ordi(d) * 256 ** 4) + |
417 | + (ordi(e) * 256 ** 3) + (ordi(f) * 256 ** 2) + |
418 | + (ordi(g) * 256) + ordi(h)) - 9223372036854775808 |
419 | + |
420 | + return float_unsanitise(n, ordi(neg), ordi(ex)) |
421 | + |
422 | |
423 | reg_dtype(BYTE) |
424 | reg_dtype(UBYTE) |
425 | @@ -356,8 +607,8 @@ |
426 | x = getattr(DataType, Register.dtype_codes[ty]) |
427 | if isinstance(x, PRESERVE) is False and x.type_check(real): |
428 | try: |
429 | - tmp = b"".join([x.sanitise(real), ty]) |
430 | - except struct_error: |
431 | + tmp = b"".join([ty, x.sanitise(real)]) |
432 | + except (ValueError, OverflowError, struct_error): |
433 | continue |
434 | else: |
435 | return tmp |
436 | @@ -374,28 +625,16 @@ |
437 | |
438 | return False |
439 | |
440 | - if sys.version_info < (3, 0): |
441 | - def unsanitise(self, raw): |
442 | - ty = raw[-1] |
443 | - raw = raw[:-1] |
444 | - |
445 | - if ty in Register.dtype_codes: |
446 | - x = getattr(DataType, Register.dtype_codes[ty]) |
447 | - else: |
448 | - raise TypeError("Could not restore type.") |
449 | - |
450 | - return x.unsanitise(raw) |
451 | - else: |
452 | - def unsanitise(self, raw): |
453 | - ty = chr(raw[-1]).encode("ISO-8859-1") |
454 | - raw = raw[:-1] |
455 | - |
456 | - if ty in Register.dtype_codes: |
457 | - x = getattr(DataType, Register.dtype_codes[ty]) |
458 | - else: |
459 | - raise TypeError("Could not restore type.") |
460 | - |
461 | - return x.unsanitise(raw) |
462 | + def unsanitise(self, raw): |
463 | + ty = char(raw[0]) |
464 | + raw = raw[1:] |
465 | + |
466 | + if ty in Register.dtype_codes: |
467 | + x = getattr(DataType, Register.dtype_codes[ty]) |
468 | + else: |
469 | + raise TypeError("Could not restore type.") |
470 | + |
471 | + return x.unsanitise(raw) |
472 | |
473 | |
474 | reg_dtype(PRESERVE) |