iron_armpack.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760
  1. #include "iron_armpack.h"
  2. #include <stdlib.h>
  3. #include <stdbool.h>
  4. #include <string.h>
  5. #include "iron_gc.h"
  6. static const int PTR_SIZE = 8;
  7. static uint32_t di; // Decoded index
  8. static uint32_t ei; // Encoded index
  9. static uint32_t bottom; // Decoded bottom
  10. static uint8_t *decoded;
  11. static uint8_t *encoded;
  12. static uint32_t capacity;
  13. static uint32_t array_count;
  14. static uint32_t string_length;
  15. static void read_store();
  16. static inline uint64_t pad(int di, int n) {
  17. return (n - (di % n)) % n;
  18. }
  19. static void store_u8(uint8_t u8) {
  20. *(uint8_t *)(decoded + di) = u8;
  21. di += 1;
  22. }
  23. static void store_i16(int16_t i16) {
  24. di += pad(di, 2);
  25. *(int16_t *)(decoded + di) = i16;
  26. di += 2;
  27. }
  28. static void store_u32(uint32_t u32) {
  29. di += pad(di, 4);
  30. *(uint32_t *)(decoded + di) = u32;
  31. di += 4;
  32. }
  33. static void store_i32(int32_t i32) {
  34. di += pad(di, 4);
  35. *(int32_t *)(decoded + di) = i32;
  36. di += 4;
  37. }
  38. static void store_f32(float f32) {
  39. di += pad(di, 4);
  40. *(float *)(decoded + di) = f32;
  41. di += 4;
  42. }
  43. static void store_ptr(uint32_t ptr) {
  44. di += pad(di, PTR_SIZE);
  45. *(uint64_t *)(decoded + di) = (uint64_t)decoded + (uint64_t)ptr;
  46. di += PTR_SIZE;
  47. }
  48. static void store_ptr_abs(void *ptr) {
  49. di += pad(di, PTR_SIZE);
  50. *(uint64_t *)(decoded + di) = (uint64_t)ptr;
  51. di += PTR_SIZE;
  52. }
  53. static void store_string_bytes(char *str) {
  54. for (int i = 0; i < string_length; ++i) {
  55. store_u8(str[i]);
  56. }
  57. store_u8('\0');
  58. }
  59. static void store_string(char *str) {
  60. // Put string at the bottom and store a pointer to it
  61. store_ptr(bottom);
  62. uint32_t _di = di;
  63. di = bottom;
  64. store_string_bytes(str);
  65. bottom = pad(di, PTR_SIZE) + di;
  66. di = _di;
  67. }
  68. static uint8_t read_u8() {
  69. uint8_t u8 = *(uint8_t *)(encoded + ei);
  70. ei += 1;
  71. return u8;
  72. }
  73. static int16_t read_i16() {
  74. int16_t i16 = *(int16_t *)(encoded + ei);
  75. ei += 2;
  76. return i16;
  77. }
  78. static int32_t read_i32() {
  79. int32_t i32 = *(int32_t *)(encoded + ei);
  80. ei += 4;
  81. return i32;
  82. }
  83. static uint32_t read_u32() {
  84. uint32_t u32 = *(uint32_t *)(encoded + ei);
  85. ei += 4;
  86. return u32;
  87. }
  88. static float read_f32() {
  89. float f32 = *(float *)(encoded + ei);
  90. ei += 4;
  91. return f32;
  92. }
  93. static char *read_string() {
  94. string_length = read_u32();
  95. char *str = (char *)(encoded + ei);
  96. ei += string_length;
  97. return str;
  98. }
  99. static uint32_t traverse(int di, bool count_arrays) {
  100. uint8_t flag = read_u8();
  101. switch (flag) {
  102. case 0xc0: // NULL
  103. return pad(di, PTR_SIZE) + PTR_SIZE;
  104. case 0xc2: // false
  105. return 1;
  106. case 0xc3: // true
  107. return 1;
  108. case 0xca: // f32
  109. ei += 4;
  110. return pad(di, 4) + 4;
  111. case 0xd2: // i32
  112. ei += 4;
  113. return pad(di, 4) + 4;
  114. case 0xdf: { // map
  115. uint32_t len = 0;
  116. int count = read_i32();
  117. for (int i = 0; i < count; ++i) {
  118. read_u8(); // 0xdb string
  119. read_string(); // key
  120. len += traverse(di + len, count_arrays); // value
  121. }
  122. len += pad(di + len, PTR_SIZE) + PTR_SIZE; // void *_
  123. return len;
  124. }
  125. case 0xdd: { // array
  126. uint32_t len = 0;
  127. uint32_t count = read_u32();
  128. uint8_t flag2 = read_u8();
  129. switch (flag2) {
  130. case 0xca: // Typed f32
  131. ei += 4 * count;
  132. len += 4 * count;
  133. break;
  134. case 0xd2: // Typed i32
  135. ei += 4 * count;
  136. len += 4 * count;
  137. break;
  138. case 0xd1: // Typed i16
  139. ei += 2 * count;
  140. len += 2 * count;
  141. break;
  142. case 0xc4: // Typed u8
  143. ei += count;
  144. len += count;
  145. break;
  146. case 0xc2: // Bool array
  147. ei -= 1;
  148. ei += count;
  149. len += count;
  150. break;
  151. case 0xc3: // Bool array
  152. ei -= 1;
  153. ei += count;
  154. len += count;
  155. break;
  156. default: // Dynamic (type (array / map / string) - value)
  157. ei -= 1; // Undo flag2 read
  158. for (uint32_t j = 0; j < count; ++j) {
  159. len += traverse(0, count_arrays);
  160. }
  161. }
  162. len += 32; // buffer ptr, length, capacity + align?
  163. if (!count_arrays) {
  164. len = 0;
  165. }
  166. // ptr (to array_t)
  167. len += pad(di, PTR_SIZE) + PTR_SIZE;
  168. return len;
  169. }
  170. case 0xdb: { // string
  171. uint32_t len = read_u32(); // string_length
  172. ei += len;
  173. len += 1; // '\0'
  174. if (!count_arrays) {
  175. len = 0;
  176. }
  177. len += pad(di, PTR_SIZE) + PTR_SIZE;
  178. return len;
  179. }
  180. default:
  181. return 0;
  182. }
  183. }
  184. static uint32_t get_struct_length() {
  185. uint32_t _ei = ei;
  186. uint32_t len = traverse(0, false);
  187. ei = _ei;
  188. return len;
  189. }
  190. static void read_store_map(uint32_t count) {
  191. ei -= 5; // u8 map, i32 count
  192. uint32_t size = get_struct_length();
  193. size += pad(size, PTR_SIZE);
  194. bottom += size * array_count;
  195. array_count = 0;
  196. ei += 5;
  197. for (uint32_t i = 0; i < count; ++i) {
  198. read_u8(); // 0xdb string
  199. read_string(); // key
  200. read_store(); // value
  201. }
  202. di += pad(di, PTR_SIZE);
  203. di += PTR_SIZE; // void *_ for runtime storage
  204. }
  205. static bool is_typed_array(uint8_t flag) {
  206. return flag == 0xca || flag == 0xd2 || flag == 0xd1 || flag == 0xc4 || flag == 0xc2 || flag == 0xc3;
  207. }
  208. static uint8_t flag_to_byte_size(uint8_t flag) {
  209. if (flag == 0xca) return 4; // f32
  210. if (flag == 0xd2) return 4; // i32
  211. if (flag == 0xd1) return 2; // i16
  212. if (flag == 0xc4) return 1; // u8
  213. if (flag == 0xc2) return 1; // u8 (true)
  214. if (flag == 0xc3) return 1; // u8 (false)
  215. return 0;
  216. }
  217. static void store_typed_array(uint8_t flag, uint32_t count) {
  218. uint32_t size = flag_to_byte_size(flag) * count;
  219. memcpy(decoded + di, encoded + ei, size);
  220. if (size > 4096) {
  221. gc_cut(decoded, di, size);
  222. }
  223. ei += size;
  224. di += size;
  225. }
  226. static void read_store_array(uint32_t count) { // Store in any/i32/../_array_t format
  227. // Store pointer to array_t struct
  228. // Put array contents at the bottom
  229. // - pointer to array_t buffer
  230. // - element count
  231. // - capacity (same as count)
  232. // - buffer
  233. store_ptr(bottom);
  234. uint32_t _di = di;
  235. di = bottom;
  236. if (count > 0) {
  237. store_ptr(di + PTR_SIZE + 4 + 4); // Pointer to buffer contents
  238. }
  239. else {
  240. store_ptr_abs(NULL);
  241. }
  242. store_u32(count); // Element count
  243. store_u32(0); // Capacity = 0 -> do not free on first realloc
  244. bottom = di;
  245. if (count == 0) {
  246. di = _di;
  247. return;
  248. }
  249. uint8_t flag = read_u8();
  250. if (is_typed_array(flag)) {
  251. if (flag == 0xc2 || flag == 0xc3) {
  252. ei--; // Bool array
  253. }
  254. store_typed_array(flag, count);
  255. bottom = pad(di, PTR_SIZE) + di;
  256. }
  257. // Dynamic (type (array / map / string) - value)
  258. else {
  259. ei -= 1; // Undo flag read
  260. // Strings
  261. if (flag == 0xdb) {
  262. // String pointers
  263. uint32_t _ei = ei;
  264. uint32_t strings_length = 0;
  265. for (uint32_t i = 0; i < count; ++i) {
  266. store_ptr(bottom + count * PTR_SIZE + strings_length);
  267. if (i < count - 1) {
  268. ei += 1; // String flag
  269. uint32_t length = read_u32(); // String length
  270. ei += length;
  271. strings_length += length;
  272. strings_length += 1; // '\0'
  273. }
  274. }
  275. ei = _ei;
  276. // String bytes
  277. for (uint32_t i = 0; i < count; ++i) {
  278. ei += 1; // String flag
  279. store_string_bytes(read_string());
  280. }
  281. bottom = pad(di, PTR_SIZE) + di;
  282. }
  283. // Arrays
  284. else if (flag == 0xdd) {
  285. // Array pointers
  286. uint32_t _ei = ei;
  287. uint32_t arrays_length = 0;
  288. for (uint32_t i = 0; i < count; ++i) {
  289. store_ptr(bottom + count * PTR_SIZE + arrays_length);
  290. if (i < count - 1) {
  291. ei += 1; // Array flag
  292. uint32_t length = read_u32(); // Array length
  293. ei += length;
  294. length += pad(length, PTR_SIZE);
  295. arrays_length += length;
  296. arrays_length += 8 + 8 + 4 + 4;
  297. }
  298. }
  299. ei = _ei;
  300. // Array contents
  301. bottom = pad(di, PTR_SIZE) + di;
  302. array_count = count;
  303. for (uint32_t i = 0; i < count; ++i) {
  304. uint8_t flag = read_u8();
  305. read_store_array(read_i32());
  306. }
  307. }
  308. // Structs
  309. else {
  310. uint32_t size = get_struct_length();
  311. size += pad(size, PTR_SIZE);
  312. // Struct pointers
  313. for (uint32_t i = 0; i < count; ++i) {
  314. store_ptr(bottom + count * PTR_SIZE + i * size);
  315. }
  316. // Struct contents
  317. bottom = pad(di, PTR_SIZE) + di;
  318. array_count = count;
  319. for (uint32_t i = 0; i < count; ++i) {
  320. di = pad(di, PTR_SIZE) + di;
  321. uint8_t flag = read_u8();
  322. read_store_map(read_i32());
  323. }
  324. }
  325. }
  326. di = _di;
  327. }
  328. static void read_store() {
  329. uint8_t flag = read_u8();
  330. switch (flag) {
  331. case 0xc0:
  332. store_ptr_abs(NULL);
  333. break;
  334. case 0xc2:
  335. store_u8(false);
  336. break;
  337. case 0xc3:
  338. store_u8(true);
  339. break;
  340. case 0xca:
  341. store_f32(read_f32());
  342. break;
  343. case 0xd2:
  344. store_i32(read_i32());
  345. break;
  346. case 0xdf: {
  347. array_count = 1;
  348. read_store_map(read_i32());
  349. break;
  350. }
  351. case 0xdd:
  352. read_store_array(read_i32());
  353. break;
  354. case 0xdb:
  355. store_string(read_string());
  356. break;
  357. }
  358. }
  359. static void reset() {
  360. di = 0;
  361. ei = 0;
  362. bottom = 0;
  363. }
  364. void *armpack_decode(buffer_t *b) {
  365. reset();
  366. encoded = b->buffer;
  367. capacity = traverse(0, true);
  368. reset();
  369. decoded = gc_alloc(capacity);
  370. read_store();
  371. return decoded;
  372. }
  373. void armpack_encode_start(void *_encoded) {
  374. encoded = _encoded;
  375. ei = 0;
  376. }
  377. int armpack_encode_end() {
  378. return ei;
  379. }
  380. static void armpack_write_u8(uint8_t i) {
  381. *(uint8_t *)(encoded + ei) = i;
  382. ei += 1;
  383. }
  384. static void armpack_write_i16(int16_t i) {
  385. *(int16_t *)(encoded + ei) = i;
  386. ei += 2;
  387. }
  388. static void armpack_write_u32(uint32_t i) {
  389. *(uint32_t *)(encoded + ei) = i;
  390. ei += 4;
  391. }
  392. static void armpack_write_i32(int32_t i) {
  393. *(int32_t *)(encoded + ei) = i;
  394. ei += 4;
  395. }
  396. static void armpack_write_f32(float i) {
  397. *(float *)(encoded + ei) = i;
  398. ei += 4;
  399. }
  400. void armpack_encode_map(uint32_t count) {
  401. armpack_write_u8(0xdf);
  402. armpack_write_i32(count);
  403. }
  404. void armpack_encode_array(uint32_t count) { // array of arrays / array of maps / array of strings
  405. armpack_write_u8(0xdd);
  406. armpack_write_u32(count);
  407. }
  408. void armpack_encode_array_f32(f32_array_t *f32a) {
  409. if (f32a == NULL) {
  410. armpack_write_u8(0xc0); // NULL
  411. return;
  412. }
  413. armpack_write_u8(0xdd);
  414. armpack_write_u32(f32a->length);
  415. armpack_write_u8(0xca);
  416. for (uint32_t i = 0; i < f32a->length; ++i) {
  417. armpack_write_f32(f32a->buffer[i]);
  418. }
  419. }
  420. void armpack_encode_array_i32(i32_array_t *i32a) {
  421. if (i32a == NULL) {
  422. armpack_write_u8(0xc0); // NULL
  423. return;
  424. }
  425. armpack_write_u8(0xdd);
  426. armpack_write_u32(i32a->length);
  427. armpack_write_u8(0xd2);
  428. for (uint32_t i = 0; i < i32a->length; ++i) {
  429. armpack_write_i32(i32a->buffer[i]);
  430. }
  431. }
  432. void armpack_encode_array_i16(i16_array_t *i16a) {
  433. if (i16a == NULL) {
  434. armpack_write_u8(0xc0); // NULL
  435. return;
  436. }
  437. armpack_write_u8(0xdd);
  438. armpack_write_u32(i16a->length);
  439. armpack_write_u8(0xd1);
  440. for (uint32_t i = 0; i < i16a->length; ++i) {
  441. armpack_write_i16(i16a->buffer[i]);
  442. }
  443. }
  444. void armpack_encode_array_u8(u8_array_t *u8a) {
  445. if (u8a == NULL) {
  446. armpack_write_u8(0xc0); // NULL
  447. return;
  448. }
  449. armpack_write_u8(0xdd);
  450. armpack_write_u32(u8a->length);
  451. armpack_write_u8(0xc4);
  452. for (uint32_t i = 0; i < u8a->length; ++i) {
  453. armpack_write_u8(u8a->buffer[i]);
  454. }
  455. }
  456. void armpack_encode_array_string(char_ptr_array_t *strings) {
  457. if (strings == NULL) {
  458. armpack_write_u8(0xc0); // NULL
  459. return;
  460. }
  461. armpack_write_u8(0xdd);
  462. armpack_write_u32(strings->length);
  463. for (uint32_t i = 0; i < strings->length; ++i) {
  464. armpack_encode_string(strings->buffer[i]);
  465. }
  466. }
  467. void armpack_encode_string(char *str) {
  468. if (str == NULL) {
  469. armpack_write_u8(0xc0); // NULL
  470. return;
  471. }
  472. armpack_write_u8(0xdb);
  473. size_t len = strlen(str);
  474. armpack_write_u32(len);
  475. for (uint32_t i = 0; i < len; ++i) {
  476. armpack_write_u8(str[i]);
  477. }
  478. }
  479. void armpack_encode_i32(int32_t i) {
  480. armpack_write_u8(0xd2);
  481. armpack_write_i32(i);
  482. }
  483. void armpack_encode_f32(float f) {
  484. armpack_write_u8(0xca);
  485. armpack_write_f32(f);
  486. }
  487. void armpack_encode_bool(bool b) {
  488. armpack_write_u8(b ? 0xc3 : 0xc2);
  489. }
  490. void armpack_encode_null() {
  491. armpack_write_u8(0xc0);
  492. }
  493. uint32_t armpack_size_map() {
  494. return 1 + 4; // u8 tag + u32 count
  495. }
  496. uint32_t armpack_size_array() {
  497. return 1 + 4; // u8 tag + u32 count
  498. }
  499. uint32_t armpack_size_array_f32(f32_array_t *f32a) {
  500. return 1 + 4 + 1 + f32a->length * 4; // u8 tag + u32 count + u8 flag + f32* contents
  501. }
  502. uint32_t armpack_size_array_u8(u8_array_t *u8a) {
  503. return 1 + 4 + 1 + u8a->length; // u8 tag + u32 count + u8 flag + u8* contents
  504. }
  505. uint32_t armpack_size_string(char *str) {
  506. return 1 + 4 + strlen(str); // u8 tag + u32 length + contents
  507. }
  508. uint32_t armpack_size_i32() {
  509. return 1 + 4; // u8 tag + i32
  510. }
  511. uint32_t armpack_size_f32() {
  512. return 1 + 4; // u8 tag + f32
  513. }
  514. uint32_t armpack_size_bool() {
  515. return 1; // u8 tag
  516. }
  517. static char *read_string_alloc() {
  518. char *s = read_string();
  519. char *allocated = gc_alloc(string_length + 1);
  520. memcpy(allocated, s, string_length);
  521. allocated[string_length] = '\0';
  522. return allocated;
  523. }
  524. typedef union ptr_storage {
  525. void *p;
  526. struct {
  527. float f;
  528. int type; // 0 - float, 1 - int
  529. };
  530. int i;
  531. } ptr_storage_t;
  532. any_map_t *_armpack_decode_to_map() {
  533. any_map_t *result = any_map_create();
  534. uint32_t count = read_u32();
  535. for (uint32_t i = 0; i < count; i++) {
  536. read_u8(); // 0xdb string
  537. char *key = read_string_alloc();
  538. uint8_t flag = read_u8();
  539. switch (flag) {
  540. case 0xc0: { // NULL
  541. any_map_set(result, key, NULL);
  542. break;
  543. }
  544. case 0xc2: { // false
  545. ptr_storage_t s;
  546. s.i = 0;
  547. s.type = 1;
  548. any_map_set(result, key, s.p);
  549. break;
  550. }
  551. case 0xc3: { // true
  552. ptr_storage_t s;
  553. s.i = 1;
  554. s.type = 1;
  555. any_map_set(result, key, s.p);
  556. break;
  557. }
  558. case 0xca: { // f32
  559. ptr_storage_t s;
  560. s.f = read_f32();
  561. s.type = 0;
  562. any_map_set(result, key, s.p);
  563. break;
  564. }
  565. case 0xd2: { // i32
  566. ptr_storage_t s;
  567. s.i = read_i32();
  568. s.type = 1;
  569. any_map_set(result, key, s.p);
  570. break;
  571. }
  572. case 0xdb: { // string
  573. any_map_set(result, key, read_string_alloc());
  574. break;
  575. }
  576. case 0xdf: { // map
  577. any_map_t *nested_map = _armpack_decode_to_map();
  578. any_map_set(result, key, nested_map);
  579. break;
  580. }
  581. case 0xdd: { // array
  582. uint32_t array_count = read_u32();
  583. uint8_t element_flag = read_u8();
  584. if (element_flag == 0xca) { // f32
  585. f32_array_t *array = f32_array_create(array_count);
  586. for (uint32_t j = 0; j < array_count; j++) {
  587. array->buffer[j] = read_f32();
  588. }
  589. any_map_set(result, key, array);
  590. }
  591. else if (element_flag == 0xd2) { // i32
  592. i32_array_t *array = i32_array_create(array_count);
  593. for (uint32_t j = 0; j < array_count; j++) {
  594. array->buffer[j] = read_i32();
  595. }
  596. any_map_set(result, key, array);
  597. }
  598. else if (element_flag == 0xd1) { // i16
  599. i16_array_t *array = i16_array_create(array_count);
  600. for (uint32_t j = 0; j < array_count; j++) {
  601. array->buffer[j] = read_i16();
  602. }
  603. any_map_set(result, key, array);
  604. }
  605. else if (element_flag == 0xc4) { // u8
  606. u8_array_t *array = u8_array_create(array_count);
  607. for (uint32_t j = 0; j < array_count; j++) {
  608. array->buffer[j] = read_u8();
  609. }
  610. any_map_set(result, key, array);
  611. }
  612. else if (element_flag == 0xdb) { // string
  613. ei--;
  614. char_ptr_array_t *array = char_ptr_array_create(array_count);
  615. for (uint32_t j = 0; j < array_count; j++) {
  616. read_u8(); // flag
  617. array->buffer[j] = read_string_alloc();
  618. }
  619. any_map_set(result, key, array);
  620. }
  621. else if (element_flag == 0xdf) { // map
  622. ei--;
  623. any_array_t *array = any_array_create(array_count);
  624. for (uint32_t j = 0; j < array_count; j++) {
  625. read_u8(); // flag
  626. array->buffer[j] = _armpack_decode_to_map();
  627. }
  628. any_map_set(result, key, array);
  629. }
  630. else if (element_flag == 0xc6) { // buffer_t (deprecated)
  631. ei--;
  632. any_array_t *array = any_array_create(array_count);
  633. for (uint32_t j = 0; j < array_count; j++) {
  634. read_u8(); // flag
  635. uint32_t buffer_size = read_u32();
  636. buffer_t *buffer = buffer_create(buffer_size);
  637. for (uint32_t k = 0; k < buffer_size; k++) {
  638. buffer->buffer[k] = read_u8();
  639. }
  640. array->buffer[j] = buffer;
  641. }
  642. any_map_set(result, key, array);
  643. }
  644. break;
  645. }
  646. case 0xc6: { // buffer_t (deprecated)
  647. uint32_t buffer_size = read_u32();
  648. buffer_t *buffer = buffer_create(buffer_size);
  649. for (uint32_t j = 0; j < buffer_size; j++) {
  650. buffer->buffer[j] = read_u8();
  651. }
  652. any_map_set(result, key, buffer);
  653. }
  654. }
  655. }
  656. return result;
  657. }
  658. any_map_t *armpack_decode_to_map(buffer_t *b) {
  659. encoded = b->buffer;
  660. ei = 0;
  661. read_u8(); // Must be 0xdf for a map
  662. return _armpack_decode_to_map();
  663. }
  664. float armpack_map_get_f32(any_map_t *map, char *key) {
  665. ptr_storage_t ps;
  666. ps.p = any_map_get(map, key);
  667. if (ps.p == NULL) {
  668. return 0.0;
  669. }
  670. return ps.type == 0 ? ps.f : (float)ps.i;
  671. }
  672. int armpack_map_get_i32(any_map_t *map, char *key) {
  673. ptr_storage_t ps;
  674. ps.p = any_map_get(map, key);
  675. if (ps.p == NULL) {
  676. return 0;
  677. }
  678. return ps.type == 1 ? ps.i : (int)ps.f;
  679. }