github.com/aergoio/aergo@v1.3.1/contract/util.c (about) 1 #include <stdlib.h> 2 #include <stdio.h> 3 #include <string.h> 4 #include <ctype.h> 5 #include "util.h" 6 #include "vm.h" 7 #include "math.h" 8 #include "lgmp.h" 9 10 typedef struct sbuff { 11 char *buf; 12 int idx; 13 int buf_len; 14 } sbuff_t; 15 16 typedef struct tcall { 17 void **ptrs; 18 int curidx; 19 int size; 20 } callinfo_t; 21 22 typedef struct sort_key { 23 char *elem; 24 int start_idx; 25 int key_len; 26 } sort_key_t; 27 28 static void lua_util_sbuf_init(sbuff_t *sbuf, int len) 29 { 30 sbuf->idx = 0; 31 sbuf->buf_len = len; 32 sbuf->buf = malloc (len); 33 } 34 35 static void copy_to_buffer(char *src, int len, sbuff_t *sbuf) 36 { 37 int orig_buf_len = sbuf->buf_len; 38 while (len + sbuf->idx >= sbuf->buf_len) { 39 sbuf->buf_len *= 2; 40 } 41 if (sbuf->buf_len != orig_buf_len) { 42 sbuf->buf = realloc (sbuf->buf, sbuf->buf_len); 43 } 44 memcpy (sbuf->buf + sbuf->idx, src, len); 45 sbuf->idx += len; 46 } 47 48 static void add_escape (sbuff_t *sbuf, char ch) 49 { 50 if (sbuf->idx + 2 >= sbuf->buf_len) { 51 sbuf->buf_len *= 2; 52 sbuf->buf = realloc (sbuf->buf, sbuf->buf_len); 53 } 54 sbuf->buf[sbuf->idx++] = '\\'; 55 sbuf->buf[sbuf->idx++] = ch; 56 } 57 58 static void copy_str_to_buffer(char *src, int len, sbuff_t *sbuf) 59 { 60 int i; 61 62 char *end = src + len; 63 64 for (; src < end; ++src) { 65 if (*src >= 0x00 && *src <= 0x1f) { 66 if (sbuf->idx + 6 >= sbuf->buf_len) { 67 sbuf->buf_len = sbuf->buf_len * 2 + 6; 68 sbuf->buf = realloc (sbuf->buf, sbuf->buf_len); 69 } 70 sprintf(sbuf->buf + sbuf->idx, "\\u00%02x", *src); 71 sbuf->idx = sbuf->idx + 6; 72 continue; 73 } 74 switch(*src) { 75 case '"': 76 case '\\': 77 add_escape(sbuf, *src); 78 break; 79 case '\t': 80 add_escape(sbuf, 't'); 81 break; 82 case '\n': 83 add_escape(sbuf, 'n'); 84 break; 85 case '\b': 86 add_escape(sbuf, 'b'); 87 break; 88 case '\f': 89 add_escape(sbuf, 'f'); 90 break; 91 case '\r': 92 add_escape(sbuf, 'r'); 93 break; 94 default: 95 if (sbuf->idx + 1 >= sbuf->buf_len) { 96 sbuf->buf_len *= 2; 97 sbuf->buf = realloc (sbuf->buf, sbuf->buf_len); 98 } 99 sbuf->buf[sbuf->idx++] = *src; 100 } 101 } 102 } 103 static callinfo_t *callinfo_new() 104 { 105 callinfo_t *callinfo = malloc(sizeof(callinfo_t)); 106 callinfo->size = 4; 107 callinfo->ptrs = malloc(sizeof(void *) * callinfo->size); 108 callinfo->curidx = 0; 109 110 return callinfo; 111 } 112 113 static void callinfo_del(callinfo_t *callinfo) 114 { 115 if (callinfo == NULL) 116 return; 117 free (callinfo->ptrs); 118 free (callinfo); 119 } 120 121 static bool register_tcall(callinfo_t *callinfo, void *ptr) 122 { 123 int i; 124 125 for(i = 0; i < callinfo->curidx; i++) { 126 if (callinfo->ptrs[i] == ptr) 127 return false; 128 } 129 if (callinfo->curidx == callinfo->size) { 130 callinfo->size *= 2; 131 callinfo->ptrs = realloc(callinfo->ptrs, sizeof(void *) * callinfo->size); 132 } 133 callinfo->ptrs[callinfo->curidx++] = ptr; 134 return true; 135 } 136 137 static void unregister_tcall(callinfo_t *callinfo) 138 { 139 callinfo->curidx--; 140 } 141 142 static int sort_key_compare (const void *first, const void*second) 143 { 144 sort_key_t *key1 = (sort_key_t *)first, *key2 = (sort_key_t *)second; 145 if (key1->key_len == key2->key_len) { 146 return strcmp(key1->elem, key2->elem); 147 } 148 else { 149 int comp_len = (key1->key_len > key2->key_len ? key2->key_len : key1->key_len); 150 int ret = strncmp (key1->elem, key2->elem, comp_len); 151 if (ret == 0) 152 return (key1->key_len > key2->key_len ? 1 : -1); 153 return ret; 154 } 155 } 156 157 char *bignum_str = "{\"_bignum\":\""; 158 159 static bool lua_util_dump_json (lua_State *L, int idx, sbuff_t *sbuf, bool json_form, bool iskey, 160 callinfo_t **pcallinfo) 161 { 162 int len; 163 char *src_val; 164 char tmp[128]; 165 166 switch (lua_type(L, idx)) { 167 case LUA_TNUMBER: { 168 if (json_form && iskey) { 169 if (luaL_isinteger(L, idx)) { 170 len = sprintf (tmp, "\"%ld\",", lua_tointeger(L, idx)); 171 } 172 else { 173 double d = lua_tonumber(L, idx); 174 if (isinf(d) || isnan(d)) { 175 lua_pushstring(L, "not support nan or infinity"); 176 return false; 177 } 178 len = sprintf (tmp, "\"%.14g\",", d); 179 } 180 } 181 else { 182 if (luaL_isinteger(L, idx)) { 183 len = sprintf (tmp, "%ld,", lua_tointeger(L, idx)); 184 } 185 else { 186 double d = lua_tonumber(L, idx); 187 if (isinf(d) || isnan(d)) { 188 lua_pushstring(L, "not support nan or infinity"); 189 return false; 190 } 191 len = sprintf (tmp, "%.14g,", lua_tonumber(L, idx)); 192 } 193 } 194 src_val = tmp; 195 break; 196 } 197 case LUA_TBOOLEAN: { 198 if (lua_toboolean(L, idx)) 199 src_val = "true,"; 200 else 201 src_val = "false,"; 202 break; 203 } 204 case LUA_TNIL: 205 if (json_form) 206 src_val = "{},"; 207 else 208 src_val = "null,"; 209 break; 210 case LUA_TSTRING: { 211 size_t len; 212 src_val = (char *)lua_tolstring(L, idx, &len); 213 copy_to_buffer ("\"", 1, sbuf); 214 copy_str_to_buffer (src_val, len, sbuf); 215 src_val = "\","; 216 break; 217 } 218 case LUA_TTABLE: { 219 int orig_bidx; 220 int table_idx = idx; 221 int tbl_len; 222 int key_idx; 223 bool is_array = false; 224 callinfo_t *callinfo = *pcallinfo; 225 if (callinfo == NULL) { 226 callinfo = callinfo_new(); 227 *pcallinfo = callinfo; 228 } 229 if (!register_tcall(callinfo, (void *)lua_topointer(L, idx))) { 230 lua_pushstring(L, "nested table error"); 231 return false; 232 } 233 234 if (table_idx < 0) 235 table_idx = lua_gettop(L) + idx + 1; 236 tbl_len = lua_objlen(L, table_idx); 237 if (json_form && tbl_len > 0) { 238 double number; 239 char *check_array = calloc(tbl_len, sizeof(char)); 240 is_array = true; 241 lua_pushnil(L); 242 while (lua_next(L, table_idx) != 0) { 243 lua_pop (L ,1); 244 if (!lua_isnumber(L, -1) || lua_tonumber(L, -1) != round(lua_tonumber(L, -1))) { 245 is_array = false; 246 lua_pop (L ,1); 247 break; 248 } 249 key_idx = lua_tointeger(L, -1) - 1; 250 if (key_idx >= tbl_len || key_idx < 0) { 251 is_array = false; 252 lua_pop (L ,1); 253 break; 254 } 255 check_array[key_idx] = 1; 256 } 257 if (is_array) { 258 for (key_idx = 0; key_idx < tbl_len; ++key_idx) { 259 if (check_array[key_idx] != 1) { 260 is_array = false; 261 break; 262 } 263 } 264 } 265 free(check_array); 266 } 267 268 if (is_array) { 269 copy_to_buffer ("[", 1, sbuf); 270 for (key_idx = 1; key_idx <= tbl_len; ++ key_idx) { 271 lua_rawgeti(L, table_idx, key_idx); 272 if (!lua_util_dump_json (L, -1, sbuf, true, false, pcallinfo)) { 273 return false; 274 } 275 lua_pop(L, 1); 276 } 277 --(sbuf->idx); 278 src_val = "],"; 279 } 280 else { 281 sbuff_t sort_buf; 282 int idx = 0, max_key = 5; 283 int i; 284 sort_key_t *sort_keys = malloc(sizeof(sort_key_t) * max_key); 285 lua_util_sbuf_init(&sort_buf, 20); 286 287 copy_to_buffer ("{", 1, sbuf); 288 orig_bidx = (sbuf->idx); 289 lua_pushnil(L); 290 while (lua_next(L, table_idx) != 0) { 291 if (idx == max_key) { 292 max_key *= 2; 293 sort_keys = realloc(sort_keys, sizeof(sort_key_t) * max_key); 294 } 295 sort_keys[idx].start_idx = sort_buf.idx; 296 if (!lua_util_dump_json (L, -2, &sort_buf, json_form, true, pcallinfo)) { 297 free(sort_keys); 298 free(sort_buf.buf); 299 return false; 300 } 301 sort_keys[idx].key_len = sort_buf.idx - sort_keys[idx].start_idx - 1; 302 sort_buf.buf[sort_buf.idx - 1]=':'; 303 if (!lua_util_dump_json (L, -1, &sort_buf, json_form, false, pcallinfo)) { 304 free(sort_keys); 305 free(sort_buf.buf); 306 return false; 307 } 308 sort_buf.buf[sort_buf.idx - 1] = '\0'; 309 lua_pop(L, 1); 310 ++idx; 311 312 } 313 if (idx > 0) { 314 for (i = 0; i < idx; ++i) 315 sort_keys[i].elem = sort_buf.buf + sort_keys[i].start_idx; 316 qsort(sort_keys, idx, sizeof(sort_key_t), sort_key_compare); 317 for (i = 0; i < idx; ++i) { 318 copy_to_buffer(sort_keys[i].elem, strlen(sort_keys[i].elem), sbuf); 319 copy_to_buffer(",", 1, sbuf); 320 } 321 } 322 free(sort_keys); 323 free(sort_buf.buf); 324 if (orig_bidx != sbuf->idx) 325 --(sbuf->idx); 326 src_val = "},"; 327 } 328 unregister_tcall(callinfo); 329 break; 330 } 331 case LUA_TUSERDATA: { 332 if (lua_isbignumber(L, idx)) { 333 char *s; 334 copy_to_buffer(bignum_str,strlen(bignum_str), sbuf); 335 s = lua_get_bignum_str(L, idx); 336 if (s != NULL) { 337 copy_str_to_buffer (s, strlen (s), sbuf); 338 free(s); 339 } 340 src_val = "\"},"; 341 break; 342 } 343 } 344 default: 345 lua_pushfstring(L, "\"unsupport type: %s\"", lua_typename (L, lua_type(L, idx))); 346 return false; 347 } 348 349 len = strlen (src_val); 350 copy_to_buffer (src_val, len, sbuf); 351 return true; 352 353 } 354 static int json_to_lua (lua_State *L, char **start, bool check, bool is_bignum); 355 356 static int json_array_to_lua_table(lua_State *L, char **start, bool check) { 357 char *json = (*start) + 1; 358 int index = 1; 359 360 lua_newtable(L); 361 while(*json != ']') { 362 lua_pushnumber(L, index++); 363 if (json_to_lua (L, &json, check, false) != 0) 364 return -1; 365 if (*json == ',') 366 ++json; 367 else if(*json != ']') 368 return -1; 369 lua_rawset(L, -3); 370 } 371 *start = json + 1; 372 return 0; 373 } 374 375 static int json_to_lua_table(lua_State *L, char **start, bool check) { 376 char *json = (*start) + 1; 377 int index = 1; 378 bool is_bignum = false; 379 int elem_cnt = 0; 380 381 lua_newtable(L); 382 while(*json != '}') { 383 lua_pushnumber(L, index++); 384 if (json_to_lua (L, &json, check, false) != 0) 385 return -1; 386 if (*json == ':') { 387 lua_remove(L, -2); 388 --index; 389 if (check && !lua_isstring(L, -1)) { 390 return -1; 391 } 392 if (elem_cnt == 0 && lua_type(L, -1) == LUA_TSTRING && 393 strcmp(lua_tostring(L, -1), "_bignum") == 0) { 394 is_bignum = true; 395 } 396 ++json; 397 if (json_to_lua (L, &json, check, is_bignum) != 0) 398 return -1; 399 } 400 if (*json == ',') { 401 if (is_bignum) 402 return -1; 403 ++json; 404 } 405 else if (*json != '}') 406 return -1; 407 408 if (is_bignum) { 409 if (!lua_isbignumber(L, -1)) 410 return -1; 411 lua_replace(L, -3); 412 lua_pop(L, 1); 413 } 414 else 415 lua_rawset(L, -3); 416 } 417 *start = json + 1; 418 return 0; 419 } 420 421 422 int lua_util_utf8_encode(char *s, unsigned ch) { 423 if (ch < 0x80) { 424 s[0] = (char)ch; 425 return 1; 426 } 427 if (ch <= 0x7FF) { 428 s[1] = (char) ((ch | 0x80) & 0xBF); 429 s[0] = (char) ((ch >> 6) | 0xC0); 430 return 2; 431 } 432 if (ch <= 0xFFFF) { 433 s[2] = (char) ((ch | 0x80) & 0xBF); 434 s[1] = (char) (((ch >> 6) | 0x80) & 0xBF); 435 s[0] = (char) ((ch >> 12) | 0xE0); 436 return 3; 437 } 438 { 439 char buff[UTF8_MAX]; 440 unsigned mfb = 0x3F; 441 int n = 1; 442 do { 443 if (n > 6) 444 return -1; 445 buff[UTF8_MAX - (n++)] = 0x80 | (ch&0x3F); 446 ch >>= 6; 447 mfb >>= 1; 448 } while (ch > mfb); 449 buff[UTF8_MAX - n] = (~mfb << 1) | ch; 450 memcpy(s, &buff[UTF8_MAX - n], n); 451 return n; 452 } 453 } 454 455 static int json_to_lua (lua_State *L, char **start, bool check, bool is_bignum) { 456 char *json = *start; 457 char special[5]; 458 459 special[4] = '\0'; 460 while(isspace(*json)) ++json; 461 if (*json == '"') { 462 if (is_bignum) { 463 char *end = strchr(json + 1, '"'); 464 if (end != NULL) { 465 *end = '\0'; 466 lua_set_bignum(L, json + 1); 467 *end = '"'; 468 json = end + 1; 469 } 470 else 471 return -1; 472 } else { 473 char *end = json + 1; 474 char *target = end; 475 while ((*end) != '"') { 476 if (*end == '\0') 477 return -1; 478 if ((*end) == '\\') { 479 end++; 480 switch(*end) { 481 case 't': 482 *target = '\t'; 483 break; 484 case 'n': 485 *target = '\n'; 486 break; 487 case 'b': 488 *target = '\b'; 489 break; 490 case 'f': 491 *target = '\f'; 492 break; 493 case 'r': 494 *target = '\r'; 495 break; 496 case 'u': { 497 int i; 498 unsigned ch; 499 int out; 500 for (i = 1; i < 5; ++i) { 501 if (!isxdigit(*(end + i))) 502 return -1; 503 } 504 memcpy (special, end+1, 4); 505 ch = strtol(special, NULL, 16); 506 out = lua_util_utf8_encode(target, ch); 507 if (out < 0) 508 return -1; 509 target = target + out - 1; 510 end += 4; 511 break; 512 } 513 default : 514 *target = *end; 515 } 516 } 517 else if (end != target) 518 *target = *end; 519 end++; 520 target++; 521 } 522 *target = '\0'; 523 lua_pushlstring(L, json + 1, target - json - 1); 524 json = end + 1; 525 } 526 } else if (isdigit(*json) || *json == '-' || *json == '+') { 527 double d; 528 char *end = json + 1; 529 530 if (is_bignum) 531 return -1; 532 while(*end != '\0') { 533 if (!isdigit(*end) && *end != '-' && *end != '.' && 534 *end != 'e' && *end != 'E' && *end != '+') { 535 break; 536 } 537 ++end; 538 } 539 sscanf(json, "%lf", &d); 540 lua_pushnumber(L, d); 541 json = end; 542 } else if (*json == '{') { 543 if (json_to_lua_table(L, &json, check) != 0) 544 return -1; 545 } else if (*json == '[') { 546 if (json_array_to_lua_table(L, &json, check) != 0) 547 return -1; 548 } else if (strncasecmp(json, "true", 4) == 0) { 549 lua_pushboolean(L, 1); 550 json = json + 4; 551 } else if (strncasecmp(json, "false", 5) == 0) { 552 lua_pushboolean(L, 0); 553 json = json + 5; 554 } else if (strncasecmp(json, "null", 4) == 0) { 555 lua_pushnil(L); 556 json = json + 4; 557 } else { 558 return -1; 559 } 560 while(isspace(*json)) ++json; 561 *start = json; 562 return 0; 563 } 564 565 void minus_inst_count(lua_State *L, int count) { 566 int cnt = luaL_instcount(L); 567 568 cnt -= count; 569 if (cnt <= 0) 570 cnt = 1; 571 luaL_setinstcount(L, cnt); 572 } 573 574 int lua_util_json_to_lua (lua_State *L, char *json, bool check) 575 { 576 if (json_to_lua (L, &json, check, false) != 0) 577 return -1; 578 if (check && *json != '\0') 579 return -1; 580 return 0; 581 } 582 583 char *lua_util_get_json_from_stack (lua_State *L, int start, int end, bool json_form) 584 { 585 int i; 586 sbuff_t sbuf; 587 int start_idx; 588 callinfo_t *callinfo = NULL; 589 lua_util_sbuf_init (&sbuf, 64); 590 591 if (!json_form || start < end) 592 copy_to_buffer ("[", 1, &sbuf); 593 start_idx = sbuf.idx; 594 for (i = start; i <= end; ++i) { 595 if (!lua_util_dump_json (L, i, &sbuf, json_form, false, &callinfo)) { 596 callinfo_del(callinfo); 597 free(sbuf.buf); 598 return NULL; 599 } 600 } 601 callinfo_del(callinfo); 602 if (sbuf.idx != start_idx) 603 sbuf.idx--; 604 if (!json_form || start < end) { 605 copy_to_buffer ("]", 2, &sbuf); 606 } 607 else { 608 sbuf.buf[sbuf.idx] = '\0'; 609 } 610 611 minus_inst_count(L, strlen(sbuf.buf)); 612 return sbuf.buf; 613 } 614 615 char *lua_util_get_json (lua_State *L, int idx, bool json_form) 616 { 617 sbuff_t sbuf; 618 callinfo_t *callinfo = NULL; 619 lua_util_sbuf_init (&sbuf, 64); 620 621 if(!lua_util_dump_json (L, idx, &sbuf, json_form, false, &callinfo)) { 622 callinfo_del(callinfo); 623 free(sbuf.buf); 624 return NULL; 625 } 626 callinfo_del(callinfo); 627 628 if (sbuf.idx != 0) 629 sbuf.buf[sbuf.idx - 1] = '\0'; 630 631 minus_inst_count(L, strlen(sbuf.buf)); 632 return sbuf.buf; 633 } 634 635 static int lua_json_encode (lua_State *L) 636 { 637 char *json = lua_util_get_json(L, -1, true); 638 if (json == NULL) 639 luaL_throwerror(L); 640 lua_pushstring(L, json); 641 free(json); 642 return 1; 643 } 644 645 static int lua_json_decode (lua_State *L) 646 { 647 char *org = (char *)luaL_checkstring(L, -1); 648 char *json = strdup(org); 649 650 minus_inst_count(L, strlen(json)); 651 if (lua_util_json_to_lua(L, json, true) != 0) { 652 free (json); 653 luaL_error(L, "not proper json format"); 654 } 655 free (json); 656 return 1; 657 } 658 659 static const luaL_Reg json_lib[] = { 660 {"encode", lua_json_encode}, 661 {"decode", lua_json_decode}, 662 {NULL, NULL} 663 }; 664 665 int luaopen_json(lua_State *L) 666 { 667 luaL_register(L, "json", json_lib); 668 lua_pop(L, 1); 669 return 1; 670 }