37 #ifndef SAJSON_NO_STD_STRING 41 #if defined(__GNUC__) || defined(__clang__) 42 #define SAJSON_LIKELY(x) __builtin_expect(!!(x), 1) 43 #define SAJSON_UNLIKELY(x) __builtin_expect(!!(x), 0) 44 #define SAJSON_ALWAYS_INLINE __attribute__((always_inline)) 45 #define SAJSON_UNREACHABLE() __builtin_unreachable() 46 #define SAJSON_snprintf snprintf 47 #elif defined(_MSC_VER) 48 #define SAJSON_LIKELY(x) x 49 #define SAJSON_UNLIKELY(x) x 50 #define SAJSON_ALWAYS_INLINE __forceinline 51 #define SAJSON_UNREACHABLE() __assume(0) 52 #if (_MSC_VER <= 1800) 53 #define SAJSON_snprintf _snprintf 55 #define SAJSON_snprintf snprintf 58 #define SAJSON_LIKELY(x) x 59 #define SAJSON_UNLIKELY(x) x 60 #define SAJSON_ALWAYS_INLINE inline 61 #define SAJSON_UNREACHABLE() assert(!"unreachable") 62 #define SAJSON_snprintf snprintf 100 return static_cast<size_t>(t) | (value << TYPE_BITS);
105 template<
typename unused=
void>
114 template<
typename unused>
117 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 2, 0, 0,
118 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
119 3, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0x11,1,
120 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, 0x11,0x11,1, 1, 1, 1, 1, 1,
121 1, 1, 1, 1, 1, 0x11,1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
122 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
123 1, 1, 1, 1, 1, 0x11,1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
124 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
127 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
128 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
129 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
130 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0
151 void* buffer =
operator new(
sizeof(size_t) + length);
152 memory =
static_cast<layout*
>(buffer);
157 : memory(that.memory)
163 : memory(that.memory)
184 memory = that.memory;
191 return memory ? memory->data : 0;
197 ++(memory->refcount);
202 if (memory && --(memory->refcount) == 0) {
203 operator delete(memory);
233 #ifndef SAJSON_NO_STD_STRING 235 return std::string(text, text + _length);
254 static_assert(sz > 0,
"!");
285 data = buffer.get_data();
286 memcpy(data, s.
data(), length_);
295 data = buffer.get_data();
296 memcpy(data, s.
data(), length_);
303 : length_(that.length_)
305 , buffer(that.buffer)
310 : length_(that.length_)
312 , buffer(
std::move(that.buffer))
322 buffer = std::move(that.buffer);
366 const size_t rhs_length = rhs.
length();
367 if (lhs_length < rhs_length) {
369 }
else if (lhs_length > rhs_length) {
372 return memcmp(data + lhs.
key_start, rhs.
data(), lhs_length) < 0;
376 return !(*this)(rhs, lhs);
385 if (lhs_length < rhs_length) {
387 }
else if (lhs_length > rhs_length) {
401 namespace integer_storage {
406 inline int load(
const size_t* location) {
408 memcpy(&value, location,
sizeof(value));
417 sizeof(value) <=
sizeof(*location),
418 "size_t must not be smaller than int");
419 memcpy(location, &value,
sizeof(value));
423 namespace double_storage {
428 inline double load(
const size_t* location) {
430 memcpy(&value, location,
sizeof(
double));
438 memcpy(location, &value,
sizeof(
double));
466 using namespace internal;
468 size_t element = payload[1 + index];
477 const size_t*
s = payload + 1 + index * 3;
478 return string(text + s[0], s[1] - s[0]);
484 using namespace internal;
486 size_t element = payload[3 + index * 3];
495 size_t i = find_object_key(key);
496 if (i < get_length()) {
497 return get_object_value(i);
508 using namespace internal;
510 const object_key_record*
start =
reinterpret_cast<const object_key_record*
>(payload + 1);
511 const object_key_record* end = start + get_length();
512 #ifdef SAJSON_UNSORTED_OBJECT_KEYS 513 for (
const object_key_record* i = start; i != end; ++i)
515 const object_key_record* i = std::lower_bound(start, end, key, object_key_comparator(text));
518 && (i->key_end - i->key_start) == key.
length()
519 && memcmp(key.
data(), text + i->key_start, key.
length()) == 0) {
544 return get_integer_value();
546 return get_double_value();
565 *out = get_integer_value();
568 double v = get_double_value();
569 if (v < -(1LL << 53) || v > (1LL << 53)) {
572 int64_t as_int =
static_cast<int64_t
>(v);
587 return payload[1] - payload[0];
598 return text + payload[0];
601 #ifndef SAJSON_NO_STD_STRING 602 std::string as_string()
const {
606 return std::string(text + payload[0], text + payload[1]);
611 const size_t* _internal_get_payload()
const {
617 explicit value(
type value_type_,
const size_t* payload_,
const char* text_)
618 : value_type(value_type_)
624 assert(expected == get_type());
628 assert(e1 == get_type() || e2 == get_type());
632 assert(i < get_length());
674 void operator=(
const ownership&) =
delete;
698 switch (error_code) {
703 case ERROR_BAD_ROOT:
return "document root must be object or array";
741 , structure(
std::move(rhs.structure))
742 , root_type(rhs.root_type)
744 , error_line(rhs.error_line)
745 , error_column(rhs.error_column)
746 , error_code(rhs.error_code)
747 , error_arg(rhs.error_arg)
751 strcpy(formatted_error_message, rhs.formatted_error_message);
767 return value(root_type, root, input.get_data());
780 #ifndef SAJSON_NO_STD_STRING 781 std::string get_error_message_as_string()
const {
783 return formatted_error_message;
789 return formatted_error_message;
795 error _internal_get_error_code()
const {
800 int _internal_get_error_argument()
const {
805 const char* _internal_get_error_text()
const {
810 type _internal_get_root_type()
const {
815 const size_t* _internal_get_root()
const {
828 void operator=(
const document&) =
delete;
832 , structure(
std::move(structure_))
833 , root_type(root_type_)
840 formatted_error_message[0] = 0;
848 , error_line(error_line_)
849 , error_column(error_column_)
850 , error_code(error_code_)
851 , error_arg(error_arg_)
853 formatted_error_message[ERROR_BUFFER_LENGTH - 1] = 0;
854 int written = has_significant_error_arg()
855 ?
SAJSON_snprintf(formatted_error_message, ERROR_BUFFER_LENGTH - 1,
"%s: %d", _internal_get_error_text(), error_arg)
856 :
SAJSON_snprintf(formatted_error_message, ERROR_BUFFER_LENGTH - 1,
"%s", _internal_get_error_text());
858 assert(written >= 0 && written < ERROR_BUFFER_LENGTH);
874 enum { ERROR_BUFFER_LENGTH = 128 };
875 char formatted_error_message[ERROR_BUFFER_LENGTH];
877 template<
typename AllocationStrategy,
typename StringType>
878 friend document parse(
const AllocationStrategy& strategy,
const StringType&
string);
879 template<
typename Allocator>
892 stack_head(stack_head&& other)
893 : stack_bottom(other.stack_bottom)
894 , stack_top(other.stack_top)
897 bool push(
size_t element) {
898 *stack_top++ = element;
902 size_t* reserve(
size_t amount,
bool* success) {
903 size_t* rv = stack_top;
916 void reset(
size_t new_top) {
917 stack_top = stack_bottom + new_top;
921 return stack_top - stack_bottom;
928 size_t* get_pointer_from_offset(
size_t offset) {
929 return stack_bottom + offset;
933 stack_head() =
delete;
934 stack_head(
const stack_head&) =
delete;
935 void operator=(
const stack_head&) =
delete;
937 explicit stack_head(
size_t* base)
942 size_t*
const stack_bottom;
950 allocator() =
delete;
951 allocator(
const allocator&) =
delete;
952 void operator=(
const allocator&) =
delete;
954 explicit allocator(
size_t* buffer,
size_t input_size,
bool should_deallocate_)
956 , structure_end(buffer ? buffer + input_size : 0)
957 , write_cursor(structure_end)
958 , should_deallocate(should_deallocate_)
961 explicit allocator(std::nullptr_t)
965 , should_deallocate(
false)
968 allocator(allocator&& other)
969 : structure(other.structure)
970 , structure_end(other.structure_end)
971 , write_cursor(other.write_cursor)
972 , should_deallocate(other.should_deallocate)
975 other.structure_end = 0;
976 other.write_cursor = 0;
977 other.should_deallocate =
false;
981 if (should_deallocate) {
986 stack_head get_stack_head(
bool* success) {
988 return stack_head(structure);
991 size_t get_write_offset() {
992 return structure_end - write_cursor;
995 size_t* get_write_pointer_of(
size_t v) {
996 return structure_end - v;
999 size_t* reserve(
size_t size,
bool* success) {
1001 write_cursor -= size;
1002 return write_cursor;
1005 size_t* get_ast_root() {
1006 return write_cursor;
1014 if (should_deallocate) {
1023 size_t* structure_end;
1024 size_t* write_cursor;
1025 bool should_deallocate;
1033 : has_existing_buffer(false)
1034 , existing_buffer(0)
1035 , existing_buffer_size(0)
1043 : has_existing_buffer(true)
1044 , existing_buffer(existing_buffer_)
1045 , existing_buffer_size(size_in_words)
1057 allocator make_allocator(
size_t input_document_size_in_bytes,
bool* succeeded)
const {
1058 if (has_existing_buffer) {
1059 if (existing_buffer_size < input_document_size_in_bytes) {
1061 return allocator(
nullptr);
1064 return allocator(existing_buffer, input_document_size_in_bytes,
false);
1066 size_t* buffer =
new(std::nothrow)
size_t[input_document_size_in_bytes];
1069 return allocator(
nullptr);
1072 return allocator(buffer, input_document_size_in_bytes,
true);
1093 stack_head(stack_head&& other)
1094 : stack_top(other.stack_top)
1095 , stack_bottom(other.stack_bottom)
1096 , stack_limit(other.stack_limit)
1098 other.stack_top = 0;
1099 other.stack_bottom = 0;
1100 other.stack_limit = 0;
1104 delete[] stack_bottom;
1107 bool push(
size_t element) {
1109 *stack_top++ = element;
1116 size_t* reserve(
size_t amount,
bool* success) {
1117 if (can_grow(amount)) {
1118 size_t* rv = stack_top;
1119 stack_top += amount;
1128 void reset(
size_t new_top) {
1129 stack_top = stack_bottom + new_top;
1133 return stack_top - stack_bottom;
1140 size_t* get_pointer_from_offset(
size_t offset) {
1141 return stack_bottom + offset;
1145 stack_head(
const stack_head&) =
delete;
1146 void operator=(
const stack_head&) =
delete;
1148 explicit stack_head(
size_t initial_capacity,
bool* success) {
1149 assert(initial_capacity);
1150 stack_bottom =
new(std::nothrow)
size_t[initial_capacity];
1151 stack_top = stack_bottom;
1153 stack_limit = stack_bottom + initial_capacity;
1157 *success = !!stack_bottom;
1160 bool can_grow(
size_t amount) {
1161 if (
SAJSON_LIKELY(amount <= static_cast<size_t>(stack_limit - stack_top))) {
1165 size_t current_size = stack_top - stack_bottom;
1166 size_t old_capacity = stack_limit - stack_bottom;
1167 size_t new_capacity = old_capacity * 2;
1168 while (new_capacity < amount + current_size) {
1171 size_t* new_stack =
new(std::nothrow)
size_t[new_capacity];
1179 memcpy(new_stack, stack_bottom, current_size *
sizeof(
size_t));
1180 delete[] stack_bottom;
1181 stack_top = new_stack + current_size;
1182 stack_bottom = new_stack;
1183 stack_limit = stack_bottom + new_capacity;
1188 size_t* stack_bottom;
1189 size_t* stack_limit;
1196 allocator() =
delete;
1197 allocator(
const allocator&) =
delete;
1198 void operator=(
const allocator&) =
delete;
1200 explicit allocator(
size_t* buffer_,
size_t current_capacity,
size_t initial_stack_capacity_)
1201 : ast_buffer_bottom(buffer_)
1202 , ast_buffer_top(buffer_ + current_capacity)
1203 , ast_write_head(ast_buffer_top)
1204 , initial_stack_capacity(initial_stack_capacity_)
1207 explicit allocator(std::nullptr_t)
1208 : ast_buffer_bottom(0)
1211 , initial_stack_capacity(0)
1214 allocator(allocator&& other)
1215 : ast_buffer_bottom(other.ast_buffer_bottom)
1216 , ast_buffer_top(other.ast_buffer_top)
1217 , ast_write_head(other.ast_write_head)
1218 , initial_stack_capacity(other.initial_stack_capacity)
1220 other.ast_buffer_bottom = 0;
1221 other.ast_buffer_top = 0;
1222 other.ast_write_head = 0;
1226 delete[] ast_buffer_bottom;
1229 stack_head get_stack_head(
bool* success) {
1230 return stack_head(initial_stack_capacity, success);
1233 size_t get_write_offset() {
1234 return ast_buffer_top - ast_write_head;
1237 size_t* get_write_pointer_of(
size_t v) {
1238 return ast_buffer_top - v;
1241 size_t* reserve(
size_t size,
bool* success) {
1242 if (can_grow(size)) {
1243 ast_write_head -= size;
1245 return ast_write_head;
1252 size_t* get_ast_root() {
1253 return ast_write_head;
1257 auto p = ast_buffer_bottom;
1258 ast_buffer_bottom = 0;
1265 bool can_grow(
size_t amount) {
1266 if (
SAJSON_LIKELY(amount <= static_cast<size_t>(ast_write_head - ast_buffer_bottom))) {
1269 size_t current_capacity = ast_buffer_top - ast_buffer_bottom;
1271 size_t current_size = ast_buffer_top - ast_write_head;
1272 size_t new_capacity = current_capacity * 2;
1273 while (new_capacity < amount + current_size) {
1277 size_t* old_buffer = ast_buffer_bottom;
1278 size_t* new_buffer =
new(std::nothrow)
size_t[new_capacity];
1280 ast_buffer_bottom = 0;
1286 size_t* old_write_head = ast_write_head;
1287 ast_buffer_bottom = new_buffer;
1288 ast_buffer_top = new_buffer + new_capacity;
1289 ast_write_head = ast_buffer_top - current_size;
1290 memcpy(ast_write_head, old_write_head, current_size *
sizeof(
size_t));
1291 delete[] old_buffer;
1296 size_t* ast_buffer_bottom;
1297 size_t* ast_buffer_top;
1298 size_t* ast_write_head;
1299 size_t initial_stack_capacity;
1307 : initial_ast_capacity(initial_ast_capacity_)
1308 , initial_stack_capacity(initial_stack_capacity_)
1313 allocator make_allocator(
size_t,
bool* succeeded)
const {
1314 size_t capacity = initial_ast_capacity;
1320 size_t* buffer =
new(std::nothrow)
size_t[capacity];
1323 return allocator(
nullptr);
1326 size_t stack_capacity = initial_stack_capacity;
1327 if (!stack_capacity) {
1328 stack_capacity = 256;
1332 return allocator(buffer, capacity, stack_capacity);
1354 stack_head(stack_head&& other)
1355 : source_allocator(other.source_allocator)
1357 other.source_allocator = 0;
1360 bool push(
size_t element) {
1362 *(source_allocator->stack_top)++ = element;
1369 size_t* reserve(
size_t amount,
bool* success) {
1371 size_t* rv = source_allocator->stack_top;
1372 source_allocator->stack_top += amount;
1381 void reset(
size_t new_top) {
1382 source_allocator->stack_top = source_allocator->structure + new_top;
1386 return source_allocator->stack_top - source_allocator->structure;
1390 return source_allocator->stack_top;
1393 size_t* get_pointer_from_offset(
size_t offset) {
1394 return source_allocator->structure + offset;
1398 stack_head(
const stack_head&) =
delete;
1399 void operator=(
const stack_head&) =
delete;
1401 explicit stack_head(allocator* source_allocator_)
1402 : source_allocator(source_allocator_)
1405 allocator* source_allocator;
1412 allocator() =
delete;
1413 allocator(
const allocator&) =
delete;
1414 void operator=(
const allocator&) =
delete;
1416 explicit allocator(
size_t* existing_buffer,
size_t existing_buffer_size)
1417 : structure(existing_buffer)
1418 , structure_end(existing_buffer + existing_buffer_size)
1419 , write_cursor(structure_end)
1420 , stack_top(structure)
1423 allocator(allocator&& other)
1424 : structure(other.structure)
1425 , structure_end(other.structure_end)
1426 , write_cursor(other.write_cursor)
1427 , stack_top(other.stack_top)
1429 other.structure = 0;
1430 other.structure_end = 0;
1431 other.write_cursor = 0;
1432 other.stack_top = 0;
1435 stack_head get_stack_head(
bool* success) {
1437 return stack_head(
this);
1440 size_t get_write_offset() {
1441 return structure_end - write_cursor;
1444 size_t* get_write_pointer_of(
size_t v) {
1445 return structure_end - v;
1448 size_t* reserve(
size_t size,
bool* success) {
1449 if (can_grow(size)) {
1450 write_cursor -= size;
1452 return write_cursor;
1459 size_t* get_ast_root() {
1460 return write_cursor;
1471 bool can_grow(
size_t amount) {
1474 return static_cast<size_t>(write_cursor - stack_top) >= amount;
1478 size_t* structure_end;
1479 size_t* write_cursor;
1491 : existing_buffer(existing_buffer_)
1492 , existing_buffer_size(size_in_words)
1504 allocator make_allocator(
size_t,
bool* succeeded)
const {
1506 return allocator(existing_buffer, existing_buffer_size);
1519 template<
typename Allocator>
1524 , input_end(input.get_data() + input.length())
1525 , allocator(std::move(allocator_))
1533 size_t* ast_root = allocator.get_ast_root();
1534 return document(input, allocator.transfer_ownership(), root_type, ast_root);
1536 return document(input, error_line, error_column, error_code, error_arg);
1541 struct error_result {
1542 operator bool()
const {
1545 operator char*()
const {
1550 bool at_eof(
const char* p) {
1551 return p == input_end;
1554 char* skip_whitespace(
char* p) {
1571 error_result oom(
char* p) {
1575 error_result unexpected_end() {
1579 error_result unexpected_end(
char* p) {
1583 error_result make_error(
char* p,
error code,
int arg = 0) {
1591 char* c = input.get_data();
1594 if (c + 1 < p && c[1] ==
'\n') {
1602 }
else if (*c ==
'\n') {
1614 return error_result();
1618 using namespace internal;
1621 char* p = input.get_data();
1624 auto stack = allocator.get_stack_head(&success);
1629 p = skip_whitespace(p);
1635 size_t current_base = stack.get_size();
1636 type current_structure_type;
1643 goto array_close_or_element;
1644 }
else if (*p ==
'{') {
1650 goto object_close_or_element;
1662 array_close_or_element:
1663 p = skip_whitespace(p + 1);
1665 return unexpected_end();
1675 object_close_or_element:
1676 p = skip_whitespace(p + 1);
1678 return unexpected_end();
1688 structure_close_or_comma:
1689 p = skip_whitespace(p);
1691 return unexpected_end();
1721 size_t* base_ptr = stack.get_pointer_from_offset(current_base);
1722 pop_element = *base_ptr;
1723 if (
SAJSON_UNLIKELY(!install_object(base_ptr + 1, stack.get_top()))) {
1732 size_t* base_ptr = stack.get_pointer_from_offset(current_base);
1733 pop_element = *base_ptr;
1742 p = skip_whitespace(p);
1744 return unexpected_end();
1750 size_t* out = stack.reserve(2, &success_);
1754 p = parse_string(p, out);
1758 p = skip_whitespace(p);
1768 p = skip_whitespace(p);
1770 return unexpected_end();
1773 type value_type_result;
1776 return unexpected_end(p);
1809 auto result = parse_number(p);
1814 value_type_result = result.second;
1819 size_t* string_tag = allocator.reserve(2, &success_);
1823 p = parse_string(p, string_tag);
1832 size_t previous_base = current_base;
1833 current_base = stack.get_size();
1834 bool s = stack.push(
make_element(current_structure_type, previous_base));
1839 goto array_close_or_element;
1842 size_t previous_base = current_base;
1843 current_base = stack.get_size();
1844 bool s = stack.push(
make_element(current_structure_type, previous_base));
1849 goto object_close_or_element;
1854 root_type = current_structure_type;
1855 p = skip_whitespace(p);
1861 stack.reset(current_base);
1862 current_base = parent;
1863 value_type_result = current_structure_type;
1876 allocator.get_write_offset()));
1881 goto structure_close_or_comma;
1887 bool has_remaining_characters(
char* p, ptrdiff_t remaining) {
1888 return input_end - p >= remaining;
1891 char* parse_null(
char* p) {
1906 char* parse_false(
char* p) {
1914 if (
SAJSON_UNLIKELY(p1 !=
'a' || p2 !=
'l' || p3 !=
's' || p4 !=
'e')) {
1920 char* parse_true(
char* p) {
1933 static double pow10(int64_t exponent) {
1935 return std::numeric_limits<double>::infinity();
1939 static const double constants[] = {
1940 1e-323,1e-322,1e-321,1e-320,1e-319,1e-318,1e-317,1e-316,1e-315,1e-314,
1941 1e-313,1e-312,1e-311,1e-310,1e-309,1e-308,1e-307,1e-306,1e-305,1e-304,
1942 1e-303,1e-302,1e-301,1e-300,1e-299,1e-298,1e-297,1e-296,1e-295,1e-294,
1943 1e-293,1e-292,1e-291,1e-290,1e-289,1e-288,1e-287,1e-286,1e-285,1e-284,
1944 1e-283,1e-282,1e-281,1e-280,1e-279,1e-278,1e-277,1e-276,1e-275,1e-274,
1945 1e-273,1e-272,1e-271,1e-270,1e-269,1e-268,1e-267,1e-266,1e-265,1e-264,
1946 1e-263,1e-262,1e-261,1e-260,1e-259,1e-258,1e-257,1e-256,1e-255,1e-254,
1947 1e-253,1e-252,1e-251,1e-250,1e-249,1e-248,1e-247,1e-246,1e-245,1e-244,
1948 1e-243,1e-242,1e-241,1e-240,1e-239,1e-238,1e-237,1e-236,1e-235,1e-234,
1949 1e-233,1e-232,1e-231,1e-230,1e-229,1e-228,1e-227,1e-226,1e-225,1e-224,
1950 1e-223,1e-222,1e-221,1e-220,1e-219,1e-218,1e-217,1e-216,1e-215,1e-214,
1951 1e-213,1e-212,1e-211,1e-210,1e-209,1e-208,1e-207,1e-206,1e-205,1e-204,
1952 1e-203,1e-202,1e-201,1e-200,1e-199,1e-198,1e-197,1e-196,1e-195,1e-194,
1953 1e-193,1e-192,1e-191,1e-190,1e-189,1e-188,1e-187,1e-186,1e-185,1e-184,
1954 1e-183,1e-182,1e-181,1e-180,1e-179,1e-178,1e-177,1e-176,1e-175,1e-174,
1955 1e-173,1e-172,1e-171,1e-170,1e-169,1e-168,1e-167,1e-166,1e-165,1e-164,
1956 1e-163,1e-162,1e-161,1e-160,1e-159,1e-158,1e-157,1e-156,1e-155,1e-154,
1957 1e-153,1e-152,1e-151,1e-150,1e-149,1e-148,1e-147,1e-146,1e-145,1e-144,
1958 1e-143,1e-142,1e-141,1e-140,1e-139,1e-138,1e-137,1e-136,1e-135,1e-134,
1959 1e-133,1e-132,1e-131,1e-130,1e-129,1e-128,1e-127,1e-126,1e-125,1e-124,
1960 1e-123,1e-122,1e-121,1e-120,1e-119,1e-118,1e-117,1e-116,1e-115,1e-114,
1961 1e-113,1e-112,1e-111,1e-110,1e-109,1e-108,1e-107,1e-106,1e-105,1e-104,
1962 1e-103,1e-102,1e-101,1e-100,1e-99,1e-98,1e-97,1e-96,1e-95,1e-94,1e-93,
1963 1e-92,1e-91,1e-90,1e-89,1e-88,1e-87,1e-86,1e-85,1e-84,1e-83,1e-82,1e-81,
1964 1e-80,1e-79,1e-78,1e-77,1e-76,1e-75,1e-74,1e-73,1e-72,1e-71,1e-70,1e-69,
1965 1e-68,1e-67,1e-66,1e-65,1e-64,1e-63,1e-62,1e-61,1e-60,1e-59,1e-58,1e-57,
1966 1e-56,1e-55,1e-54,1e-53,1e-52,1e-51,1e-50,1e-49,1e-48,1e-47,1e-46,1e-45,
1967 1e-44,1e-43,1e-42,1e-41,1e-40,1e-39,1e-38,1e-37,1e-36,1e-35,1e-34,1e-33,
1968 1e-32,1e-31,1e-30,1e-29,1e-28,1e-27,1e-26,1e-25,1e-24,1e-23,1e-22,1e-21,
1969 1e-20,1e-19,1e-18,1e-17,1e-16,1e-15,1e-14,1e-13,1e-12,1e-11,1e-10,1e-9,
1970 1e-8,1e-7,1e-6,1e-5,1e-4,1e-3,1e-2,1e-1,1e0,1e1,1e2,1e3,1e4,1e5,1e6,1e7,
1971 1e8,1e9,1e10,1e11,1e12,1e13,1e14,1e15,1e16,1e17,1e18,1e19,1e20,1e21,
1972 1e22,1e23,1e24,1e25,1e26,1e27,1e28,1e29,1e30,1e31,1e32,1e33,1e34,1e35,
1973 1e36,1e37,1e38,1e39,1e40,1e41,1e42,1e43,1e44,1e45,1e46,1e47,1e48,1e49,
1974 1e50,1e51,1e52,1e53,1e54,1e55,1e56,1e57,1e58,1e59,1e60,1e61,1e62,1e63,
1975 1e64,1e65,1e66,1e67,1e68,1e69,1e70,1e71,1e72,1e73,1e74,1e75,1e76,1e77,
1976 1e78,1e79,1e80,1e81,1e82,1e83,1e84,1e85,1e86,1e87,1e88,1e89,1e90,1e91,
1977 1e92,1e93,1e94,1e95,1e96,1e97,1e98,1e99,1e100,1e101,1e102,1e103,1e104,
1978 1e105,1e106,1e107,1e108,1e109,1e110,1e111,1e112,1e113,1e114,1e115,1e116,
1979 1e117,1e118,1e119,1e120,1e121,1e122,1e123,1e124,1e125,1e126,1e127,1e128,
1980 1e129,1e130,1e131,1e132,1e133,1e134,1e135,1e136,1e137,1e138,1e139,1e140,
1981 1e141,1e142,1e143,1e144,1e145,1e146,1e147,1e148,1e149,1e150,1e151,1e152,
1982 1e153,1e154,1e155,1e156,1e157,1e158,1e159,1e160,1e161,1e162,1e163,1e164,
1983 1e165,1e166,1e167,1e168,1e169,1e170,1e171,1e172,1e173,1e174,1e175,1e176,
1984 1e177,1e178,1e179,1e180,1e181,1e182,1e183,1e184,1e185,1e186,1e187,1e188,
1985 1e189,1e190,1e191,1e192,1e193,1e194,1e195,1e196,1e197,1e198,1e199,1e200,
1986 1e201,1e202,1e203,1e204,1e205,1e206,1e207,1e208,1e209,1e210,1e211,1e212,
1987 1e213,1e214,1e215,1e216,1e217,1e218,1e219,1e220,1e221,1e222,1e223,1e224,
1988 1e225,1e226,1e227,1e228,1e229,1e230,1e231,1e232,1e233,1e234,1e235,1e236,
1989 1e237,1e238,1e239,1e240,1e241,1e242,1e243,1e244,1e245,1e246,1e247,1e248,
1990 1e249,1e250,1e251,1e252,1e253,1e254,1e255,1e256,1e257,1e258,1e259,1e260,
1991 1e261,1e262,1e263,1e264,1e265,1e266,1e267,1e268,1e269,1e270,1e271,1e272,
1992 1e273,1e274,1e275,1e276,1e277,1e278,1e279,1e280,1e281,1e282,1e283,1e284,
1993 1e285,1e286,1e287,1e288,1e289,1e290,1e291,1e292,1e293,1e294,1e295,1e296,
1994 1e297,1e298,1e299,1e300,1e301,1e302,1e303,1e304,1e305,1e306,1e307,1e308
1996 return constants[exponent + 323];
1999 std::pair<char*, type> parse_number(
char* p) {
2000 bool negative =
false;
2010 bool try_double =
false;
2020 unsigned char c = *p;
2021 if (c < '0' || c >
'9') {
2031 unsigned char digit = c -
'0';
2039 d = 10.0 * d + digit;
2045 }
while (c >=
'0' && c <=
'9');
2048 int64_t exponent = 0;
2060 if (c < '0' || c >
'9') {
2069 d = d * 10 + (c -
'0');
2080 }
while (c >=
'0' && c <=
'9');
2084 if (
'e' == e ||
'E' == e) {
2094 bool negativeExponent =
false;
2096 negativeExponent =
true;
2101 }
else if (
'+' == *p) {
2116 unsigned char digit = c -
'0';
2117 if (exp > (INT_MAX - digit) / 10) {
2123 exp = 10 * exp + digit;
2132 if (c < '0' || c >
'9') {
2136 static_assert(-INT_MAX >= INT_MIN,
"exp can be negated without loss or UB");
2137 exponent += (negativeExponent ? -exp : exp);
2145 d *= pow10(exponent);
2160 return std::make_pair(oom(p),
TYPE_NULL);
2168 return std::make_pair(oom(p),
TYPE_NULL);
2175 bool install_array(
size_t* array_base,
size_t* array_end) {
2178 const size_t length = array_end - array_base;
2180 size_t*
const new_base = allocator.reserve(length + 1, &success);
2184 size_t* out = new_base + length + 1;
2185 size_t*
const structure_end = allocator.get_write_pointer_of(0);
2187 while (array_end > array_base) {
2188 size_t element = *--array_end;
2191 size_t* element_ptr = structure_end - element_value;
2192 *--out =
make_element(element_type, element_ptr - new_base);
2198 bool install_object(
size_t* object_base,
size_t* object_end) {
2199 using namespace internal;
2201 assert((object_end - object_base) % 3 == 0);
2202 const size_t length_times_3 = object_end - object_base;
2203 #ifndef SAJSON_UNSORTED_OBJECT_KEYS 2205 reinterpret_cast<object_key_record*>(object_base),
2206 reinterpret_cast<object_key_record*>(object_end),
2211 size_t*
const new_base = allocator.reserve(length_times_3 + 1, &success);
2215 size_t* out = new_base + length_times_3 + 1;
2216 size_t*
const structure_end = allocator.get_write_pointer_of(0);
2218 while (object_end > object_base) {
2219 size_t element = *--object_end;
2222 size_t* element_ptr = structure_end - element_value;
2224 *--out =
make_element(element_type, element_ptr - new_base);
2225 *--out = *--object_end;
2226 *--out = *--object_end;
2228 *--out = length_times_3 / 3;
2232 char* parse_string(
char* p,
size_t* tag) {
2233 using namespace internal;
2236 size_t start = p - input.get_data();
2237 char* input_end_local = input_end;
2238 while (input_end_local - p >= 4) {
2259 tag[1] = p - input.get_data();
2264 if (*p >= 0 && *p < 0x20) {
2268 return parse_string_slow(p, tag, start);
2272 char* read_hex(
char* p,
unsigned& u) {
2276 unsigned char c = *p++;
2277 if (c >=
'0' && c <=
'9') {
2279 }
else if (c >=
'a' && c <=
'f') {
2281 }
else if (c >=
'A' && c <=
'F') {
2293 void write_utf8(
unsigned codepoint,
char*& end) {
2294 if (codepoint < 0x80) {
2295 *end++ = char(codepoint);
2296 }
else if (codepoint < 0x800) {
2297 *end++ = 0xC0 | char(codepoint >> 6);
2298 *end++ = 0x80 | char(codepoint & 0x3F);
2299 }
else if (codepoint < 0x10000) {
2300 *end++ = 0xE0 | char(codepoint >> 12);
2301 *end++ = 0x80 | char((codepoint >> 6) & 0x3F);
2302 *end++ = 0x80 | char(codepoint & 0x3F);
2304 assert(codepoint < 0x200000);
2305 *end++ = 0xF0 | char(codepoint >> 18);
2306 *end++ = 0x80 | char((codepoint >> 12) & 0x3F);
2307 *end++ = 0x80 | char((codepoint >> 6) & 0x3F);
2308 *end++ = 0x80 | char(codepoint & 0x3F);
2312 char* parse_string_slow(
char* p,
size_t* tag,
size_t start) {
2314 char* input_end_local = input_end;
2328 tag[1] = end - input.get_data();
2340 case '"': replacement =
'"';
goto replace;
2341 case '\\': replacement =
'\\';
goto replace;
2342 case '/': replacement =
'/';
goto replace;
2343 case 'b': replacement =
'\b';
goto replace;
2344 case 'f': replacement =
'\f';
goto replace;
2345 case 'n': replacement =
'\n';
goto replace;
2346 case 'r': replacement =
'\r';
goto replace;
2347 case 't': replacement =
'\t';
goto replace;
2349 *end++ = replacement;
2362 if (u >= 0xD800 && u <= 0xDBFF) {
2368 if (p0 !=
'\\' || p1 !=
'u') {
2378 if (v < 0xDC00 || v > 0xDFFF) {
2381 u = 0x10000 + (((u - 0xD800) << 10) | (v - 0xDC00));
2393 unsigned char c0 = p[0];
2396 }
else if (c0 < 224) {
2398 return unexpected_end(p);
2400 unsigned char c1 = p[1];
2401 if (c1 < 128 || c1 >= 192) {
2408 }
else if (c0 < 240) {
2410 return unexpected_end(p);
2412 unsigned char c1 = p[1];
2413 if (c1 < 128 || c1 >= 192) {
2416 unsigned char c2 = p[2];
2417 if (c2 < 128 || c2 >= 192) {
2425 }
else if (c0 < 248) {
2427 return unexpected_end(p);
2429 unsigned char c1 = p[1];
2430 if (c1 < 128 || c1 >= 192) {
2433 unsigned char c2 = p[2];
2434 if (c2 < 128 || c2 >= 192) {
2437 unsigned char c3 = p[3];
2438 if (c3 < 128 || c3 >= 192) {
2456 char*
const input_end;
2457 Allocator allocator;
2461 size_t error_column;
2478 template<
typename AllocationStrategy,
typename StringType>
2483 auto allocator = strategy.make_allocator(input.
length(), &success);
2488 return parser<typename AllocationStrategy::allocator>(
2490 std::move(allocator)
literal(const char(&text_)[sz])
type
Tag indicating a JSON value's type.
bounded_allocation(size_t *existing_buffer_, size_t size_in_words)
string(const char *text_, size_t length)
bounded_allocation(size_t(&existing_buffer_)[N])
size_t existing_buffer_size
document(const mutable_string_view &input_, internal::ownership &&structure_, type root_type_, const size_t *root_)
bool operator()(const object_key_record &lhs, const object_key_record &rhs)
mutable_string_view(const mutable_string_view &that)
size_t existing_buffer_size
size_t get_string_length() const
ownership(ownership &&p_)
document(const mutable_string_view &input_, size_t error_line_, size_t error_column_, const error error_code_, int error_arg_)
allocated_buffer(size_t length)
bool is_plain_string_character(char c)
const char * get_error_text(error error_code)
internal::allocated_buffer buffer
value get_value_of_key(const string &key) const
std::string as_string() const
static const unsigned char parse_flags[256]
size_t find_object_key(const string &key) const
allocated_buffer & operator=(allocated_buffer &&that)
object_key_comparator(const char *object_data)
static const size_t ROOT_MARKER
void store(size_t *location, int value)
static const size_t TYPE_BITS
int get_integer_value() const
const char * as_cstring() const
GLenum GLuint GLenum GLsizei length
const char * get_error_message_as_cstring() const
If not is_valid(), returns a null-terminated C string indicating why the parse failed.
mutable_string_view(size_t length, char *data_)
allocated_buffer & operator=(const allocated_buffer &that)
mutable_string_view & operator=(const mutable_string_view &that)
const char * data() const
value get_array_element(size_t index) const
size_t initial_ast_capacity
bool get_int53_value(int64_t *out) const
bool operator()(const string &lhs, const object_key_record &rhs) const
size_t get_length() const
mutable_string_view & operator=(mutable_string_view &&that)
void assert_type(type expected) const
string get_object_key(size_t index) const
internal::ownership structure
single_allocation(size_t(&existing_buffer_)[N])
size_t get_element_value(size_t s)
size_t get_error_line() const
If not is_valid(), returns the one-based line number where the parse failed.
const size_t error_column
const size_t *const payload
bool operator()(const object_key_record &lhs, const string &rhs) const
mutable_string_view input
value get_root() const
If is_valid(), returns the document's root value.
size_t get_error_column() const
If not is_valid(), returns the one-based column number where the parse failed.
mutable_string_view(const literal &s)
mutable_string_view()
Creates an empty, zero-sized view.
dynamic_allocation(size_t initial_ast_capacity_=0, size_t initial_stack_capacity_=0)
allocated_buffer(allocated_buffer &&that)
bool is_whitespace(char c)
typedef void(GLAD_API_PTR *GLDEBUGPROC)(GLenum source
size_t initial_stack_capacity
INLINE Rall1d< T, V, S > exp(const Rall1d< T, V, S > &arg)
void assert_in_bounds(size_t i) const
void assert_type_2(type e1, type e2) const
type get_element_type(size_t s)
mutable_string_view(const string &s)
value get_object_value(size_t index) const
mutable_string_view(mutable_string_view &&that)
Move constructor - neuters the old mutable_string_view.
double get_double_value() const
value(type value_type_, const size_t *payload_, const char *text_)
allocated_buffer(const allocated_buffer &that)
static const size_t VALUE_MASK
bool has_significant_error_arg() const
double get_number_value() const
size_t make_element(type t, size_t value)
void store(size_t *location, double value)
static const size_t TYPE_MASK
int load(const size_t *location)
error
Error code indicating why parse failed.
type get_type() const
Returns the JSON value's type.
document parse(const AllocationStrategy &strategy, const StringType &string)
#define SAJSON_UNLIKELY(x)
#define SAJSON_UNREACHABLE()
single_allocation(size_t *existing_buffer_, size_t size_in_words)
double load(const size_t *location)