diff options
author | Damien George <damien.p.george@gmail.com> | 2014-09-10 22:10:33 +0100 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2014-09-10 22:10:33 +0100 |
commit | 953074315e594f5a30f455dc6a1a67340a3e6ea7 (patch) | |
tree | 9bce234da3c55224ee5cb6edd9cfd830be3e7960 /py/binary.c | |
parent | 6eae861685e8860e7542097ad20f69168e639a93 (diff) |
py: Enable struct/binary-helper to parse q and Q sized ints.
Addresses issue #848.
Diffstat (limited to 'py/binary.c')
-rw-r--r-- | py/binary.c | 27 |
1 files changed, 20 insertions, 7 deletions
diff --git a/py/binary.c b/py/binary.c index 919ba8784..835ba8aa2 100644 --- a/py/binary.c +++ b/py/binary.c @@ -34,6 +34,7 @@ #include "misc.h" #include "qstr.h" #include "obj.h" +#include "smallint.h" #include "binary.h" // Helpers to work with binary-encoded data @@ -136,7 +137,10 @@ mp_obj_t mp_binary_get_val_array(char typecode, void *p, int index) { return MP_OBJ_NEW_SMALL_INT(val); } -mp_int_t mp_binary_get_int(mp_uint_t size, bool is_signed, bool big_endian, byte *p) { +// The long long type is guaranteed to hold at least 64 bits, and size is at +// most 8 (for q and Q), so we will always be able to parse the given data +// and fit it into a long long. +long long mp_binary_get_int(mp_uint_t size, bool is_signed, bool big_endian, byte *p) { int delta; if (!big_endian) { delta = -1; @@ -145,7 +149,7 @@ mp_int_t mp_binary_get_int(mp_uint_t size, bool is_signed, bool big_endian, byte delta = 1; } - mp_int_t val = 0; + long long val = 0; if (is_signed && *p & 0x80) { val = -1; } @@ -175,16 +179,25 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) { } *ptr = p + size; - mp_int_t val = mp_binary_get_int(size, is_signed(val_type), (struct_type == '>'), p); + long long val = mp_binary_get_int(size, is_signed(val_type), (struct_type == '>'), p); if (val_type == 'O') { - return (mp_obj_t)val; + return (mp_obj_t)(mp_uint_t)val; } else if (val_type == 'S') { - return mp_obj_new_str((char*)val, strlen((char*)val), false); + const char *s_val = (const char*)(mp_uint_t)val; + return mp_obj_new_str(s_val, strlen(s_val), false); } else if (is_signed(val_type)) { - return mp_obj_new_int(val); + if ((long long)MP_SMALL_INT_MIN <= val && val <= (long long)MP_SMALL_INT_MAX) { + return mp_obj_new_int((mp_int_t)val); + } else { + return mp_obj_new_int_from_ll(val); + } } else { - return mp_obj_new_int_from_uint(val); + if ((unsigned long long)val <= (unsigned long long)MP_SMALL_INT_MAX) { + return mp_obj_new_int_from_uint((mp_uint_t)val); + } else { + return mp_obj_new_int_from_ull(val); + } } } |