github.com/cloudwego/dynamicgo@v0.2.6-0.20240519101509-707f41b6b834/native/thrift.c (about) 1 /* 2 * Copyright 2023 CloudWeGo Authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "native.h" 18 #include "map.h" 19 #include "scanning.h" 20 #include "memops.h" 21 #include "thrift.h" 22 #include <stdint.h> 23 #include "test/xprintf.h" 24 25 uint64_t buf_malloc(GoSlice *buf, size_t size) 26 { 27 if (size == 0) 28 { 29 return 0; 30 } 31 size_t d = buf->len + size; 32 if (d > buf->cap) 33 { 34 WRAP_ERR0(ERR_OOM_BUF, d - buf->cap); 35 } 36 buf->len = d; 37 return 0; 38 } 39 40 uint64_t tb_write_byte(GoSlice *buf, char v) 41 { 42 size_t s = buf->len; 43 J2T_ZERO(buf_malloc(buf, 1)); 44 buf->buf[s] = v; 45 return 0; 46 } 47 48 uint64_t tb_write_bool(GoSlice *buf, bool v) 49 { 50 if (v) 51 { 52 return tb_write_byte(buf, 1); 53 } 54 return tb_write_byte(buf, 0); 55 } 56 57 uint64_t tb_write_i16(GoSlice *buf, int16_t v) 58 { 59 size_t s = buf->len; 60 J2T_ZERO(buf_malloc(buf, 2)); 61 *(int16_t *)(&buf->buf[s]) = __builtin_bswap16(v); 62 return 0; 63 } 64 65 uint64_t tb_write_i32(GoSlice *buf, int32_t v) 66 { 67 size_t s = buf->len; 68 J2T_ZERO(buf_malloc(buf, 4)); 69 *(int32_t *)(&buf->buf[s]) = __builtin_bswap32(v); 70 return 0; 71 } 72 73 uint64_t tb_write_i64(GoSlice *buf, int64_t v) 74 { 75 size_t s = buf->len; 76 J2T_ZERO(buf_malloc(buf, 8)); 77 *(int64_t *)(&buf->buf[s]) = __builtin_bswap64(v); 78 return 0; 79 } 80 81 uint64_t tb_write_double(GoSlice *buf, double v) 82 { 83 uint64_t f = *(uint64_t *)(&v); 84 return tb_write_i64(buf, f); 85 } 86 87 uint64_t tb_write_string(GoSlice *buf, const char *v, size_t n) 88 { 89 size_t s = buf->len; 90 J2T_ZERO(buf_malloc(buf, n + 4)); 91 *(int32_t *)(&buf->buf[s]) = __builtin_bswap32(n); 92 xprintf("[tb_write_string] %c%c%c%c\n", buf->buf[s], buf->buf[s + 1], buf->buf[s + 2], buf->buf[s + 3]); 93 memcpy2(&buf->buf[s + 4], v, n); 94 return 0; 95 } 96 97 uint64_t tb_write_binary(GoSlice *buf, const GoSlice v) 98 { 99 size_t s = buf->len; 100 J2T_ZERO(buf_malloc(buf, v.len + 4)); 101 *(int32_t *)(&buf->buf[s]) = __builtin_bswap32(v.len); 102 memcpy2(&buf->buf[s + 4], v.buf, v.len); 103 return 0; 104 } 105 106 void tb_write_struct_begin(GoSlice *buf) 107 { 108 return; 109 } 110 111 uint64_t tb_write_struct_end(GoSlice *buf) 112 { 113 J2T_ZERO(tb_write_byte(buf, TTYPE_STOP)); 114 xprintf("[tb_write_struct_end]:%c\n", buf->buf[buf->len - 1]); 115 return 0; 116 } 117 118 uint64_t tb_write_field_begin(GoSlice *buf, ttype type, int16_t id) 119 { 120 J2T_ZERO(tb_write_byte(buf, type)); 121 return tb_write_i16(buf, id); 122 } 123 124 uint64_t tb_write_map_n(GoSlice *buf, ttype key, ttype val, int32_t n) 125 { 126 J2T_ZERO(tb_write_byte(buf, key)); 127 J2T_ZERO(tb_write_byte(buf, val)); 128 J2T_ZERO(tb_write_i32(buf, n)); 129 return 0; 130 } 131 132 uint64_t tb_write_map_begin(GoSlice *buf, ttype key, ttype val, size_t *back) 133 { 134 J2T_ZERO(tb_write_byte(buf, key)); 135 J2T_ZERO(tb_write_byte(buf, val)); 136 *back = buf->len; 137 J2T_ZERO(buf_malloc(buf, 4)); 138 139 return 0; 140 } 141 142 void tb_write_map_end(GoSlice *buf, size_t back, size_t size) 143 { 144 xprintf("[tb_write_map_end]: %d, bp pos: %d\n", size, back); 145 *(int32_t *)(&buf->buf[back]) = __builtin_bswap32(size); 146 return; 147 } 148 149 uint64_t tb_write_list_begin(GoSlice *buf, ttype elem, size_t *back) 150 { 151 J2T_ZERO(tb_write_byte(buf, elem)); 152 *back = buf->len; 153 J2T_ZERO(buf_malloc(buf, 4)); 154 return 0; 155 } 156 157 void tb_write_list_end(GoSlice *buf, size_t back, size_t size) 158 { 159 xprintf("[tb_write_list_end]: %d, bp pos: %d\n", size, back); 160 *(int32_t *)(&buf->buf[back]) = __builtin_bswap32(size); 161 return; 162 } 163 164 uint64_t tb_write_list_n(GoSlice *buf, ttype elem, int32_t size) 165 { 166 J2T_ZERO(tb_write_byte(buf, elem)); 167 J2T_ZERO(tb_write_i32(buf, size)); 168 return 0; 169 } 170 171 uint64_t tb_write_default_or_empty(GoSlice *buf, const tFieldDesc *field, long p) 172 { 173 if (field->default_value != NULL) 174 { 175 xprintf("[tb_write_default_or_empty] json_val: %s\n", &field->default_value->json_val); 176 size_t n = field->default_value->thrift_binary.len; 177 size_t l = buf->len; 178 J2T_ZERO(buf_malloc(buf, n)); 179 memcpy2(&buf->buf[l], field->default_value->thrift_binary.buf, n); 180 return 0; 181 } 182 tTypeDesc *desc = field->type; 183 switch (desc->type) 184 { 185 case TTYPE_BOOL: 186 return tb_write_bool(buf, false); 187 case TTYPE_BYTE: 188 return tb_write_byte(buf, 0); 189 case TTYPE_I16: 190 return tb_write_i16(buf, 0); 191 case TTYPE_I32: 192 return tb_write_i32(buf, 0); 193 case TTYPE_I64: 194 return tb_write_i64(buf, 0); 195 case TTYPE_DOUBLE: 196 return tb_write_double(buf, 0); 197 case TTYPE_STRING: 198 return tb_write_string(buf, NULL, 0); 199 case TTYPE_LIST: 200 case TTYPE_SET: 201 J2T_ZERO(tb_write_list_n(buf, desc->elem->type, 0)); 202 return 0; 203 case TTYPE_MAP: 204 J2T_ZERO(tb_write_map_n(buf, desc->key->type, desc->elem->type, 0)); 205 return 0; 206 case TTYPE_STRUCT: 207 tb_write_struct_begin(buf); 208 tFieldDesc **f = desc->st->ids.buf_all; 209 size_t l = desc->st->ids.len_all; 210 for (int i = 0; i < l; i++) 211 { 212 if (f[i]->required == REQ_OPTIONAL) 213 { 214 continue; 215 } 216 J2T_ZERO(tb_write_field_begin(buf, f[i]->type->type, f[i]->ID)); 217 J2T_ZERO(tb_write_default_or_empty(buf, f[i], p)); 218 } 219 J2T_ZERO(tb_write_struct_end(buf)); 220 return 0; 221 default: 222 WRAP_ERR_POS(ERR_UNSUPPORT_THRIFT_TYPE, desc->type, p); 223 } 224 } 225 226 uint64_t tb_write_message_begin(GoSlice *buf, const GoString name, int32_t type, int32_t seq) 227 { 228 uint32_t version = THRIFT_VERSION_1 | (uint32_t)type; 229 J2T_ZERO(tb_write_i32(buf, version)); 230 J2T_ZERO(tb_write_string(buf, name.buf, name.len)); 231 return tb_write_i32(buf, seq); 232 } 233 234 void tb_write_message_end(GoSlice *buf) 235 { 236 return; 237 } 238 239 uint64_t bm_malloc_reqs(GoSlice *cache, ReqBitMap src, ReqBitMap *copy, long p) 240 { 241 xprintf("[bm_malloc_reqs oom] malloc, cache.len:%d, cache.cap:%d, src.len:%d\n", cache->len, cache->cap, src.len); 242 size_t n = src.len * SIZE_INT64; 243 size_t d = cache->len + n; 244 if unlikely (d > cache->cap) 245 { 246 xprintf("[bm_malloc_reqs] oom d:%d, cap:%d\n", d, cache->cap); 247 WRAP_ERR0(ERR_OOM_BM, (d - cache->cap)); 248 } 249 250 copy->buf = (uint64_t *)&cache->buf[cache->len]; 251 copy->len = src.len; 252 memcpy2((char *)copy->buf, (char *)src.buf, n); 253 cache->len = d; 254 // xprintf("[bm_malloc_reqs] copy:%n, src:%n \n", copy, &src); 255 256 return 0; 257 } 258 259 void bm_free_reqs(GoSlice *cache, size_t len) 260 { 261 xprintf("[bm_free_reqs] free, cache.len: %d, src.len:%d", cache->len, len); 262 cache->len -= (len * SIZE_INT64); 263 } 264 265 uint64_t j2t_write_unset_fields(J2TStateMachine *self, GoSlice *buf, const tStructDesc *st, ReqBitMap reqs, uint64_t flags, long p) 266 { 267 bool wr_enabled = flags & F_WRITE_REQUIRE; 268 bool wd_enabled = flags & F_WRITE_DEFAULT; 269 bool wo_enabled = flags & F_WRITE_OPTIONAL; 270 bool tb_enabled = flags & F_TRACE_BACK; 271 uint64_t *s = reqs.buf; 272 // xprintf("[j2t_write_unset_fields] reqs: %n \n", &reqs); 273 for (int i = 0; i < reqs.len; i++) 274 { 275 uint64_t v = *s; 276 for (int j = 0; v != 0 && j < BSIZE_INT64; j++) 277 { 278 if ((v % 2) != 0) 279 { 280 tid id = i * BSIZE_INT64 + j; 281 if (id >= st->ids.len) 282 { 283 continue; 284 } 285 tFieldDesc *f = (st->ids.buf)[id]; 286 // xprintf("[j2t_write_unset_fields] field:%d, f.name:%s\n", (int64_t)id, &f->name); 287 288 // NOTICE: if traceback is enabled AND (field is required OR current state is root layer), 289 // return field id to traceback field value from http-mapping in Go. 290 if (tb_enabled && (f->required == REQ_REQUIRED || self->sp == 1)) 291 { 292 if (self->field_cache.cap <= self->field_cache.len) 293 { 294 WRAP_ERR0(ERR_OOM_FIELD, p); 295 } 296 self->field_cache.buf[self->field_cache.len++] = f->ID; 297 } 298 else if (!wr_enabled && f->required == REQ_REQUIRED) 299 { 300 WRAP_ERR_POS(ERR_NULL_REQUIRED, id, p); 301 } 302 else if ((wr_enabled && f->required == REQ_REQUIRED) || (wd_enabled && f->required == REQ_DEFAULT) || (wo_enabled && f->required == REQ_OPTIONAL)) 303 { 304 J2T_ZERO(tb_write_field_begin(buf, f->type->type, f->ID)); 305 J2T_ZERO(tb_write_default_or_empty(buf, f, p)); 306 } 307 } 308 v >>= 1; 309 } 310 s++; 311 } 312 return 0; 313 } 314 315 uint64_t j2t_number(GoSlice *buf, const tTypeDesc *desc, const GoString *src, long *p, JsonState *ret) 316 { 317 long s = *p; 318 vnumber(src, p, ret); 319 xprintf("[j2t_number] p:%d, ret.vt:%d, ret.iv:%d, ret.dv:%f\n", s, ret->vt, ret->iv, ret->dv); 320 if (ret->vt < 0) 321 { 322 WRAP_ERR(-ret->vt, s); 323 } 324 // FIXME: check double-integer overflow 325 switch (desc->type) 326 { 327 case TTYPE_I08: 328 if (ret->vt == V_INTEGER) 329 { 330 return tb_write_byte(buf, (uint8_t)ret->iv); 331 } 332 else 333 { 334 return tb_write_byte(buf, (uint8_t)ret->dv); 335 } 336 case TTYPE_I16: 337 if (ret->vt == V_INTEGER) 338 { 339 return tb_write_i16(buf, (int16_t)ret->iv); 340 } 341 else 342 { 343 return tb_write_i16(buf, (int16_t)ret->dv); 344 } 345 case TTYPE_I32: 346 if (ret->vt == V_INTEGER) 347 { 348 return tb_write_i32(buf, (int32_t)ret->iv); 349 } 350 else 351 { 352 return tb_write_i32(buf, (int32_t)ret->dv); 353 } 354 case TTYPE_I64: 355 if (ret->vt == V_INTEGER) 356 { 357 return tb_write_i64(buf, (int64_t)ret->iv); 358 } 359 else 360 { 361 return tb_write_i64(buf, (int64_t)ret->dv); 362 } 363 case TTYPE_DOUBLE: 364 // NOTICE: vnumber() has set dv when V_INTEGER 365 return tb_write_double(buf, (double)(ret->dv)); 366 } 367 WRAP_ERR2(ERR_DISMATCH_TYPE, desc->type, V_INTEGER); 368 } 369 370 uint64_t j2t_string(GoSlice *buf, const GoString *src, long *p, uint64_t flags) 371 { 372 long s = *p; 373 int64_t ep; 374 ssize_t e = advance_string(src, s, &ep); 375 J2T_XERR(e, s); 376 *p = e; 377 size_t n = e - s - 1; 378 xprintf("[j2t_string]s:%d, p:%d, ep:%d, n:%d\n", s, e, ep, n); 379 if unlikely (ep >= s && ep < e) 380 { 381 char *sp = &buf->buf[buf->len]; 382 J2T_ZERO(buf_malloc(buf, 4)); 383 // unescape string 384 size_t o = buf->len; 385 ep = -1; 386 J2T_ZERO(buf_malloc(buf, n)); 387 xprintf("[j2t_string] unquote o:%d, n:%d, ep:%d, flags:%d\n", o, n, ep, flags); 388 ssize_t l = unquote(&src->buf[s], n, &buf->buf[o], &ep, flags); 389 xprintf("[j2t_string] unquote end, l:%d\n", l); 390 if (l < 0) 391 { 392 WRAP_ERR(-l, s); 393 } 394 buf->len = o + l; 395 *(int32_t *)sp = __builtin_bswap32(l); 396 } 397 else 398 { 399 J2T_ZERO(tb_write_string(buf, &src->buf[s], n)); 400 } 401 return 0; 402 } 403 404 uint64_t j2t_binary(GoSlice *buf, const GoString *src, long *p, uint64_t flags) 405 { 406 long s = *p; 407 int64_t ep; 408 ssize_t e = advance_string(src, s, &ep); 409 J2T_XERR(e, s); 410 *p = e; 411 size_t n = e - s - 1; 412 xprintf("[j2t_binary]s:%d, p:%d, ep:%d, n:%d\n", s, *p, ep, n); 413 char *back = &buf->buf[buf->len]; 414 J2T_ZERO(buf_malloc(buf, 4)); 415 ssize_t l = b64decode(buf, &src->buf[s], n, 0); 416 xprintf("[j2t_binary] base64 endm l:%d\n", l); 417 if (l < 0) 418 { 419 WRAP_ERR(ERR_DECODE_BASE64, -l - 1); 420 } 421 *(int32_t *)(back) = __builtin_bswap32(l); 422 return 0; 423 } 424 425 uint64_t j2t_map_key(GoSlice *buf, const char *sp, size_t n, const tTypeDesc *dc, JsonState *js, long p) 426 { 427 xprintf("[j2t_map_key]\n"); 428 switch (dc->type) 429 { 430 case TTYPE_STRING: 431 { 432 J2T_ZERO(tb_write_string(buf, sp, n)); 433 break; 434 } 435 case TTYPE_I08: 436 case TTYPE_I16: 437 case TTYPE_I32: 438 case TTYPE_I64: 439 case TTYPE_DOUBLE: 440 { 441 GoString tmp = (GoString){.buf = sp, .len = n}; 442 long p = 0; 443 J2T_ZERO(j2t_number(buf, dc, &tmp, &p, js)); 444 break; 445 } 446 default: 447 WRAP_ERR_POS(ERR_UNSUPPORT_THRIFT_TYPE, dc->type, p); 448 } 449 return 0; 450 } 451 452 tFieldDesc *j2t_find_field_key(const GoString *key, const tStructDesc *st) 453 { 454 xprintf("[j2t_find_field_key] key:%s\t", key); 455 if unlikely (st->names.hash != NULL) 456 { 457 tFieldDesc *ret = (tFieldDesc *)hm_get(st->names.hash, key); 458 xprintf("hash field:%x\n", ret); 459 return ret; 460 } 461 else 462 { 463 tFieldDesc *ret = (tFieldDesc *)trie_get(st->names.trie, key); 464 xprintf("trie field:%x\n", ret); 465 return ret; 466 } 467 } 468 469 uint64_t j2t_read_key(J2TStateMachine *self, const GoString *src, long *p, const char **spp, size_t *knp) 470 { 471 long s = *p; 472 int64_t ep = -1; 473 ssize_t e = advance_string(src, s, &ep); 474 J2T_XERR(e, s); 475 *p = e; 476 size_t kn = e - s - 1; 477 const char *sp = &src->buf[s]; 478 xprintf("[j2t_read_key] s:%d, e:%d, kn:%d, ep:%d\n", s, e, kn, ep); 479 if unlikely (ep >= s && ep < e) 480 { 481 if unlikely (kn > self->key_cache.cap) 482 { 483 WRAP_ERR0(ERR_OOM_KEY, kn - self->key_cache.cap); 484 } 485 else 486 { 487 ep = -1; 488 char *dp = self->key_cache.buf; 489 ssize_t l = unquote(sp, kn, dp, &ep, 0); 490 xprintf("[j2t_read_key] unquote end l:%d\n", l); 491 if unlikely (l < 0) 492 { 493 WRAP_ERR(-l, s); 494 } 495 sp = dp; 496 kn = l; 497 } 498 } 499 *spp = sp; 500 *knp = kn; 501 xprintf("[j2t_read_key]sp:%c, kn:%d\n", *sp, kn); 502 return 0; 503 } 504 505 uint64_t j2t_field_vm(J2TStateMachine *self, GoSlice *buf, const GoString *src, long *p, J2TState *vt) 506 { 507 tFieldDesc *f = vt->ex.ef.f; 508 xprintf("[j2t_field_vm] f->ID:%d, f->type->type:%d, p:%d \n", f->ID, f->type->type, *p); 509 // if it is inlined value-mapping, write field tag first 510 if (f->vm <= VM_INLINE_MAX) 511 { 512 J2T_ZERO(tb_write_field_begin(buf, f->type->type, f->ID)); 513 switch (f->vm) 514 { 515 case VM_JSCONV: 516 { 517 char ch = src->buf[*p - 1]; 518 if (ch == '"') 519 { 520 // If the field is a string and value is also a string, we just handle it normally. 521 if (f->type->type == TTYPE_STRING) 522 { 523 J2T_ZERO(j2t_string(buf, src, p, 0)); 524 return 0; 525 } 526 if (src->buf[*p] == '"') 527 { 528 // empty string 529 J2T_ZERO(tb_write_default_or_empty(buf, f, *p)); 530 *p += 1; 531 return 0; 532 } 533 } 534 else 535 { 536 // invalid number 537 if (ch != '-' && (ch < '0' || ch > '9')) 538 { 539 WRAP_ERR(ERR_INVAL, ch); 540 } 541 // back to begin of number 542 *p -= 1; 543 } 544 545 // handle it as number 546 long s = *p; 547 vnumber(src, p, &self->jt); 548 if (self->jt.vt != V_INTEGER && self->jt.vt != V_DOUBLE) 549 { 550 WRAP_ERR(ERR_NUMBER_FMT, self->jt.vt); 551 } 552 xprintf("[j2t_field_vm] jt.vt:%d, jt.iv:%d, jt.dv:%d\n", self->jt.vt, self->jt.iv, self->jt.dv); 553 switch (f->type->type) 554 { 555 case TTYPE_STRING: 556 { 557 J2T_ZERO(tb_write_string(buf, &src->buf[s], *p - s)); 558 return 0; 559 } 560 case TTYPE_I64: 561 { 562 int64_t v = 0; 563 if (self->jt.vt == V_INTEGER) 564 { 565 v = (int64_t)self->jt.iv; 566 } 567 else 568 { 569 v = (int64_t)self->jt.dv; 570 } 571 J2T_ZERO(tb_write_i64(buf, v)); 572 break; 573 } 574 case TTYPE_I32: 575 { 576 xprintf("[j2t_field_vm] TTYPE_I32\n"); 577 int32_t v = 0; 578 if (self->jt.vt == V_INTEGER) 579 { 580 v = (int32_t)self->jt.iv; 581 } 582 else 583 { 584 v = (int32_t)self->jt.dv; 585 } 586 J2T_ZERO(tb_write_i32(buf, v)); 587 break; 588 } 589 case TTYPE_I16: 590 { 591 int16_t v = 0; 592 if (self->jt.vt == V_INTEGER) 593 { 594 v = (int16_t)self->jt.iv; 595 } 596 else 597 { 598 v = (int16_t)self->jt.dv; 599 } 600 J2T_ZERO(tb_write_i16(buf, v)); 601 } 602 case TTYPE_I08: 603 { 604 char v = 0; 605 if (self->jt.vt == V_INTEGER) 606 { 607 v = (char)self->jt.iv; 608 } 609 else 610 { 611 v = (char)self->jt.dv; 612 } 613 J2T_ZERO(tb_write_byte(buf, v)); 614 break; 615 } 616 case TTYPE_DOUBLE: 617 { 618 J2T_ZERO(tb_write_double(buf, (double)self->jt.dv)); 619 break; 620 } 621 default: 622 WRAP_ERR(ERR_UNSUPPORT_THRIFT_TYPE, f->type->type); 623 } 624 625 // for int/float field and string value, we need to skip the quote. 626 if (ch == '"') 627 { 628 if (src->buf[*p] != '"') 629 { 630 WRAP_ERR(ERR_INVAL, src->buf[*p]); 631 } 632 *p += 1; 633 } 634 return 0; 635 } 636 default: 637 WRAP_ERR(ERR_UNSUPPORT_VM_TYPE, f->vm); 638 } 639 } 640 else 641 { 642 // non-inline implementation, need return to caller 643 *p -= 1; 644 long s = *p; 645 self->sm.sp = 0; 646 long r = skip_one(src, p, &self->sm); 647 if (r < 0) 648 { 649 WRAP_ERR(-r, s); 650 } 651 // check if the fval_cache if full 652 // if (self->fval_cache.len >= self->fval_cache.cap) 653 // { 654 // WRAP_ERR0(ERR_OOM_FVAL, s); 655 // } 656 // self->fval_cache.len += 1; 657 // FieldVal *fv = (FieldVal *)&self->fval_cache.buf[self->fval_cache.len - 1]; 658 // record field id and value (begin and end) into FSM.FieldValueCache 659 FieldVal *fv = &self->fval_cache; 660 fv->id = f->ID; 661 fv->start = r; 662 fv->end = *p; 663 WRAP_ERR0(ERR_VM_END, *p); 664 } 665 } 666 667 #define j2t_key(obj0) \ 668 do \ 669 { \ 670 const char *sp; \ 671 size_t kn; \ 672 J2T_STORE(j2t_read_key(self, src, p, &sp, &kn)); \ 673 if (dc->type == TTYPE_MAP) \ 674 { \ 675 unwindPos = buf->len; \ 676 J2T_STORE(j2t_map_key(buf, sp, kn, dc->key, &self->jt, *p)); \ 677 if (obj0) \ 678 { \ 679 vt->ex.ec.size = 0; \ 680 J2T_PUSH(self, J2T_ELEM, *p, dc->elem); \ 681 } \ 682 else \ 683 { \ 684 J2T_REPL(self, J2T_ELEM, *p, dc->elem); \ 685 } \ 686 } \ 687 else \ 688 { \ 689 J2TExtra *pex; \ 690 if (obj0) \ 691 { \ 692 pex = &vt->ex; \ 693 } \ 694 else \ 695 { \ 696 pex = &self->vt[self->sp - 2].ex; \ 697 } \ 698 GoString tmp_str = (GoString){.buf = sp, .len = kn}; \ 699 tFieldDesc *f = j2t_find_field_key(&tmp_str, dc->st); \ 700 if (f == NULL) \ 701 { \ 702 xprintf("[J2T_KEY] unknown field %s\n", &tmp_str); \ 703 if ((flag & F_ALLOW_UNKNOWN) == 0) \ 704 { \ 705 WRAP_ERR(ERR_UNKNOWN_FIELD, kn); \ 706 } \ 707 if (obj0) \ 708 { \ 709 J2T_PUSH(self, J2T_ELEM | STATE_SKIP, *p, NULL); \ 710 } \ 711 else \ 712 { \ 713 J2T_REPL(self, J2T_ELEM | STATE_SKIP, *p, NULL); \ 714 } \ 715 } \ 716 else \ 717 { \ 718 if unlikely ((flag & F_ENABLE_HM) && (f->http_mappings.len != 0) && !bm_is_set(pex->es.reqs, f->ID)) \ 719 { \ 720 xprintf("[J2T_KEY] skip field %s\n", &tmp_str); \ 721 if (obj0) \ 722 { \ 723 J2T_PUSH(self, J2T_ELEM | STATE_SKIP, *p, f->type); \ 724 } \ 725 else \ 726 { \ 727 J2T_REPL(self, J2T_ELEM | STATE_SKIP, *p, f->type); \ 728 } \ 729 } \ 730 else \ 731 { \ 732 J2TExtra ex = {}; \ 733 ex.ef.f = f; \ 734 uint64_t vm = STATE_VM; \ 735 if ((flag & F_ENABLE_VM) == 0 || f->vm == VM_NONE) \ 736 { \ 737 vm = STATE_FIELD; \ 738 unwindPos = buf->len; \ 739 lastField = f; \ 740 J2T_STORE(tb_write_field_begin(buf, f->type->type, f->ID)); \ 741 } \ 742 xprintf("[J2T_KEY] vm: %d\n", vm); \ 743 if (obj0) \ 744 { \ 745 J2T_PUSH_EX(self, J2T_ELEM | vm, *p, f->type, ex); \ 746 } \ 747 else \ 748 { \ 749 J2T_REPL_EX(self, J2T_ELEM | vm, *p, f->type, ex); \ 750 } \ 751 } \ 752 bm_set_req(pex->es.reqs, f->ID, REQ_OPTIONAL); \ 753 } \ 754 } \ 755 } while (0) 756 757 uint64_t j2t_fsm_exec(J2TStateMachine *self, GoSlice *buf, const GoString *src, uint64_t flag) 758 { 759 if (self->sp <= 0) 760 { 761 return 0; 762 } 763 // load json position from last state 764 long pv = self->vt[self->sp - 1].jp; 765 long *p = &pv; 766 767 // for 'null' value backtrace 768 bool null_val = false; 769 size_t unwindPos = 0; 770 tFieldDesc *lastField = NULL; 771 772 /* run until no more nested values */ 773 while (self->sp) 774 { 775 if unlikely (self->sp >= MAX_RECURSE) 776 { 777 WRAP_ERR(ERR_RECURSE_MAX, self->sp); 778 } 779 // load varialbes for current state 780 J2TState *vt = &self->vt[self->sp - 1]; 781 J2TState bt = *vt; 782 const tTypeDesc *dc = bt.td; 783 uint64_t st = bt.st; 784 size_t wp = buf->len; 785 786 // advance to next char 787 const char ch = advance_ns(src, p); 788 DEBUG_PRINT_STATE(0, self->sp - 1, *p); 789 790 /* check for special types */ 791 switch (J2T_ST(st)) 792 { 793 794 default: 795 { 796 xprintf("[J2T_VAL] drop: %d\n", self->sp); 797 J2T_DROP(self); 798 break; 799 } 800 801 /* arrays, first element */ 802 case J2T_ARR_0: 803 { 804 xprintf("[J2T_ARR_0] 0\n"); 805 switch (ch) 806 { 807 case ']': 808 { 809 xprintf("[J2T_ARR_0] end\n"); 810 tb_write_list_end(buf, vt->ex.ec.bp, 0); 811 J2T_DROP(self); 812 continue; 813 } 814 default: 815 { 816 xprintf("[J2T_ARR_0] start\n"); 817 vt->ex.ec.size = 0; 818 // set parent state as J2T_ARR 819 vt->st = J2T_ARR; 820 *p -= 1; 821 J2T_PUSH(self, J2T_VAL, *p, dc->elem); 822 continue; 823 } 824 } 825 } 826 827 /* arrays */ 828 case J2T_ARR: 829 { 830 xprintf("[J2T_ARR] 0\n"); 831 switch (ch) 832 { 833 case ']': 834 { 835 xprintf("[J2T_ARR] end\n"); 836 if (!null_val) 837 { 838 // count last element 839 vt->ex.ec.size += 1; 840 } 841 else 842 { 843 // last element is null, so don't count it 844 null_val = false; 845 } 846 // since the encoding of list and set, we call only one type's func here. 847 // TODO: add thrift type choose for corresponding func 848 tb_write_list_end(buf, vt->ex.ec.bp, vt->ex.ec.size); 849 J2T_DROP(self); 850 continue; 851 } 852 case ',': 853 xprintf("[J2T_ARR] add\n"); 854 if (!null_val) 855 { 856 vt->ex.ec.size += 1; 857 } 858 else 859 { 860 null_val = false; 861 } 862 J2T_PUSH_EX(self, J2T_VAL, *p, dc->elem, vt->ex); 863 continue; 864 default: 865 WRAP_ERR2(ERR_INVAL, ch, J2T_ARR); 866 } 867 } 868 869 /* objects, first pair */ 870 case J2T_OBJ_0: 871 { 872 xprintf("[J2T_OBJ_0] 0\n"); 873 switch (ch) 874 { 875 default: 876 { 877 WRAP_ERR2(ERR_INVAL, ch, J2T_OBJ_0); 878 } 879 880 /* empty object */ 881 case '}': 882 { 883 xprintf("[J2T_OBJ_0] end\n"); 884 if (dc->type == TTYPE_STRUCT) 885 { 886 // check if all required/default fields got written 887 J2T_STORE(j2t_write_unset_fields(self, buf, vt->ex.es.sd, vt->ex.es.reqs, flag, *p - 1)); 888 bm_free_reqs(&self->reqs_cache, vt->ex.es.reqs.len); 889 // http-mapping enalbed and some fields remain not written 890 if (flag & F_ENABLE_HM && self->field_cache.len > 0) 891 { // return back to go handler 892 xprintf("[J2T_OBJ_0] fallback http-mapping pos: %d\n", *p); 893 WRAP_ERR0(ERR_HM_END, *p); 894 // NOTICE: should tb_write_struct_end(), then J2T_DROP(self) in Go handler 895 } 896 else 897 { 898 J2T_STORE(tb_write_struct_end(buf)); 899 } 900 } 901 else 902 { 903 tb_write_map_end(buf, vt->ex.ec.bp, 0); 904 } 905 J2T_DROP(self); 906 continue; 907 } 908 909 /* the quote of the first key */ 910 case '"': 911 { 912 xprintf("[J2T_OBJ_0] start\n"); 913 // set parent state 914 vt->st = J2T_OBJ; 915 j2t_key(true); 916 continue; 917 } 918 } 919 } 920 921 /* objects */ 922 case J2T_OBJ: 923 { 924 xprintf("[J2T_OBJ] 0\n"); 925 switch (ch) 926 { 927 case '}': 928 xprintf("[J2T_OBJ] end\n"); 929 // update backtrace position, in case of OOM return 930 bt.jp = *p - 1; 931 if (dc->type == TTYPE_STRUCT) 932 { 933 // last field value is null, so must unwind written field header 934 if (null_val) 935 { 936 null_val = false; 937 bm_set_req(vt->ex.es.reqs, lastField->ID, lastField->required); 938 buf->len = unwindPos; 939 } 940 // check if all required/default fields got written 941 J2T_STORE(j2t_write_unset_fields(self, buf, vt->ex.es.sd, vt->ex.es.reqs, flag, *p - 1)); 942 bm_free_reqs(&self->reqs_cache, vt->ex.es.reqs.len); 943 // http-mapping enalbed and some fields remain not written 944 if (flag & F_ENABLE_HM && self->field_cache.len != 0) 945 { 946 // return back to go handler 947 xprintf("[J2T_OBJ] fallback http-mapping pos: %d\n", *p); 948 WRAP_ERR0(ERR_HM_END, *p); 949 // NOTICE: should tb_write_struct_end(), then J2T_DROP(self) in Go handler 950 } 951 else 952 { 953 J2T_STORE(tb_write_struct_end(buf)); 954 } 955 } 956 else 957 { 958 if (!null_val) 959 { 960 vt->ex.ec.size += 1; 961 } 962 else 963 { 964 // last element value is null, so must rewind to written key 965 null_val = false; 966 buf->len = unwindPos; 967 } 968 tb_write_map_end(buf, vt->ex.ec.bp, vt->ex.ec.size); 969 } 970 J2T_DROP(self); 971 continue; 972 case ',': 973 xprintf("[J2T_OBJ] add\n"); 974 if (dc->type == TTYPE_MAP) 975 { 976 if (!null_val) 977 { 978 vt->ex.ec.size += 1; 979 } 980 else 981 { 982 null_val = false; 983 buf->len = unwindPos; 984 } 985 } 986 else 987 { 988 if (null_val) 989 { 990 null_val = false; 991 bm_set_req(vt->ex.es.reqs, lastField->ID, lastField->required); 992 buf->len = unwindPos; 993 } 994 } 995 J2T_PUSH(self, J2T_KEY, *p, dc); 996 continue; 997 default: 998 WRAP_ERR2(ERR_INVAL, ch, J2T_OBJ); 999 } 1000 } 1001 1002 /* object keys */ 1003 case J2T_KEY: 1004 { 1005 xprintf("[J2T_KEY] 0\n"); 1006 J2T_CHAR('"', J2T_KEY); 1007 j2t_key(false); 1008 continue; 1009 } 1010 1011 /* object element */ 1012 case J2T_ELEM: 1013 { 1014 xprintf("[J2T_ELEM] 0\n"); 1015 J2T_CHAR(':', J2T_ELEM); 1016 J2T_REPL(self, J2T_VAL | J2T_EX(st), *p, dc); 1017 continue; 1018 } 1019 } 1020 // skip 1021 if unlikely (IS_STATE_SKIP(st)) 1022 { 1023 xprintf("[J2T_VAL] skip: %d\n", *p); 1024 *p -= 1; 1025 long s = *p; 1026 self->sm.sp = 0; 1027 J2T_XERR(skip_one(src, p, &self->sm), s); 1028 continue; 1029 } 1030 // value-mapping 1031 if unlikely (flag & F_ENABLE_VM && IS_STATE_VM(st)) 1032 { 1033 xprintf("[J2T_VAL] value mapping\n"); 1034 J2T_STORE_NEXT(j2t_field_vm(self, buf, src, p, vt)); 1035 continue; 1036 } 1037 // normal value 1038 xprintf("[J2T_VAL] switch\n"); 1039 /* simple values */ 1040 switch (ch) 1041 { 1042 case '0': /* fallthrough */ 1043 case '1': /* fallthrough */ 1044 case '2': /* fallthrough */ 1045 case '3': /* fallthrough */ 1046 case '4': /* fallthrough */ 1047 case '5': /* fallthrough */ 1048 case '6': /* fallthrough */ 1049 case '7': /* fallthrough */ 1050 case '8': /* fallthrough */ 1051 case '9': /* fallthrough */ 1052 case '-': 1053 { 1054 xprintf("[J2T_VAL] number\n"); 1055 *p -= 1; 1056 J2T_STORE_NEXT(j2t_number(buf, dc, src, p, &self->jt)); 1057 break; 1058 } 1059 case 'n': 1060 { 1061 xprintf("[J2T_VAL] null\n"); 1062 long s = *p; 1063 J2T_XERR(advance_dword(src, p, 1, *p - 1, VS_NULL), s); 1064 null_val = true; 1065 break; 1066 } 1067 case 't': 1068 { 1069 xprintf("[J2T_VAL] true\n"); 1070 long s = *p; 1071 J2T_XERR(advance_dword(src, p, 1, *p - 1, VS_TRUE), s); 1072 J2T_EXP(TTYPE_BOOL, dc->type); 1073 J2T_STORE_NEXT(tb_write_bool(buf, true)); 1074 break; 1075 } 1076 case 'f': 1077 { 1078 xprintf("[J2T_VAL] false\n"); 1079 long s = *p; 1080 J2T_XERR(advance_dword(src, p, 0, *p - 1, VS_ALSE), s); 1081 J2T_EXP(TTYPE_BOOL, dc->type); 1082 J2T_STORE_NEXT(tb_write_bool(buf, false)); 1083 break; 1084 } 1085 case '[': 1086 { 1087 xprintf("[J2T_VAL] array\n"); 1088 J2T_EXP2(TTYPE_LIST, TTYPE_SET, dc->type); 1089 J2TState *v = &self->vt[self->sp]; 1090 // TODO: since the encoding of list and set, we call only one type's func here. 1091 // add thrift type choose for corresponding func 1092 v->ex.ec.size = 0; 1093 xprintf("[J2T_ARRAY]ex size: %d, vt: %d, vt.ex.ec: %d, vt.ex.ec.bp: %d, vt.ex.ec.size: %d\n", sizeof(J2TExtra), vt, &vt->ex.ec, &vt->ex.ec.bp, &vt->ex.ec.size); 1094 J2T_STORE_NEXT(tb_write_list_begin(buf, dc->elem->type, &v->ex.ec.bp)); // pass write-back address bp to v.ex.ec.bp 1095 J2T_PUSH_EX(self, J2T_ARR_0, *p, dc, v->ex); // pass bp to state 1096 break; 1097 } 1098 case '{': 1099 { 1100 xprintf("[J2T_VAL] object\n"); 1101 J2T_EXP2(TTYPE_STRUCT, TTYPE_MAP, dc->type); 1102 J2TState *v = &self->vt[self->sp]; 1103 if (dc->type == TTYPE_STRUCT) 1104 { 1105 xprintf("[J2T_VAL] object struct name: %s\n", &dc->st->name); 1106 tb_write_struct_begin(buf); 1107 J2TExtra_Struct es = {.sd = dc->st}; 1108 v->ex.es = es; 1109 J2T_PUSH(self, J2T_OBJ_0, *p, dc); 1110 J2T_STORE(bm_malloc_reqs(&self->reqs_cache, dc->st->reqs, &v->ex.es.reqs, *p)); 1111 if ((flag & F_ENABLE_HM) != 0 && dc->st->hms.len > 0) 1112 { 1113 xprintf("[J2T_VAL] HTTP_MAPPING begin pos: %d\n", *p - 1); 1114 WRAP_ERR0(ERR_HM, *p - 1); 1115 } 1116 } 1117 else 1118 { 1119 J2TExtra_Cont ec = {}; 1120 v->ex.ec = ec; 1121 J2T_STORE_NEXT(tb_write_map_begin(buf, dc->key->type, dc->elem->type, &v->ex.ec.bp)); // pass write-back address bp to v.ex.ec.bp 1122 J2T_PUSH(self, J2T_OBJ_0, *p, dc); 1123 } 1124 break; 1125 } 1126 case '"': 1127 { 1128 xprintf("[J2T_VAL] string\n"); 1129 if (dc->type == TTYPE_STRING) 1130 { 1131 if unlikely ((flag & F_NO_BASE64) == 0 && memeq(dc->name.buf, "binary", 6)) 1132 { 1133 J2T_STORE_NEXT(j2t_binary(buf, src, p, 0)); 1134 } 1135 else 1136 { 1137 J2T_STORE_NEXT(j2t_string(buf, src, p, 0)); 1138 } 1139 } 1140 else if ((flag & F_ENABLE_I2S) != 0 && (dc->type == TTYPE_I64 || dc->type == TTYPE_I32 || dc->type == TTYPE_I16 || dc->type == TTYPE_BYTE || dc->type == TTYPE_DOUBLE)) 1141 { 1142 J2T_STORE_NEXT(j2t_number(buf, dc, src, p, &self->jt)); 1143 long x = *p; 1144 if (x >= src->len) 1145 { 1146 WRAP_ERR(ERR_EOF, J2T_VAL); 1147 } 1148 // must end with a comma 1149 if (src->buf[x] != '"') 1150 { 1151 WRAP_ERR2(ERR_INVAL, src->buf[x], J2T_VAL); 1152 } 1153 *p += 1; 1154 } 1155 else 1156 { 1157 WRAP_ERR2(ERR_DISMATCH_TYPE, dc->type, TTYPE_STRING); 1158 } 1159 break; 1160 } 1161 case 0: 1162 WRAP_ERR(ERR_EOF, J2T_VAL); 1163 default: 1164 WRAP_ERR2(ERR_INVAL, ch, J2T_VAL); 1165 } 1166 } 1167 1168 xprintf("[J2T] return\n"); 1169 /* all done */ 1170 return 0; 1171 }