simdjson 5.0.2
Ridiculously Fast JSON
Loading...
Searching...
No Matches
document-inl.h
1#ifndef SIMDJSON_DOCUMENT_INL_H
2#define SIMDJSON_DOCUMENT_INL_H
3
4// Inline implementations go in here.
5
6#include "simdjson/dom/base.h"
7#include "simdjson/dom/document.h"
8#include "simdjson/dom/element-inl.h"
9#include "simdjson/internal/tape_ref-inl.h"
10#include "simdjson/internal/jsonformatutils.h"
11
12#include <cstring>
13
14namespace simdjson {
15namespace dom {
16
17//
18// document inline implementation
19//
20inline element document::root() const noexcept {
21 return element(internal::tape_ref(this, 1));
22}
23simdjson_warn_unused
24inline size_t document::capacity() const noexcept {
25 return allocated_capacity;
26}
27
28simdjson_warn_unused
29inline error_code document::allocate(size_t capacity) noexcept {
30 if (capacity == 0) {
31 string_buf.reset();
32 tape.reset();
33 allocated_capacity = 0;
34 return SUCCESS;
35 }
36 if (capacity > SIMDJSON_MAXSIZE_BYTES) {
37 return CAPACITY;
38 }
39
40 // a pathological input like "[[[[..." would generate capacity tape elements, so
41 // need a capacity of at least capacity + 1, but it is also possible to do
42 // worse with "[7,7,7,7,6,7,7,7,6,7,7,6,[7,7,7,7,6,7,7,7,6,7,7,6,7,7,7,7,7,7,6"
43 //where capacity + 1 tape elements are
44 // generated, see issue https://github.com/simdjson/simdjson/issues/345
45 if(capacity + 3 < capacity) {
46 return CAPACITY; // overflow, only happen on legacy 32-bit systems with very large capacity
47 }
48 size_t tape_capacity = SIMDJSON_ROUNDUP_N(capacity + 3, 64);
49 // a document with only zero-length strings... could have capacity/3 string
50 // and we would need capacity/3 * 5 bytes on the string buffer
51 if(5 * (capacity / 3) + SIMDJSON_PADDING < SIMDJSON_PADDING) {
52 return CAPACITY; // overflow, only happen on legacy 32-bit systems with very large capacity
53 }
54 size_t string_capacity = SIMDJSON_ROUNDUP_N(5 * (capacity / 3) + SIMDJSON_PADDING, 64);
55 string_buf.reset( new (std::nothrow) uint8_t[string_capacity]);
56 tape.reset(new (std::nothrow) uint64_t[tape_capacity]);
57 if(!(string_buf && tape)) {
58 allocated_capacity = 0;
59 string_buf.reset();
60 tape.reset();
61 return MEMALLOC;
62 }
63 // Technically the allocated_capacity might be larger than capacity
64 // so the next line is pessimistic.
65 allocated_capacity = capacity;
66 return SUCCESS;
67}
68
69inline bool document::dump_raw_tape(std::ostream &os) const noexcept {
70 uint32_t string_length;
71 size_t tape_idx = 0;
72 uint64_t tape_val = tape[tape_idx];
73 uint8_t type = uint8_t(tape_val >> 56);
74 os << tape_idx << " : " << type;
75 tape_idx++;
76 size_t how_many = 0;
77 if (type == 'r') {
78 how_many = size_t(tape_val & internal::JSON_VALUE_MASK);
79 } else {
80 // Error: no starting root node?
81 return false;
82 }
83 os << "\t// pointing to " << how_many << " (right after last node)\n";
84 uint64_t payload;
85 for (; tape_idx < how_many; tape_idx++) {
86 os << tape_idx << " : ";
87 tape_val = tape[tape_idx];
88 payload = tape_val & internal::JSON_VALUE_MASK;
89 type = uint8_t(tape_val >> 56);
90 switch (type) {
91 case '"': // we have a string
92 os << "string \"";
93 std::memcpy(&string_length, string_buf.get() + payload, sizeof(uint32_t));
94 os << internal::escape_json_string(std::string_view(
95 reinterpret_cast<const char *>(string_buf.get() + payload + sizeof(uint32_t)),
96 string_length
97 ));
98 os << '"';
99 os << '\n';
100 break;
101 case 'l': // we have a long int
102 if (tape_idx + 1 >= how_many) {
103 return false;
104 }
105 os << "integer " << static_cast<int64_t>(tape[++tape_idx]) << "\n";
106 break;
107 case 'u': // we have a long uint
108 if (tape_idx + 1 >= how_many) {
109 return false;
110 }
111 os << "unsigned integer " << tape[++tape_idx] << "\n";
112 break;
113 case 'd': // we have a double
114 os << "float ";
115 if (tape_idx + 1 >= how_many) {
116 return false;
117 }
118 double answer;
119 std::memcpy(&answer, &tape[++tape_idx], sizeof(answer));
120 os << answer << '\n';
121 break;
122 case 'n': // we have a null
123 os << "null\n";
124 break;
125 case 't': // we have a true
126 os << "true\n";
127 break;
128 case 'f': // we have a false
129 os << "false\n";
130 break;
131 case '{': // we have an object
132 os << "{\t// pointing to next tape location " << uint32_t(payload)
133 << " (first node after the scope), "
134 << " saturated count "
135 << ((payload >> 32) & internal::JSON_COUNT_MASK)<< "\n";
136 break; case '}': // we end an object
137 os << "}\t// pointing to previous tape location " << uint32_t(payload)
138 << " (start of the scope)\n";
139 break;
140 case '[': // we start an array
141 os << "[\t// pointing to next tape location " << uint32_t(payload)
142 << " (first node after the scope), "
143 << " saturated count "
144 << ((payload >> 32) & internal::JSON_COUNT_MASK)<< "\n";
145 break;
146 case ']': // we end an array
147 os << "]\t// pointing to previous tape location " << uint32_t(payload)
148 << " (start of the scope)\n";
149 break;
150 case 'r': // we start and end with the root node
151 // should we be hitting the root node?
152 return false;
153 case 'Z': // we have a big integer
154 os << "bigint ";
155 std::memcpy(&string_length, string_buf.get() + payload, sizeof(uint32_t));
156 os << std::string_view(
157 reinterpret_cast<const char *>(string_buf.get() + payload + sizeof(uint32_t)),
158 string_length
159 );
160 os << '\n';
161 break;
162 default:
163 return false;
164 }
165 }
166 tape_val = tape[tape_idx];
167 payload = tape_val & internal::JSON_VALUE_MASK;
168 type = uint8_t(tape_val >> 56);
169 os << tape_idx << " : " << type << "\t// pointing to " << payload
170 << " (start root)\n";
171 return true;
172}
173
174} // namespace dom
175} // namespace simdjson
176
177#endif // SIMDJSON_DOCUMENT_INL_H
element root() const noexcept
Get the root element of this document as a JSON array.
A JSON element.
Definition element.h:36
The top level simdjson namespace, containing everything the library provides.
Definition base.h:8
error_code
All possible errors returned by simdjson.
Definition error.h:19
@ CAPACITY
This parser can't support a document that big.
Definition error.h:21
@ MEMALLOC
Error allocating memory, most likely out of memory.
Definition error.h:22
@ SUCCESS
No error.
Definition error.h:20
SIMDJSON_PUSH_DISABLE_UNUSED_WARNINGS constexpr size_t SIMDJSON_MAXSIZE_BYTES
The maximum document size supported by simdjson.
Definition base.h:28
constexpr size_t SIMDJSON_PADDING
The amount of padding needed in a buffer to parse JSON.
Definition base.h:42