source: chevmsgr/trunk/json.cpp@ 4

Last change on this file since 4 was 4, checked in by cheese, 9 years ago

자 이제 시작이야 (졸작을)

File size: 24.6 KB
Line 
1#include "json.h"
2#include <stdlib.h>
3#include <string>
4#include <algorithm>
5#include <cstdlib>
6#include <cstdio>
7#include <climits>
8#include <string.h>
9#include <functional>
10#include <cctype>
11#include <stack>
12#include <cerrno>
13
14#ifndef WIN32
15#define _stricmp strcasecmp
16#endif
17
18#ifdef _MSC_VER
19#define snprintf sprintf_s
20#endif
21
22#define nullptr NULL
23
24using namespace json;
25
26namespace json
27{
28 enum StackDepthType
29 {
30 InObject,
31 InArray
32 };
33}
34
35////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
36// Helper functions
37////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
38static std::string Trim(const std::string& str)
39{
40 std::string s = str;
41
42 // remove white space in front
43 s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
44
45 // remove trailing white space
46 s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
47
48 return s;
49}
50
51// Finds the position of the first " character that is NOT preceeded immediately by a \ character.
52// In JSON, \" is valid and has a different meaning than the escaped " character.
53static size_t GetQuotePos(const std::string& str, size_t start_pos = 0)
54{
55 bool found_slash = false;
56 for (size_t i = start_pos; i < str.length(); i++)
57 {
58 char c = str[i];
59 if ((c == '\\') && !found_slash)
60 {
61 found_slash = true;
62 continue;
63 }
64 else if ((c == '\"') && !found_slash)
65 return i;
66
67 found_slash = false;
68 }
69
70 return std::string::npos;
71}
72
73////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
74////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
75Value::Value(const Value& v) : mValueType(v.mValueType)
76{
77 switch (mValueType)
78 {
79 case StringVal : mStringVal = v.mStringVal; break;
80 case IntVal : mIntVal = v.mIntVal; mFloatVal = (float)v.mIntVal; mDoubleVal = (double)v.mIntVal; break;
81 case FloatVal : mFloatVal = v.mFloatVal; mIntVal = (int)v.mFloatVal; mDoubleVal = (double)v.mDoubleVal; break;
82 case DoubleVal : mDoubleVal = v.mDoubleVal; mIntVal = (int)v.mDoubleVal; mFloatVal = (float)v.mDoubleVal; break;
83 case BoolVal : mBoolVal = v.mBoolVal; break;
84 case ObjectVal : mObjectVal = v.mObjectVal; break;
85 case ArrayVal : mArrayVal = v.mArrayVal; break;
86 default : break;
87 }
88}
89
90Value& Value::operator =(const Value& v)
91{
92 if (&v == this)
93 return *this;
94
95 mValueType = v.mValueType;
96
97 switch (mValueType)
98 {
99 case StringVal : mStringVal = v.mStringVal; break;
100 case IntVal : mIntVal = v.mIntVal; mFloatVal = (float)v.mIntVal; mDoubleVal = (double)v.mIntVal; break;
101 case FloatVal : mFloatVal = v.mFloatVal; mIntVal = (int)v.mFloatVal; mDoubleVal = (double)v.mDoubleVal; break;
102 case DoubleVal : mDoubleVal = v.mDoubleVal; mIntVal = (int)v.mDoubleVal; mFloatVal = (float)v.mDoubleVal; break;
103 case BoolVal : mBoolVal = v.mBoolVal; break;
104 case ObjectVal : mObjectVal = v.mObjectVal; break;
105 case ArrayVal : mArrayVal = v.mArrayVal; break;
106 default : break;
107 }
108
109 return *this;
110}
111
112Value& Value::operator [](size_t idx)
113{
114 if (mValueType != ArrayVal)
115 throw std::runtime_error("json mValueType==ArrayVal required");
116
117 return mArrayVal[idx];
118}
119
120const Value& Value::operator [](size_t idx) const
121{
122 if (mValueType != ArrayVal)
123 throw std::runtime_error("json mValueType==ArrayVal required");
124
125 return mArrayVal[idx];
126}
127
128Value& Value::operator [](const std::string& key)
129{
130 if (mValueType != ObjectVal)
131 throw std::runtime_error("json mValueType==ObjectVal required");
132
133 return mObjectVal[key];
134}
135
136Value& Value::operator [](const char* key)
137{
138 if (mValueType != ObjectVal)
139 throw std::runtime_error("json mValueType==ObjectVal required");
140
141 return mObjectVal[key];
142}
143
144const Value& Value::operator [](const char* key) const
145{
146 if (mValueType != ObjectVal)
147 throw std::runtime_error("json mValueType==ObjectVal required");
148
149 return mObjectVal[key];
150}
151
152const Value& Value::operator [](const std::string& key) const
153{
154 if (mValueType != ObjectVal)
155 throw std::runtime_error("json mValueType==ObjectVal required");
156
157 return mObjectVal[key];
158}
159
160void Value::Clear()
161{
162 mValueType = NULLVal;
163}
164
165size_t Value::size() const
166{
167 if ((mValueType != ObjectVal) && (mValueType != ArrayVal))
168 return 1;
169
170 return mValueType == ObjectVal ? mObjectVal.size() : mArrayVal.size();
171}
172
173bool Value::HasKey(const std::string &key) const
174{
175 if (mValueType != ObjectVal)
176 throw std::runtime_error("json mValueType==ObjectVal required");
177
178 return mObjectVal.HasKey(key);
179}
180
181int Value::HasKeys(const std::vector<std::string> &keys) const
182{
183 if (mValueType != ObjectVal)
184 throw std::runtime_error("json mValueType==ObjectVal required");
185
186 return mObjectVal.HasKeys(keys);
187}
188
189int Value::HasKeys(const char **keys, int key_count) const
190{
191 if (mValueType != ObjectVal)
192 throw std::runtime_error("json mValueType==ObjectVal required");
193
194 return mObjectVal.HasKeys(keys, key_count);
195}
196
197int Value::ToInt() const
198{
199 if (!IsNumeric())
200 throw std::runtime_error("json mValueType==IsNumeric() required");
201
202 return mIntVal;
203}
204
205float Value::ToFloat() const
206{
207 if (!IsNumeric())
208 throw std::runtime_error("json mValueType==IsNumeric() required");
209
210 return mFloatVal;
211}
212
213double Value::ToDouble() const
214{
215 if (!IsNumeric())
216 throw std::runtime_error("json mValueType==IsNumeric() required");
217
218 return mDoubleVal;
219}
220
221bool Value::ToBool() const
222{
223 if (mValueType != BoolVal)
224 throw std::runtime_error("json mValueType==BoolVal required");
225
226 return mBoolVal;
227}
228
229const std::string& Value::ToString() const
230{
231 if (mValueType != StringVal)
232 throw std::runtime_error("json mValueType==StringVal required");
233
234 return mStringVal;
235}
236
237Object Value::ToObject() const
238{
239 if (mValueType != ObjectVal)
240 throw std::runtime_error("json mValueType==ObjectVal required");
241
242 return mObjectVal;
243}
244
245Array Value::ToArray() const
246{
247 if (mValueType != ArrayVal)
248 throw std::runtime_error("json mValueType==ArrayVal required");
249
250 return mArrayVal;
251}
252
253Value::operator int() const
254{
255 if (!IsNumeric())
256 throw std::runtime_error("json mValueType==IsNumeric() required");
257
258 return mIntVal;
259}
260
261Value::operator float() const
262{
263 if (!IsNumeric())
264 throw std::runtime_error("json mValueType==IsNumeric() required");
265
266 return mFloatVal;
267}
268
269Value::operator double() const
270{
271 if (!IsNumeric())
272 throw std::runtime_error("json mValueType==IsNumeric() required");
273
274 return mDoubleVal;
275}
276
277Value::operator bool() const
278{
279 if (mValueType != BoolVal)
280 throw std::runtime_error("json mValueType==BoolVal required");
281
282 return mBoolVal;
283}
284
285Value::operator std::string() const
286{
287 if (mValueType != StringVal)
288 throw std::runtime_error("json mValueType==StringVal required");
289
290 return mStringVal;
291}
292
293Value::operator Object() const
294{
295 if (mValueType != ObjectVal)
296 throw std::runtime_error("json mValueType==ObjectVal required");
297
298 return mObjectVal;
299}
300
301Value::operator Array() const
302{
303 if (mValueType != ArrayVal)
304 throw std::runtime_error("json mValueType==ArrayVal required");
305
306 return mArrayVal;
307}
308
309////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
310////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
311Array::Array()
312{
313}
314
315Array::Array(const Array& a) : mValues(a.mValues)
316{
317}
318
319Array& Array::operator =(const Array& a)
320{
321 if (&a == this)
322 return *this;
323
324 Clear();
325 mValues = a.mValues;
326
327 return *this;
328}
329
330Value& Array::operator [](size_t i)
331{
332 return mValues[i];
333}
334
335const Value& Array::operator [](size_t i) const
336{
337 return mValues[i];
338}
339
340
341Array::ValueVector::const_iterator Array::begin() const
342{
343 return mValues.begin();
344}
345
346Array::ValueVector::const_iterator Array::end() const
347{
348 return mValues.end();
349}
350
351Array::ValueVector::iterator Array::begin()
352{
353 return mValues.begin();
354}
355
356Array::ValueVector::iterator Array::end()
357{
358 return mValues.end();
359}
360
361void Array::push_back(const Value& v)
362{
363 mValues.push_back(v);
364}
365
366void Array::insert(size_t index, const Value& v)
367{
368 mValues.insert(mValues.begin() + index, v);
369}
370
371size_t Array::size() const
372{
373 return mValues.size();
374}
375
376void Array::Clear()
377{
378 mValues.clear();
379}
380
381Array::ValueVector::iterator Array::find(const Value& v)
382{
383 return std::find(mValues.begin(), mValues.end(), v);
384}
385
386Array::ValueVector::const_iterator Array::find(const Value& v) const
387{
388 return std::find(mValues.begin(), mValues.end(), v);
389}
390
391bool Array::HasValue(const Value& v) const
392{
393 return find(v) != end();
394}
395
396////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
397////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
398Object::Object()
399{
400}
401
402Object::Object(const Object& obj) : mValues(obj.mValues)
403{
404
405}
406
407Object& Object::operator =(const Object& obj)
408{
409 if (&obj == this)
410 return *this;
411
412 Clear();
413 mValues = obj.mValues;
414
415 return *this;
416}
417
418Value& Object::operator [](const std::string& key)
419{
420 return mValues[key];
421}
422
423const Value& Object::operator [](const std::string& key) const
424{
425 ValueMap::const_iterator it = mValues.find(key);
426 return it->second;
427}
428
429Value& Object::operator [](const char* key)
430{
431 return mValues[key];
432}
433
434const Value& Object::operator [](const char* key) const
435{
436 ValueMap::const_iterator it = mValues.find(key);
437 return it->second;
438}
439
440Object::ValueMap::const_iterator Object::begin() const
441{
442 return mValues.begin();
443}
444
445Object::ValueMap::const_iterator Object::end() const
446{
447 return mValues.end();
448}
449
450Object::ValueMap::iterator Object::begin()
451{
452 return mValues.begin();
453}
454
455Object::ValueMap::iterator Object::end()
456{
457 return mValues.end();
458}
459
460Object::ValueMap::iterator Object::find(const std::string& key)
461{
462 return mValues.find(key);
463}
464
465Object::ValueMap::const_iterator Object::find(const std::string& key) const
466{
467 return mValues.find(key);
468}
469
470bool Object::HasKey(const std::string& key) const
471{
472 return find(key) != end();
473}
474
475int Object::HasKeys(const std::vector<std::string>& keys) const
476{
477 for (size_t i = 0; i < keys.size(); i++)
478 {
479 if (!HasKey(keys[i]))
480 return (int)i;
481 }
482
483 return -1;
484}
485
486int Object::HasKeys(const char** keys, int key_count) const
487{
488 for (int i = 0; i < key_count; i++)
489 if (!HasKey(keys[i]))
490 return i;
491
492 return -1;
493}
494
495void Object::Clear()
496{
497 mValues.clear();
498}
499
500
501////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
502////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
503std::string SerializeArray(const Array& a);
504
505std::string SerializeValue(const Value& v)
506{
507 std::string str;
508
509 static const int BUFF_SZ = 500;
510 char buff[BUFF_SZ];
511 switch (v.GetType())
512 {
513 case IntVal : snprintf(buff, BUFF_SZ, "%d", (int)v); str = buff; break;
514 case FloatVal : snprintf(buff, BUFF_SZ, "%f", (float)v); str = buff; break;
515 case DoubleVal : snprintf(buff, BUFF_SZ, "%f", (double)v); str = buff; break;
516 case BoolVal : str = v ? "true" : "false"; break;
517 case NULLVal : str = "null"; break;
518 case ObjectVal : str = Serialize(v); break;
519 case ArrayVal : str = SerializeArray(v); break;
520 case StringVal : str = std::string("\"") + (std::string)v + std::string("\""); break;
521 }
522
523 return str;
524}
525
526std::string SerializeArray(const Array& a)
527{
528 std::string str = "[";
529
530 bool first = true;
531 for (size_t i = 0; i < a.size(); i++)
532 {
533 const Value& v = a[i];
534 if (!first)
535 str += std::string(",");
536
537 str += SerializeValue(v);
538
539 first = false;
540 }
541
542 str += "]";
543 return str;
544}
545
546std::string json::Serialize(const Value& v)
547{
548 std::string str;
549
550 bool first = true;
551
552 if (v.GetType() == ObjectVal)
553 {
554 str = "{";
555 Object obj = v.ToObject();
556 for (Object::ValueMap::const_iterator it = obj.begin(); it != obj.end(); ++it)
557 {
558 if (!first)
559 str += std::string(",");
560
561 str += std::string("\"") + it->first + std::string("\":") + SerializeValue(it->second);
562 first = false;
563 }
564
565 str += "}";
566 }
567 else if (v.GetType() == ArrayVal)
568 {
569 str = "[";
570 Array a = v.ToArray();
571 for (Array::ValueVector::const_iterator it = a.begin(); it != a.end(); ++it)
572 {
573 if (!first)
574 str += std::string(",");
575
576 str += SerializeValue(*it);
577 first = false;
578 }
579
580 str += "]";
581
582 }
583 // else it's not valid JSON, as a JSON data structure must be an array or an object. We'll return an empty string.
584
585
586 return str;
587}
588
589////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
590////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
591static Value DeserializeArray(std::string& str, std::stack<StackDepthType>& depth_stack);
592static Value DeserializeObj(const std::string& _str, std::stack<StackDepthType>& depth_stack);
593
594static Value DeserializeInternal(const std::string& _str, std::stack<StackDepthType>& depth_stack)
595{
596 Value v;
597
598 std::string str = Trim(_str);
599 if (str[0] == '{')
600 {
601 // Error: Began with a { but doesn't end with one
602 if (str[str.length() - 1] != '}')
603 return Value();
604
605 depth_stack.push(InObject);
606 v = DeserializeObj(str, depth_stack);
607 if ((v.GetType() == NULLVal) || (depth_stack.top() != InObject))
608 return v;
609
610 depth_stack.pop();
611 }
612 else if (str[0] == '[')
613 {
614 // Error: Began with a [ but doesn't end with one
615 if (str[str.length() - 1] != ']')
616 return Value();
617
618 depth_stack.push(InArray);
619 v = DeserializeArray(str, depth_stack);
620 if ((v.GetType() == NULLVal) || (depth_stack.top() != InArray))
621 return v;
622
623 depth_stack.pop();
624 }
625 else
626 {
627 // Will never get here unless _str is not valid JSON
628 return Value();
629 }
630
631 return v;
632}
633
634static size_t GetEndOfArrayOrObj(const std::string& str, std::stack<StackDepthType>& depth_stack)
635{
636 size_t i = 1;
637 bool in_quote = false;
638 size_t original_count = depth_stack.size();
639
640 for (; i < str.length(); i++)
641 {
642 if (str[i] == '\"')
643 {
644 if (str[i - 1] != '\\')
645 in_quote = !in_quote;
646 }
647 else if (!in_quote)
648 {
649 if (str[i] == '[')
650 depth_stack.push(InArray);
651 else if (str[i] == '{')
652 depth_stack.push(InObject);
653 else if (str[i] == ']')
654 {
655 StackDepthType t = depth_stack.top();
656 if (t != InArray)
657 {
658 // expected to be closing an array but instead we're inside an object block.
659 // Example problem: {]}
660 return std::string::npos;
661 }
662
663 size_t count = depth_stack.size();
664 depth_stack.pop();
665 if (count == original_count)
666 break;
667 }
668 else if (str[i] == '}')
669 {
670 StackDepthType t = depth_stack.top();
671 if (t != InObject)
672 {
673 // expected to be closing an object but instead we're inside an array.
674 // Example problem: [}]
675 return std::string::npos;
676 }
677
678 size_t count = depth_stack.size();
679 depth_stack.pop();
680 if (count == original_count)
681 break;
682 }
683 }
684 }
685
686 return i;
687}
688
689static std::string UnescapeJSONString(const std::string& str)
690{
691 std::string s = "";
692
693 for (std::string::size_type i = 0; i < str.length(); i++)
694 {
695 char c = str[i];
696 if ((c == '\\') && (i + 1 < str.length()))
697 {
698 int skip_ahead = 1;
699 unsigned int hex;
700 std::string hex_str;
701
702 switch (str[i+1])
703 {
704 case '"' : s.push_back('\"'); break;
705 case '\\': s.push_back('\\'); break;
706 case '/' : s.push_back('/'); break;
707 case 't' : s.push_back('\t'); break;
708 case 'n' : s.push_back('\n'); break;
709 case 'r' : s.push_back('\r'); break;
710 case 'b' : s.push_back('\b'); break;
711 case 'f' : s.push_back('\f'); break;
712 case 'u' : skip_ahead = 5;
713 hex_str = str.substr(i + 4, 2);
714 hex = (unsigned int)std::strtoul(hex_str.c_str(), nullptr, 16);
715 s.push_back((char)hex);
716 break;
717
718 default: break;
719 }
720
721 i += skip_ahead;
722 }
723 else
724 s.push_back(c);
725 }
726
727 return Trim(s);
728}
729
730static Value DeserializeValue(std::string& str, bool* had_error, std::stack<StackDepthType>& depth_stack)
731{
732 Value v;
733
734 *had_error = false;
735 str = Trim(str);
736
737 if (str.length() == 0)
738 return v;
739
740 if (str[0] == '[')
741 {
742 // This value is an array, determine the end of it and then deserialize the array
743 depth_stack.push(InArray);
744 size_t i = GetEndOfArrayOrObj(str, depth_stack);
745 if (i == std::string::npos)
746 {
747 *had_error = true;
748 return Value();
749 }
750
751 std::string array_str = str.substr(0, i + 1);
752 v = Value(DeserializeArray(array_str, depth_stack));
753 str = str.substr(i + 1, str.length());
754 }
755 else if (str[0] == '{')
756 {
757 // This value is an object, determine the end of it and then deserialize the object
758 depth_stack.push(InObject);
759 size_t i = GetEndOfArrayOrObj(str, depth_stack);
760
761 if (i == std::string::npos)
762 {
763 *had_error = true;
764 return Value();
765 }
766
767 std::string obj_str = str.substr(0, i + 1);
768 v = Value(DeserializeInternal(obj_str, depth_stack));
769 str = str.substr(i + 1, str.length());
770 }
771 else if (str[0] == '\"')
772 {
773 // This value is a string
774 size_t end_quote = GetQuotePos(str, 1);
775 if (end_quote == std::string::npos)
776 {
777 *had_error = true;
778 return Value();
779 }
780
781 v = Value(UnescapeJSONString(str.substr(1, end_quote - 1)));
782 str = str.substr(end_quote + 1, str.length());
783 }
784 else
785 {
786 // it's not an object, string, or array so it's either a boolean or a number or null.
787 // Numbers can contain an exponent indicator ('e') or a decimal point.
788 bool has_dot = false;
789 bool has_e = false;
790 std::string temp_val;
791 size_t i = 0;
792 bool found_digit = false;
793 bool found_first_valid_char = false;
794
795 for (; i < str.length(); i++)
796 {
797 if (str[i] == '.')
798 {
799 if (!found_digit)
800 {
801 // As per JSON standards, there must be a digit preceding a decimal point
802 *had_error = true;
803 return Value();
804 }
805
806 has_dot = true;
807 }
808 else if ((str[i] == 'e') || (str[i] == 'E'))
809 {
810 if ((_stricmp(temp_val.c_str(), "fals") != 0) && (_stricmp(temp_val.c_str(), "tru") != 0))
811 {
812 // it's not a boolean, check for scientific notation validity. This will also trap booleans with extra 'e' characters like falsee/truee
813 if (!found_digit)
814 {
815 // As per JSON standards, a digit must precede the 'e' notation
816 *had_error = true;
817 return Value();
818 }
819 else if (has_e)
820 {
821 // multiple 'e' characters not allowed
822 *had_error = true;
823 return Value();
824 }
825
826 has_e = true;
827 }
828 }
829 else if (str[i] == ']')
830 {
831 if (depth_stack.empty() || (depth_stack.top() != InArray))
832 {
833 *had_error = true;
834 return Value();
835 }
836
837 depth_stack.pop();
838 }
839 else if (str[i] == '}')
840 {
841 if (depth_stack.empty() || (depth_stack.top() != InObject))
842 {
843 *had_error = true;
844 return Value();
845 }
846
847 depth_stack.pop();
848 }
849 else if (str[i] == ',')
850 break;
851 else if ((str[i] == '[') || (str[i] == '{'))
852 {
853 // error, we're supposed to be processing things besides arrays/objects in here
854 *had_error = true;
855 return Value();
856 }
857
858 if (!std::isspace(str[i]))
859 {
860 if (std::isdigit(str[i]))
861 found_digit = true;
862
863 found_first_valid_char = true;
864 temp_val += str[i];
865 }
866 }
867
868 // store all floating point as doubles. This will also set the float and int values as well.
869 if (_stricmp(temp_val.c_str(), "true") == 0)
870 v = Value(true);
871 else if (_stricmp(temp_val.c_str(), "false") == 0)
872 v = Value(false);
873 else if (has_e || has_dot)
874 {
875 char* end_char;
876 errno = 0;
877 double d = strtod(temp_val.c_str(), &end_char);
878 if ((errno != 0) || (*end_char != '\0'))
879 {
880 // invalid conversion or out of range
881 *had_error = true;
882 return Value();
883 }
884
885 v = Value(d);
886 }
887 else if (_stricmp(temp_val.c_str(), "null") == 0)
888 v = Value();
889 else
890 {
891 // Check if the value is beyond the size of an int and if so, store it as a double
892 char* end_char;
893 errno = 0;
894 long int ival = strtol(temp_val.c_str(), &end_char, 10);
895 if (*end_char != '\0')
896 {
897 // invalid character sequence, not a number
898 *had_error = true;
899 return Value();
900 }
901 else if ((errno == ERANGE) && ((ival == LONG_MAX) || (ival == LONG_MIN)))
902 {
903 // value is out of range for a long int, should be a double then. See if we can convert it correctly.
904 errno = 0;
905 double dval = strtod(temp_val.c_str(), &end_char);
906 if ((errno != 0) || (*end_char != '\0'))
907 {
908 // error in conversion or it's too big for a double
909 *had_error = true;
910 return Value();
911 }
912
913 v = Value(dval);
914 }
915 else if ((ival >= INT_MIN) && (ival <= INT_MAX))
916 {
917 // valid integer range
918 v = Value((int)ival);
919 }
920 else
921 {
922 // probably running on a very old OS since this block implies that long isn't the same size as int.
923 // int is guaranteed to be at least 16 bits and long 32 bits...however nowadays they're almost
924 // always the same 32 bit size. But it's possible someone is running this on a very old architecture
925 // so for correctness, we'll error out here
926 *had_error = true;
927 return Value();
928 }
929 }
930
931 str = str.substr(i, str.length());
932 }
933
934 return v;
935}
936
937static Value DeserializeArray(std::string& str, std::stack<StackDepthType>& depth_stack)
938{
939 Array a;
940 bool had_error = false;
941
942 str = Trim(str);
943
944 // Arrays begin and end with [], so if we don't find one, it's an error
945 if ((str[0] == '[') && (str[str.length() - 1] == ']'))
946 str = str.substr(1, str.length() - 2);
947 else
948 return Value();
949
950 // extract out all values from the array (remember, a value can also be an array or an object)
951 while (str.length() > 0)
952 {
953 std::string tmp;
954
955 size_t i = 0;
956 for (; i < str.length(); i++)
957 {
958 // If we get to an object or array, parse it:
959 if ((str[i] == '{') || (str[i] == '['))
960 {
961 Value v = DeserializeValue(str, &had_error, depth_stack);
962 if (had_error)
963 return Value();
964
965 if (v.GetType() != NULLVal)
966 a.push_back(v);
967
968 break;
969 }
970
971 bool terminate_parsing = false;
972
973 if ((str[i] == ',') || (str[i] == ']'))
974 terminate_parsing = true; // hit the end of a value, parse it in the next block
975 else
976 {
977 // keep grabbing chars to build up the value
978 tmp += str[i];
979 if (i == str.length() - 1)
980 terminate_parsing = true; // end of string, finish parsing
981 }
982
983 if (terminate_parsing)
984 {
985 Value v = DeserializeValue(tmp, &had_error, depth_stack);
986 if (had_error)
987 return Value();
988
989 if (v.GetType() != NULLVal)
990 a.push_back(v);
991
992 str = str.substr(i + 1, str.length());
993 break;
994 }
995 }
996 }
997
998 return a;
999}
1000
1001static Value DeserializeObj(const std::string& _str, std::stack<StackDepthType>& depth_stack)
1002{
1003 Object obj;
1004
1005 std::string str = Trim(_str);
1006
1007 // Objects begin and end with {} so if we don't find a pair, it's an error
1008 if ((str[0] != '{') && (str[str.length() - 1] != '}'))
1009 return Value();
1010 else
1011 str = str.substr(1, str.length() - 2);
1012
1013 // Get all key/value pairs in this object...
1014 while (str.length() > 0)
1015 {
1016 // Get the key name
1017 size_t start_quote_idx = GetQuotePos(str);
1018 size_t end_quote_idx = GetQuotePos(str, start_quote_idx + 1);
1019 size_t colon_idx = str.find(':', end_quote_idx);
1020
1021 if ((start_quote_idx == std::string::npos) || (end_quote_idx == std::string::npos) || (colon_idx == std::string::npos))
1022 return Value(); // can't find key name
1023
1024 std::string key = str.substr(start_quote_idx + 1, end_quote_idx - start_quote_idx - 1);
1025 if (key.length() == 0)
1026 return Value();
1027
1028 bool had_error = false;
1029 str = str.substr(colon_idx + 1, str.length());
1030
1031 // We have the key, now extract the value from the string
1032 obj[key] = DeserializeValue(str, &had_error, depth_stack);
1033 if (had_error)
1034 return Value();
1035 }
1036
1037 return obj;
1038}
1039
1040Value json::Deserialize(const std::string &str)
1041{
1042 std::stack<StackDepthType> depth_stack;
1043 return DeserializeInternal(str, depth_stack);
1044}
1045
Note: See TracBrowser for help on using the repository browser.