binary.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. /*
  2. * This file is part of the MicroPython project, http://micropython.org/
  3. *
  4. * The MIT License (MIT)
  5. *
  6. * Copyright (c) 2013, 2014 Damien P. George
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documentation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be included in
  16. * all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. * THE SOFTWARE.
  25. */
  26. #include <stdint.h>
  27. #include <stdlib.h>
  28. #include <stddef.h>
  29. #include <string.h>
  30. #include <assert.h>
  31. #include "py/binary.h"
  32. #include "py/smallint.h"
  33. #include "py/objint.h"
  34. #include "py/runtime.h"
  35. // Helpers to work with binary-encoded data
  36. #ifndef alignof
  37. #define alignof(type) offsetof(struct { char c; type t; }, t)
  38. #endif
  39. size_t mp_binary_get_size(char struct_type, char val_type, mp_uint_t *palign) {
  40. size_t size = 0;
  41. int align = 1;
  42. switch (struct_type) {
  43. case '<': case '>':
  44. switch (val_type) {
  45. case 'b': case 'B':
  46. size = 1; break;
  47. case 'h': case 'H':
  48. size = 2; break;
  49. case 'i': case 'I':
  50. size = 4; break;
  51. case 'l': case 'L':
  52. size = 4; break;
  53. case 'q': case 'Q':
  54. size = 8; break;
  55. case 'P': case 'O': case 'S':
  56. size = sizeof(void*); break;
  57. case 'f':
  58. size = sizeof(float); break;
  59. case 'd':
  60. size = sizeof(double); break;
  61. }
  62. break;
  63. case '@': {
  64. // TODO:
  65. // The simplest heuristic for alignment is to align by value
  66. // size, but that doesn't work for "bigger than int" types,
  67. // for example, long long may very well have long alignment
  68. // So, we introduce separate alignment handling, but having
  69. // formal support for that is different from actually supporting
  70. // particular (or any) ABI.
  71. switch (val_type) {
  72. case BYTEARRAY_TYPECODE:
  73. case 'b': case 'B':
  74. align = size = 1; break;
  75. case 'h': case 'H':
  76. align = alignof(short);
  77. size = sizeof(short); break;
  78. case 'i': case 'I':
  79. align = alignof(int);
  80. size = sizeof(int); break;
  81. case 'l': case 'L':
  82. align = alignof(long);
  83. size = sizeof(long); break;
  84. case 'q': case 'Q':
  85. align = alignof(long long);
  86. size = sizeof(long long); break;
  87. case 'P': case 'O': case 'S':
  88. align = alignof(void*);
  89. size = sizeof(void*); break;
  90. case 'f':
  91. align = alignof(float);
  92. size = sizeof(float); break;
  93. case 'd':
  94. align = alignof(double);
  95. size = sizeof(double); break;
  96. }
  97. }
  98. }
  99. if (size == 0) {
  100. mp_raise_ValueError("bad typecode");
  101. }
  102. if (palign != NULL) {
  103. *palign = align;
  104. }
  105. return size;
  106. }
  107. mp_obj_t mp_binary_get_val_array(char typecode, void *p, mp_uint_t index) {
  108. mp_int_t val = 0;
  109. switch (typecode) {
  110. case 'b':
  111. val = ((signed char*)p)[index];
  112. break;
  113. case BYTEARRAY_TYPECODE:
  114. case 'B':
  115. val = ((unsigned char*)p)[index];
  116. break;
  117. case 'h':
  118. val = ((short*)p)[index];
  119. break;
  120. case 'H':
  121. val = ((unsigned short*)p)[index];
  122. break;
  123. case 'i':
  124. return mp_obj_new_int(((int*)p)[index]);
  125. case 'I':
  126. return mp_obj_new_int_from_uint(((unsigned int*)p)[index]);
  127. case 'l':
  128. return mp_obj_new_int(((long*)p)[index]);
  129. case 'L':
  130. return mp_obj_new_int_from_uint(((unsigned long*)p)[index]);
  131. #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
  132. case 'q':
  133. return mp_obj_new_int_from_ll(((long long*)p)[index]);
  134. case 'Q':
  135. return mp_obj_new_int_from_ull(((unsigned long long*)p)[index]);
  136. #endif
  137. #if MICROPY_PY_BUILTINS_FLOAT
  138. case 'f':
  139. return mp_obj_new_float(((float*)p)[index]);
  140. case 'd':
  141. return mp_obj_new_float(((double*)p)[index]);
  142. #endif
  143. // Extension to CPython: array of objects
  144. case 'O':
  145. return ((mp_obj_t*)p)[index];
  146. // Extension to CPython: array of pointers
  147. case 'P':
  148. return mp_obj_new_int((mp_int_t)(uintptr_t)((void**)p)[index]);
  149. }
  150. return MP_OBJ_NEW_SMALL_INT(val);
  151. }
  152. // The long long type is guaranteed to hold at least 64 bits, and size is at
  153. // most 8 (for q and Q), so we will always be able to parse the given data
  154. // and fit it into a long long.
  155. long long mp_binary_get_int(mp_uint_t size, bool is_signed, bool big_endian, const byte *src) {
  156. int delta;
  157. if (!big_endian) {
  158. delta = -1;
  159. src += size - 1;
  160. } else {
  161. delta = 1;
  162. }
  163. long long val = 0;
  164. if (is_signed && *src & 0x80) {
  165. val = -1;
  166. }
  167. for (uint i = 0; i < size; i++) {
  168. val <<= 8;
  169. val |= *src;
  170. src += delta;
  171. }
  172. return val;
  173. }
  174. #define is_signed(typecode) (typecode > 'Z')
  175. mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) {
  176. byte *p = *ptr;
  177. mp_uint_t align;
  178. size_t size = mp_binary_get_size(struct_type, val_type, &align);
  179. if (struct_type == '@') {
  180. // Make pointer aligned
  181. p = (byte*)MP_ALIGN(p, (size_t)align);
  182. #if MP_ENDIANNESS_LITTLE
  183. struct_type = '<';
  184. #else
  185. struct_type = '>';
  186. #endif
  187. }
  188. *ptr = p + size;
  189. long long val = mp_binary_get_int(size, is_signed(val_type), (struct_type == '>'), p);
  190. if (val_type == 'O') {
  191. return (mp_obj_t)(mp_uint_t)val;
  192. } else if (val_type == 'S') {
  193. const char *s_val = (const char*)(uintptr_t)(mp_uint_t)val;
  194. return mp_obj_new_str(s_val, strlen(s_val));
  195. #if MICROPY_PY_BUILTINS_FLOAT
  196. } else if (val_type == 'f') {
  197. union { uint32_t i; float f; } fpu = {val};
  198. return mp_obj_new_float(fpu.f);
  199. } else if (val_type == 'd') {
  200. union { uint64_t i; double f; } fpu = {val};
  201. return mp_obj_new_float(fpu.f);
  202. #endif
  203. } else if (is_signed(val_type)) {
  204. if ((long long)MP_SMALL_INT_MIN <= val && val <= (long long)MP_SMALL_INT_MAX) {
  205. return mp_obj_new_int((mp_int_t)val);
  206. } else {
  207. return mp_obj_new_int_from_ll(val);
  208. }
  209. } else {
  210. if ((unsigned long long)val <= (unsigned long long)MP_SMALL_INT_MAX) {
  211. return mp_obj_new_int_from_uint((mp_uint_t)val);
  212. } else {
  213. return mp_obj_new_int_from_ull(val);
  214. }
  215. }
  216. }
  217. void mp_binary_set_int(mp_uint_t val_sz, bool big_endian, byte *dest, mp_uint_t val) {
  218. if (MP_ENDIANNESS_LITTLE && !big_endian) {
  219. memcpy(dest, &val, val_sz);
  220. } else if (MP_ENDIANNESS_BIG && big_endian) {
  221. // only copy the least-significant val_sz bytes
  222. memcpy(dest, (byte*)&val + sizeof(mp_uint_t) - val_sz, val_sz);
  223. } else {
  224. const byte *src;
  225. if (MP_ENDIANNESS_LITTLE) {
  226. src = (const byte*)&val + val_sz;
  227. } else {
  228. src = (const byte*)&val + sizeof(mp_uint_t);
  229. }
  230. while (val_sz--) {
  231. *dest++ = *--src;
  232. }
  233. }
  234. }
  235. void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **ptr) {
  236. byte *p = *ptr;
  237. mp_uint_t align;
  238. size_t size = mp_binary_get_size(struct_type, val_type, &align);
  239. if (struct_type == '@') {
  240. // Make pointer aligned
  241. p = (byte*)MP_ALIGN(p, (size_t)align);
  242. if (MP_ENDIANNESS_LITTLE) {
  243. struct_type = '<';
  244. } else {
  245. struct_type = '>';
  246. }
  247. }
  248. *ptr = p + size;
  249. mp_uint_t val;
  250. switch (val_type) {
  251. case 'O':
  252. val = (mp_uint_t)val_in;
  253. break;
  254. #if MICROPY_PY_BUILTINS_FLOAT
  255. case 'f': {
  256. union { uint32_t i; float f; } fp_sp;
  257. fp_sp.f = mp_obj_get_float(val_in);
  258. val = fp_sp.i;
  259. break;
  260. }
  261. case 'd': {
  262. union { uint64_t i64; uint32_t i32[2]; double f; } fp_dp;
  263. fp_dp.f = mp_obj_get_float(val_in);
  264. if (BYTES_PER_WORD == 8) {
  265. val = fp_dp.i64;
  266. } else {
  267. int be = struct_type == '>';
  268. mp_binary_set_int(sizeof(uint32_t), be, p, fp_dp.i32[MP_ENDIANNESS_BIG ^ be]);
  269. p += sizeof(uint32_t);
  270. val = fp_dp.i32[MP_ENDIANNESS_LITTLE ^ be];
  271. }
  272. break;
  273. }
  274. #endif
  275. default:
  276. #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
  277. if (MP_OBJ_IS_TYPE(val_in, &mp_type_int)) {
  278. mp_obj_int_to_bytes_impl(val_in, struct_type == '>', size, p);
  279. return;
  280. } else
  281. #endif
  282. {
  283. val = mp_obj_get_int(val_in);
  284. // zero/sign extend if needed
  285. if (BYTES_PER_WORD < 8 && size > sizeof(val)) {
  286. int c = (is_signed(val_type) && (mp_int_t)val < 0) ? 0xff : 0x00;
  287. memset(p, c, size);
  288. if (struct_type == '>') {
  289. p += size - sizeof(val);
  290. }
  291. }
  292. }
  293. }
  294. mp_binary_set_int(MIN((size_t)size, sizeof(val)), struct_type == '>', p, val);
  295. }
  296. void mp_binary_set_val_array(char typecode, void *p, mp_uint_t index, mp_obj_t val_in) {
  297. switch (typecode) {
  298. #if MICROPY_PY_BUILTINS_FLOAT
  299. case 'f':
  300. ((float*)p)[index] = mp_obj_get_float(val_in);
  301. break;
  302. case 'd':
  303. ((double*)p)[index] = mp_obj_get_float(val_in);
  304. break;
  305. #endif
  306. // Extension to CPython: array of objects
  307. case 'O':
  308. ((mp_obj_t*)p)[index] = val_in;
  309. break;
  310. default:
  311. #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
  312. if (MP_OBJ_IS_TYPE(val_in, &mp_type_int)) {
  313. size_t size = mp_binary_get_size('@', typecode, NULL);
  314. mp_obj_int_to_bytes_impl(val_in, MP_ENDIANNESS_BIG,
  315. size, (uint8_t*)p + index * size);
  316. return;
  317. }
  318. #endif
  319. mp_binary_set_val_array_from_int(typecode, p, index, mp_obj_get_int(val_in));
  320. }
  321. }
  322. void mp_binary_set_val_array_from_int(char typecode, void *p, mp_uint_t index, mp_int_t val) {
  323. switch (typecode) {
  324. case 'b':
  325. ((signed char*)p)[index] = val;
  326. break;
  327. case BYTEARRAY_TYPECODE:
  328. case 'B':
  329. ((unsigned char*)p)[index] = val;
  330. break;
  331. case 'h':
  332. ((short*)p)[index] = val;
  333. break;
  334. case 'H':
  335. ((unsigned short*)p)[index] = val;
  336. break;
  337. case 'i':
  338. ((int*)p)[index] = val;
  339. break;
  340. case 'I':
  341. ((unsigned int*)p)[index] = val;
  342. break;
  343. case 'l':
  344. ((long*)p)[index] = val;
  345. break;
  346. case 'L':
  347. ((unsigned long*)p)[index] = val;
  348. break;
  349. #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
  350. case 'q':
  351. ((long long*)p)[index] = val;
  352. break;
  353. case 'Q':
  354. ((unsigned long long*)p)[index] = val;
  355. break;
  356. #endif
  357. #if MICROPY_PY_BUILTINS_FLOAT
  358. case 'f':
  359. ((float*)p)[index] = val;
  360. break;
  361. case 'd':
  362. ((double*)p)[index] = val;
  363. break;
  364. #endif
  365. // Extension to CPython: array of pointers
  366. case 'P':
  367. ((void**)p)[index] = (void*)(uintptr_t)val;
  368. break;
  369. }
  370. }