| 31 | |
| 32 | template <unsigned serializeFlags, typename NodeType> |
| 33 | sonic_force_inline SonicError SerializeImpl(const NodeType* node, |
| 34 | WriteBuffer& wb) { |
| 35 | struct ParentCtx { |
| 36 | uint64_t len; |
| 37 | const NodeType* ptr; |
| 38 | }; |
| 39 | |
| 40 | /* preallocate buffer */ |
| 41 | constexpr size_t kExpectMinifyRatio = 18; |
| 42 | constexpr size_t kNumberSize = 33; |
| 43 | |
| 44 | size_t node_nums = node->IsContainer() ? node->Size() : 1; |
| 45 | size_t estimate = node_nums * kExpectMinifyRatio + 64; |
| 46 | bool is_obj = node->IsObject(); |
| 47 | bool is_key, is_obj_nxt; |
| 48 | uint32_t member_cnt = 0; |
| 49 | uint32_t val_cnt, val_cnt_nxt; |
| 50 | size_t str_len; |
| 51 | long inc_len; |
| 52 | const char* str_ptr; |
| 53 | ssize_t rn = 0; |
| 54 | internal::Stack stk; |
| 55 | ParentCtx* parent; |
| 56 | |
| 57 | wb.Clear(); |
| 58 | wb.Reserve(estimate); |
| 59 | |
| 60 | bool is_single = (!node->IsContainer()) || node->Empty(); |
| 61 | if (sonic_unlikely(is_single)) { |
| 62 | val_cnt = 1; |
| 63 | goto val_begin; |
| 64 | } |
| 65 | val_cnt = node->Size() << is_obj; |
| 66 | member_cnt = node->Size(); |
| 67 | wb.PushUnsafe<char>('[' | (uint8_t)(is_obj) << 5); |
| 68 | node = is_obj ? node->getObjChildrenFirstUnsafe() |
| 69 | : node->getArrChildrenFirstUnsafe(); |
| 70 | val_begin: |
| 71 | switch (node->getBasicType()) { |
| 72 | case kString: { |
| 73 | is_key = ((size_t)(is_obj) & (~val_cnt)); |
| 74 | str_len = node->Size(); |
| 75 | inc_len = str_len * 6 + 32 + 3; |
| 76 | wb.Grow(inc_len); |
| 77 | str_ptr = node->GetStringView().data(); |
| 78 | rn = internal::Quote(str_ptr, str_len, wb.End<char>()) - wb.End<char>(); |
| 79 | wb.PushSizeUnsafe<char>(rn); |
| 80 | wb.PushUnsafe<char>(is_key ? ':' : ','); |
| 81 | member_cnt -= is_key; |
| 82 | break; |
| 83 | } |
| 84 | |
| 85 | case kNumber: { |
| 86 | wb.Grow(kNumberSize); |
| 87 | switch (node->GetType()) { |
| 88 | case kSint: |
| 89 | rn = internal::I64toa(wb.End<char>(), node->GetInt64()) - |
| 90 | wb.End<char>(); |
nothing calls this directly
no test coverage detected