iron_armpack.c 16 KB

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