25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

626 satır
16 KiB

  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 1024
  9. typedef struct {
  10. ErlNifEnv* env;
  11. jiffy_st* atoms;
  12. int count;
  13. int iolen;
  14. ERL_NIF_TERM iolist;
  15. ErlNifBinary* curr;
  16. char* p;
  17. unsigned char* u;
  18. size_t i;
  19. } Encoder;
  20. int
  21. enc_init(Encoder* e, ErlNifEnv* env, ErlNifBinary* bin)
  22. {
  23. e->env = env;
  24. e->atoms = enif_priv_data(env);
  25. e->count = 0;
  26. e->iolen = 0;
  27. e->iolist = enif_make_list(env, 0);
  28. e->curr = bin;
  29. if(!enif_alloc_binary(BIN_INC_SIZE, e->curr)) {
  30. return 0;
  31. }
  32. memset(e->curr->data, 0, e->curr->size);
  33. e->p = (char*) e->curr->data;
  34. e->u = (unsigned char*) e->curr->data;
  35. e->i = 0;
  36. return 1;
  37. }
  38. void
  39. enc_destroy(Encoder* e)
  40. {
  41. if(e->curr != NULL) {
  42. enif_release_binary(e->curr);
  43. }
  44. }
  45. ERL_NIF_TERM
  46. enc_error(Encoder* e, const char* msg)
  47. {
  48. //assert(0 && msg);
  49. return make_error(e->atoms, e->env, msg);
  50. }
  51. int
  52. enc_ensure(Encoder* e, size_t req)
  53. {
  54. size_t new_sz;
  55. if(req < e->curr->size - e->i) {
  56. return 1;
  57. }
  58. new_sz = req - (e->curr->size - e->i) + e->curr->size;
  59. new_sz += BIN_INC_SIZE - (new_sz % BIN_INC_SIZE);
  60. assert(new_sz > e->curr->size && "Invalid size calculation.");
  61. if(!enif_realloc_binary(e->curr, new_sz)) {
  62. return 0;
  63. }
  64. e->p = (char*) e->curr->data;
  65. e->u = (unsigned char*) e->curr->data;
  66. memset(&(e->u[e->i]), 0, e->curr->size - e->i);
  67. return 1;
  68. }
  69. int
  70. enc_result(Encoder* e, ERL_NIF_TERM* value)
  71. {
  72. if(e->i != e->curr->size) {
  73. if(!enif_realloc_binary(e->curr, e->i)) {
  74. return 0;
  75. }
  76. }
  77. *value = enif_make_binary(e->env, e->curr);
  78. e->curr = NULL;
  79. return 1;
  80. }
  81. int
  82. enc_done(Encoder* e, ERL_NIF_TERM* value)
  83. {
  84. ERL_NIF_TERM last;
  85. if(e->iolen == 0) {
  86. return enc_result(e, value);
  87. }
  88. if(e->i > 0 ) {
  89. if(!enc_result(e, &last)) {
  90. return 0;
  91. }
  92. e->iolist = enif_make_list_cell(e->env, last, e->iolist);
  93. e->iolen++;
  94. }
  95. *value = e->iolist;
  96. return 1;
  97. }
  98. int
  99. enc_unknown(Encoder* e, ERL_NIF_TERM value)
  100. {
  101. ErlNifBinary* bin = e->curr;
  102. ERL_NIF_TERM curr;
  103. if(e->i > 0) {
  104. if(!enc_result(e, &curr)) {
  105. return 0;
  106. }
  107. e->iolist = enif_make_list_cell(e->env, curr, e->iolist);
  108. e->iolen++;
  109. }
  110. e->iolist = enif_make_list_cell(e->env, value, e->iolist);
  111. e->iolen++;
  112. // Reinitialize our binary for the next buffer.
  113. e->curr = bin;
  114. if(!enif_alloc_binary(BIN_INC_SIZE, e->curr)) {
  115. return 0;
  116. }
  117. memset(e->curr->data, 0, e->curr->size);
  118. e->p = (char*) e->curr->data;
  119. e->u = (unsigned char*) e->curr->data;
  120. e->i = 0;
  121. return 1;
  122. }
  123. int
  124. enc_literal(Encoder* e, const char* literal, size_t len)
  125. {
  126. if(!enc_ensure(e, len)) {
  127. return 0;
  128. }
  129. memcpy(&(e->p[e->i]), literal, len);
  130. e->i += len;
  131. e->count++;
  132. return 1;
  133. }
  134. int
  135. enc_string(Encoder* e, ERL_NIF_TERM val)
  136. {
  137. ErlNifBinary bin;
  138. char atom[512];
  139. unsigned char* data;
  140. size_t size;
  141. int esc_extra = 0;
  142. int ulen;
  143. int ui;
  144. int i;
  145. if(enif_is_binary(e->env, val)) {
  146. if(!enif_inspect_binary(e->env, val, &bin)) {
  147. return 0;
  148. }
  149. data = bin.data;
  150. size = bin.size;
  151. } else if(enif_is_atom(e->env, val)) {
  152. if(!enif_get_atom(e->env, val, atom, 512, ERL_NIF_LATIN1)) {
  153. return 0;
  154. }
  155. data = (unsigned char*) atom;
  156. size = strlen(atom);
  157. } else {
  158. return 0;
  159. }
  160. i = 0;
  161. while(i < size) {
  162. switch((char) data[i]) {
  163. case '\"':
  164. case '\\':
  165. case '/':
  166. case '\b':
  167. case '\f':
  168. case '\n':
  169. case '\r':
  170. case '\t':
  171. esc_extra += 1;
  172. i++;
  173. continue;
  174. default:
  175. if(data[i] < 0x20) {
  176. esc_extra += 5;
  177. i++;
  178. continue;
  179. } else if(data[i] < 0x80) {
  180. i++;
  181. continue;
  182. }
  183. ulen = -1;
  184. if((data[i] & 0xE0) == 0xC0) {
  185. ulen = 1;
  186. } else if((data[i] & 0xF0) == 0xE0) {
  187. ulen = 2;
  188. } else if((data[i] & 0xF8) == 0xF0) {
  189. ulen = 3;
  190. } else if((data[i] & 0xFC) == 0xF8) {
  191. ulen = 4;
  192. } else if((data[i] & 0xFE) == 0xFC) {
  193. ulen = 5;
  194. }
  195. if(ulen < 0) {
  196. return 0;
  197. }
  198. if(i+1+ulen > size) {
  199. return 0;
  200. }
  201. for(ui = 0; ui < ulen; ui++) {
  202. if((data[i+1+ui] & 0xC0) != 0x80) {
  203. return 0;
  204. }
  205. }
  206. if(ulen == 1) {
  207. if((data[i] & 0x1E) == 0)
  208. return 0;
  209. } else if(ulen == 2) {
  210. if((data[i] & 0x0F) + (data[i+1] & 0x20) == 0)
  211. return 0;
  212. } else if(ulen == 3) {
  213. if((data[i] & 0x07) + (data[i+1] & 0x30) == 0)
  214. return 0;
  215. } else if(ulen == 4) {
  216. if((data[i] & 0x03) + (data[i+1] & 0x38) == 0)
  217. return 0;
  218. } else if(ulen == 5) {
  219. if((data[i] & 0x01) + (data[i+1] & 0x3C) == 0)
  220. return 0;
  221. }
  222. i += 1 + ulen;
  223. }
  224. }
  225. if(!enc_ensure(e, size + esc_extra + 2)) {
  226. return 0;
  227. }
  228. e->p[e->i++] = '\"';
  229. i = 0;
  230. while(i < size) {
  231. switch((char) data[i]) {
  232. case '\"':
  233. case '\\':
  234. case '/':
  235. e->p[e->i++] = '\\';
  236. e->u[e->i++] = data[i];
  237. i++;
  238. continue;
  239. case '\b':
  240. e->p[e->i++] = '\\';
  241. e->p[e->i++] = 'b';
  242. i++;
  243. continue;
  244. case '\f':
  245. e->p[e->i++] = '\\';
  246. e->p[e->i++] = 'f';
  247. i++;
  248. continue;
  249. case '\n':
  250. e->p[e->i++] = '\\';
  251. e->p[e->i++] = 'n';
  252. i++;
  253. continue;
  254. case '\r':
  255. e->p[e->i++] = '\\';
  256. e->p[e->i++] = 'r';
  257. i++;
  258. continue;
  259. case '\t':
  260. e->p[e->i++] = '\\';
  261. e->p[e->i++] = 't';
  262. i++;
  263. continue;
  264. default:
  265. if(data[i] < 0x20) {
  266. e->p[e->i++] = '\\';
  267. e->p[e->i++] = 'u';
  268. if(!int_to_hex(data[i], &(e->p[e->i]))) {
  269. return 0;
  270. }
  271. e->i += 4;
  272. i++;
  273. } else {
  274. e->u[e->i++] = data[i++];
  275. }
  276. }
  277. }
  278. e->p[e->i++] = '\"';
  279. e->count++;
  280. return 1;
  281. }
  282. int
  283. enc_long(Encoder* e, long val)
  284. {
  285. if(!enc_ensure(e, 32)) {
  286. return 0;
  287. }
  288. snprintf(&(e->p[e->i]), 32, "%ld", val);
  289. e->i += strlen(&(e->p[e->i]));
  290. e->count++;
  291. return 1;
  292. }
  293. int
  294. enc_double(Encoder* e, double val)
  295. {
  296. if(!enc_ensure(e, 32)) {
  297. return 0;
  298. }
  299. snprintf(&(e->p[e->i]), 31, "%0.20g", val);
  300. e->i += strlen(&(e->p[e->i]));
  301. e->count++;
  302. return 1;
  303. }
  304. int
  305. enc_char(Encoder* e, char c)
  306. {
  307. if(!enc_ensure(e, 1)) {
  308. return 0;
  309. }
  310. e->p[e->i++] = c;
  311. return 1;
  312. }
  313. int
  314. enc_start_object(Encoder* e)
  315. {
  316. e->count++;
  317. return enc_char(e, '{');
  318. }
  319. int
  320. enc_end_object(Encoder* e)
  321. {
  322. return enc_char(e, '}');
  323. }
  324. int
  325. enc_start_array(Encoder* e)
  326. {
  327. e->count++;
  328. return enc_char(e, '[');
  329. }
  330. int
  331. enc_end_array(Encoder* e)
  332. {
  333. return enc_char(e, ']');
  334. }
  335. int
  336. enc_colon(Encoder* e)
  337. {
  338. return enc_char(e, ':');
  339. }
  340. int
  341. enc_comma(Encoder* e)
  342. {
  343. return enc_char(e, ',');
  344. }
  345. ERL_NIF_TERM
  346. encode(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
  347. {
  348. Encoder enc;
  349. Encoder* e = &enc;
  350. ErlNifBinary bin;
  351. ERL_NIF_TERM ret;
  352. ERL_NIF_TERM stack;
  353. ERL_NIF_TERM curr;
  354. ERL_NIF_TERM item;
  355. const ERL_NIF_TERM* tuple;
  356. int arity;
  357. double dval;
  358. long lval;
  359. int is_partial = 0;
  360. if(argc != 1) {
  361. return enif_make_badarg(env);
  362. }
  363. if(!enc_init(e, env, &bin)) {
  364. return enif_make_badarg(env);
  365. }
  366. stack = enif_make_list(env, 1, argv[0]);
  367. while(!enif_is_empty_list(env, stack)) {
  368. if(!enif_get_list_cell(env, stack, &curr, &stack)) {
  369. ret = enc_error(e, "internal_error");
  370. goto done;
  371. }
  372. if(enif_is_identical(curr, e->atoms->ref_object)) {
  373. if(!enif_get_list_cell(env, stack, &curr, &stack)) {
  374. ret = enc_error(e, "internal_error");
  375. goto done;
  376. }
  377. if(enif_is_empty_list(env, curr)) {
  378. if(!enc_end_object(e)) {
  379. ret = enc_error(e, "internal_error");
  380. goto done;
  381. }
  382. continue;
  383. }
  384. if(!enif_get_list_cell(env, curr, &item, &curr)) {
  385. ret = enc_error(e, "internal_error");
  386. goto done;
  387. }
  388. if(!enif_get_tuple(env, item, &arity, &tuple)) {
  389. ret = enc_error(e, "invalid_object_pair");
  390. goto done;
  391. }
  392. if(arity != 2) {
  393. ret = enc_error(e, "invalid_object_pair");
  394. goto done;
  395. }
  396. if(!enc_comma(e)) {
  397. ret = enc_error(e, "internal_error");
  398. goto done;
  399. }
  400. if(!enc_string(e, tuple[0])) {
  401. ret = enc_error(e, "invalid_object_key");
  402. goto done;
  403. }
  404. if(!enc_colon(e)) {
  405. ret = enc_error(e, "internal_error");
  406. goto done;
  407. }
  408. stack = enif_make_list_cell(env, curr, stack);
  409. stack = enif_make_list_cell(env, e->atoms->ref_object, stack);
  410. stack = enif_make_list_cell(env, tuple[1], stack);
  411. } else if(enif_is_identical(curr, e->atoms->ref_array)) {
  412. if(!enif_get_list_cell(env, stack, &curr, &stack)) {
  413. ret = enc_error(e, "internal_error");
  414. goto done;
  415. }
  416. if(enif_is_empty_list(env, curr)) {
  417. if(!enc_end_array(e)) {
  418. ret = enc_error(e, "internal_error");
  419. goto done;
  420. }
  421. continue;
  422. }
  423. if(!enc_comma(e)) {
  424. ret = enc_error(e, "internal_error");
  425. goto done;
  426. }
  427. if(!enif_get_list_cell(env, curr, &item, &curr)) {
  428. ret = enc_error(e, "internal_error");
  429. goto done;
  430. }
  431. stack = enif_make_list_cell(env, curr, stack);
  432. stack = enif_make_list_cell(env, e->atoms->ref_array, stack);
  433. stack = enif_make_list_cell(env, item, stack);
  434. } else if(enif_compare(curr, e->atoms->atom_null) == 0) {
  435. if(!enc_literal(e, "null", 4)) {
  436. ret = enc_error(e, "null");
  437. goto done;
  438. }
  439. } else if(enif_compare(curr, e->atoms->atom_true) == 0) {
  440. if(!enc_literal(e, "true", 4)) {
  441. ret = enc_error(e, "true");
  442. goto done;
  443. }
  444. } else if(enif_compare(curr, e->atoms->atom_false) == 0) {
  445. if(!enc_literal(e, "false", 5)) {
  446. ret = enc_error(e, "false");
  447. goto done;
  448. }
  449. } else if(enif_is_binary(env, curr)) {
  450. if(!enc_string(e, curr)) {
  451. ret = enc_error(e, "invalid_string");
  452. goto done;
  453. }
  454. } else if(enif_is_atom(env, curr)) {
  455. if(!enc_string(e, curr)) {
  456. ret = enc_error(e, "invalid_string");
  457. goto done;
  458. }
  459. } else if(enif_get_int64(env, curr, &lval)) {
  460. if(!enc_long(e, lval)) {
  461. ret = enc_error(e, "internal_error");
  462. goto done;
  463. }
  464. } else if(enif_get_double(env, curr, &dval)) {
  465. if(!enc_double(e, dval)) {
  466. ret = enc_error(e, "internal_error");
  467. goto done;
  468. }
  469. } else if(enif_get_tuple(env, curr, &arity, &tuple)) {
  470. if(arity != 1) {
  471. ret = enc_error(e, "invalid_ejson");
  472. goto done;
  473. }
  474. if(!enif_is_list(env, tuple[0])) {
  475. ret = enc_error(e, "invalid_object");
  476. goto done;
  477. }
  478. if(!enc_start_object(e)) {
  479. ret = enc_error(e, "internal_error");
  480. goto done;
  481. }
  482. if(enif_is_empty_list(env, tuple[0])) {
  483. if(!enc_end_object(e)) {
  484. ret = enc_error(e, "internal_error");
  485. goto done;
  486. }
  487. continue;
  488. }
  489. if(!enif_get_list_cell(env, tuple[0], &item, &curr)) {
  490. ret = enc_error(e, "internal_error");
  491. goto done;
  492. }
  493. if(!enif_get_tuple(env, item, &arity, &tuple)) {
  494. ret = enc_error(e, "invalid_object_pair");
  495. goto done;
  496. }
  497. if(arity != 2) {
  498. ret = enc_error(e, "invalid_object_pair");
  499. goto done;
  500. }
  501. if(!enc_string(e, tuple[0])) {
  502. ret = enc_error(e, "invalid_object_key");
  503. goto done;
  504. }
  505. if(!enc_colon(e)) {
  506. ret = enc_error(e, "internal_error");
  507. goto done;
  508. }
  509. stack = enif_make_list_cell(env, curr, stack);
  510. stack = enif_make_list_cell(env, e->atoms->ref_object, stack);
  511. stack = enif_make_list_cell(env, tuple[1], stack);
  512. } else if(enif_is_list(env, curr)) {
  513. if(!enc_start_array(e)) {
  514. ret = enc_error(e, "internal_error");
  515. goto done;
  516. }
  517. if(enif_is_empty_list(env, curr)) {
  518. if(!enc_end_array(e)) {
  519. ret = enc_error(e, "internal_error");
  520. goto done;
  521. }
  522. continue;
  523. }
  524. if(!enif_get_list_cell(env, curr, &item, &curr)) {
  525. ret = enc_error(e, "internal_error");
  526. goto done;
  527. }
  528. stack = enif_make_list_cell(env, curr, stack);
  529. stack = enif_make_list_cell(env, e->atoms->ref_array, stack);
  530. stack = enif_make_list_cell(env, item, stack);
  531. } else {
  532. is_partial = 1;
  533. if(!enc_unknown(e, curr)) {
  534. ret = enc_error(e, "internal_error");
  535. goto done;
  536. }
  537. }
  538. } while(!enif_is_empty_list(env, stack));
  539. if(!enc_done(e, &item)) {
  540. ret = enc_error(e, "internal_error");
  541. goto done;
  542. }
  543. if(!is_partial) {
  544. ret = enif_make_tuple2(env, e->atoms->atom_ok, item);
  545. } else {
  546. ret = enif_make_tuple2(env, e->atoms->atom_partial, item);
  547. }
  548. done:
  549. enc_destroy(e);
  550. return ret;
  551. }