blob: d3dd00954615ba89cc9ea4fe7d614af67938aac9 [file] [log] [blame]
Paul Sokolovsky8bc35162014-02-14 17:16:35 +02001#include <stdint.h>
2#include <assert.h>
3
4#include "misc.h"
5#include "mpconfig.h"
6#include "qstr.h"
7#include "obj.h"
Paul Sokolovsky8bc35162014-02-14 17:16:35 +02008#include "binary.h"
9
10// Helpers to work with binary-encoded data
11
Paul Sokolovskyc2033242014-02-14 20:21:50 +020012int mp_binary_get_size(char typecode) {
13 // This assumes that unsigned and signed types are of the same type,
14 // which is invariant for [u]intN_t.
15 switch (typecode) {
16 case BYTEARRAY_TYPECODE:
17 case 'b':
18 case 'B':
19 return sizeof(int8_t);
20 case 'h':
21 case 'H':
22 return sizeof(int16_t);
23 case 'i':
24 case 'I':
25 return sizeof(int32_t);
26 case 'l':
27 case 'L':
28 return sizeof(int32_t);
29 case 'q':
30 case 'Q':
31 return sizeof(long long);
32#if MICROPY_ENABLE_FLOAT
33 case 'f':
34 return sizeof(float);
35 case 'd':
36 return sizeof(double);
37#endif
38 }
39 return -1;
40}
41
Paul Sokolovskyef9124f2014-04-11 03:46:09 +030042mp_obj_t mp_binary_get_val_array(char typecode, void *p, int index) {
Paul Sokolovsky76f8ced2014-02-15 00:28:41 +020043 machine_int_t val = 0;
Paul Sokolovsky8bc35162014-02-14 17:16:35 +020044 switch (typecode) {
45 case 'b':
46 val = ((int8_t*)p)[index];
47 break;
48 case BYTEARRAY_TYPECODE:
49 case 'B':
50 val = ((uint8_t*)p)[index];
51 break;
52 case 'h':
53 val = ((int16_t*)p)[index];
54 break;
55 case 'H':
56 val = ((uint16_t*)p)[index];
57 break;
58 case 'i':
59 case 'l':
60 return mp_obj_new_int(((int32_t*)p)[index]);
61 case 'I':
62 case 'L':
63 return mp_obj_new_int_from_uint(((uint32_t*)p)[index]);
Damien George96056a62014-02-15 23:02:00 +000064#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
Paul Sokolovsky8bc35162014-02-14 17:16:35 +020065 case 'q':
66 case 'Q':
67 // TODO: Explode API more to cover signedness
68 return mp_obj_new_int_from_ll(((long long*)p)[index]);
69#endif
70#if MICROPY_ENABLE_FLOAT
71 case 'f':
72 return mp_obj_new_float(((float*)p)[index]);
73 case 'd':
74 return mp_obj_new_float(((double*)p)[index]);
75#endif
76 }
77 return MP_OBJ_NEW_SMALL_INT(val);
78}
79
Paul Sokolovsky6582d642014-04-10 22:19:32 +030080#define is_signed(typecode) (typecode > 'Z')
Paul Sokolovsky0c43cf92014-04-11 03:47:21 +030081mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) {
Paul Sokolovskye9db8402014-04-10 03:45:38 +030082 byte *p = *ptr;
Paul Sokolovsky0c43cf92014-04-11 03:47:21 +030083 uint size = 0;
84 switch (struct_type) {
Paul Sokolovsky6582d642014-04-10 22:19:32 +030085 case '<': case '>':
Paul Sokolovsky0c43cf92014-04-11 03:47:21 +030086 switch (val_type) {
Paul Sokolovsky6582d642014-04-10 22:19:32 +030087 case 'b': case 'B':
88 size = 1; break;
89 case 'h': case 'H':
90 size = 2; break;
91 case 'i': case 'I':
92 size = 4; break;
Paul Sokolovsky0c43cf92014-04-11 03:47:21 +030093 case 'l': case 'L':
94 size = 4; break;
Paul Sokolovsky6582d642014-04-10 22:19:32 +030095 }
Paul Sokolovskye9db8402014-04-10 03:45:38 +030096 break;
Paul Sokolovsky0c43cf92014-04-11 03:47:21 +030097 case '@': {
98 // TODO:
99 // The simplest heuristic for alignment is to align by value
100 // size, but that doesn't work for "bigger than int" types,
101 // for example, long long may very well have long alignment
102 // So, we introduce separate alignment handling, but having
103 // formal support for that is different from actually supporting
104 // particular (or any) ABI.
105 uint align = 0;
106 switch (val_type) {
107 case 'b': case 'B':
108 align = size = 1; break;
109 case 'h': case 'H':
110 align = size = sizeof(short); break;
111 case 'i': case 'I':
112 align = size = sizeof(int); break;
113 case 'l': case 'L':
114 align = size = sizeof(long); break;
115 }
116 // Make pointer aligned
117 p = (byte*)(((machine_uint_t)p + align - 1) & ~(align - 1));
118 #if MP_ENDIANNESS_LITTLE
119 struct_type = '<';
120 #else
121 struct_type = '>';
122 #endif
123 break;
124 }
Paul Sokolovskye9db8402014-04-10 03:45:38 +0300125 }
Paul Sokolovsky6582d642014-04-10 22:19:32 +0300126
127 int delta;
Paul Sokolovsky0c43cf92014-04-11 03:47:21 +0300128 if (struct_type == '<') {
Paul Sokolovsky6582d642014-04-10 22:19:32 +0300129 delta = -1;
130 p += size - 1;
131 } else {
132 delta = 1;
133 }
134
135 machine_int_t val = 0;
Paul Sokolovsky0c43cf92014-04-11 03:47:21 +0300136 if (is_signed(val_type) && *p & 0x80) {
Paul Sokolovsky6582d642014-04-10 22:19:32 +0300137 val = -1;
138 }
139 for (uint i = 0; i < size; i++) {
140 val <<= 8;
141 val |= *p;
142 p += delta;
143 }
144
Paul Sokolovsky0c43cf92014-04-11 03:47:21 +0300145 *ptr += size;
146 if (is_signed(val_type)) {
Paul Sokolovsky6582d642014-04-10 22:19:32 +0300147 return mp_obj_new_int(val);
148 } else {
149 return mp_obj_new_int_from_uint(val);
150 }
Paul Sokolovskye9db8402014-04-10 03:45:38 +0300151}
152
Paul Sokolovskyef9124f2014-04-11 03:46:09 +0300153void mp_binary_set_val_array(char typecode, void *p, int index, mp_obj_t val_in) {
Damien George71e9bfa2014-04-18 23:28:12 +0100154 switch (typecode) {
155#if MICROPY_ENABLE_FLOAT
156 case 'f':
157 ((float*)p)[index] = mp_obj_float_get(val_in);
158 break;
159 case 'd':
160 ((double*)p)[index] = mp_obj_float_get(val_in);
161 break;
162#endif
163 default:
164 mp_binary_set_val_array_from_int(typecode, p, index, mp_obj_get_int(val_in));
Paul Sokolovsky8bc35162014-02-14 17:16:35 +0200165 }
Damien George71e9bfa2014-04-18 23:28:12 +0100166}
Paul Sokolovsky8bc35162014-02-14 17:16:35 +0200167
Damien George71e9bfa2014-04-18 23:28:12 +0100168void mp_binary_set_val_array_from_int(char typecode, void *p, int index, machine_int_t val) {
Paul Sokolovsky8bc35162014-02-14 17:16:35 +0200169 switch (typecode) {
170 case 'b':
171 ((int8_t*)p)[index] = val;
172 break;
173 case BYTEARRAY_TYPECODE:
174 case 'B':
175 val = ((uint8_t*)p)[index] = val;
176 break;
177 case 'h':
178 val = ((int16_t*)p)[index] = val;
179 break;
180 case 'H':
181 val = ((uint16_t*)p)[index] = val;
182 break;
183 case 'i':
184 case 'l':
185 ((int32_t*)p)[index] = val;
186 break;
187 case 'I':
188 case 'L':
189 ((uint32_t*)p)[index] = val;
190 break;
191#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
192 case 'q':
193 case 'Q':
194 assert(0);
195 ((long long*)p)[index] = val;
196 break;
197#endif
198#if MICROPY_ENABLE_FLOAT
199 case 'f':
Damien George71e9bfa2014-04-18 23:28:12 +0100200 ((float*)p)[index] = val;
Paul Sokolovsky8bc35162014-02-14 17:16:35 +0200201 break;
202 case 'd':
Damien George71e9bfa2014-04-18 23:28:12 +0100203 ((double*)p)[index] = val;
Paul Sokolovsky8bc35162014-02-14 17:16:35 +0200204 break;
205#endif
206 }
207}