1 /**************************************************************************
3 * Copyright 2013-2014 RAD Game Tools and Valve Software
4 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 **************************************************************************/
28 #include "vogl_core.h"
29 #include "vogl_json.h"
30 #include "vogl_console.h"
31 #include "vogl_growable_array.h"
32 #include "vogl_hash_map.h"
38 json_node_object_pool *g_pJSON_node_pool;
39 json_value g_null_json_value;
41 static const char *g_to_hex = "0123456789ABCDEF";
43 const uint cMaxValidDepth = 511;
45 const uint cJSONTabSize = 3;
47 void json_node_pool_init()
49 if (!g_pJSON_node_pool)
50 g_pJSON_node_pool = vogl_new(json_node_object_pool, 256, cObjectPoolGrowExponential);
53 // class json_deserialize_buf_ptr
55 class json_deserialize_buf_ptr
58 inline json_deserialize_buf_ptr(const char *p, size_t len)
63 inline void init(const char *p, size_t len)
70 inline const char *get_end() const
74 inline bool at_end() const
76 return m_pPtr >= m_pEnd;
79 inline size_t get_num_remaining() const
81 return m_pEnd - m_pPtr;
84 inline char get_char() const
86 char c = (m_pPtr < m_pEnd) ? *m_pPtr : 0;
92 inline uint get_cur_line() const
97 inline char operator*() const
101 inline operator const char *() const
106 inline json_deserialize_buf_ptr &operator++()
112 inline json_deserialize_buf_ptr operator++(int)
114 json_deserialize_buf_ptr cur(*this);
119 inline char get_and_advance()
121 char c = (m_pPtr < m_pEnd) ? *m_pPtr++ : 0;
124 if ((c == '\r') && (m_pPtr < m_pEnd) && (*m_pPtr == '\n'))
126 if ((c == '\n') || (c == '\r'))
135 inline void advance()
140 json_deserialize_buf_ptr &skip_whitespace();
142 inline bool compare_string(const char *pStr, size_t n) const
144 return ((m_pEnd - m_pPtr) < (int)n) ? false : !strncmp(m_pPtr, pStr, n);
147 inline json_deserialize_buf_ptr &advance_in_line(uint n)
149 m_pPtr = VOGL_MIN(m_pEnd, m_pPtr + n);
152 inline json_deserialize_buf_ptr &advance_in_line_no_end_check(uint n)
155 VOGL_ASSERT(m_pPtr <= m_pEnd);
165 json_deserialize_buf_ptr &json_deserialize_buf_ptr::skip_whitespace()
167 while (m_pPtr < m_pEnd)
170 if ((c == ' ') || (c == '\t'))
176 if ((c == '/') && (((m_pPtr + 1) < m_pEnd) && (m_pPtr[1] == '/')))
179 while ((!at_end()) && (get_char() != '\n'))
187 if (((m_pPtr + 1) < m_pEnd) && (m_pPtr[1] == '\n'))
199 // class json_growable_char_buf
201 class json_growable_char_buf
203 VOGL_NO_COPY_OR_ASSIGNMENT_OP(json_growable_char_buf);
206 inline json_growable_char_buf(vogl::vector<char> &buf)
211 inline uint size() const
216 inline const vogl::vector<char> &get() const
220 inline vogl::vector<char> &get()
225 void puts(const char *pStr);
226 void printf(const char *pFmt, ...);
227 void print_escaped(const char *pStr);
228 void print_tabs(uint n);
229 inline void print_char(char c)
235 vogl::vector<char> &m_buf;
238 void json_growable_char_buf::puts(const char *pStr)
240 size_t l = strlen(pStr);
244 char *p = m_buf.try_enlarge(static_cast<uint>(l));
249 void json_growable_char_buf::printf(const char *pFmt, ...)
254 va_start(args, pFmt);
256 int l = _vsnprintf_s(str, sizeof(str), pFmt, args);
258 int l = vsnprintf(str, sizeof(str), pFmt, args);
259 str[sizeof(str) - 1] = '\0';
263 char *p = m_buf.try_enlarge(l);
268 void json_growable_char_buf::print_tabs(uint n)
271 // Apparently tabs are not valid JSON.
272 char *p = m_buf.enlarge(n);
276 char *p = m_buf.enlarge(n * cJSONTabSize);
278 memset(p, ' ', n * cJSONTabSize);
282 void json_growable_char_buf::print_escaped(const char *pStr)
284 m_buf.push_back('\"');
289 if ((static_cast<uint8>(c) >= 32U) && (c != '\"') && (c != '\\'))
293 m_buf.push_back('\\');
297 m_buf.push_back('b');
300 m_buf.push_back('r');
303 m_buf.push_back('t');
306 m_buf.push_back('f');
309 m_buf.push_back('n');
312 m_buf.push_back('\\');
315 m_buf.push_back('\"');
318 m_buf.push_back('u');
319 m_buf.push_back('0');
320 m_buf.push_back('0');
321 m_buf.push_back(g_to_hex[static_cast<uint8>(c) >> 4]);
322 m_buf.push_back(g_to_hex[c & 0xF]);
328 m_buf.push_back('\"');
331 void json_error_info_t::set_error(uint line, const char *pMsg, ...)
336 va_start(args, pMsg);
337 m_error_msg.format_args(pMsg, args);
343 json_value::json_value(const json_value &other)
344 : m_type(other.m_type),
347 if (other.m_type == cJSONValueTypeString)
348 m_data.m_pStr = vogl_strdup(other.m_data.m_pStr);
349 else if (other.m_type == cJSONValueTypeNode)
350 m_data.m_pNode = get_json_node_pool()->alloc(*other.get_node_ptr());
352 memcpy(&m_data, &other.m_data, sizeof(m_data));
355 void json_value::set_value(uint64_t nVal)
359 if (nVal > static_cast<uint64_t>(cINT64_MAX))
361 // Encode as a hex string because otherwise some json parsers have a fit, and the UJB format doesn't directly support uint64_t.
363 vogl_sprintf_s(buf, sizeof(buf), "0x%" PRIX64, nVal);
368 set_value(static_cast<int64_t>(nVal));
372 json_value &json_value::operator=(const json_value &rhs)
378 if (m_type == cJSONValueTypeString)
379 m_data.m_pStr = vogl_strdup(rhs.m_data.m_pStr);
380 else if (m_type == cJSONValueTypeNode)
381 m_data.m_pNode = get_json_node_pool()->alloc(*rhs.get_node_ptr());
383 memcpy(&m_data, &rhs.m_data, sizeof(m_data));
390 bool json_value::convert_to_bool(bool &val, bool def) const
394 case cJSONValueTypeBool:
395 case cJSONValueTypeInt:
397 val = (m_data.m_nVal != 0);
400 case cJSONValueTypeDouble:
402 val = (m_data.m_flVal != 0);
405 case cJSONValueTypeString:
407 if (!vogl_stricmp(m_data.m_pStr, "false"))
412 else if (!vogl_stricmp(m_data.m_pStr, "true"))
419 const char *pStr = m_data.m_pStr;
420 if (!string_ptr_to_double(pStr, flVal))
435 bool json_value::convert_to_int32(int32 &val, int32 def) const
439 if (!convert_to_int64(val64, def))
441 if ((val64 < cINT32_MIN) || (val64 > cINT32_MAX))
443 val = static_cast<int32>(val64);
447 bool json_value::convert_to_int64(int64_t &val, int64_t def) const
451 case cJSONValueTypeBool:
452 case cJSONValueTypeInt:
457 case cJSONValueTypeDouble:
459 val = static_cast<int64_t>(m_data.m_flVal);
462 case cJSONValueTypeString:
464 if (!vogl_stricmp(m_data.m_pStr, "false"))
469 else if (!vogl_stricmp(m_data.m_pStr, "true"))
475 const char *pStr = m_data.m_pStr;
477 // string_to_ptr_int64() will handle hex or decimal conversions
478 if (!string_ptr_to_int64(pStr, val))
492 bool json_value::convert_to_uint64(uint64_t &val, uint64_t def) const
496 case cJSONValueTypeBool:
501 case cJSONValueTypeInt:
503 if (m_data.m_nVal < 0)
509 case cJSONValueTypeDouble:
511 if (m_data.m_flVal < 0)
514 val = static_cast<uint64_t>(m_data.m_flVal);
517 case cJSONValueTypeString:
519 if (!vogl_stricmp(m_data.m_pStr, "false"))
524 else if (!vogl_stricmp(m_data.m_pStr, "true"))
530 const char *pStr = m_data.m_pStr;
532 // string_to_uint64() will handle hex or decimal conversions
533 if (!string_ptr_to_uint64(pStr, val))
545 bool json_value::convert_to_float(float &val, float def) const
549 case cJSONValueTypeBool:
550 case cJSONValueTypeInt:
552 val = static_cast<float>(m_data.m_nVal);
555 case cJSONValueTypeDouble:
557 val = static_cast<float>(m_data.m_flVal);
560 case cJSONValueTypeString:
562 if (!vogl_stricmp(m_data.m_pStr, "false"))
567 else if (!vogl_stricmp(m_data.m_pStr, "true"))
573 const char *pStr = m_data.m_pStr;
574 if (!string_ptr_to_float(pStr, val))
586 bool json_value::convert_to_double(double &val, double def) const
590 case cJSONValueTypeBool:
591 case cJSONValueTypeInt:
593 val = static_cast<double>(m_data.m_nVal);
596 case cJSONValueTypeDouble:
598 val = m_data.m_flVal;
601 case cJSONValueTypeString:
603 if (!vogl_stricmp(m_data.m_pStr, "false"))
608 else if (!vogl_stricmp(m_data.m_pStr, "true"))
614 const char *pStr = m_data.m_pStr;
615 if (!string_ptr_to_double(pStr, val))
629 bool json_value::convert_to_string(dynamic_string &val, const char *pDef) const
633 case cJSONValueTypeNull:
638 case cJSONValueTypeBool:
640 val.set(!m_data.m_nVal ? "false" : "true");
643 case cJSONValueTypeInt:
645 val.format("%" PRIi64, m_data.m_nVal);
648 case cJSONValueTypeDouble:
650 val.format("%1.18f", m_data.m_flVal);
652 if ((!val.contains('E')) && (!val.contains('e')))
654 // Remove trailing 0's, except the first after the decimal point which is required for valid JSON.
655 int dot_ofs = val.find_right('.');
658 int len = val.get_len();
661 for (i = dot_ofs + 1; i < len; i++)
664 if (!vogl_isdigit(c))
669 int cur_ofs = len - 1;
670 while ((val[cur_ofs] == '0') && (cur_ofs > (dot_ofs + 1)))
672 val.set_len(cur_ofs);
680 case cJSONValueTypeString:
692 static int scan_string_list(const char *p, const char **pList, int def)
697 const char *s = pList[index];
700 if (vogl_stricmp(p, s) == 0)
707 bool json_value::get_enum(const char **pStringList, int &val, int def) const
711 dynamic_string tmp_str;
714 if (get_type() == cJSONValueTypeString)
715 pStr = m_data.m_pStr;
718 if (!convert_to_string(tmp_str, ""))
720 pStr = tmp_str.get_ptr();
723 int val_index = scan_string_list(pStr, pStringList, -1);
730 bool json_value::get_numeric(int8 &val, int8 def) const
733 if (!get_numeric(val64))
738 if ((val64 < static_cast<int64_t>(cINT8_MIN)) || (val64 > static_cast<int64_t>(cINT8_MAX)))
743 val = static_cast<int8>(val64);
747 bool json_value::get_numeric(int16 &val, int16 def) const
750 if (!get_numeric(val64))
755 if ((val64 < static_cast<int64_t>(cINT16_MIN)) || (val64 > static_cast<int64_t>(cINT16_MAX)))
760 val = static_cast<int16>(val64);
764 bool json_value::get_numeric(uint8 &val, uint8 def) const
767 if (!get_numeric(val64))
772 if (val64 > static_cast<int64_t>(cUINT8_MAX))
777 val = static_cast<uint8>(val64);
781 bool json_value::get_numeric(uint16 &val, uint16 def) const
784 if (!get_numeric(val64))
789 if (val64 > static_cast<int64_t>(cUINT16_MAX))
794 val = static_cast<uint16>(val64);
798 bool json_value::get_numeric(uint32 &val, uint32 def) const
801 if (!get_numeric(val64))
806 if ((val64 < 0) || (val64 > static_cast<int64_t>(cUINT32_MAX)))
811 val = static_cast<uint32>(val64);
815 bool json_value::validate(const json_node *pParent) const
819 const json_node *pNode = get_node_ptr();
823 if (!pNode->basic_validation(pParent))
826 for (uint i = 0; i < pNode->size(); i++)
827 if ((pNode->is_child(i)) && (!pNode->get_value(i).validate(pNode)))
830 else if (is_string())
839 void json_value::binary_serialize_value(vogl::vector<uint8> &buf) const
843 case cJSONValueTypeNull:
848 case cJSONValueTypeBool:
850 buf.push_back(m_data.m_nVal ? 'T' : 'F');
853 case cJSONValueTypeInt:
857 if (static_cast<uint64_t>(m_data.m_nVal) <= 0xFFU)
859 pDst = buf.enlarge(2);
863 else if ((m_data.m_nVal >= cINT16_MIN) && (m_data.m_nVal <= cINT16_MAX))
865 pDst = buf.enlarge(3);
869 else if ((m_data.m_nVal >= cINT32_MIN) && (m_data.m_nVal <= cINT32_MAX))
871 pDst = buf.enlarge(5);
877 pDst = buf.enlarge(9);
882 uint64_t n = static_cast<uint64_t>(m_data.m_nVal);
885 *pDst++ = static_cast<uint8>(n >> shift);
886 } while ((shift -= 8) >= 0);
890 case cJSONValueTypeDouble:
892 float flVal32 = static_cast<float>(m_data.m_flVal);
893 if (math::equal_tol(m_data.m_flVal, static_cast<double>(flVal32), 1e-17))
895 uint8 *pDst = buf.enlarge(5);
897 utils::write_obj(flVal32, pDst + 1, false);
901 uint8 *pDst = buf.enlarge(9);
903 utils::write_obj(m_data.m_flVal, pDst + 1, false);
908 case cJSONValueTypeString:
910 uint len = static_cast<uint>(strlen(m_data.m_pStr));
913 uint8 *pDst = buf.enlarge(2 + len);
915 pDst[1] = static_cast<uint8>(len);
916 memcpy(pDst + 2, m_data.m_pStr, len);
920 uint8 *pDst = buf.enlarge(5 + len);
922 pDst[1] = static_cast<uint8>(len >> 24);
923 pDst[2] = static_cast<uint8>(len >> 16);
924 pDst[3] = static_cast<uint8>(len >> 8);
925 pDst[4] = static_cast<uint8>(len);
926 memcpy(pDst + 5, m_data.m_pStr, len);
936 void json_value::binary_serialize(vogl::vector<uint8> &buf) const
938 const json_node *pNode = get_node_ptr();
940 pNode->binary_serialize(buf);
942 binary_serialize_value(buf);
945 bool json_value::binary_serialize_to_file(const char *pFilename)
947 FILE *pFile = vogl_fopen(pFilename, "wb");
950 bool success = binary_serialize(pFile);
951 if (vogl_fclose(pFile) == EOF)
956 bool json_value::binary_serialize(FILE *pFile)
958 vogl::vector<uint8> buf;
959 binary_serialize(buf);
960 return fwrite(buf.get_ptr(), 1, buf.size(), pFile) == buf.size();
963 void json_value::serialize(vogl::vector<char> &buf, bool formatted, uint cur_indent, bool null_terminate, uint max_line_len) const
965 const json_node *pNode = get_node_ptr();
968 pNode->serialize(buf, formatted, cur_indent, false, max_line_len);
979 // Apparently tabs are not valid JSON.
982 for (uint i = 0; i < cJSONTabSize; i++)
989 json_growable_char_buf growable_buf(buf);
990 growable_buf.print_escaped(m_data.m_pStr);
996 buf.append(str.get_ptr(), str.get_len());
1001 buf.push_back('\0');
1004 bool json_value::binary_deserialize_file(const char *pFilename)
1006 FILE *pFile = vogl_fopen(pFilename, "rb");
1009 bool success = binary_deserialize(pFile);
1010 if (vogl_fclose(pFile) == EOF)
1015 bool json_value::binary_deserialize(FILE *pFile)
1017 vogl_fseek(pFile, 0, SEEK_END);
1018 const uint64_t filesize = vogl_ftell(pFile);
1019 vogl_fseek(pFile, 0, SEEK_SET);
1024 if ((filesize > VOGL_MAX_POSSIBLE_HEAP_BLOCK_SIZE) || (filesize != static_cast<size_t>(filesize)))
1027 uint8 *pBuf = (uint8 *)vogl_malloc(static_cast<size_t>(filesize));
1031 if (vogl_fread(pBuf, 1, static_cast<size_t>(filesize), pFile) != filesize)
1037 bool status = binary_deserialize(pBuf, static_cast<size_t>(filesize));
1044 bool json_value::binary_deserialize(const vogl::vector<uint8> &buf)
1046 return buf.size() ? binary_deserialize(buf.get_ptr(), buf.size()) : false;
1049 bool json_value::binary_deserialize(const uint8 *pBuf, size_t n)
1051 return binary_deserialize(pBuf, pBuf + n, NULL, 0);
1054 bool json_value::binary_deserialize(const uint8 *&pBuf, const uint8 *pBuf_end, json_node *pParent, uint depth)
1056 #define JSON_BD_FAIL() \
1062 const uint8 *pSrc = pBuf;
1063 set_value_to_null();
1065 if (depth > cMaxValidDepth)
1071 if (pSrc >= pBuf_end)
1078 size_t n = pBuf_end - pSrc;
1080 // Process huge nums as strings
1097 const bool is_object = ((c == 'O') || (c == 'o'));
1105 bool unknown_len = false;
1111 l = (l << 24) | (pSrc[0] << 16) | (pSrc[1] << 8) | pSrc[2];
1119 json_node *pNode = set_value_to_node(is_object, pParent);
1124 while ((unknown_len) || (idx < l))
1148 if ((q != 'S') && (q != 's'))
1164 l = (l << 24) | (pSrc[0] << 16) | (pSrc[1] << 8) | pSrc[2];
1172 pNode->get_key(idx).set_from_buf(pSrc, l);
1177 if (!pNode->get_value(idx).binary_deserialize(pSrc, pBuf_end, pNode, depth + 1))
1198 l = (l << 24) | (pSrc[0] << 16) | (pSrc[1] << 8) | pSrc[2];
1206 m_type = cJSONValueTypeString;
1207 m_data.m_pStr = (char *)vogl_malloc(l + 1);
1210 set_value_to_null();
1213 memcpy(m_data.m_pStr, pSrc, l);
1214 m_data.m_pStr[l] = '\0';
1232 m_type = cJSONValueTypeInt;
1233 m_data.m_nVal = *pSrc++;
1240 m_type = cJSONValueTypeInt;
1241 m_data.m_nVal = static_cast<int16>((pSrc[0] << 8) | pSrc[1]);
1249 m_type = cJSONValueTypeInt;
1250 m_data.m_nVal = static_cast<int32>((pSrc[0] << 24) | (pSrc[1] << 16) | (pSrc[2] << 8) | pSrc[3]);
1258 m_type = cJSONValueTypeInt;
1260 for (uint i = 8; i; --i)
1261 v = (v << 8) | *pSrc++;
1262 m_data.m_nVal = static_cast<int64_t>(v);
1269 m_type = cJSONValueTypeDouble;
1275 bits.m_u32 = static_cast<uint32>((pSrc[0] << 24) | (pSrc[1] << 16) | (pSrc[2] << 8) | pSrc[3]);
1277 m_data.m_flVal = static_cast<double>(bits.m_fl32);
1284 m_type = cJSONValueTypeDouble;
1286 for (uint i = 8; i; --i)
1287 v = (v << 8) | *pSrc++;
1301 dynamic_string &json_value::serialize(dynamic_string &str, bool formatted, uint cur_indent, uint max_line_len) const
1303 vogl::vector<char> buf;
1304 serialize(buf, formatted, cur_indent, false, max_line_len);
1305 return str.set_from_buf(buf.get_ptr(), buf.size_in_bytes());
1308 void json_value::print(bool formatted, uint cur_indent, uint max_line_len) const
1310 vogl::vector<char> buf;
1311 serialize(buf, formatted, cur_indent, true, max_line_len);
1312 puts(buf.get_ptr());
1315 bool json_value::serialize_to_file(const char *pFilename, bool formatted, uint max_line_len) const
1317 FILE *pFile = vogl_fopen(pFilename, "wb");
1320 bool success = serialize(pFile, formatted, max_line_len);
1321 if (vogl_fclose(pFile) == EOF)
1326 bool json_value::serialize(FILE *pFile, bool formatted, uint max_line_len) const
1328 vogl::vector<char> buf;
1329 serialize(buf, formatted, 0, false, max_line_len);
1330 return fwrite(buf.get_ptr(), 1, buf.size(), pFile) == buf.size();
1333 bool json_value::deserialize_node(json_deserialize_buf_ptr &pStr, json_node *pParent, uint level, json_error_info_t &error_info)
1335 const bool is_object = (*pStr == '{');
1336 const char end_char = is_object ? '}' : ']';
1338 json_node *pNode = set_value_to_node(is_object, pParent);
1339 pNode->m_line = pStr.get_cur_line();
1341 pStr.advance_in_line_no_end_check(1);
1342 pStr.skip_whitespace();
1346 char c = pStr.get_char();
1350 uint value_index = pNode->enlarge(1);
1356 error_info.set_error(pStr.get_cur_line(), "Expected quoted key string");
1360 pStr.advance_in_line_no_end_check(1);
1363 if (!estimate_deserialized_string_size(pStr, error_info, estimated_len))
1366 if (estimated_len >= cMaxDynamicStringLen)
1368 error_info.set_error(pStr.get_cur_line(), "Quoted name string is too long");
1371 uint buf_size = estimated_len + 1;
1372 char *pBuf = dynamic_string::create_raw_buffer(buf_size);
1375 if (!deserialize_quoted_string_to_buf(pDst, buf_size, pStr, error_info))
1377 dynamic_string::free_raw_buffer(pBuf);
1380 pNode->get_key(value_index).set_from_raw_buf_and_assume_ownership(pBuf, buf_size, static_cast<uint>(pDst - pBuf));
1382 pStr.skip_whitespace();
1386 error_info.set_error(pStr.get_cur_line(), "Missing colon after key");
1390 pStr.advance_in_line_no_end_check(1);
1392 pStr.skip_whitespace();
1395 json_value &newVal = pNode->m_values[value_index];
1396 if (level > cMaxValidDepth)
1398 error_info.set_error(pStr.get_cur_line(), "Document is too complex");
1402 if (!newVal.deserialize(pStr, pNode, level + 1, error_info))
1405 pStr.skip_whitespace();
1410 pStr.advance_in_line_no_end_check(1);
1412 pStr.skip_whitespace();
1415 if (pStr.get_and_advance() != end_char)
1417 error_info.set_error(pStr.get_cur_line(), "Unexpected character within object or array");
1424 static const uint8 g_utf8_first_byte[7] =
1426 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC
1429 bool json_value::estimate_deserialized_string_size(json_deserialize_buf_ptr &pStr, json_error_info_t &error_info, uint &size)
1431 json_deserialize_buf_ptr pTmpStr(pStr);
1435 char c = pTmpStr.get_and_advance();
1436 if ((!c) || (c == '\n'))
1438 error_info.set_error(pStr.get_cur_line(), "Missing end quote in string");
1445 c = pTmpStr.get_and_advance();
1446 if ((!c) || (c == '\n'))
1448 error_info.set_error(pStr.get_cur_line(), "Missing escape character");
1451 len++; // in case the escape char is a backslash
1459 // Note: This method assumes estimate_deserialized_string_size() was called on the string first, so it skips some checks.
1460 bool json_value::deserialize_quoted_string_to_buf(char *&pBuf, uint buf_size, json_deserialize_buf_ptr &pStr, json_error_info_t &error_info)
1462 VOGL_NOTE_UNUSED(buf_size);
1467 char c = pStr.get_and_advance();
1472 c = pStr.get_and_advance();
1476 for (uint i = 0; i < 4; i++)
1479 int c = vogl_tolower(pStr.get_and_advance());
1480 if ((c >= 'a') && (c <= 'f'))
1482 else if ((c >= '0') && (c <= '9'))
1486 error_info.set_error(pStr.get_cur_line(), "Invalid Unicode escape");
1492 if ((u) && (u < 0x80))
1503 *--pDst = static_cast<char>((u | 0x80) & 0xBF);
1504 u >>= 6; // falls through
1506 *--pDst = static_cast<char>((u | 0x80) & 0xBF);
1507 u >>= 6; // falls through
1509 *--pDst = static_cast<char>(u | g_utf8_first_byte[len]);
1538 break; // unrecognized escape, so forcefully escape the backslash
1552 VOGL_ASSERT((pDst - pBuf) < (int)buf_size);
1559 bool json_value::deserialize_string(json_deserialize_buf_ptr &pStr, json_error_info_t &error_info)
1561 pStr.advance_in_line_no_end_check(1);
1564 if (!estimate_deserialized_string_size(pStr, error_info, estimated_len))
1567 uint buf_size = estimated_len + 1;
1568 char *pBuf = (char *)vogl_malloc(buf_size);
1571 error_info.set_error(pStr.get_cur_line(), "Out of memory");
1576 if (!deserialize_quoted_string_to_buf(pDst, buf_size, pStr, error_info))
1579 set_value_assume_ownership(pBuf);
1584 bool json_value::is_equal(const json_value &other, double tol) const
1589 if (get_type() != other.get_type())
1591 if (is_numeric() && other.is_numeric())
1592 return math::equal_tol(as_double(), other.as_double(), tol);
1598 case cJSONValueTypeNull:
1600 case cJSONValueTypeBool:
1601 case cJSONValueTypeInt:
1602 return m_data.m_nVal == other.m_data.m_nVal;
1603 case cJSONValueTypeDouble:
1604 return math::equal_tol(m_data.m_flVal, other.m_data.m_flVal, tol);
1605 case cJSONValueTypeString:
1606 return !strcmp(m_data.m_pStr, other.m_data.m_pStr);
1607 case cJSONValueTypeNode:
1609 const json_node *pNode = get_node_ptr();
1610 const json_node *pOther_node = other.get_node_ptr();
1611 if (pNode->is_object() != pOther_node->is_object())
1614 if (pNode->size() != pOther_node->size())
1617 for (uint i = 0; i < pNode->size(); i++)
1619 if ((pNode->is_object()) && (pNode->get_key(i).compare(pOther_node->get_key(i), true) != 0))
1621 if (!pNode->get_value(i).is_equal(pOther_node->get_value(i), tol))
1630 static const double g_pow10_table[63] =
1632 1.e-031, 1.e-030, 1.e-029, 1.e-028, 1.e-027, 1.e-026, 1.e-025, 1.e-024, 1.e-023, 1.e-022, 1.e-021, 1.e-020, 1.e-019, 1.e-018, 1.e-017, 1.e-016,
1633 1.e-015, 1.e-014, 1.e-013, 1.e-012, 1.e-011, 1.e-010, 1.e-009, 1.e-008, 1.e-007, 1.e-006, 1.e-005, 1.e-004, 1.e-003, 1.e-002, 1.e-001, 1.e+000,
1634 1.e+001, 1.e+002, 1.e+003, 1.e+004, 1.e+005, 1.e+006, 1.e+007, 1.e+008, 1.e+009, 1.e+010, 1.e+011, 1.e+012, 1.e+013, 1.e+014, 1.e+015, 1.e+016,
1635 1.e+017, 1.e+018, 1.e+019, 1.e+020, 1.e+021, 1.e+022, 1.e+023, 1.e+024, 1.e+025, 1.e+026, 1.e+027, 1.e+028, 1.e+029, 1.e+030, 1.e+031
1638 bool json_value::deserialize_number(json_deserialize_buf_ptr &pStr, json_error_info_t &error_info)
1640 uint64_t n = 0, limit = cINT64_MAX;
1642 bool bParseAsDouble = false;
1644 char c = pStr.get_char();
1649 pStr.advance_in_line_no_end_check(1);
1650 c = pStr.get_char();
1653 while ((c >= '0') && (c <= '9'))
1655 if (n > 0x1999999999999998ULL)
1657 bParseAsDouble = true;
1660 n = n * 10U + c - '0';
1661 pStr.advance_in_line_no_end_check(1);
1662 c = pStr.get_char();
1665 if ((bParseAsDouble) || (n > limit) || (c == 'e') || (c == 'E') || (c == '.'))
1667 double f = static_cast<double>(n);
1668 int scale = 0, escalesign = 1, escale = 0;
1670 while ((c >= '0') && (c <= '9'))
1672 f = f * 10.0f + (c - '0');
1673 pStr.advance_in_line_no_end_check(1);
1674 c = pStr.get_char();
1679 pStr.advance_in_line_no_end_check(1);
1680 c = pStr.get_char();
1681 while ((c >= '0') && (c <= '9'))
1684 f = f * 10.0f + (c - '0');
1685 pStr.advance_in_line_no_end_check(1);
1686 c = pStr.get_char();
1690 if ((c == 'e') || (c == 'E'))
1692 pStr.advance_in_line_no_end_check(1);
1693 char c = pStr.get_char();
1697 pStr.advance_in_line_no_end_check(1);
1698 c = pStr.get_char();
1702 pStr.advance_in_line_no_end_check(1);
1703 c = pStr.get_char();
1705 while ((c >= '0') && (c <= '9'))
1707 if (escale > 0xCCCCCCB)
1709 error_info.set_error(pStr.get_cur_line(), "Failed parsing numeric value");
1712 escale = escale * 10 + (c - '0');
1713 pStr.advance_in_line_no_end_check(1);
1714 c = pStr.get_char();
1718 double v = sign * f;
1719 int64_t final_scale = scale + escale * escalesign;
1720 if ((final_scale < -31) || (final_scale > 31))
1722 if ((final_scale < cINT32_MIN) || (final_scale > cINT32_MAX))
1724 error_info.set_error(pStr.get_cur_line(), "Failed parsing numeric value");
1727 v *= pow(10.0, static_cast<int>(final_scale));
1730 v *= g_pow10_table[static_cast<int>(final_scale) + 31];
1736 int64_t v = static_cast<int64_t>(n);
1745 bool json_value::deserialize_file(const char *pFilename, json_error_info_t *pError_info)
1749 FILE *pFile = vogl_fopen(pFilename, "rb");
1753 pError_info->set_error(0, "Unable to open file");
1757 bool success = deserialize(pFile, pError_info);
1759 if (vogl_fclose(pFile) == EOF)
1765 bool json_value::deserialize(const vogl::vector<char> &buf, json_error_info_t *pError_info)
1767 return deserialize(buf.get_ptr(), buf.size(), pError_info);
1770 bool json_value::deserialize(FILE *pFile, json_error_info_t *pError_info)
1772 vogl_fseek(pFile, 0, SEEK_END);
1773 const uint64_t filesize = vogl_ftell(pFile);
1774 vogl_fseek(pFile, 0, SEEK_SET);
1776 if ((filesize > VOGL_MAX_POSSIBLE_HEAP_BLOCK_SIZE) || (filesize != static_cast<size_t>(filesize)))
1779 pError_info->set_error(0, "File too large");
1783 char *pBuf = (char *)vogl_malloc(static_cast<size_t>(filesize) + 1);
1787 pError_info->set_error(0, "Out of memory");
1791 if (vogl_fread(pBuf, 1, static_cast<size_t>(filesize), pFile) != static_cast<size_t>(filesize))
1795 pError_info->set_error(0, "Failed reading from file");
1799 // Not really necesssary
1800 pBuf[filesize] = '\0';
1802 bool status = deserialize(pBuf, static_cast<size_t>(filesize), pError_info);
1809 bool json_value::deserialize(const char *pStr, json_error_info_t *pError_info)
1811 return deserialize(pStr, strlen(pStr), pError_info);
1814 bool json_value::deserialize(const dynamic_string &str, json_error_info_t *pError_info)
1816 return deserialize(str.get_ptr(), str.get_len(), pError_info);
1819 bool json_value::deserialize(const char *pBuf, size_t buf_size, json_error_info_t *pError_info)
1821 set_value_to_null();
1826 pError_info->set_error(0, "Nothing to deserialize");
1830 json_deserialize_buf_ptr buf_ptr(pBuf, buf_size);
1831 buf_ptr.skip_whitespace();
1832 if (*buf_ptr == '\0')
1835 pError_info->set_error(0, "Nothing to deserialize");
1839 json_error_info_t dummy_error_info;
1840 if (!deserialize(buf_ptr, NULL, 0, pError_info ? *pError_info : dummy_error_info))
1843 buf_ptr.skip_whitespace();
1844 if (!buf_ptr.at_end())
1847 pError_info->set_error(buf_ptr.get_cur_line(), "Syntax error on/near line");
1853 bool json_value::deserialize(json_deserialize_buf_ptr &pStr, json_node *pParent, uint level, json_error_info_t &error_info)
1855 m_line = pStr.get_cur_line();
1862 return deserialize_node(pStr, pParent, level, error_info);
1864 return deserialize_string(pStr, error_info);
1867 if (pStr.compare_string("null", 4))
1869 set_value_to_null();
1870 pStr.advance_in_line(4);
1877 if (pStr.compare_string("true", 4))
1880 pStr.advance_in_line(4);
1887 if (pStr.compare_string("false", 5))
1890 pStr.advance_in_line(5);
1897 if ((c == '-') || (c == '.') || ((c >= '0') && (c <= '9')))
1898 return deserialize_number(pStr, error_info);
1902 error_info.set_error(pStr.get_cur_line(), "Unrecognized character: '%c'", c);
1908 json_node::json_node()
1915 json_node::json_node(const json_node &other)
1923 json_node::json_node(const json_node *pParent, bool is_object)
1924 : m_pParent(pParent),
1926 m_is_object(is_object)
1930 json_node::~json_node()
1935 json_node &json_node::operator=(const json_node &rhs)
1942 set_is_object(rhs.is_object());
1943 m_pParent = rhs.m_pParent;
1946 m_keys.resize(rhs.size());
1947 m_values.resize(rhs.size());
1949 for (uint i = 0; i < rhs.size(); i++)
1952 m_keys[i] = rhs.m_keys[i];
1954 m_values[i] = rhs.m_values[i];
1955 if (m_values[i].is_node())
1956 m_values[i].get_node_ptr()->m_pParent = this;
1958 //VOGL_ASSERT(m_values[i].validate(this));
1961 m_line = rhs.m_line;
1966 const json_value &json_node::find_value(const char *pKey) const
1968 int index = find_key(pKey);
1969 return (index < 0) ? g_null_json_value : m_values[index];
1972 int json_node::find_key(const char *pKey) const
1974 for (uint i = 0; i < m_keys.size(); i++)
1975 if (m_keys[i] == pKey)
1977 return cInvalidIndex;
1980 int json_node::find_child(const json_node *pNode) const
1982 for (uint i = 0; i < m_values.size(); i++)
1983 if (m_values[i].get_node_ptr() == pNode)
1985 return cInvalidIndex;
1988 json_value_type_t json_node::find_value_type(const char *pKey) const
1990 int index = find_key(pKey);
1991 return (index >= 0) ? get_value_type(index) : cJSONValueTypeNull;
1994 const json_node *json_node::find_child(const char *pKey) const
1996 int index = find_key(pKey);
1997 return (index >= 0) ? get_child(index) : NULL;
2000 json_node *json_node::find_child(const char *pKey)
2002 int index = find_key(pKey);
2003 return (index >= 0) ? get_child(index) : NULL;
2006 const json_node *json_node::find_child_array(const char *pKey) const
2008 const json_node *pNode = find_child(pKey);
2009 return (pNode && pNode->is_array()) ? pNode : NULL;
2012 json_node *json_node::find_child_array(const char *pKey)
2014 json_node *pNode = find_child(pKey);
2015 return (pNode && pNode->is_array()) ? pNode : NULL;
2018 const json_node *json_node::find_child_object(const char *pKey) const
2020 const json_node *pNode = find_child(pKey);
2021 return (pNode && pNode->is_object()) ? pNode : NULL;
2024 bool json_node::are_all_children_values() const
2026 for (uint i = 0; i < m_values.size(); i++)
2027 if (m_values[i].is_object_or_array())
2032 bool json_node::are_all_children_objects() const
2034 for (uint i = 0; i < m_values.size(); i++)
2035 if (!m_values[i].is_object())
2040 bool json_node::are_all_children_arrays() const
2042 for (uint i = 0; i < m_values.size(); i++)
2043 if (!m_values[i].is_array())
2048 bool json_node::are_all_children_objects_or_arrays() const
2050 for (uint i = 0; i < m_values.size(); i++)
2051 if (!m_values[i].is_object_or_array())
2056 json_node *json_node::find_child_object(const char *pKey)
2058 json_node *pNode = find_child(pKey);
2059 return (pNode && pNode->is_object()) ? pNode : NULL;
2062 bool json_node::get_value_as_string(const char *pKey, dynamic_string &val, const char *pDef) const
2064 int index = find_key(pKey);
2070 return m_values[index].get_string(val, pDef);
2073 bool json_node::get_value_as_int64(const char *pKey, int64_t &val, int64_t def) const
2075 int index = find_key(pKey);
2081 return m_values[index].get_numeric(val, def);
2084 bool json_node::get_value_as_uint32(const char *pKey, uint32 &val, uint32 def) const
2086 int index = find_key(pKey);
2092 return m_values[index].get_numeric(val, def);
2095 bool json_node::get_value_as_uint64(const char *pKey, uint64_t &val, uint64_t def) const
2097 int index = find_key(pKey);
2103 return m_values[index].get_numeric(val, def);
2106 bool json_node::get_value_as_float(const char *pKey, float &val, float def) const
2108 int index = find_key(pKey);
2114 return m_values[index].get_numeric(val, def);
2117 bool json_node::get_value_as_double(const char *pKey, double &val, double def) const
2119 int index = find_key(pKey);
2125 return m_values[index].get_numeric(val, def);
2128 bool json_node::get_value_as_bool(const char *pKey, bool &val, bool def) const
2130 int index = find_key(pKey);
2136 return m_values[index].get_bool(val, def);
2139 dynamic_string json_node::value_as_string(const char *pKey, const char *pDef) const
2141 dynamic_string result;
2142 get_value_as_string(pKey, result, pDef);
2146 const char *json_node::value_as_string_ptr(const char *pKey, const char *pDef) const
2148 int index = find_key(pKey);
2151 return value_as_string_ptr(index, pDef);
2154 int json_node::value_as_int(const char *pKey, int def) const
2157 get_value_as_int(pKey, result, def);
2161 int32 json_node::value_as_int32(const char *pKey, int32 def) const
2164 get_value_as_int(pKey, result, def);
2168 uint32 json_node::value_as_uint32(const char *pKey, uint32 def) const
2171 get_value_as_uint32(pKey, result, def);
2175 uint64_t json_node::value_as_uint64(const char *pKey, uint64_t def) const
2178 get_value_as_uint64(pKey, result, def);
2182 int64_t json_node::value_as_int64(const char *pKey, int64_t def) const
2185 get_value_as_int(pKey, result, def);
2189 float json_node::value_as_float(const char *pKey, float def) const
2192 get_value_as_float(pKey, result, def);
2196 double json_node::value_as_double(const char *pKey, double def) const
2199 get_value_as_double(pKey, result, def);
2203 bool json_node::value_as_bool(const char *pKey, bool def) const
2206 get_value_as_bool(pKey, result, def);
2210 dynamic_string json_node::value_as_string(uint index, const char *pDef) const
2212 return m_values[index].as_string(pDef);
2215 const char *json_node::value_as_string_ptr(uint index, const char *pDef) const
2217 return m_values[index].as_string_ptr(pDef);
2220 int json_node::value_as_int(uint index, int def) const
2222 return m_values[index].as_int(def);
2225 int32 json_node::value_as_int32(uint index, int32 def) const
2227 return m_values[index].as_int32(def);
2230 int64_t json_node::value_as_int64(uint index, int64_t def) const
2232 return m_values[index].as_int64(def);
2235 uint64_t json_node::value_as_uint64(uint index, uint64_t def) const
2237 return m_values[index].as_uint64(def);
2240 uint32 json_node::value_as_uint32(uint index, uint32 def) const
2242 return m_values[index].as_uint32(def);
2245 float json_node::value_as_float(uint index, float def) const
2247 return m_values[index].as_float(def);
2250 double json_node::value_as_double(uint index, double def) const
2252 return m_values[index].as_double(def);
2255 bool json_node::value_as_bool(uint index, bool def) const
2257 return m_values[index].as_bool(def);
2260 void json_node::clear()
2264 m_is_object = false;
2268 void json_node::resize(uint new_size)
2271 m_keys.resize(new_size, true);
2272 m_values.resize(new_size, true);
2275 void json_node::reserve(uint new_capacity)
2278 m_keys.reserve(new_capacity);
2279 m_values.reserve(new_capacity);
2282 void json_node::set_is_object(bool is_object)
2284 if (m_is_object == is_object)
2287 m_keys.resize(size());
2290 m_is_object = is_object;
2293 void json_node::ensure_is_object()
2298 m_keys.resize(m_values.size());
2302 json_value &json_node::add_key_value(const char *pKey, const json_value &val)
2306 uint new_index = m_values.size();
2308 m_keys.push_back(pKey);
2310 m_values.push_back(val);
2312 m_values[new_index].get_node_ptr()->m_pParent = this;
2314 return m_values[new_index];
2317 json_value &json_node::add_value()
2321 return *m_values.enlarge(1);
2324 json_value &json_node::add_value(const json_value &val)
2326 uint new_index = m_values.size();
2331 m_values.push_back(val);
2333 m_values[new_index].get_node_ptr()->m_pParent = this;
2335 return m_values[new_index];
2338 bool json_node::add_key_and_parsed_value(const char *pKey, const char *pStr)
2341 if (!val.deserialize(pStr))
2346 m_keys.push_back(pKey);
2348 json_value *p = m_values.enlarge(1);
2349 val.release_ownership(*p);
2351 p->get_node_ptr()->m_pParent = this;
2356 bool json_node::add_parsed_value(const char *pStr)
2359 if (!val.deserialize(pStr))
2365 json_value *p = m_values.enlarge(1);
2366 val.release_ownership(*p);
2368 p->get_node_ptr()->m_pParent = this;
2373 dynamic_string &json_node::get_key(uint index)
2378 return g_empty_dynamic_string;
2380 return m_keys[index];
2383 void json_node::set_key_value(uint index, const char *pKey, const json_value &val)
2386 m_keys[index].set(pKey);
2388 m_values[index] = val;
2389 if (m_values[index].is_node())
2390 m_values[index].get_node_ptr()->m_pParent = this;
2393 void json_node::set_key(uint index, const char *pKey)
2396 m_keys[index].set(pKey);
2399 void json_node::set_value(uint index, const json_value &val)
2401 m_values[index] = val;
2402 if (m_values[index].is_node())
2403 m_values[index].get_node_ptr()->m_pParent = this;
2406 void json_node::set_value_assume_ownership(uint index, json_value &val)
2408 json_value &val_to_set = m_values[index];
2409 val_to_set.set_value_to_null();
2410 val_to_set.swap(val);
2412 if (val_to_set.is_node())
2413 val_to_set.get_node_ptr()->m_pParent = this;
2416 void json_node::add_value_assume_ownership(json_value &val)
2420 uint new_index = m_values.size();
2421 m_values.enlarge(1);
2422 set_value_assume_ownership(new_index, val);
2425 void json_node::add_key_value_assume_ownership(const char *pKey, json_value &val)
2428 m_keys.push_back(pKey);
2430 uint new_index = m_values.size();
2431 m_values.enlarge(1);
2432 set_value_assume_ownership(new_index, val);
2435 json_value &json_node::get_or_add(const char *pKey)
2437 int index = find_key(pKey);
2439 return m_values[index];
2442 m_keys.push_back(pKey);
2443 return *m_values.enlarge(1);
2446 json_value &json_node::add(const char *pKey)
2449 m_keys.push_back(pKey);
2450 return *m_values.enlarge(1);
2453 json_node &json_node::add_object(const char *pKey)
2456 m_keys.push_back(pKey);
2458 json_node *pNode = get_json_node_pool()->alloc(this, true);
2459 m_values.enlarge(1);
2460 m_values.back().set_value_assume_ownership(pNode);
2464 json_node &json_node::add_array(const char *pKey)
2467 m_keys.push_back(pKey);
2469 json_node *pNode = get_json_node_pool()->alloc(this, false);
2470 m_values.enlarge(1)->set_value_assume_ownership(pNode);
2474 json_node &json_node::add_object()
2478 json_node *pNode = get_json_node_pool()->alloc(this, true);
2479 m_values.enlarge(1)->set_value_assume_ownership(pNode);
2483 json_node &json_node::add_array()
2487 json_node *pNode = get_json_node_pool()->alloc(this, false);
2488 m_values.enlarge(1)->set_value_assume_ownership(pNode);
2492 bool json_node::erase(const char *pKey)
2494 int index = find_key(pKey);
2503 void json_node::erase(uint index)
2506 m_keys.erase(index);
2507 m_values.erase(index);
2510 bool json_node::basic_validation(const json_node *pParent) const
2512 if (m_pParent != pParent)
2520 else if (m_keys.size() != m_values.size())
2526 bool json_node::validate(const json_node *pParent) const
2528 if (!basic_validation(pParent))
2531 for (uint i = 0; i < m_values.size(); i++)
2532 if (!m_values[i].validate(this))
2538 dynamic_string json_node::get_path_to_node() const
2540 dynamic_string_array node_names;
2542 const json_node *pCur_node = this;
2546 const json_node *pParent = pCur_node->m_pParent;
2550 node_names.push_back("[root]");
2554 int parent_child_index = pParent->find_child(pCur_node);
2555 if (parent_child_index < 0)
2561 if (pParent->is_array())
2562 node_names.push_back(dynamic_string(cVarArg, "[%u]", parent_child_index));
2564 node_names.push_back(pParent->get_key(parent_child_index));
2566 pCur_node = pParent;
2569 dynamic_string result;
2570 for (int i = node_names.size() - 1; i >= 0; i--)
2572 result.append(node_names[i]);
2580 dynamic_string json_node::get_path_to_key(const char *pKey) const
2582 dynamic_string path(get_path_to_node());
2588 dynamic_string json_node::get_path_to_item(uint index) const
2590 dynamic_string path(get_path_to_node());
2592 path.append(dynamic_string(cVarArg, "/[%u]", index).get_ptr());
2594 path.append(dynamic_string(cVarArg, "/%s", m_keys[index].get_ptr()).get_ptr());
2598 bool json_node::check_for_duplicate_keys() const
2600 VOGL_VERIFY(validate(m_pParent));
2602 bool status = false;
2606 dynamic_string_array sorted_keys(m_keys);
2608 sorted_keys.sort(dynamic_string_less_than_case_sensitive());
2610 for (uint i = 0; i < sorted_keys.size(); i++)
2614 while (((i + 1) < sorted_keys.size()) && (sorted_keys[i].compare(sorted_keys[i + 1], true) == 0))
2620 VOGL_ASSERT(((i + 1) == sorted_keys.size()) || (sorted_keys[i].compare(sorted_keys[i + 1], true) < 0));
2626 console::debug("%s: Key appears %u times in node: %s\n", VOGL_METHOD_NAME, count, get_path_to_item(i).get_ptr());
2631 for (uint i = 0; i < m_values.size(); i++)
2633 const json_node *pChild = get_child(i);
2635 if ((pChild) && (pChild->check_for_duplicate_keys()))
2642 void json_node::serialize(vogl::vector<char> &buf, bool formatted, uint cur_indent, bool null_terminate, uint max_line_len) const
2644 json_growable_char_buf growable_buf(buf);
2645 if ((cur_indent) && (formatted))
2646 growable_buf.print_tabs(cur_indent);
2647 serialize(growable_buf, formatted, cur_indent, max_line_len);
2649 buf.push_back('\0');
2652 void json_node::serialize(dynamic_string &str, bool formatted, uint cur_index, uint max_line_len) const
2654 vogl::vector<char> buf;
2655 serialize(buf, formatted, cur_index, max_line_len);
2657 // FIXME: Pass along string ownership once dynamic_string supports non-pow2 sized buffers
2658 str.set_from_buf(buf.get_ptr(), vogl_strlen(buf.get_ptr()));
2661 void json_node::serialize(json_growable_char_buf &buf, bool formatted, uint cur_indent, uint max_line_len) const
2665 VOGL_ASSERT(m_keys.size() == m_values.size());
2669 VOGL_ASSERT(!m_keys.size());
2675 buf.puts(is_object() ? "{ }" : "[ ]");
2677 buf.puts(is_object() ? "{}" : "[]");
2681 const uint cMaxLineLen = max_line_len;
2684 if (formatted && !has_children() && !is_object() && (size() <= 40))
2686 uint orig_buf_size = buf.size();
2689 for (uint i = 0; i < size(); i++)
2692 get_value(i).get_string(val);
2693 if (get_value_type(i) == cJSONValueTypeString)
2694 buf.print_escaped(val.get_ptr());
2696 buf.puts(val.get_ptr());
2698 if (i != size() - 1)
2700 buf.print_char(',');
2701 buf.print_char(' ');
2704 if ((buf.size() - orig_buf_size) > cMaxLineLen)
2710 if ((buf.size() - orig_buf_size) <= cMaxLineLen)
2713 buf.get().resize(orig_buf_size);
2716 if (formatted && !has_children() && !is_object())
2718 uint line_start_ofs = buf.size();
2721 if (formatted && !cMaxLineLen)
2722 buf.print_char('\n');
2724 for (uint i = 0; i < size(); i++)
2727 get_value(i).get_string(val);
2729 if (formatted && !cMaxLineLen)
2730 buf.print_tabs(cur_indent);
2732 if (get_value_type(i) == cJSONValueTypeString)
2733 buf.print_escaped(val.get_ptr());
2735 buf.puts(val.get_ptr());
2737 if (i != size() - 1)
2739 buf.print_char(',');
2740 if (formatted && !cMaxLineLen)
2741 buf.print_char('\n');
2746 if ((buf.size() - line_start_ofs) >= cMaxLineLen)
2748 buf.print_char('\n');
2750 buf.print_tabs(cur_indent);
2752 line_start_ofs = buf.size();
2754 else if (i != size() - 1)
2755 buf.print_char(' ');
2765 buf.print_char(is_object() ? '{' : '[');
2767 buf.print_char('\n');
2773 for (uint i = 0; i < size(); i++)
2776 buf.print_tabs(cur_indent);
2779 buf.print_escaped(get_key(i).get_ptr());
2780 buf.puts(formatted ? " : " : ":");
2783 json_value_type_t val_type = get_value_type(i);
2784 if (val_type == cJSONValueTypeNode)
2785 get_child(i)->serialize(buf, formatted, cur_indent, max_line_len);
2786 else if (val_type == cJSONValueTypeString)
2787 buf.print_escaped(get_value(i).as_string_ptr());
2790 get_value(i).get_string(val);
2791 buf.puts(val.get_ptr());
2794 if (i != size() - 1)
2795 buf.print_char(',');
2797 buf.print_char('\n');
2803 buf.print_tabs(cur_indent);
2804 buf.print_char(is_object() ? '}' : ']');
2807 void json_node::binary_serialize(vogl::vector<uint8> &buf) const
2810 uint n = m_values.size();
2813 pDst = buf.enlarge(2);
2814 pDst[0] = m_is_object ? 'o' : 'a';
2815 pDst[1] = static_cast<uint8>(n);
2819 pDst = buf.enlarge(5);
2820 pDst[0] = m_is_object ? 'O' : 'A';
2821 pDst[1] = static_cast<uint8>(n >> 24);
2822 pDst[2] = static_cast<uint8>(n >> 16);
2823 pDst[3] = static_cast<uint8>(n >> 8);
2824 pDst[4] = static_cast<uint8>(n);
2829 const dynamic_string *pKey = m_keys.get_ptr();
2830 const json_value *pVal = m_values.get_ptr();
2831 for (uint i = n; i; --i, ++pKey, ++pVal)
2835 uint len = pKey->get_len();
2838 uint8 *pDst = buf.enlarge(2 + len);
2840 pDst[1] = static_cast<uint8>(len);
2841 memcpy(pDst + 2, pKey->get_ptr(), len);
2845 uint8 *pDst = buf.enlarge(5 + len);
2847 pDst[1] = static_cast<uint8>(len >> 24);
2848 pDst[2] = static_cast<uint8>(len >> 16);
2849 pDst[3] = static_cast<uint8>(len >> 8);
2850 pDst[4] = static_cast<uint8>(len);
2851 memcpy(pDst + 5, pKey->get_ptr(), len);
2855 if (pVal->is_node())
2856 pVal->get_node_ptr()->binary_serialize(buf);
2858 pVal->binary_serialize_value(buf);
2862 bool json_node::has_children() const
2864 for (uint i = 0; i < m_values.size(); i++)
2865 if (m_values[i].get_type() == cJSONValueTypeNode)
2870 bool json_node::get_value_as_enum(const char *pKey, const char **pStringList, int &val, int def) const
2873 int index = find_key(pKey);
2876 return get_value(index).get_enum(pStringList, val, def);
2879 // class json_document
2881 json_document::json_document()
2887 json_document::json_document(const json_value &other)
2890 get_value() = other;
2893 json_document &json_document::operator=(const json_value &rhs)
2895 if (&get_value() == &rhs)
2905 json_document::json_document(const json_document &other)
2906 : json_value(other),
2912 json_document &json_document::operator=(const json_document &rhs)
2919 m_error_msg = rhs.m_error_msg;
2920 m_error_line = rhs.m_error_line;
2921 m_filename = rhs.m_filename;
2923 get_value() = rhs.get_value();
2928 json_document::json_document(const char *pStr, const char *pFilename)
2931 deserialize(pStr, pFilename);
2934 json_document::json_document(const char *pBuf, uint n, const char *pFilename)
2937 deserialize(pBuf, n, pFilename);
2940 json_document::json_document(json_value_type_t value_type)
2946 json_document::~json_document()
2951 void json_document::swap(json_document &other)
2953 std::swap(m_error_line, other.m_error_line);
2954 m_error_msg.swap(other.m_error_msg);
2955 m_filename.swap(other.m_filename);
2956 get_value().swap(other.get_value());
2959 bool json_document::deserialize_file(const char *pFilename)
2961 set_filename(pFilename);
2963 json_error_info_t err_info;
2964 if (!json_value::deserialize_file(pFilename, &err_info))
2966 m_error_msg.swap(err_info.m_error_msg);
2967 m_error_line = err_info.m_error_line;
2975 bool json_document::deserialize(const vogl::vector<char> &buf, const char *pFilename)
2977 return deserialize(buf.get_ptr(), buf.size(), pFilename);
2980 bool json_document::deserialize(FILE *pFile, const char *pFilename)
2982 set_filename(pFilename);
2984 json_error_info_t err_info;
2985 if (!json_value::deserialize(pFile, &err_info))
2987 m_error_msg.swap(err_info.m_error_msg);
2988 m_error_line = err_info.m_error_line;
2996 bool json_document::deserialize(const char *pBuf, size_t n, const char *pFilename)
2998 set_filename(pFilename);
3000 json_error_info_t err_info;
3001 if (!json_value::deserialize(pBuf, n, &err_info))
3003 m_error_msg.swap(err_info.m_error_msg);
3004 m_error_line = err_info.m_error_line;
3012 bool json_document::deserialize(const char *pStr, const char *pFilename)
3014 return deserialize(pStr, static_cast<uint>(strlen(pStr)), pFilename);
3017 bool json_document::deserialize(const dynamic_string &str, const char *pFilename)
3019 return deserialize(str.get_ptr(), str.get_len(), pFilename);
3025 vogl::vector<dynamic_string> a1;
3026 vogl::map<dynamic_string, dynamic_string_array> a2;
3030 bool json_serialize(json_value &val) const
3032 json_node *pObj = val.init_object();
3033 pObj->add_object("a1", a1);
3034 pObj->add_object("a2", a2);
3035 pObj->add_object("a", a);
3036 pObj->add_object("b", b);
3040 bool json_deserialize(const json_value &val)
3042 const json_node *pObj = val.get_node_ptr();
3045 pObj->get_object("a1", a1);
3046 pObj->get_object("a2", a2);
3047 pObj->get_object("a", a);
3048 pObj->get_object("b", b);
3053 // TODO: Actually test these classes.
3056 // Create a JSON document
3058 json_node *pRoot = doc.get_root();
3060 typedef vogl::growable_array<uint, 16> my_growable_array_type;
3061 my_growable_array_type growable_array;
3062 growable_array.push_back(99);
3063 growable_array.push_back(100);
3064 pRoot->add_object("growable_array", growable_array);
3065 pRoot->get_object("growable_array", growable_array);
3067 pRoot->add_vector("growable_array2", growable_array);
3068 pRoot->get_vector("growable_array2", growable_array);
3070 // Create a vector of my_type's, put it into a JSON document, then retrieve it into another vector.
3071 typedef vogl::vector<my_type> my_type_vec;
3075 mv[0].a1.push_back("a");
3076 mv[0].a1.push_back("b");
3077 mv[0].a1.push_back("c");
3078 dynamic_string_array dsa;
3080 mv[0].a2.insert("zz", dsa);
3082 mv[0].a2.insert("xx", dsa);
3084 mv[0].a2.insert("yy", dsa);
3090 pRoot->add_vector("my_type_vec", mv);
3092 pRoot->add_object("hey", 2);
3094 pRoot->get_object("hey", z);
3096 pRoot->add_object("blah", mv);
3097 pRoot->get_object("blah", mv);
3100 pRoot->get_vector("my_type_vec", mv2);
3102 printf("my_type_vec:\n");
3103 for (uint i = 0; i < mv2.size(); i++)
3105 printf("a: %s\nb: %s\n", mv2[i].a.get_ptr(), mv2[i].b.get_ptr());
3108 // Create a string set and add it to the JSON document under the "set" object
3109 typedef vogl::map<dynamic_string> string_set;
3112 pRoot->add_map("set", ss);
3114 typedef vogl::vector<int16> cool_vec;
3119 pRoot->add_vector("vec", blah);
3122 pRoot->get_vector("vec", blah2);
3124 for (uint i = 0; i < blah2.size(); i++)
3125 printf("%i\n", blah2[i]);
3127 // Now create a string to string array map
3128 typedef vogl::map<dynamic_string, dynamic_string_array> string_map;
3131 dynamic_string_array sa;
3135 dynamic_string_array sb;
3141 // Add the string to string map to the JSON document under the "hashmap" object
3142 pRoot->add_map("hashmap", s);
3144 // Now serialize the JSON document to text and print it to stdout
3147 printf("JSON: %s\n", str.get_ptr());
3149 // Retrieve the string map under the "hashmap" object and put it into q
3151 pRoot->get_map("hashmap", q);
3154 printf("hashmap:\n");
3155 for (string_map::const_iterator it = q.begin(); it != q.end(); ++it)
3157 const dynamic_string_array &b = it->second;
3159 printf("%s :\n", it->first.get_ptr());
3160 for (uint i = 0; i < b.size(); i++)
3161 printf(" %s\n", b[i].get_ptr());