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