OpenCPN Partial API docs
Loading...
Searching...
No Matches
jsonreader.cpp
Go to the documentation of this file.
1
2// Name: jsonreader.cpp
3// Purpose: the wxJSONReader class: a JSON text parser
4// Author: Luciano Cattani
5// Created: 2007/10/14
6// RCS-ID: $Id: jsonreader.cpp,v 1.12 2008/03/12 10:48:19 luccat Exp $
7// Copyright: (c) 2007 Luciano Cattani
8// Licence: wxWidgets licence
10
14#ifdef NDEBUG
15// make wxLogTrace a noop if no debug set, it's really slow
16// must be defined before including debug.h
17#define wxDEBUG_LEVEL 0
18#endif
19
20#include <wx/jsonreader.h>
21
22#include <wx/mstream.h>
23#include <wx/sstream.h>
24#include <wx/debug.h>
25#include <wx/log.h>
26
172// if you have the debug build of wxWidgets and wxJSON you can see
173// trace messages by setting the:
174// WXTRACE=traceReader StoreComment
175// environment variable
176#if wxDEBUG_LEVEL > 0
177static const wxChar* traceMask = _T("traceReader");
178static const wxChar* storeTraceMask = _T("StoreComment");
179#endif
180
182
240wxJSONReader::wxJSONReader(int flags, int maxErrors) {
241 m_flags = flags;
242 m_maxErrors = maxErrors;
243 m_noUtf8 = false;
244#if !defined(wxJSON_USE_UNICODE)
245 // in ANSI builds we can suppress UTF-8 conversion for both the writer and the
246 // reader
247 if (m_flags & wxJSONREADER_NOUTF8_STREAM) {
248 m_noUtf8 = true;
249 }
250#endif
251}
252
255
257
302int wxJSONReader::Parse(const wxString& doc, wxJSONValue* val) {
303#if !defined(wxJSON_USE_UNICODE)
304 // in ANSI builds input from a string never use UTF-8 conversion
305 bool noUtf8_bak = m_noUtf8; // save the current setting
306 m_noUtf8 = true;
307#endif
308
309 // convert the string to a UTF-8 / ANSI memory stream and calls overloaded
310 // Parse()
311 char* readBuff = nullptr;
312 wxCharBuffer utf8CB = doc.ToUTF8(); // the UTF-8 buffer
313#if !defined(wxJSON_USE_UNICODE)
314 wxCharBuffer ansiCB(doc.c_str()); // the ANSI buffer
315 if (m_noUtf8) {
316 readBuff = ansiCB.data();
317 } else {
318 readBuff = utf8CB.data();
319 }
320#else
321 readBuff = utf8CB.data();
322#endif
323
324 // now construct the temporary memory input stream
325 size_t len = strlen(readBuff);
326 wxMemoryInputStream is(readBuff, len);
327
328 int numErr = Parse(is, val);
329#if !defined(wxJSON_USE_UNICODE)
330 m_noUtf8 = noUtf8_bak;
331#endif
332 return numErr;
333}
334
336int wxJSONReader::Parse(wxInputStream& is, wxJSONValue* val) {
337 // if val == 0 the 'temp' JSON value will be passed to DoRead()
338 wxJSONValue temp;
339 m_level = 0;
340 m_depth = 0;
341 m_lineNo = 1;
342 m_colNo = 1;
343 m_peekChar = -1;
344 m_errors.clear();
345 m_warnings.clear();
346
347 // if a wxJSONValue is not passed to the Parse function
348 // we set the temparary object created on the stack
349 // I know this will slow down the validation of input
350 if (val == nullptr) {
351 val = &temp;
352 }
353 wxASSERT(val);
354
355 // set the wxJSONValue object's pointers for comment storage
356 m_next = val;
357 m_next->SetLineNo(-1);
358 m_lastStored = 0;
359 m_current = 0;
360
361 int ch = GetStart(is);
362 switch (ch) {
363 case '{':
364 val->SetType(wxJSONTYPE_OBJECT);
365 break;
366 case '[':
367 val->SetType(wxJSONTYPE_ARRAY);
368 break;
369 default:
370 AddError(_T("Cannot find a start object/array character" ));
371 return m_errors.size();
372 break;
373 }
374
375 // returning from DoRead() could be for EOF or for
376 // the closing array-object character
377 // if -1 is returned, it is as an error because the lack
378 // of close-object/array characters
379 // note that the missing close-chars error messages are
380 // added by the DoRead() function
381 ch = DoRead(is, *val);
382 return m_errors.size();
383}
384
386
397int wxJSONReader::GetStart(wxInputStream& is) {
398 int ch = 0;
399 do {
400 switch (ch) {
401 case 0:
402 ch = ReadChar(is);
403 break;
404 case '{':
405 return ch;
406 break;
407 case '[':
408 return ch;
409 break;
410 case '/':
411 ch = SkipComment(is);
412 StoreComment(0);
413 break;
414 default:
415 ch = ReadChar(is);
416 break;
417 }
418 } while (ch >= 0);
419 return ch;
420}
421
423const wxArrayString& wxJSONReader::GetErrors() const { return m_errors; }
424
426const wxArrayString& wxJSONReader::GetWarnings() const { return m_warnings; }
427
429
434int wxJSONReader::GetDepth() const { return m_depth; }
435
437int wxJSONReader::GetErrorCount() const { return m_errors.size(); }
438
440int wxJSONReader::GetWarningCount() const { return m_warnings.size(); }
441
443
458int wxJSONReader::ReadChar(wxInputStream& is) {
459 if (is.Eof()) {
460 return -1;
461 }
462
463 unsigned char ch = is.GetC();
464 size_t last = is.LastRead(); // returns ZERO if EOF
465 if (last == 0) {
466 return -1;
467 }
468
469 // the function also converts CR in LF. only LF is returned
470 // in the case of CR+LF
471 int nextChar;
472
473 if (ch == '\r') {
474 m_colNo = 1;
475 nextChar = PeekChar(is);
476 if (nextChar == -1) {
477 return -1;
478 } else if (nextChar == '\n') {
479 ch = is.GetC();
480 }
481 }
482 if (ch == '\n') {
483 ++m_lineNo;
484 m_colNo = 1;
485 } else {
486 ++m_colNo;
487 }
488 return (int)ch;
489}
490
492
500int wxJSONReader::PeekChar(wxInputStream& is) {
501 int ch = -1;
502 unsigned char c;
503 if (!is.Eof()) {
504 c = is.Peek();
505 ch = c;
506 }
507 return ch;
508}
509
511
534int wxJSONReader::DoRead(wxInputStream& is, wxJSONValue& parent) {
535 ++m_level;
536 if (m_depth < m_level) {
538 }
539
540 // 'value' is the wxJSONValue structure that has to be
541 // read. Data read from the JSON text input is stored
542 // in the following object.
543 wxJSONValue value(wxJSONTYPE_INVALID);
544
545 // sets the pointers to the current, next and last-stored objects
546 // in order to determine the value to which a comment refers to
547 m_next = &value;
548 m_current = &parent;
550 m_lastStored = 0;
551
552 // the 'key' string is stored from 'value' when a ':' is encontered
553 wxString key;
554
555 // the character read: -1=EOF, 0=to be read
556 int ch = 0;
557
558 do { // we read until ch < 0
559 switch (ch) {
560 case 0:
561 ch = ReadChar(is);
562 break;
563 case ' ':
564 case '\t':
565 case '\n':
566 case '\r':
567 ch = SkipWhiteSpace(is);
568 break;
569 case -1: // the EOF
570 break;
571 case '/':
572 ch = SkipComment(is);
573 StoreComment(&parent);
574 break;
575
576 case '{':
577 if (parent.IsObject()) {
578 if (key.empty()) {
579 AddError(_T("\'{\' is not allowed here (\'name\' is missing"));
580 }
581 if (value.IsValid()) {
582 AddError(_T("\'{\' cannot follow a \'value\'"));
583 }
584 } else if (parent.IsArray()) {
585 if (value.IsValid()) {
586 AddError(_T("\'{\' cannot follow a \'value\' in JSON array"));
587 }
588 } else {
589 wxJSON_ASSERT(0); // always fails
590 }
591
592 // the openobject char cause the DoRead() to be called recursively
593 value.SetType(wxJSONTYPE_OBJECT);
594 ch = DoRead(is, value);
595 break;
596
597 case '}':
598 if (!parent.IsObject()) {
600 wxJSONREADER_MISSING,
601 _T("Trying to close an array using the \'}\' (close-object) char" ));
602 }
603 // close-object: store the current value, if any
604 StoreValue(ch, key, value, parent);
605 m_current = &parent;
606 m_next = nullptr;
608 ch = ReadChar(is);
609 return ch;
610 break;
611
612 case '[':
613 if (parent.IsObject()) {
614 if (key.empty()) {
615 AddError(_T("\'[\' is not allowed here (\'name\' is missing"));
616 }
617 if (value.IsValid()) {
618 AddError(_T("\'[\' cannot follow a \'value\' text"));
619 }
620 } else if (parent.IsArray()) {
621 if (value.IsValid()) {
622 AddError(_T("\'[\' cannot follow a \'value\'"));
623 }
624 } else {
625 wxJSON_ASSERT(0); // always fails
626 }
627 // open-array cause the DoRead() to be called recursively
628 value.SetType(wxJSONTYPE_ARRAY);
629 ch = DoRead(is, value);
630 break;
631
632 case ']':
633 if (!parent.IsArray()) {
634 // wrong close-array char (should be close-object)
636 wxJSONREADER_MISSING,
637 _T("Trying to close an object using the \']\' (close-array) char" ));
638 }
639 StoreValue(ch, key, value, parent);
640 m_current = &parent;
641 m_next = nullptr;
643 return 0; // returning ZERO for reading the next char
644 break;
645
646 case ',':
647 // store the value, if any
648 StoreValue(ch, key, value, parent);
649 key.clear();
650 ch = ReadChar(is);
651 break;
652
653 case '\"':
654 ch = ReadString(is, value); // read a JSON string type
655 m_current = &value;
656 m_next = nullptr;
657 break;
658
659 case '\'':
660 ch = ReadMemoryBuff(is, value); // read a memory buffer type
661 m_current = &value;
662 m_next = nullptr;
663 break;
664
665 case ':': // key / value separator
666 m_current = &value;
668 m_next = nullptr;
669 if (!parent.IsObject()) {
670 AddError(_T( "\':\' can only used in object's values" ));
671 } else if (!value.IsString()) {
672 AddError(
673 _T( "\':\' follows a value which is not of type \'string\'" ));
674 } else if (!key.empty()) {
675 AddError(
676 _T( "\':\' not allowed where a \'name\' string was already available" ));
677 } else {
678 // the string in 'value' is set as the 'key'
679 key = value.AsString();
680 value.SetType(wxJSONTYPE_INVALID);
681 }
682 ch = ReadChar(is);
683 break;
684
685 default:
686 // no special char: it is a literal or a number
687 // errors are checked in the 'ReadValue()' function.
688 m_current = &value;
690 m_next = nullptr;
691 ch = ReadValue(is, ch, value);
692 break;
693 } // end switch
694 } while (ch >= 0);
695
696 // the DoRead() should return when the close-object/array char is encontered
697 // if we are here, the EOF condition was encontered so one or more
698 // close-something characters are missing
699 if (parent.IsArray()) {
700 AddWarning(wxJSONREADER_MISSING, _T("\']\' missing at end of file"));
701 } else if (parent.IsObject()) {
702 AddWarning(wxJSONREADER_MISSING, _T("\'}\' missing at end of file"));
703 } else {
704 wxJSON_ASSERT(0);
705 }
706
707 // we store the value, as there is a missing close-object/array char
708 StoreValue(ch, key, value, parent);
709
710 --m_level;
711 return ch;
712}
713
715
728void wxJSONReader::StoreValue(int ch, const wxString& key, wxJSONValue& value,
729 wxJSONValue& parent) {
730 // if 'ch' == } or ] than value AND key may be empty when a open object/array
731 // is immediatly followed by a close object/array
732 //
733 // if 'ch' == , (comma) value AND key (for TypeMap) cannot be empty
734 //
735 wxLogTrace(traceMask, _T("(%s) ch=%d char=%c"), __PRETTY_FUNCTION__, ch,
736 (char)ch);
737 wxLogTrace(traceMask, _T("(%s) value=%s"), __PRETTY_FUNCTION__,
738 value.AsString().c_str());
739
740 m_current = 0;
741 m_next = &value;
742 m_lastStored = 0;
743 m_next->SetLineNo(-1);
744
745 if (!value.IsValid() && key.empty()) {
746 // OK, if the char read is a close-object or close-array
747 if (ch == '}' || ch == ']') {
748 m_lastStored = 0;
749 wxLogTrace(traceMask, _T("(%s) key and value are empty, returning"),
750 __PRETTY_FUNCTION__);
751 } else {
752 AddError(_T("key or value is missing for JSON value"));
753 }
754 } else {
755 // key or value are not empty
756 if (parent.IsObject()) {
757 if (!value.IsValid()) {
758 AddError(
759 _T("cannot store the value: \'value\' is missing for JSON object ")
760 _T("type"));
761 } else if (key.empty()) {
762 AddError(
763 _T("cannot store the value: \'key\' is missing for JSON object ")
764 _T("type"));
765 } else {
766 // OK, adding the value to parent key/value map
767 wxLogTrace(traceMask, _T("(%s) adding value to key:%s"),
768 __PRETTY_FUNCTION__, key.c_str());
769 parent[key] = value;
770 m_lastStored = &(parent[key]);
772 }
773 } else if (parent.IsArray()) {
774 if (!value.IsValid()) {
775 AddError(
776 _T("cannot store the item: \'value\' is missing for JSON array ")
777 _T("type"));
778 }
779 if (!key.empty()) {
780 AddError(
781 _T("cannot store the item: \'key\' (\'%s\') is not permitted in ")
782 _T("JSON array type"),
783 key);
784 }
785 wxLogTrace(traceMask, _T("(%s) appending value to parent array"),
786 __PRETTY_FUNCTION__);
787 parent.Append(value);
788 const wxJSONInternalArray* arr = parent.AsArray();
789 wxJSON_ASSERT(arr);
790 m_lastStored = &(arr->Last());
792 } else {
793 wxJSON_ASSERT(0); // should never happen
794 }
795 }
796 value.SetType(wxJSONTYPE_INVALID);
797 value.ClearComments();
798}
799
801
816void wxJSONReader::AddError(const wxString& msg) {
817 wxString err;
818 err.Printf(_T("Error: line %d, col %d - %s"), m_lineNo, m_colNo, msg.c_str());
819
820 wxLogTrace(traceMask, _T("(%s) %s"), __PRETTY_FUNCTION__, err.c_str());
821
822 if ((int)m_errors.size() < m_maxErrors) {
823 m_errors.Add(err);
824 } else if ((int)m_errors.size() == m_maxErrors) {
825 m_errors.Add(
826 _T("ERROR: too many error messages - ignoring further errors"));
827 }
828 // else if ( m_errors > m_maxErrors ) do nothing, thus ignore the error
829 // message
830}
831
833void wxJSONReader::AddError(const wxString& fmt, const wxString& str) {
834 wxString s;
835 s.Printf(fmt.c_str(), str.c_str());
836 AddError(s);
837}
838
840void wxJSONReader::AddError(const wxString& fmt, wxChar c) {
841 wxString s;
842 s.Printf(fmt.c_str(), c);
843 AddError(s);
844}
845
847
869void wxJSONReader::AddWarning(int type, const wxString& msg) {
870 // if 'type' AND 'm_flags' == 1 than the extension is
871 // ON. Otherwise it is OFF anf the function calls AddError()
872 if (type != 0) {
873 if ((type & m_flags) == 0) {
874 AddError(msg);
875 return;
876 }
877 }
878
879 wxString err;
880 err.Printf(_T( "Warning: line %d, col %d - %s"), m_lineNo, m_colNo,
881 msg.c_str());
882
883 wxLogTrace(traceMask, _T("(%s) %s"), __PRETTY_FUNCTION__, err.c_str());
884 if ((int)m_warnings.size() < m_maxErrors) {
885 m_warnings.Add(err);
886 } else if ((int)m_warnings.size() == m_maxErrors) {
887 m_warnings.Add(
888 _T("Error: too many warning messages - ignoring further warnings"));
889 }
890 // else do nothing, thus ignore the warning message
891}
892
894
902int wxJSONReader::SkipWhiteSpace(wxInputStream& is) {
903 // just read one byte at a time and check for whitespaces
904 int ch;
905 do {
906 ch = ReadChar(is);
907 if (ch < 0) {
908 break;
909 }
910 } while (ch == ' ' || ch == '\n' || ch == '\t');
911 wxLogTrace(traceMask, _T("(%s) end whitespaces line=%d col=%d"),
912 __PRETTY_FUNCTION__, m_lineNo, m_colNo);
913 return ch;
914}
915
917
928int wxJSONReader::SkipComment(wxInputStream& is) {
929 static const wxChar* warn =
930 _T("Comments may be tolerated in JSON text but they are not part of ")
931 _T("JSON syntax");
932
933 // if it is a comment, then a warning is added to the array
934 // otherwise it is an error: values cannot start with a '/'
935 // read the char next to the first slash
936 int ch = ReadChar(is);
937 if (ch < 0) {
938 return -1;
939 }
940
941 wxLogTrace(storeTraceMask, _T("(%s) start comment line=%d col=%d"),
942 __PRETTY_FUNCTION__, m_lineNo, m_colNo);
943
944 // the temporary UTF-8/ANSI buffer that holds the comment string. This will be
945 // converted to a wxString object using wxString::FromUTF8() or From8BitData()
946 wxMemoryBuffer utf8Buff;
947 unsigned char c;
948
949 if (ch == '/') { // C++ comment, read until end-of-line
950 // C++ comment strings are in UTF-8 format. we store all
951 // UTF-8 code units until the first LF or CR+LF
952 AddWarning(wxJSONREADER_ALLOW_COMMENTS, warn);
954 utf8Buff.AppendData("//", 2);
955
956 while (ch >= 0) {
957 if (ch == '\n') {
958 break;
959 }
960 if (ch == '\r') {
961 ch = PeekChar(is);
962 if (ch == '\n') {
963 ch = ReadChar(is);
964 }
965 break;
966 } else {
967 // store the char in the UTF8 temporary buffer
968 c = (unsigned char)ch;
969 utf8Buff.AppendByte(c);
970 }
971 ch = ReadChar(is);
972 }
973 // now convert the temporary UTF-8 buffer
974 m_comment = wxString::FromUTF8((const char*)utf8Buff.GetData(),
975 utf8Buff.GetDataLen());
976 }
977
978 // check if a C-style comment
979 else if (ch == '*') { // C-style comment
980 AddWarning(wxJSONREADER_ALLOW_COMMENTS, warn);
982 utf8Buff.AppendData("/*", 2);
983 while (ch >= 0) {
984 // check the END-COMMENT chars ('*/')
985 if (ch == '*') {
986 ch = PeekChar(is);
987 if (ch == '/') {
988 ch = ReadChar(is); // read the '/' char
989 ch = ReadChar(is); // read the next char that will be returned
990 utf8Buff.AppendData("*/", 2);
991 break;
992 }
993 }
994 // store the char in the UTF8 temporary buffer
995 c = (unsigned char)ch;
996 utf8Buff.AppendByte(c);
997 ch = ReadChar(is);
998 }
999 // now convert the temporary buffer in a wxString object
1000 if (m_noUtf8) {
1001 m_comment = wxString::From8BitData((const char*)utf8Buff.GetData(),
1002 utf8Buff.GetDataLen());
1003 } else {
1004 m_comment = wxString::FromUTF8((const char*)utf8Buff.GetData(),
1005 utf8Buff.GetDataLen());
1006 }
1007 }
1008
1009 else { // it is not a comment, return the character next the first '/'
1010 AddError(_T( "Strange '/' (did you want to insert a comment?)"));
1011 // we read until end-of-line OR end of C-style comment OR EOF
1012 // because a '/' should be a start comment
1013 while (ch >= 0) {
1014 ch = ReadChar(is);
1015 if (ch == '*' && PeekChar(is) == '/') {
1016 break;
1017 }
1018 if (ch == '\n') {
1019 break;
1020 }
1021 }
1022 // read the next char that will be returned
1023 ch = ReadChar(is);
1024 }
1025 wxLogTrace(traceMask, _T("(%s) end comment line=%d col=%d"),
1026 __PRETTY_FUNCTION__, m_lineNo, m_colNo);
1027 wxLogTrace(storeTraceMask, _T("(%s) end comment line=%d col=%d"),
1028 __PRETTY_FUNCTION__, m_lineNo, m_colNo);
1029 wxLogTrace(storeTraceMask, _T("(%s) comment=%s"), __PRETTY_FUNCTION__,
1030 m_comment.c_str());
1031 return ch;
1032}
1033
1035
1078int wxJSONReader::ReadString(wxInputStream& is, wxJSONValue& val) {
1079 // the char last read is the opening qoutes (")
1080
1081 wxMemoryBuffer utf8Buff;
1082 char ues[8]; // stores a Unicode Escaped Esquence: \uXXXX
1083
1084 int ch = 0;
1085 while (ch >= 0) {
1086 ch = ReadChar(is);
1087 unsigned char c = (unsigned char)ch;
1088 if (ch == '\\') { // an escape sequence
1089 ch = ReadChar(is);
1090 switch (ch) {
1091 case -1: // EOF
1092 break;
1093 case 't':
1094 utf8Buff.AppendByte('\t');
1095 break;
1096 case 'n':
1097 utf8Buff.AppendByte('\n');
1098 break;
1099 case 'b':
1100 utf8Buff.AppendByte('\b');
1101 break;
1102 case 'r':
1103 utf8Buff.AppendByte('\r');
1104 break;
1105 case '\"':
1106 utf8Buff.AppendByte('\"');
1107 break;
1108 case '\\':
1109 utf8Buff.AppendByte('\\');
1110 break;
1111 case '/':
1112 utf8Buff.AppendByte('/');
1113 break;
1114 case 'f':
1115 utf8Buff.AppendByte('\f');
1116 break;
1117 case 'u':
1118 ch = ReadUES(is, ues);
1119 if (ch < 0) { // if EOF, returns
1120 return ch;
1121 }
1122 // append the escaped character to the UTF8 buffer
1123 AppendUES(utf8Buff, ues);
1124 // many thanks to Bryan Ashby who discovered this bug
1125 continue;
1126 // break;
1127 default:
1128 AddError(_T( "Unknow escaped character \'\\%c\'"), ch);
1129 }
1130 } else {
1131 // we have read a non-escaped character so we have to append it to
1132 // the temporary UTF-8 buffer until the next quote char
1133 if (ch == '\"') {
1134 break;
1135 }
1136 utf8Buff.AppendByte(c);
1137 }
1138 }
1139
1140 // if UTF-8 conversion is disabled (ANSI builds only) we just copy the
1141 // bit data to a wxString object
1142 wxString s;
1143 if (m_noUtf8) {
1144 s = wxString::From8BitData((const char*)utf8Buff.GetData(),
1145 utf8Buff.GetDataLen());
1146 } else {
1147 // perform UTF-8 conversion
1148 // first we check that the UTF-8 buffer is correct, i.e. it contains valid
1149 // UTF-8 code points.
1150 // this works in both ANSI and Unicode builds.
1151 size_t convLen =
1152 wxConvUTF8.ToWChar(0, // wchar_t destination
1153 0, // size_t destLenght
1154 (const char*)utf8Buff.GetData(), // char_t source
1155 utf8Buff.GetDataLen()); // size_t sourceLenght
1156
1157 if (convLen == wxCONV_FAILED) {
1158 AddError(_T( "String value: the UTF-8 stream is invalid"));
1159 s.append(_T( "<UTF-8 stream not valid>"));
1160 } else {
1161#if defined(wxJSON_USE_UNICODE)
1162 // in Unicode just convert to wxString
1163 s = wxString::FromUTF8((const char*)utf8Buff.GetData(),
1164 utf8Buff.GetDataLen());
1165#else
1166 // in ANSI, the conversion may fail and an empty string is returned
1167 // in this case, the reader do a char-by-char conversion storing
1168 // unicode escaped sequences of unrepresentable characters
1169 s = wxString::FromUTF8((const char*)utf8Buff.GetData(),
1170 utf8Buff.GetDataLen());
1171 if (s.IsEmpty()) {
1172 int r = ConvertCharByChar(
1173 s, utf8Buff); // return number of escaped sequences
1174 if (r > 0) {
1175 AddWarning(
1176 0,
1177 _T( "The string value contains unrepresentable Unicode characters"));
1178 }
1179 }
1180#endif
1181 }
1182 }
1183 wxLogTrace(traceMask, _T("(%s) line=%d col=%d"), __PRETTY_FUNCTION__,
1184 m_lineNo, m_colNo);
1185 wxLogTrace(traceMask, _T("(%s) string read=%s"), __PRETTY_FUNCTION__,
1186 s.c_str());
1187 wxLogTrace(traceMask, _T("(%s) value=%s"), __PRETTY_FUNCTION__,
1188 val.AsString().c_str());
1189
1190 // now assign the string to the JSON-value 'value'
1191 // must check that:
1192 // 'value' is empty
1193 // 'value' is a string; concatenate it but emit warning
1194 if (!val.IsValid()) {
1195 wxLogTrace(traceMask, _T("(%s) assigning the string to value"),
1196 __PRETTY_FUNCTION__);
1197 val = s;
1198 } else if (val.IsString()) {
1199 AddWarning(wxJSONREADER_MULTISTRING,
1200 _T("Multiline strings are not allowed by JSON syntax"));
1201 wxLogTrace(traceMask, _T("(%s) concatenate the string to value"),
1202 __PRETTY_FUNCTION__);
1203 val.Cat(s);
1204 } else {
1205 AddError(_T( "String value \'%s\' cannot follow another value"), s);
1206 }
1207
1208 // store the input text's line number when the string was stored in 'val'
1209 val.SetLineNo(m_lineNo);
1210
1211 // read the next char after the closing quotes and returns it
1212 if (ch >= 0) {
1213 ch = ReadChar(is);
1214 }
1215 return ch;
1216}
1217
1219
1238int wxJSONReader::ReadToken(wxInputStream& is, int ch, wxString& s) {
1239 int nextCh = ch;
1240 while (nextCh >= 0) {
1241 switch (nextCh) {
1242 case ' ':
1243 case ',':
1244 case ':':
1245 case '[':
1246 case ']':
1247 case '{':
1248 case '}':
1249 case '\t':
1250 case '\n':
1251 case '\r':
1252 case '\b':
1253 wxLogTrace(traceMask, _T("(%s) line=%d col=%d"), __PRETTY_FUNCTION__,
1254 m_lineNo, m_colNo);
1255 wxLogTrace(traceMask, _T("(%s) token read=%s"), __PRETTY_FUNCTION__,
1256 s.c_str());
1257 return nextCh;
1258 break;
1259 default:
1260 s.Append((unsigned char)nextCh, 1);
1261 break;
1262 }
1263 // read the next character
1264 nextCh = ReadChar(is);
1265 }
1266 wxLogTrace(traceMask, _T("(%s) EOF on line=%d col=%d"), __PRETTY_FUNCTION__,
1267 m_lineNo, m_colNo);
1268 wxLogTrace(traceMask, _T("(%s) EOF - token read=%s"), __PRETTY_FUNCTION__,
1269 s.c_str());
1270 return nextCh;
1271}
1272
1274
1297int wxJSONReader::ReadValue(wxInputStream& is, int ch, wxJSONValue& val) {
1298 wxString s;
1299 int nextCh = ReadToken(is, ch, s);
1300 wxLogTrace(traceMask, _T("(%s) value=%s"), __PRETTY_FUNCTION__,
1301 val.AsString().c_str());
1302
1303 if (val.IsValid()) {
1304 AddError(_T( "Value \'%s\' cannot follow a value: \',\' or \':\' missing?"),
1305 s);
1306 return nextCh;
1307 }
1308
1309 // variables used for converting numeric values
1310 bool r;
1311 double d;
1312#if defined(wxJSON_64BIT_INT)
1313 wxInt64 i64;
1314 wxUint64 ui64;
1315#else
1316 unsigned long int ul;
1317 long int l;
1318#endif
1319
1320 // first try the literal strings lowercase and nocase
1321 if (s == _T("null")) {
1322 val.SetType(wxJSONTYPE_NULL);
1323 wxLogTrace(traceMask, _T("(%s) value = nullptr"), __PRETTY_FUNCTION__);
1324 return nextCh;
1325 } else if (s.CmpNoCase(_T( "null" )) == 0) {
1326 wxLogTrace(traceMask, _T("(%s) value = nullptr"), __PRETTY_FUNCTION__);
1327 AddWarning(wxJSONREADER_CASE,
1328 _T( "the \'null\' literal must be lowercase" ));
1329 val.SetType(wxJSONTYPE_NULL);
1330 return nextCh;
1331 } else if (s == _T("true")) {
1332 wxLogTrace(traceMask, _T("(%s) value = TRUE"), __PRETTY_FUNCTION__);
1333 val = true;
1334 return nextCh;
1335 } else if (s.CmpNoCase(_T( "true" )) == 0) {
1336 wxLogTrace(traceMask, _T("(%s) value = TRUE"), __PRETTY_FUNCTION__);
1337 AddWarning(wxJSONREADER_CASE,
1338 _T( "the \'true\' literal must be lowercase" ));
1339 val = true;
1340 return nextCh;
1341 } else if (s == _T("false")) {
1342 wxLogTrace(traceMask, _T("(%s) value = FALSE"), __PRETTY_FUNCTION__);
1343 val = false;
1344 return nextCh;
1345 } else if (s.CmpNoCase(_T( "false" )) == 0) {
1346 wxLogTrace(traceMask, _T("(%s) value = FALSE"), __PRETTY_FUNCTION__);
1347 AddWarning(wxJSONREADER_CASE,
1348 _T( "the \'false\' literal must be lowercase" ));
1349 val = false;
1350 return nextCh;
1351 }
1352
1353 // try to convert to a number if the token starts with a digit, a plus or a
1354 // minus sign. The function first states what type of conversion are tested:
1355 // 1. first signed integer (not if 'ch' == '+')
1356 // 2. unsigned integer (not if 'ch' == '-')
1357 // 3. finally double
1358 bool tSigned = true, tUnsigned = true, tDouble = true;
1359 switch (ch) {
1360 case '0':
1361 case '1':
1362 case '2':
1363 case '3':
1364 case '4':
1365 case '5':
1366 case '6':
1367 case '7':
1368 case '8':
1369 case '9':
1370 // first try a signed integer, then a unsigned integer, then a double
1371 break;
1372
1373 case '+':
1374 // the plus sign forces a unsigned integer
1375 tSigned = false;
1376 break;
1377
1378 case '-':
1379 // try signed and double
1380 tUnsigned = false;
1381 break;
1382 default:
1383 AddError(_T( "Literal \'%s\' is incorrect (did you forget quotes?)"), s);
1384 return nextCh;
1385 }
1386
1387 if (tSigned) {
1388#if defined(wxJSON_64BIT_INT)
1389 r = Strtoll(s, &i64);
1390 wxLogTrace(traceMask, _T("(%s) convert to wxInt64 result=%d"),
1391 __PRETTY_FUNCTION__, r);
1392 if (r) {
1393 // store the value
1394 val = i64;
1395 return nextCh;
1396 }
1397#else
1398 r = s.ToLong(&l);
1399 wxLogTrace(traceMask, _T("(%s) convert to int result=%d"),
1400 __PRETTY_FUNCTION__, r);
1401 if (r) {
1402 // store the value
1403 val = (int)l;
1404 return nextCh;
1405 }
1406#endif
1407 }
1408
1409 if (tUnsigned) {
1410#if defined(wxJSON_64BIT_INT)
1411 r = Strtoull(s, &ui64);
1412 wxLogTrace(traceMask, _T("(%s) convert to wxUint64 result=%d"),
1413 __PRETTY_FUNCTION__, r);
1414 if (r) {
1415 // store the value
1416 val = ui64;
1417 return nextCh;
1418 }
1419#else
1420 r = s.ToULong(&ul);
1421 wxLogTrace(traceMask, _T("(%s) convert to int result=%d"),
1422 __PRETTY_FUNCTION__, r);
1423 if (r) {
1424 // store the value
1425 val = (unsigned int)ul;
1426 return nextCh;
1427 }
1428#endif
1429 }
1430
1431 if (tDouble) {
1432 r = s.ToDouble(&d);
1433 wxLogTrace(traceMask, _T("(%s) convert to double result=%d"),
1434 __PRETTY_FUNCTION__, r);
1435 if (r) {
1436 // store the value
1437 val = d;
1438 return nextCh;
1439 }
1440 }
1441
1442 // the value is not syntactically correct
1443 AddError(_T( "Literal \'%s\' is incorrect (did you forget quotes?)"), s);
1444 return nextCh;
1445 return nextCh;
1446}
1447
1449
1467int wxJSONReader::ReadUES(wxInputStream& is, char* uesBuffer) {
1468 int ch;
1469 for (int i = 0; i < 4; i++) {
1470 ch = ReadChar(is);
1471 if (ch < 0) {
1472 return ch;
1473 }
1474 uesBuffer[i] = (unsigned char)ch;
1475 }
1476 uesBuffer[4] = 0; // makes a ASCIIZ string
1477
1478 return 0;
1479}
1480
1482
1508int wxJSONReader::AppendUES(wxMemoryBuffer& utf8Buff, const char* uesBuffer) {
1509 unsigned long l;
1510 int r = sscanf(uesBuffer, "%lx", &l); // r is the assigned items
1511 if (r != 1) {
1512 AddError(_T( "Invalid Unicode Escaped Sequence"));
1513 return -1;
1514 }
1515 wxLogTrace(traceMask, _T("(%s) unicode sequence=%s code=%ld"),
1516 __PRETTY_FUNCTION__, uesBuffer, l);
1517
1518 wchar_t ch = (wchar_t)l;
1519 char buffer[16];
1520 size_t len = wxConvUTF8.FromWChar(buffer, 10, &ch, 1);
1521
1522 // seems that the wxMBConv classes always appends a nullptr byte to
1523 // the converted buffer
1524 if (len > 1) {
1525 len = len - 1;
1526 }
1527 utf8Buff.AppendData(buffer, len);
1528
1529 // sould never fail
1530 wxASSERT(len != wxCONV_FAILED);
1531 return 0;
1532}
1533
1535
1561 wxLogTrace(storeTraceMask, _T("(%s) m_comment=%s"), __PRETTY_FUNCTION__,
1562 m_comment.c_str());
1563 wxLogTrace(storeTraceMask, _T("(%s) m_flags=%d m_commentLine=%d"),
1564 __PRETTY_FUNCTION__, m_flags, m_commentLine);
1565 wxLogTrace(storeTraceMask, _T("(%s) m_current=%p"), __PRETTY_FUNCTION__,
1566 m_current);
1567 wxLogTrace(storeTraceMask, _T("(%s) m_next=%p"), __PRETTY_FUNCTION__, m_next);
1568 wxLogTrace(storeTraceMask, _T("(%s) m_lastStored=%p"), __PRETTY_FUNCTION__,
1569 m_lastStored);
1570
1571 // first check if the 'store comment' bit is on
1572 if ((m_flags & wxJSONREADER_STORE_COMMENTS) == 0) {
1573 m_comment.clear();
1574 return;
1575 }
1576
1577 // check if the comment is on the same line of one of the
1578 // 'current', 'next' or 'lastStored' value
1579 if (m_current != 0) {
1580 wxLogTrace(storeTraceMask, _T("(%s) m_current->lineNo=%d"),
1581 __PRETTY_FUNCTION__, m_current->GetLineNo());
1582 if (m_current->GetLineNo() == m_commentLine) {
1583 wxLogTrace(storeTraceMask,
1584 _T("(%s) comment added to \'m_current\' INLINE"),
1585 __PRETTY_FUNCTION__);
1586 m_current->AddComment(m_comment, wxJSONVALUE_COMMENT_INLINE);
1587 m_comment.clear();
1588 return;
1589 }
1590 }
1591 if (m_next != 0) {
1592 wxLogTrace(storeTraceMask, _T("(%s) m_next->lineNo=%d"),
1593 __PRETTY_FUNCTION__, m_next->GetLineNo());
1594 if (m_next->GetLineNo() == m_commentLine) {
1595 wxLogTrace(storeTraceMask, _T("(%s) comment added to \'m_next\' INLINE"),
1596 __PRETTY_FUNCTION__);
1597 m_next->AddComment(m_comment, wxJSONVALUE_COMMENT_INLINE);
1598 m_comment.clear();
1599 return;
1600 }
1601 }
1602 if (m_lastStored != 0) {
1603 wxLogTrace(storeTraceMask, _T("(%s) m_lastStored->lineNo=%d"),
1604 __PRETTY_FUNCTION__, m_lastStored->GetLineNo());
1606 wxLogTrace(storeTraceMask,
1607 _T("(%s) comment added to \'m_lastStored\' INLINE"),
1608 __PRETTY_FUNCTION__);
1609 m_lastStored->AddComment(m_comment, wxJSONVALUE_COMMENT_INLINE);
1610 m_comment.clear();
1611 return;
1612 }
1613 }
1614
1615 // if comment is BEFORE, store the comment in the 'm_next'
1616 // or 'm_current' value
1617 // if comment is AFTER, store the comment in the 'm_lastStored'
1618 // or 'm_current' value
1619
1620 if (m_flags & wxJSONREADER_COMMENTS_AFTER) { // comment AFTER
1621 if (m_current) {
1622 if (m_current == parent || !m_current->IsValid()) {
1623 AddError(
1624 _T("Cannot find a value for storing the comment (flag AFTER)"));
1625 } else {
1626 wxLogTrace(storeTraceMask,
1627 _T("(%s) comment added to m_current (AFTER)"),
1628 __PRETTY_FUNCTION__);
1629 m_current->AddComment(m_comment, wxJSONVALUE_COMMENT_AFTER);
1630 }
1631 } else if (m_lastStored) {
1632 wxLogTrace(storeTraceMask,
1633 _T("(%s) comment added to m_lastStored (AFTER)"),
1634 __PRETTY_FUNCTION__);
1635 m_lastStored->AddComment(m_comment, wxJSONVALUE_COMMENT_AFTER);
1636 } else {
1637 wxLogTrace(storeTraceMask,
1638 _T("(%s) cannot find a value for storing the AFTER comment"),
1639 __PRETTY_FUNCTION__);
1640 AddError(_T("Cannot find a value for storing the comment (flag AFTER)"));
1641 }
1642 } else { // comment BEFORE can only be added to the 'next' value
1643 if (m_next) {
1644 wxLogTrace(storeTraceMask, _T("(%s) comment added to m_next (BEFORE)"),
1645 __PRETTY_FUNCTION__);
1646 m_next->AddComment(m_comment, wxJSONVALUE_COMMENT_BEFORE);
1647 } else {
1648 // cannot find a value for storing the comment
1649 AddError(_T("Cannot find a value for storing the comment (flag BEFORE)"));
1650 }
1651 }
1652 m_comment.clear();
1653}
1654
1656
1666 int n = UTF8NumBytes(ch);
1667 return n;
1668}
1669
1671
1692 int num = 0; // the counter of '1' bits
1693 for (int i = 0; i < 8; i++) {
1694 if ((ch & 0x80) == 0) {
1695 break;
1696 }
1697 ++num;
1698 ch = ch << 1;
1699 }
1700
1701 // note that if the char contains more than six '1' bits it is not
1702 // a valid UTF-8 encoded character
1703 if (num > 6) {
1704 num = -1;
1705 } else if (num == 0) {
1706 num = 1;
1707 }
1708 return num;
1709}
1710
1712
1728 const wxMemoryBuffer& utf8Buffer) {
1729 size_t len = utf8Buffer.GetDataLen();
1730 char* buff = (char*)utf8Buffer.GetData();
1731 char* buffEnd = buff + len;
1732
1733 int result = 0;
1734 char temp[16]; // the UTF-8 code-point
1735
1736 while (buff < buffEnd) {
1737 temp[0] = *buff; // the first UTF-8 code-unit
1738 // compute the number of code-untis that make one UTF-8 code-point
1739 int numBytes = NumBytes(*buff);
1740 ++buff;
1741 for (int i = 1; i < numBytes; i++) {
1742 if (buff >= buffEnd) {
1743 break;
1744 }
1745 temp[i] = *buff; // the first UTF-8 code-unit
1746 ++buff;
1747 }
1748 // if ( buff >= buffEnd ) {
1749 // break;
1750 //}
1751 // now convert 'temp' to a wide-character
1752 wchar_t dst[10];
1753 size_t outLength = wxConvUTF8.ToWChar(dst, 10, temp, numBytes);
1754
1755 // now convert the wide char to a locale dependent character
1756 // len = wxConvLocal.FromWChar( temp, 16, dst, outLength );
1757 // len = wxConviso8859_1.FromWChar( temp, 16, dst, outLength );
1758 len = wxConvLibc.FromWChar(temp, 16, dst, outLength);
1759 if (len == wxCONV_FAILED) {
1760 ++result;
1761 wxString t;
1762 t.Printf(_T( "\\u%04X"), (int)dst[0]);
1763 s.Append(t);
1764 } else {
1765 s.Append(temp[0], 1);
1766 }
1767 } // end while
1768 return result;
1769}
1770
1772
1788 unsigned char cu[2];
1789 short int bu;
1790};
1791
1792int wxJSONReader::ReadMemoryBuff(wxInputStream& is, wxJSONValue& val) {
1793 static const wxChar* membuffError =
1794 _T("the \'memory buffer\' type contains %d invalid digits" );
1795
1796 AddWarning(wxJSONREADER_MEMORYBUFF,
1797 _T( "the \'memory buffer\' type is not valid JSON text" ));
1798
1799 wxMemoryBuffer buff;
1800 int ch = 0;
1801 int errors = 0;
1802 unsigned char byte = 0;
1803 while (ch >= 0) {
1804 ch = ReadChar(is);
1805 if (ch < 0) {
1806 break;
1807 }
1808 if (ch == '\'') {
1809 break;
1810 }
1811 // the conversion is done two chars at a time
1812 unsigned char c1 = (unsigned char)ch;
1813 ch = ReadChar(is);
1814 if (ch < 0) {
1815 break;
1816 }
1817 unsigned char c2 = (unsigned char)ch;
1818 c1 -= '0';
1819 c2 -= '0';
1820 if (c1 > 9) {
1821 c1 -= 7;
1822 }
1823 if (c2 > 9) {
1824 c2 -= 7;
1825 }
1826 if (c1 > 15) {
1827 ++errors;
1828 } else if (c2 > 15) {
1829 ++errors;
1830 } else {
1831 byte = (c1 * 16) + c2;
1832 buff.AppendByte(byte);
1833 }
1834 } // end while
1835
1836 if (errors > 0) {
1837 wxString err;
1838 err.Printf(membuffError, errors);
1839 AddError(err);
1840 }
1841
1842 // now assign the memory buffer object to the JSON-value 'value'
1843 // must check that:
1844 // 'value' is invalid OR
1845 // 'value' is a memory buffer; concatenate it
1846 if (!val.IsValid()) {
1847 wxLogTrace(traceMask, _T("(%s) assigning the memory buffer to value"),
1848 __PRETTY_FUNCTION__);
1849 val = buff;
1850 } else if (val.IsMemoryBuff()) {
1851 wxLogTrace(traceMask, _T("(%s) concatenate memory buffer to value"),
1852 __PRETTY_FUNCTION__);
1853 val.Cat(buff);
1854 } else {
1855 AddError(_T( "Memory buffer value cannot follow another value"));
1856 }
1857
1858 // store the input text's line number when the string was stored in 'val'
1859 val.SetLineNo(m_lineNo);
1860
1861 // read the next char after the closing quotes and returns it
1862 if (ch >= 0) {
1863 ch = ReadChar(is);
1864 }
1865 return ch;
1866}
1867
1868#if defined(wxJSON_64BIT_INT)
1870
1896bool wxJSONReader::Strtoll(const wxString& str, wxInt64* i64) {
1897 wxChar sign = ' ';
1898 wxUint64 ui64;
1899 bool r = DoStrto_ll(str, &ui64, &sign);
1900
1901 if (r) {
1902 // check overflow for signed long long
1903 switch (sign) {
1904 case '-':
1905 if (ui64 > (wxUint64)LLONG_MAX + 1) {
1906 r = false;
1907 } else {
1908 *i64 = (wxInt64)(ui64 * -1);
1909 }
1910 break;
1911
1912 // case '+' :
1913 default:
1914 if (ui64 > LLONG_MAX) {
1915 r = false;
1916 } else {
1917 *i64 = (wxInt64)ui64;
1918 }
1919 break;
1920 }
1921 }
1922 return r;
1923}
1924
1926
1929bool wxJSONReader::Strtoull(const wxString& str, wxUint64* ui64) {
1930 wxChar sign = ' ';
1931 bool r = DoStrto_ll(str, ui64, &sign);
1932 if (sign == '-') {
1933 r = false;
1934 }
1935 return r;
1936}
1937
1939
1950bool wxJSONReader::DoStrto_ll(const wxString& str, wxUint64* ui64,
1951 wxChar* sign) {
1952 // the conversion is done by multiplying the individual digits
1953 // in reverse order to the corresponding power of 10
1954 //
1955 // 10's power: 987654321.9876543210
1956 //
1957 // LLONG_MAX: 9223372036854775807
1958 // LLONG_MIN: -9223372036854775808
1959 // ULLONG_MAX: 18446744073709551615
1960 //
1961 // the function does not take into account the sign: only a
1962 // unsigned long long int is returned
1963
1964 int maxDigits = 20; // 20 + 1 (for the sign)
1965
1966 wxUint64 power10[] = {wxULL(1),
1967 wxULL(10),
1968 wxULL(100),
1969 wxULL(1000),
1970 wxULL(10000),
1971 wxULL(100000),
1972 wxULL(1000000),
1973 wxULL(10000000),
1974 wxULL(100000000),
1975 wxULL(1000000000),
1976 wxULL(10000000000),
1977 wxULL(100000000000),
1978 wxULL(1000000000000),
1979 wxULL(10000000000000),
1980 wxULL(100000000000000),
1981 wxULL(1000000000000000),
1982 wxULL(10000000000000000),
1983 wxULL(100000000000000000),
1984 wxULL(1000000000000000000),
1985 wxULL(10000000000000000000)};
1986
1987 wxUint64 temp1 = wxULL(0); // the temporary converted integer
1988
1989 int strLen = str.length();
1990 if (strLen == 0) {
1991 // an empty string is converted to a ZERO value: the function succeeds
1992 *ui64 = wxLL(0);
1993 return true;
1994 }
1995
1996 int index = 0;
1997 wxChar ch = str[0];
1998 if (ch == '+' || ch == '-') {
1999 *sign = ch;
2000 ++index;
2001 ++maxDigits;
2002 }
2003
2004 if (strLen > maxDigits) {
2005 return false;
2006 }
2007
2008 // check the overflow: check the string length and the individual digits
2009 // of the string; the overflow is checked for unsigned long long
2010 if (strLen == maxDigits) {
2011 wxString uLongMax(_T("18446744073709551615"));
2012 int j = 0;
2013 for (int i = index; i < strLen - 1; i++) {
2014 ch = str[i];
2015 if (ch < '0' || ch > '9') {
2016 return false;
2017 }
2018 if (ch > uLongMax[j]) {
2019 return false;
2020 }
2021 if (ch < uLongMax[j]) {
2022 break;
2023 }
2024 ++j;
2025 }
2026 }
2027
2028 // get the digits in the reverse order and multiply them by the
2029 // corresponding power of 10
2030 int exponent = 0;
2031 for (int i = strLen - 1; i >= index; i--) {
2032 wxChar ch = str[i];
2033 if (ch < '0' || ch > '9') {
2034 return false;
2035 }
2036 ch = ch - '0';
2037 // compute the new temporary value
2038 temp1 += ch * power10[exponent];
2039 ++exponent;
2040 }
2041 *ui64 = temp1;
2042 return true;
2043}
2044
2045#endif // defined( wxJSON_64BIT_INT )
2046
2047/*
2048{
2049}
2050*/
int m_colNo
The current column number (start at 1).
Definition jsonreader.h:105
int ReadToken(wxInputStream &is, int ch, wxString &s)
Reads a token string.
int DoRead(wxInputStream &doc, wxJSONValue &val)
Reads the JSON text document (internal use)
void AddWarning(int type, const wxString &descr)
Add a warning message to the warning's array.
int ConvertCharByChar(wxString &s, const wxMemoryBuffer &utf8Buffer)
Convert a UTF-8 memory buffer one char at a time.
int m_maxErrors
Maximum number of errors stored in the error's array.
Definition jsonreader.h:99
bool m_noUtf8
ANSI: do not convert UTF-8 strings.
Definition jsonreader.h:138
wxJSONValue * m_lastStored
The pointer to the value object that was last stored.
Definition jsonreader.h:117
int AppendUES(wxMemoryBuffer &utf8Buff, const char *uesBuffer)
The function appends a Unice Escaped Sequence to the temporary UTF8 buffer.
int ReadChar(wxInputStream &is)
Read a character from the input JSON document.
int SkipComment(wxInputStream &is)
Skip a comment.
int ReadString(wxInputStream &is, wxJSONValue &val)
Read a string value.
int m_flags
Flag that control the parser behaviour,.
Definition jsonreader.h:96
int ReadUES(wxInputStream &is, char *uesBuffer)
Read a 4-hex-digit unicode character.
wxJSONReader(int flags=wxJSONREADER_TOLERANT, int maxErrors=30)
Ctor.
void StoreComment(const wxJSONValue *parent)
Store the comment string in the value it refers to.
static int UTF8NumBytes(char ch)
Compute the number of bytes that makes a UTF-8 encoded wide character.
int m_lineNo
The current line number (start at 1).
Definition jsonreader.h:102
int GetDepth() const
Return the depth of the JSON input text.
int m_commentLine
The starting line of the comment string.
Definition jsonreader.h:126
int m_depth
The depth level of the read JSON text.
Definition jsonreader.h:111
wxJSONValue * m_current
The pointer to the value object that is being read.
Definition jsonreader.h:114
int m_level
The current level of object/array annidation (start at ZERO).
Definition jsonreader.h:108
void StoreValue(int ch, const wxString &key, wxJSONValue &value, wxJSONValue &parent)
Store a value in the parent object.
const wxArrayString & GetWarnings() const
Return a reference to the warning message's array.
const wxArrayString & GetErrors() const
Return a reference to the error message's array.
wxArrayString m_errors
The array of error messages.
Definition jsonreader.h:129
wxArrayString m_warnings
The array of warning messages.
Definition jsonreader.h:132
int GetErrorCount() const
Return the size of the error message's array.
void AddError(const wxString &descr)
Add a error message to the error's array.
wxJSONValue * m_next
The pointer to the value object that will be read.
Definition jsonreader.h:120
int GetWarningCount() const
Return the size of the warning message's array.
wxString m_comment
The comment string read by SkipComment().
Definition jsonreader.h:123
int ReadValue(wxInputStream &is, int ch, wxJSONValue &val)
Read a value from input stream.
int Parse(const wxString &doc, wxJSONValue *val)
Parse the JSON document.
int ReadMemoryBuff(wxInputStream &is, wxJSONValue &val)
Read a memory buffer type.
virtual ~wxJSONReader()
Dtor - does nothing.
int GetStart(wxInputStream &is)
Returns the start of the document.
int NumBytes(char ch)
Return the number of bytes that make a character in stream input.
int SkipWhiteSpace(wxInputStream &is)
Skip all whitespaces.
int m_peekChar
The character read by the PeekChar() function (-1 none)
Definition jsonreader.h:135
int PeekChar(wxInputStream &is)
Peek a character from the input JSON document.
The JSON value class implementation.
Definition jsonval.h:84
bool IsArray() const
Return TRUE if the type of the value stored is an array type.
Definition jsonval.cpp:746
int AddComment(const wxString &str, int position=wxJSONVALUE_COMMENT_DEFAULT)
Add a comment to this JSON value object.
Definition jsonval.cpp:2346
bool IsString() const
Return TRUE if the type of the value stored is a wxString object.
Definition jsonval.cpp:717
wxJSONValue & Append(const wxJSONValue &value)
Append the specified value in the array.
Definition jsonval.cpp:1385
wxString AsString() const
Return the stored value as a wxWidget's string.
Definition jsonval.cpp:872
int GetLineNo() const
Return the line number of this JSON value object.
Definition jsonval.cpp:2617
bool IsValid() const
Return TRUE if the value stored is valid.
Definition jsonval.cpp:521
bool IsMemoryBuff() const
Return TRUE if the type of this value is a binary memory buffer.
Definition jsonval.cpp:766
void SetLineNo(int num)
Set the line number of this JSON value object.
Definition jsonval.cpp:2628
bool IsObject() const
Return TRUE if the type of this value is a key/value map.
Definition jsonval.cpp:756
wxJSONRefData * SetType(wxJSONType type)
Set the type of the stored value.
Definition jsonval.cpp:2535
const wxJSONInternalArray * AsArray() const
Return the stored value as an array object.
Definition jsonval.cpp:1281
Read a memory buffer type.