Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

565 righe
14 KiB

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