Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

921 строка
22 KiB

13 лет назад
13 лет назад
13 лет назад
13 лет назад
13 лет назад
13 лет назад
13 лет назад
13 лет назад
13 лет назад
13 лет назад
  1. // This file is part of Jiffy released under the MIT license.
  2. // See the LICENSE file for more information.
  3. #include <assert.h>
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include "erl_nif.h"
  7. #include "jiffy.h"
  8. #define BIN_INC_SIZE 2048
  9. #define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
  10. #define MAYBE_PRETTY(e) \
  11. do { \
  12. if(e->pretty) { \
  13. if(!enc_shift(e)) \
  14. return 0; \
  15. } \
  16. } while(0)
  17. #if WINDOWS || WIN32
  18. #define inline __inline
  19. #define snprintf _snprintf
  20. #endif
  21. typedef struct {
  22. ErlNifEnv* env;
  23. jiffy_st* atoms;
  24. size_t bytes_per_red;
  25. int uescape;
  26. int pretty;
  27. int use_nil;
  28. int escape_forward_slashes;
  29. int shiftcnt;
  30. int count;
  31. size_t iolen;
  32. size_t iosize;
  33. ERL_NIF_TERM iolist;
  34. ErlNifBinary bin;
  35. ErlNifBinary* curr;
  36. char* p;
  37. unsigned char* u;
  38. size_t i;
  39. } Encoder;
  40. // String constants for pretty printing.
  41. // Every string starts with its length.
  42. #define NUM_SHIFTS 8
  43. static char* shifts[NUM_SHIFTS] = {
  44. "\x01\n",
  45. "\x03\n ",
  46. "\x05\n ",
  47. "\x07\n ",
  48. "\x09\n ",
  49. "\x0b\n ",
  50. "\x0d\n ",
  51. "\x0f\n "
  52. };
  53. Encoder*
  54. enc_new(ErlNifEnv* env)
  55. {
  56. jiffy_st* st = (jiffy_st*) enif_priv_data(env);
  57. Encoder* e = enif_alloc_resource(st->res_enc, sizeof(Encoder));
  58. e->atoms = st;
  59. e->bytes_per_red = DEFAULT_BYTES_PER_REDUCTION;
  60. e->uescape = 0;
  61. e->pretty = 0;
  62. e->use_nil = 0;
  63. e->escape_forward_slashes = 0;
  64. e->shiftcnt = 0;
  65. e->count = 0;
  66. e->iolen = 0;
  67. e->iosize = 0;
  68. e->curr = &(e->bin);
  69. if(!enif_alloc_binary(BIN_INC_SIZE, e->curr)) {
  70. e->curr = NULL;
  71. enif_release_resource(e);
  72. return NULL;
  73. }
  74. memset(e->curr->data, 0, e->curr->size);
  75. e->p = (char*) e->curr->data;
  76. e->u = (unsigned char*) e->curr->data;
  77. e->i = 0;
  78. return e;
  79. }
  80. int
  81. enc_init(Encoder* e, ErlNifEnv* env)
  82. {
  83. e->env = env;
  84. return 1;
  85. }
  86. void
  87. enc_destroy(ErlNifEnv* env, void* obj)
  88. {
  89. Encoder* e = (Encoder*) obj;
  90. if(e->curr != NULL) {
  91. enif_release_binary(e->curr);
  92. }
  93. }
  94. ERL_NIF_TERM
  95. enc_error(Encoder* e, const char* msg)
  96. {
  97. //assert(0 && msg);
  98. return make_error(e->atoms, e->env, msg);
  99. }
  100. ERL_NIF_TERM
  101. enc_obj_error(Encoder* e, const char* msg, ERL_NIF_TERM obj)
  102. {
  103. return make_obj_error(e->atoms, e->env, msg, obj);
  104. }
  105. static inline int
  106. enc_ensure(Encoder* e, size_t req)
  107. {
  108. size_t need = e->curr->size;
  109. while(req >= (need - e->i)) need <<= 1;
  110. if(need != e->curr->size) {
  111. if(!enif_realloc_binary(e->curr, need)) {
  112. return 0;
  113. }
  114. e->p = (char*) e->curr->data;
  115. e->u = (unsigned char*) e->curr->data;
  116. }
  117. return 1;
  118. }
  119. int
  120. enc_result(Encoder* e, ERL_NIF_TERM* value)
  121. {
  122. if(e->i != e->curr->size) {
  123. if(!enif_realloc_binary(e->curr, e->i)) {
  124. return 0;
  125. }
  126. }
  127. *value = enif_make_binary(e->env, e->curr);
  128. e->curr = NULL;
  129. return 1;
  130. }
  131. int
  132. enc_done(Encoder* e, ERL_NIF_TERM* value)
  133. {
  134. ERL_NIF_TERM last;
  135. if(e->iolen == 0) {
  136. return enc_result(e, value);
  137. }
  138. if(e->i > 0 ) {
  139. if(!enc_result(e, &last)) {
  140. return 0;
  141. }
  142. e->iolist = enif_make_list_cell(e->env, last, e->iolist);
  143. e->iolen++;
  144. }
  145. *value = e->iolist;
  146. return 1;
  147. }
  148. #define SMALL_TERMSTACK_SIZE 16
  149. typedef struct {
  150. ERL_NIF_TERM *elements;
  151. size_t size;
  152. size_t top;
  153. ERL_NIF_TERM __default_elements[SMALL_TERMSTACK_SIZE];
  154. } TermStack;
  155. static inline void
  156. termstack_push(TermStack *stack, ERL_NIF_TERM term)
  157. {
  158. if(stack->top == stack->size) {
  159. size_t new_size = stack->size * 2;
  160. if (stack->elements == &stack->__default_elements[0]) {
  161. stack->elements = enif_alloc(new_size * sizeof(ERL_NIF_TERM));
  162. stack->size = new_size;
  163. } else {
  164. stack->elements = enif_realloc(stack->elements,
  165. new_size * sizeof(ERL_NIF_TERM));
  166. stack->size = new_size;
  167. }
  168. }
  169. assert(stack->top < stack->size);
  170. stack->elements[stack->top++] = term;
  171. }
  172. static inline ERL_NIF_TERM
  173. termstack_pop(TermStack *stack)
  174. {
  175. assert(stack->top > 0 && stack->top <= stack->size);
  176. return stack->elements[--stack->top];
  177. }
  178. static inline int
  179. termstack_is_empty(TermStack *stack)
  180. {
  181. return stack->top == 0;
  182. }
  183. ERL_NIF_TERM termstack_save(ErlNifEnv *env, TermStack *stack)
  184. {
  185. return enif_make_tuple_from_array(env, stack->elements, stack->top);
  186. }
  187. int termstack_restore(ErlNifEnv *env, ERL_NIF_TERM from, TermStack *stack)
  188. {
  189. const ERL_NIF_TERM *elements;
  190. int arity;
  191. if(enif_get_tuple(env, from, &arity, &elements)) {
  192. stack->top = arity;
  193. if(arity <= SMALL_TERMSTACK_SIZE) {
  194. stack->elements = &stack->__default_elements[0];
  195. stack->size = SMALL_TERMSTACK_SIZE;
  196. } else {
  197. stack->size = arity * 2;
  198. stack->elements = enif_alloc(stack->size * sizeof(ERL_NIF_TERM));
  199. if(!stack->elements) {
  200. return 0;
  201. }
  202. }
  203. memcpy(stack->elements, elements, arity * sizeof(ERL_NIF_TERM));
  204. return 1;
  205. }
  206. return 0;
  207. }
  208. static void
  209. termstack_destroy(TermStack *stack)
  210. {
  211. if(stack->elements != &stack->__default_elements[0]) {
  212. enif_free(stack->elements);
  213. }
  214. }
  215. static inline int
  216. enc_unknown(Encoder* e, ERL_NIF_TERM value)
  217. {
  218. ErlNifBinary* bin = e->curr;
  219. ERL_NIF_TERM curr;
  220. if(e->i > 0) {
  221. if(!enc_result(e, &curr)) {
  222. return 0;
  223. }
  224. e->iolist = enif_make_list_cell(e->env, curr, e->iolist);
  225. e->iolen++;
  226. }
  227. e->iolist = enif_make_list_cell(e->env, value, e->iolist);
  228. e->iolen++;
  229. // Track the total number of bytes produced before
  230. // splitting our IO buffer. We add 16 to this value
  231. // as a rough estimate of the number of bytes that
  232. // a bignum might produce when encoded.
  233. e->iosize += e->i + 16;
  234. // Reinitialize our binary for the next buffer if we
  235. // used any data in the buffer. If we haven't used any
  236. // bytes in the buffer then we can safely reuse it
  237. // for anything following the unknown value.
  238. if(e->i > 0) {
  239. e->curr = bin;
  240. if(!enif_alloc_binary(BIN_INC_SIZE, e->curr)) {
  241. return 0;
  242. }
  243. memset(e->curr->data, 0, e->curr->size);
  244. e->p = (char*) e->curr->data;
  245. e->u = (unsigned char*) e->curr->data;
  246. e->i = 0;
  247. }
  248. return 1;
  249. }
  250. static inline int
  251. enc_literal(Encoder* e, const char* literal, size_t len)
  252. {
  253. if(!enc_ensure(e, len)) {
  254. return 0;
  255. }
  256. memcpy(&(e->p[e->i]), literal, len);
  257. e->i += len;
  258. e->count++;
  259. return 1;
  260. }
  261. static inline int
  262. enc_string(Encoder* e, ERL_NIF_TERM val)
  263. {
  264. static const int MAX_ESCAPE_LEN = 12;
  265. ErlNifBinary bin;
  266. char atom[512];
  267. unsigned char* data;
  268. size_t size;
  269. int ulen;
  270. int uval;
  271. int i;
  272. if(enif_is_binary(e->env, val)) {
  273. if(!enif_inspect_binary(e->env, val, &bin)) {
  274. return 0;
  275. }
  276. data = bin.data;
  277. size = bin.size;
  278. } else if(enif_is_atom(e->env, val)) {
  279. if(!enif_get_atom(e->env, val, atom, 512, ERL_NIF_LATIN1)) {
  280. return 0;
  281. }
  282. data = (unsigned char*) atom;
  283. size = strlen(atom);
  284. } else {
  285. return 0;
  286. }
  287. /* Reserve space for the first quotation mark and most of the output. */
  288. if(!enc_ensure(e, size + MAX_ESCAPE_LEN + 1)) {
  289. return 0;
  290. }
  291. e->p[e->i++] = '\"';
  292. i = 0;
  293. while(i < size) {
  294. if(!enc_ensure(e, MAX_ESCAPE_LEN)) {
  295. return 0;
  296. }
  297. switch((char) data[i]) {
  298. case '\"':
  299. case '\\':
  300. e->p[e->i++] = '\\';
  301. e->u[e->i++] = data[i];
  302. i++;
  303. continue;
  304. case '\b':
  305. e->p[e->i++] = '\\';
  306. e->p[e->i++] = 'b';
  307. i++;
  308. continue;
  309. case '\f':
  310. e->p[e->i++] = '\\';
  311. e->p[e->i++] = 'f';
  312. i++;
  313. continue;
  314. case '\n':
  315. e->p[e->i++] = '\\';
  316. e->p[e->i++] = 'n';
  317. i++;
  318. continue;
  319. case '\r':
  320. e->p[e->i++] = '\\';
  321. e->p[e->i++] = 'r';
  322. i++;
  323. continue;
  324. case '\t':
  325. e->p[e->i++] = '\\';
  326. e->p[e->i++] = 't';
  327. i++;
  328. continue;
  329. case '/':
  330. if(e->escape_forward_slashes) {
  331. e->p[e->i++] = '\\';
  332. }
  333. e->u[e->i++] = '/';
  334. i++;
  335. continue;
  336. default:
  337. if(data[i] < 0x20) {
  338. ulen = unicode_uescape(data[i], &(e->p[e->i]));
  339. if(ulen < 0) {
  340. return 0;
  341. }
  342. e->i += ulen;
  343. i++;
  344. } else if(data[i] & 0x80) {
  345. ulen = utf8_validate(&(data[i]), size - i);
  346. if (ulen < 0) {
  347. return 0;
  348. } else if (e->uescape) {
  349. int esc_len;
  350. uval = utf8_to_unicode(&(data[i]), size-i);
  351. if(uval < 0) {
  352. return 0;
  353. }
  354. esc_len = unicode_uescape(uval, &(e->p[e->i]));
  355. if(esc_len < 0) {
  356. return 0;
  357. }
  358. e->i += esc_len;
  359. } else {
  360. memcpy(&e->u[e->i], &data[i], ulen);
  361. e->i += ulen;
  362. }
  363. i += ulen;
  364. } else {
  365. e->u[e->i++] = data[i++];
  366. }
  367. }
  368. }
  369. if(!enc_ensure(e, 1)) {
  370. return 0;
  371. }
  372. e->p[e->i++] = '\"';
  373. e->count++;
  374. return 1;
  375. }
  376. static inline int
  377. enc_long(Encoder* e, ErlNifSInt64 val)
  378. {
  379. if(!enc_ensure(e, 32)) {
  380. return 0;
  381. }
  382. #if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_))
  383. snprintf(&(e->p[e->i]), 32, "%lld", val);
  384. #elif SIZEOF_LONG == 8
  385. snprintf(&(e->p[e->i]), 32, "%ld", val);
  386. #else
  387. snprintf(&(e->p[e->i]), 32, "%lld", val);
  388. #endif
  389. e->i += strlen(&(e->p[e->i]));
  390. e->count++;
  391. return 1;
  392. }
  393. static inline int
  394. enc_double(Encoder* e, double val)
  395. {
  396. char* start;
  397. size_t len;
  398. if(!enc_ensure(e, 32)) {
  399. return 0;
  400. }
  401. start = &(e->p[e->i]);
  402. if(!double_to_shortest(start, e->curr->size, &len, val)) {
  403. return 0;
  404. }
  405. e->i += len;
  406. e->count++;
  407. return 1;
  408. }
  409. static inline int
  410. enc_char(Encoder* e, char c)
  411. {
  412. if(!enc_ensure(e, 1)) {
  413. return 0;
  414. }
  415. e->p[e->i++] = c;
  416. return 1;
  417. }
  418. static int
  419. enc_shift(Encoder* e) {
  420. int i;
  421. char* shift;
  422. assert(e->shiftcnt >= 0 && "Invalid shift count.");
  423. shift = shifts[MIN(e->shiftcnt, NUM_SHIFTS-1)];
  424. if(!enc_literal(e, shift + 1, *shift))
  425. return 0;
  426. // Finish the rest of this shift it's it bigger than
  427. // our largest predefined constant.
  428. for(i = NUM_SHIFTS - 1; i < e->shiftcnt; i++) {
  429. if(!enc_literal(e, " ", 2))
  430. return 0;
  431. }
  432. return 1;
  433. }
  434. static inline int
  435. enc_start_object(Encoder* e)
  436. {
  437. e->count++;
  438. e->shiftcnt++;
  439. if(!enc_char(e, '{'))
  440. return 0;
  441. MAYBE_PRETTY(e);
  442. return 1;
  443. }
  444. static inline int
  445. enc_end_object(Encoder* e)
  446. {
  447. e->shiftcnt--;
  448. MAYBE_PRETTY(e);
  449. return enc_char(e, '}');
  450. }
  451. static inline int
  452. enc_start_array(Encoder* e)
  453. {
  454. e->count++;
  455. e->shiftcnt++;
  456. if(!enc_char(e, '['))
  457. return 0;
  458. MAYBE_PRETTY(e);
  459. return 1;
  460. }
  461. static inline int
  462. enc_end_array(Encoder* e)
  463. {
  464. e->shiftcnt--;
  465. MAYBE_PRETTY(e);
  466. return enc_char(e, ']');
  467. }
  468. static inline int
  469. enc_colon(Encoder* e)
  470. {
  471. if(e->pretty)
  472. return enc_literal(e, " : ", 3);
  473. return enc_char(e, ':');
  474. }
  475. static inline int
  476. enc_comma(Encoder* e)
  477. {
  478. if(!enc_char(e, ','))
  479. return 0;
  480. MAYBE_PRETTY(e);
  481. return 1;
  482. }
  483. #if MAP_TYPE_PRESENT
  484. int
  485. enc_map_to_ejson(ErlNifEnv* env, ERL_NIF_TERM map, ERL_NIF_TERM* out)
  486. {
  487. ErlNifMapIterator iter;
  488. size_t size;
  489. ERL_NIF_TERM list;
  490. ERL_NIF_TERM tuple;
  491. ERL_NIF_TERM key;
  492. ERL_NIF_TERM val;
  493. if(!enif_get_map_size(env, map, &size)) {
  494. return 0;
  495. }
  496. list = enif_make_list(env, 0);
  497. if(size == 0) {
  498. *out = enif_make_tuple1(env, list);
  499. return 1;
  500. }
  501. if(!enif_map_iterator_create(env, map, &iter, ERL_NIF_MAP_ITERATOR_HEAD)) {
  502. return 0;
  503. }
  504. do {
  505. if(!enif_map_iterator_get_pair(env, &iter, &key, &val)) {
  506. enif_map_iterator_destroy(env, &iter);
  507. return 0;
  508. }
  509. tuple = enif_make_tuple2(env, key, val);
  510. list = enif_make_list_cell(env, tuple, list);
  511. } while(enif_map_iterator_next(env, &iter));
  512. enif_map_iterator_destroy(env, &iter);
  513. *out = enif_make_tuple1(env, list);
  514. return 1;
  515. }
  516. #endif
  517. ERL_NIF_TERM
  518. encode_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
  519. {
  520. jiffy_st* st = (jiffy_st*) enif_priv_data(env);
  521. Encoder* e;
  522. ERL_NIF_TERM opts;
  523. ERL_NIF_TERM val;
  524. ERL_NIF_TERM tmp_argv[3];
  525. if(argc != 2) {
  526. return enif_make_badarg(env);
  527. }
  528. e = enc_new(env);
  529. if(e == NULL) {
  530. return make_error(st, env, "internal_error");
  531. }
  532. tmp_argv[0] = enif_make_resource(env, e);
  533. tmp_argv[1] = enif_make_tuple1(env, argv[0]);
  534. tmp_argv[2] = enif_make_list(env, 0);
  535. enif_release_resource(e);
  536. opts = argv[1];
  537. if(!enif_is_list(env, opts)) {
  538. return enif_make_badarg(env);
  539. }
  540. while(enif_get_list_cell(env, opts, &val, &opts)) {
  541. if(enif_compare(val, e->atoms->atom_uescape) == 0) {
  542. e->uescape = 1;
  543. } else if(enif_compare(val, e->atoms->atom_pretty) == 0) {
  544. e->pretty = 1;
  545. } else if(enif_compare(val, e->atoms->atom_escape_forward_slashes) == 0) {
  546. e->escape_forward_slashes = 1;
  547. } else if(enif_compare(val, e->atoms->atom_use_nil) == 0) {
  548. e->use_nil = 1;
  549. } else if(enif_compare(val, e->atoms->atom_force_utf8) == 0) {
  550. // Ignore, handled in Erlang
  551. } else if(get_bytes_per_iter(env, val, &(e->bytes_per_red))) {
  552. continue;
  553. } else if(get_bytes_per_red(env, val, &(e->bytes_per_red))) {
  554. continue;
  555. } else {
  556. return enif_make_badarg(env);
  557. }
  558. }
  559. return encode_iter(env, 3, tmp_argv);
  560. }
  561. ERL_NIF_TERM
  562. encode_iter(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
  563. {
  564. TermStack stack;
  565. Encoder* e;
  566. jiffy_st* st = (jiffy_st*) enif_priv_data(env);
  567. ERL_NIF_TERM ret = 0;
  568. ERL_NIF_TERM curr;
  569. ERL_NIF_TERM item;
  570. const ERL_NIF_TERM* tuple;
  571. int arity;
  572. ErlNifSInt64 lval;
  573. double dval;
  574. size_t start;
  575. size_t bytes_written = 0;
  576. if(argc != 3) {
  577. return enif_make_badarg(env);
  578. } else if(!enif_get_resource(env, argv[0], st->res_enc, (void**) &e)) {
  579. return enif_make_badarg(env);
  580. } else if(!enif_is_list(env, argv[2])) {
  581. return enif_make_badarg(env);
  582. }
  583. if(!enc_init(e, env)) {
  584. return enif_make_badarg(env);
  585. }
  586. if(!termstack_restore(env, argv[1], &stack)) {
  587. return enif_make_badarg(env);
  588. }
  589. e->iolist = argv[2];
  590. start = e->iosize + e->i;
  591. while(!termstack_is_empty(&stack)) {
  592. bytes_written += (e->iosize + e->i) - start;
  593. if(should_yield(env, &bytes_written, e->bytes_per_red)) {
  594. ERL_NIF_TERM saved_stack = termstack_save(env, &stack);
  595. termstack_destroy(&stack);
  596. return enif_make_tuple4(
  597. env,
  598. st->atom_iter,
  599. argv[0],
  600. saved_stack,
  601. e->iolist
  602. );
  603. }
  604. curr = termstack_pop(&stack);
  605. if(enif_is_identical(curr, e->atoms->ref_object)) {
  606. curr = termstack_pop(&stack);
  607. if(!enif_get_list_cell(env, curr, &item, &curr)) {
  608. if(!enc_end_object(e)) {
  609. ret = enc_error(e, "internal_error");
  610. goto done;
  611. }
  612. continue;
  613. }
  614. if(!enif_get_tuple(env, item, &arity, &tuple)) {
  615. ret = enc_obj_error(e, "invalid_object_member", item);
  616. goto done;
  617. }
  618. if(arity != 2) {
  619. ret = enc_obj_error(e, "invalid_object_member_arity", item);
  620. goto done;
  621. }
  622. if(!enc_comma(e)) {
  623. ret = enc_error(e, "internal_error");
  624. goto done;
  625. }
  626. if(!enc_string(e, tuple[0])) {
  627. ret = enc_obj_error(e, "invalid_object_member_key", tuple[0]);
  628. goto done;
  629. }
  630. if(!enc_colon(e)) {
  631. ret = enc_error(e, "internal_error");
  632. goto done;
  633. }
  634. termstack_push(&stack, curr);
  635. termstack_push(&stack, e->atoms->ref_object);
  636. termstack_push(&stack, tuple[1]);
  637. } else if(enif_is_identical(curr, e->atoms->ref_array)) {
  638. curr = termstack_pop(&stack);
  639. if(!enif_get_list_cell(env, curr, &item, &curr)) {
  640. if(!enc_end_array(e)) {
  641. ret = enc_error(e, "internal_error");
  642. goto done;
  643. }
  644. continue;
  645. }
  646. if(!enc_comma(e)) {
  647. ret = enc_error(e, "internal_error");
  648. goto done;
  649. }
  650. termstack_push(&stack, curr);
  651. termstack_push(&stack, e->atoms->ref_array);
  652. termstack_push(&stack, item);
  653. } else if(enif_compare(curr, e->atoms->atom_null) == 0) {
  654. if(!enc_literal(e, "null", 4)) {
  655. ret = enc_error(e, "null");
  656. goto done;
  657. }
  658. } else if(e->use_nil && enif_compare(curr, e->atoms->atom_nil) == 0) {
  659. if(!enc_literal(e, "null", 4)) {
  660. ret = enc_error(e, "null");
  661. goto done;
  662. }
  663. } else if(enif_compare(curr, e->atoms->atom_true) == 0) {
  664. if(!enc_literal(e, "true", 4)) {
  665. ret = enc_error(e, "true");
  666. goto done;
  667. }
  668. } else if(enif_compare(curr, e->atoms->atom_false) == 0) {
  669. if(!enc_literal(e, "false", 5)) {
  670. ret = enc_error(e, "false");
  671. goto done;
  672. }
  673. } else if(enif_is_binary(env, curr)) {
  674. if(!enc_string(e, curr)) {
  675. ret = enc_obj_error(e, "invalid_string", curr);
  676. goto done;
  677. }
  678. } else if(enif_is_atom(env, curr)) {
  679. if(!enc_string(e, curr)) {
  680. ret = enc_obj_error(e, "invalid_string", curr);
  681. goto done;
  682. }
  683. } else if(enif_get_int64(env, curr, &lval)) {
  684. if(!enc_long(e, lval)) {
  685. ret = enc_error(e, "internal_error");
  686. goto done;
  687. }
  688. } else if(enif_get_double(env, curr, &dval)) {
  689. if(!enc_double(e, dval)) {
  690. ret = enc_error(e, "internal_error");
  691. goto done;
  692. }
  693. } else if(enif_get_tuple(env, curr, &arity, &tuple)) {
  694. if(arity != 1) {
  695. ret = enc_obj_error(e, "invalid_ejson", curr);
  696. goto done;
  697. }
  698. if(!enif_is_list(env, tuple[0])) {
  699. ret = enc_obj_error(e, "invalid_object", curr);
  700. goto done;
  701. }
  702. if(!enc_start_object(e)) {
  703. ret = enc_error(e, "internal_error");
  704. goto done;
  705. }
  706. if(!enif_get_list_cell(env, tuple[0], &item, &curr)) {
  707. if(!enc_end_object(e)) {
  708. ret = enc_error(e, "internal_error");
  709. goto done;
  710. }
  711. continue;
  712. }
  713. if(!enif_get_tuple(env, item, &arity, &tuple)) {
  714. ret = enc_obj_error(e, "invalid_object_member", item);
  715. goto done;
  716. }
  717. if(arity != 2) {
  718. ret = enc_obj_error(e, "invalid_object_member_arity", item);
  719. goto done;
  720. }
  721. if(!enc_string(e, tuple[0])) {
  722. ret = enc_obj_error(e, "invalid_object_member_key", tuple[0]);
  723. goto done;
  724. }
  725. if(!enc_colon(e)) {
  726. ret = enc_error(e, "internal_error");
  727. goto done;
  728. }
  729. termstack_push(&stack, curr);
  730. termstack_push(&stack, e->atoms->ref_object);
  731. termstack_push(&stack, tuple[1]);
  732. #if MAP_TYPE_PRESENT
  733. } else if(enif_is_map(env, curr)) {
  734. if(!enc_map_to_ejson(env, curr, &curr)) {
  735. ret = enc_error(e, "internal_error");
  736. goto done;
  737. }
  738. termstack_push(&stack, curr);
  739. #endif
  740. } else if(enif_is_list(env, curr)) {
  741. if(!enc_start_array(e)) {
  742. ret = enc_error(e, "internal_error");
  743. goto done;
  744. }
  745. if(!enif_get_list_cell(env, curr, &item, &curr)) {
  746. if(!enc_end_array(e)) {
  747. ret = enc_error(e, "internal_error");
  748. goto done;
  749. }
  750. continue;
  751. }
  752. termstack_push(&stack, curr);
  753. termstack_push(&stack, e->atoms->ref_array);
  754. termstack_push(&stack, item);
  755. } else {
  756. if(!enc_unknown(e, curr)) {
  757. ret = enc_error(e, "internal_error");
  758. goto done;
  759. }
  760. }
  761. }
  762. if(!enc_done(e, &item)) {
  763. ret = enc_error(e, "internal_error");
  764. goto done;
  765. }
  766. if(e->iolen == 0) {
  767. ret = item;
  768. } else {
  769. ret = enif_make_tuple2(env, e->atoms->atom_partial, item);
  770. }
  771. done:
  772. termstack_destroy(&stack);
  773. return ret;
  774. }