OpenCPN Partial API docs
Loading...
Searching...
No Matches
jsonwriter.cpp
Go to the documentation of this file.
1
2// Name: jsonwriter.cpp
3// Purpose: the wxJSONWriter class: a JSON text generator
4// Author: Luciano Cattani
5// Created: 2007/10/12
6// RCS-ID: $Id: jsonwriter.cpp,v 1.6 2008/03/03 19:05:47 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/jsonwriter.h>
21
22#include <wx/sstream.h>
23#include <wx/mstream.h>
24#include <wx/debug.h>
25#include <wx/log.h>
26
27#if wxDEBUG_LEVEL > 0
28static const wxChar* writerTraceMask = "traceWriter";
29#endif
30
129
194wxJSONWriter::wxJSONWriter(int style, int indent, int step) {
195 m_indent = indent;
196 m_step = step;
197 m_style = style;
198 m_noUtf8 = false;
199 if (m_style == wxJSONWRITER_NONE) {
200 m_indent = 0;
201 m_step = 0;
202 }
203 // set the default format string for doubles as
204 // 10 significant digits and suppress trailing ZEROes
205 SetDoubleFmtString("%.10g");
206
207#if !defined(wxJSON_USE_UNICODE)
208 // in ANSI builds we can suppress UTF-8 conversion for both the writer and the
209 // reader
210 if (m_style == wxJSONWRITER_NOUTF8_STREAM) {
211 m_noUtf8 = true;
212 }
213#endif
214}
215
218
220
260void wxJSONWriter::Write(const wxJSONValue& value, wxString& str) {
261#if !defined(wxJSON_USE_UNICODE)
262 // in ANSI builds output to a string never use UTF-8 conversion
263 bool noUtf8_bak = m_noUtf8; // save the current setting
264 m_noUtf8 = true;
265#endif
266
267 wxMemoryOutputStream os;
268 Write(value, os);
269
270 // get the address of the buffer
271 wxFileOffset len = os.GetLength();
272 wxStreamBuffer* osBuff = os.GetOutputStreamBuffer();
273 void* buffStart = osBuff->GetBufferStart();
274
275 if (m_noUtf8) {
276 str = wxString::From8BitData((const char*)buffStart, len);
277 } else {
278 str = wxString::FromUTF8((const char*)buffStart, len);
279 }
280#if !defined(wxJSON_USE_UNICODE)
281 m_noUtf8 = noUtf8_bak; // restore the old setting
282#endif
283}
284
286void wxJSONWriter::Write(const wxJSONValue& value, wxOutputStream& os) {
287 m_level = 0;
288 DoWrite(os, value, 0, false);
289}
290
292
306void wxJSONWriter::SetDoubleFmtString(const char* fmt) { m_fmt = (char*)fmt; }
307
309
325int wxJSONWriter::DoWrite(wxOutputStream& os, const wxJSONValue& value,
326 const wxString* key, bool comma) {
327 // note that this function is recursive
328
329 // some variables that cannot be allocated in the switch statement
330 const wxJSONInternalMap* map = nullptr;
331 int size;
332 m_colNo = 1;
333 m_lineNo = 1;
334 // determine the comment position; it is one of:
335 //
336 // wxJSONVALUE_COMMENT_BEFORE
337 // wxJSONVALUE_COMMENT_AFTER
338 // wxJSONVALUE_COMMENT_INLINE
339 //
340 // or -1 if comments have not to be written
341 int commentPos = -1;
342 if (value.GetCommentCount() > 0 && (m_style & wxJSONWRITER_WRITE_COMMENTS)) {
343 commentPos = value.GetCommentPos();
344 if ((m_style & wxJSONWRITER_COMMENTS_BEFORE) != 0) {
345 commentPos = wxJSONVALUE_COMMENT_BEFORE;
346 } else if ((m_style & wxJSONWRITER_COMMENTS_AFTER) != 0) {
347 commentPos = wxJSONVALUE_COMMENT_AFTER;
348 }
349 }
350
351 int lastChar = 0; // check if WriteComment() writes the last LF char
352
353 // first write the comment if it is BEFORE
354 if (commentPos == wxJSONVALUE_COMMENT_BEFORE) {
355 lastChar = WriteComment(os, value, true);
356 if (lastChar < 0) {
357 return lastChar;
358 } else if (lastChar != '\n') {
359 WriteSeparator(os);
360 }
361 }
362
363 lastChar = WriteIndent(os);
364 if (lastChar < 0) {
365 return lastChar;
366 }
367
368 // now write the key if it is not nullptr
369 if (key) {
370 lastChar = WriteKey(os, *key);
371 }
372 if (lastChar < 0) {
373 return lastChar;
374 }
375
376 // now write the value
377 wxJSONInternalMap::const_iterator it; // declare the map object
378 long int count = 0;
379
380 wxJSONType t = value.GetType();
381 switch (t) {
382 case wxJSONTYPE_INVALID:
383 WriteInvalid(os);
384 wxFAIL_MSG(
385 "wxJSONWriter::WriteEmpty() cannot be called (not a valid JSON "
386 "text");
387 break;
388
389 case wxJSONTYPE_INT:
390 case wxJSONTYPE_SHORT:
391 case wxJSONTYPE_LONG:
392 case wxJSONTYPE_INT64:
393 lastChar = WriteIntValue(os, value);
394 break;
395
396 case wxJSONTYPE_UINT:
397 case wxJSONTYPE_USHORT:
398 case wxJSONTYPE_ULONG:
399 case wxJSONTYPE_UINT64:
400 lastChar = WriteUIntValue(os, value);
401 break;
402
403 case wxJSONTYPE_NULL:
404 lastChar = WriteNullValue(os);
405 break;
406 case wxJSONTYPE_BOOL:
407 lastChar = WriteBoolValue(os, value);
408 break;
409
410 case wxJSONTYPE_DOUBLE:
411 lastChar = WriteDoubleValue(os, value);
412 break;
413
414 case wxJSONTYPE_STRING:
415 case wxJSONTYPE_CSTRING:
416 lastChar = WriteStringValue(os, value.AsString());
417 break;
418
419 case wxJSONTYPE_MEMORYBUFF:
420 lastChar = WriteMemoryBuff(os, value.AsMemoryBuff());
421 break;
422
423 case wxJSONTYPE_ARRAY:
424 ++m_level;
425 os.PutC('[');
426 // the inline comment for objects and arrays are printed in the open char
427 if (commentPos == wxJSONVALUE_COMMENT_INLINE) {
428 commentPos = -1; // we have already written the comment
429 lastChar = WriteComment(os, value, false);
430 if (lastChar < 0) {
431 return lastChar;
432 }
433 if (lastChar != '\n') {
434 lastChar = WriteSeparator(os);
435 }
436 } else { // comment is not to be printed inline, so write a LF
437 lastChar = WriteSeparator(os);
438 if (lastChar < 0) {
439 return lastChar;
440 }
441 }
442
443 // now iterate through all sub-items and call DoWrite() recursively
444 size = value.Size();
445 for (int i = 0; i < size; i++) {
446 bool comma = false;
447 if (i < size - 1) {
448 comma = true;
449 }
450 wxJSONValue v = value.ItemAt(i);
451 lastChar = DoWrite(os, v, 0, comma);
452 if (lastChar < 0) {
453 return lastChar;
454 }
455 }
456 --m_level;
457 lastChar = WriteIndent(os);
458 if (lastChar < 0) {
459 return lastChar;
460 }
461 os.PutC(']');
462 break;
463
464 case wxJSONTYPE_OBJECT:
465 ++m_level;
466
467 os.PutC('{');
468 // the inline comment for objects and arrays are printed in the open char
469 if (commentPos == wxJSONVALUE_COMMENT_INLINE) {
470 commentPos = -1; // we have already written the comment
471 lastChar = WriteComment(os, value, false);
472 if (lastChar < 0) {
473 return lastChar;
474 }
475 if (lastChar != '\n') {
476 WriteSeparator(os);
477 }
478 } else {
479 lastChar = WriteSeparator(os);
480 }
481
482 map = value.AsMap();
483 size = value.Size();
484 count = 0;
485 for (it = map->begin(); it != map->end(); ++it) {
486 // get the key and the value
487 wxString key = it->first;
488 const wxJSONValue& v = it->second;
489 bool comma = false;
490 if (count < size - 1) {
491 comma = true;
492 }
493 lastChar = DoWrite(os, v, &key, comma);
494 if (lastChar < 0) {
495 return lastChar;
496 }
497 count++;
498 }
499 --m_level;
500 lastChar = WriteIndent(os);
501 if (lastChar < 0) {
502 return lastChar;
503 }
504 os.PutC('}');
505 break;
506
507 default:
508 // a not yet defined wxJSONType: we FAIL
509 wxFAIL_MSG("wxJSONWriter::DoWrite() undefined wxJSONType type");
510 break;
511 }
512
513 // writes the comma character before the inline comment
514 if (comma) {
515 os.PutC(',');
516 }
517
518 if (commentPos == wxJSONVALUE_COMMENT_INLINE) {
519 lastChar = WriteComment(os, value, false);
520 if (lastChar < 0) {
521 return lastChar;
522 }
523 } else if (commentPos == wxJSONVALUE_COMMENT_AFTER) {
524 WriteSeparator(os);
525 lastChar = WriteComment(os, value, true);
526 if (lastChar < 0) {
527 return lastChar;
528 }
529 }
530 if (lastChar != '\n') {
531 lastChar = WriteSeparator(os);
532 }
533 return lastChar;
534}
535
537int wxJSONWriter::WriteComment(wxOutputStream& os, const wxJSONValue& value,
538 bool indent) {
539 // the function returns the last character written which should be
540 // a LF char or -1 in case of errors
541 // if nothing is written, returns ZERO
542 int lastChar = 0;
543
544 // only write comments if the style include the WRITE_COMMENTS flag
545 if ((m_style & wxJSONWRITER_WRITE_COMMENTS) == 0) {
546 return lastChar;
547 }
548
549 const wxArrayString cmt = value.GetCommentArray();
550 int cmtSize = cmt.GetCount();
551 for (int i = 0; i < cmtSize; i++) {
552 if (indent) {
553 WriteIndent(os);
554 } else {
555 os.PutC('\t');
556 }
557 WriteString(os, cmt[i]);
558 lastChar = cmt[i].Last();
559 if (lastChar != '\n') {
560 os.PutC('\n');
561 lastChar = '\n';
562 }
563 }
564 return lastChar;
565}
566
568
580int wxJSONWriter::WriteIndent(wxOutputStream& os) {
581 int lastChar = WriteIndent(os, m_level);
582 return lastChar;
583}
584
586
600int wxJSONWriter::WriteIndent(wxOutputStream& os, int num) {
601 int lastChar = 0;
602 if (!(m_style & wxJSONWRITER_STYLED) ||
603 (m_style & wxJSONWRITER_NO_INDENTATION)) {
604 return lastChar;
605 }
606
607 int numChars = m_indent + (m_step * num);
608 char c = ' ';
609 if (m_style & wxJSONWRITER_TAB_INDENT) {
610 c = '\t';
611 numChars = num;
612 }
613
614 for (int i = 0; i < numChars; i++) {
615 os.PutC(c);
616 if (os.GetLastError() != wxSTREAM_NO_ERROR) {
617 return -1;
618 }
619 }
620 return c;
621}
622
624
637int wxJSONWriter::WriteStringValue(wxOutputStream& os, const wxString& str) {
638 // JSON values of type STRING are written by converting the whole string
639 // to UTF-8 and then copying the UTF-8 buffer to the 'os' stream
640 // one byte at a time and processing them
641 os.PutC('\"'); // open quotes
642
643 // the buffer that has to be written is either UTF-8 or ANSI c_str() depending
644 // on the 'm_noUtf8' flag
645 char* writeBuff = 0;
646 wxCharBuffer utf8CB = str.ToUTF8(); // the UTF-8 buffer
647#if !defined(wxJSON_USE_UNICODE)
648 wxCharBuffer ansiCB(str.c_str()); // the ANSI buffer
649 if (m_noUtf8) {
650 writeBuff = ansiCB.data();
651 } else {
652 writeBuff = utf8CB.data();
653 }
654#else
655 writeBuff = utf8CB.data();
656#endif
657
658 // NOTE: in ANSI builds UTF-8 conversion may fail (see samples/test5.cpp,
659 // test 7.3) although I do not know why
660 if (writeBuff == nullptr) {
661 const char* err =
662 "<wxJSONWriter::WriteStringValue(): error converting the string to a "
663 "UTF8 buffer>";
664 os.Write(err, strlen(err));
665 return 0;
666 }
667 size_t len = strlen(writeBuff);
668 int lastChar = 0;
669
670 // store the column at which the string starts
671 // splitting strings only happen if the string starts within
672 // column wxJSONWRITER_LAST_COL (default 50)
673 // see 'include/wx/json_defs.h' for the defines
674 int tempCol = m_colNo;
675
676 // now write the UTF8 buffer processing the bytes
677 size_t i;
678 for (i = 0; i < len; i++) {
679 bool shouldEscape = false;
680 unsigned char ch = *writeBuff;
681 ++writeBuff; // point to the next byte
682
683 // the escaped character
684 char escCh = 0;
685
686 // for every character we have to check if it is a character that
687 // needs to be escaped: note that characters that should be escaped
688 // may be not if some writer's flags are specified
689 switch (ch) {
690 case '\"': // quotes
691 shouldEscape = true;
692 escCh = '\"';
693 break;
694 case '\\': // reverse solidus
695 shouldEscape = true;
696 escCh = '\\';
697 break;
698 case '/': // solidus
699 shouldEscape = true;
700 escCh = '/';
701 break;
702 case '\b': // backspace
703 shouldEscape = true;
704 escCh = 'b';
705 break;
706 case '\f': // formfeed
707 shouldEscape = true;
708 escCh = 'f';
709 break;
710 case '\n': // newline
711 shouldEscape = true;
712 escCh = 'n';
713 break;
714 case '\r': // carriage-return
715 shouldEscape = true;
716 escCh = 'r';
717 break;
718 case '\t': // horizontal tab
719 shouldEscape = true;
720 escCh = 't';
721 break;
722 default:
723 shouldEscape = false;
724 break;
725 } // end switch
726
727 // if the character is a control character that is not identified by a
728 // lowercase letter, we should escape it
729 if (!shouldEscape && ch < 32) {
730 char b[8];
731 snprintf(b, 8, "\\u%04X", (int)ch);
732 os.Write(b, 6);
733 if (os.GetLastError() != wxSTREAM_NO_ERROR) {
734 return -1;
735 }
736 }
737
738 // the char is not a control character
739 else {
740 // some characters that should be escaped are not escaped
741 // if the writer was constructed with some flags
742 if (shouldEscape && !(m_style & wxJSONWRITER_ESCAPE_SOLIDUS)) {
743 if (ch == '/') {
744 shouldEscape = false;
745 }
746 }
747 if (shouldEscape && (m_style & wxJSONWRITER_MULTILINE_STRING)) {
748 if (ch == '\n' || ch == '\t') {
749 shouldEscape = false;
750 }
751 }
752
753 // now write the character prepended by ESC if it should be escaped
754 if (shouldEscape) {
755 os.PutC('\\');
756 os.PutC(escCh);
757 if (os.GetLastError() != wxSTREAM_NO_ERROR) {
758 return -1;
759 }
760 } else {
761 // a normal char or a UTF-8 units: write the character
762 os.PutC(ch);
763 if (os.GetLastError() != wxSTREAM_NO_ERROR) {
764 return -1;
765 }
766 }
767 }
768
769 // check if SPLIT_STRING flag is set and if the string has to
770 // be splitted
771 if ((m_style & wxJSONWRITER_STYLED) &&
772 (m_style & wxJSONWRITER_SPLIT_STRING)) {
773 // split the string if the character written is LF
774 if (ch == '\n') {
775 // close quotes and CR
776 os.Write("\"\n", 2);
777 lastChar = WriteIndent(os, m_level + 2); // write indentation
778 os.PutC('\"'); // reopen quotes
779 if (lastChar < 0) {
780 return lastChar;
781 }
782 }
783 // split the string only if there is at least wxJSONWRITER_MIN_LENGTH
784 // character to write and the character written is a punctuation or space
785 // BUG: the following does not work because the columns are not counted
786 else if ((m_colNo >= wxJSONWRITER_SPLIT_COL) &&
787 (tempCol <= wxJSONWRITER_LAST_COL)) {
788 if (IsSpace(ch) || IsPunctuation(ch)) {
789 if (len - i > wxJSONWRITER_MIN_LENGTH) {
790 // close quotes and CR
791 os.Write("\"\n", 2);
792 lastChar = WriteIndent(os, m_level + 2); // write indentation
793 os.PutC('\"'); // reopen quotes
794 if (lastChar < 0) {
795 return lastChar;
796 }
797 }
798 }
799 }
800 }
801 } // end for
802 os.PutC('\"'); // close quotes
803 return 0;
804}
805
807
813int wxJSONWriter::WriteString(wxOutputStream& os, const wxString& str) {
814 wxLogTrace(writerTraceMask, "(%s) string to write=%s", __PRETTY_FUNCTION__,
815 str.c_str());
816 int lastChar = 0;
817 char* writeBuff = nullptr;
818
819 // the buffer that has to be written is either UTF-8 or ANSI c_str() depending
820 // on the 'm_noUtf8' flag
821 wxCharBuffer utf8CB = str.ToUTF8(); // the UTF-8 buffer
822#if !defined(wxJSON_USE_UNICODE)
823 wxCharBuffer ansiCB(str.c_str()); // the ANSI buffer
824
825 if (m_noUtf8) {
826 writeBuff = ansiCB.data();
827 } else {
828 writeBuff = utf8CB.data();
829 }
830#else
831 writeBuff = utf8CB.data();
832#endif
833
834 // NOTE: in ANSI builds UTF-8 conversion may fail (see samples/test5.cpp,
835 // test 7.3) although I do not know why
836 if (writeBuff == nullptr) {
837 const char* err =
838 "<wxJSONWriter::WriteComment(): error converting the string to UTF-8>";
839 os.Write(err, strlen(err));
840 return 0;
841 }
842 size_t len = strlen(writeBuff);
843
844 os.Write(writeBuff, len);
845 if (os.GetLastError() != wxSTREAM_NO_ERROR) {
846 return -1;
847 }
848
849 wxLogTrace(writerTraceMask, "(%s) result=%d", __PRETTY_FUNCTION__, lastChar);
850 return lastChar;
851}
852
854
857int wxJSONWriter::WriteNullValue(wxOutputStream& os) {
858 os.Write("null", 4);
859 if (os.GetLastError() != wxSTREAM_NO_ERROR) {
860 return -1;
861 }
862 return 0;
863}
864
866
872int wxJSONWriter::WriteIntValue(wxOutputStream& os, const wxJSONValue& value) {
873 int r = 0;
874 char buffer[32]; // need to store 64-bits integers (max 20 digits)
875 size_t len;
876
877 wxJSONRefData* data = value.GetRefData();
878 wxASSERT(data);
879
880#if defined(wxJSON_64BIT_INT)
881#if wxCHECK_VERSION(2, 9, 0) || !defined(wxJSON_USE_UNICODE)
882 // this is fine for wxW 2.9 and for wxW 2.8 ANSI
883 snprintf(buffer, 32, "%" wxLongLongFmtSpec "d", data->m_value.m_valInt64);
884#else
885 // this is for wxW 2.8 Unicode: in order to use the cross-platform
886 // format specifier, we use the wxString's sprintf() function and then
887 // convert to UTF-8 before writing to the stream
888 wxString s;
889 s.Printf("%" wxLongLongFmtSpec "d", data->m_value.m_valInt64);
890 wxCharBuffer cb = s.ToUTF8();
891 const char* cbData = cb.data();
892 len = strlen(cbData);
893 wxASSERT(len < 32);
894 memcpy(buffer, cbData, len);
895 buffer[len] = 0;
896#endif
897#else
898 snprintf(buffer, 32, "%ld", data->m_value.m_valLong);
899#endif
900 len = strlen(buffer);
901 os.Write(buffer, len);
902 if (os.GetLastError() != wxSTREAM_NO_ERROR) {
903 r = -1;
904 }
905 return r;
906}
907
909
917int wxJSONWriter::WriteUIntValue(wxOutputStream& os, const wxJSONValue& value) {
918 int r = 0;
919 size_t len;
920
921 // prepend a plus sign if the style specifies that unsigned integers
922 // have to be recognized by the JSON reader
923 if (m_style & wxJSONWRITER_RECOGNIZE_UNSIGNED) {
924 os.PutC('+');
925 }
926
927 char buffer[32]; // need to store 64-bits integers (max 20 digits)
928 wxJSONRefData* data = value.GetRefData();
929 wxASSERT(data);
930
931#if defined(wxJSON_64BIT_INT)
932#if wxCHECK_VERSION(2, 9, 0) || !defined(wxJSON_USE_UNICODE)
933 // this is fine for wxW 2.9 and for wxW 2.8 ANSI
934 snprintf(buffer, 32, "%" wxLongLongFmtSpec "u", data->m_value.m_valUInt64);
935#else
936 // this is for wxW 2.8 Unicode: in order to use the cross-platform
937 // format specifier, we use the wxString's sprintf() function and then
938 // convert to UTF-8 before writing to the stream
939 wxString s;
940 s.Printf("%" wxLongLongFmtSpec "u", data->m_value.m_valInt64);
941 wxCharBuffer cb = s.ToUTF8();
942 const char* cbData = cb.data();
943 len = strlen(cbData);
944 wxASSERT(len < 32);
945 memcpy(buffer, cbData, len);
946 buffer[len] = 0;
947#endif
948#else
949 snprintf(buffer, 32, "%lu", data->m_value.m_valULong);
950#endif
951 len = strlen(buffer);
952 os.Write(buffer, len);
953 if (os.GetLastError() != wxSTREAM_NO_ERROR) {
954 r = -1;
955 }
956 return r;
957}
958
960
971int wxJSONWriter::WriteDoubleValue(wxOutputStream& os,
972 const wxJSONValue& value) {
973 int r = 0;
974
975 char buffer[32];
976 wxJSONRefData* data = value.GetRefData();
977 wxASSERT(data);
978 snprintf(buffer, 32, m_fmt, data->m_value.m_valDouble);
979 size_t len = strlen(buffer);
980 os.Write(buffer, len);
981 if (os.GetLastError() != wxSTREAM_NO_ERROR) {
982 r = -1;
983 }
984 return r;
985}
986
988
994int wxJSONWriter::WriteBoolValue(wxOutputStream& os, const wxJSONValue& value) {
995 int r = 0;
996 const char* f = "false";
997 const char* t = "true";
998 wxJSONRefData* data = value.GetRefData();
999 wxASSERT(data);
1000
1001 const char* c = f; // defaults to FALSE
1002
1003 if (data->m_value.m_valBool) {
1004 c = t;
1005 }
1006
1007 size_t len = strlen(c);
1008 os.Write(c, len);
1009 if (os.GetLastError() != wxSTREAM_NO_ERROR) {
1010 r = -1;
1011 }
1012 return r;
1013}
1014
1016int wxJSONWriter::WriteKey(wxOutputStream& os, const wxString& key) {
1017 wxLogTrace(writerTraceMask, "(%s) key write=%s", __PRETTY_FUNCTION__,
1018 key.c_str());
1019
1020 int lastChar = WriteStringValue(os, key);
1021 os.Write(" : ", 3);
1022 return lastChar;
1023}
1024
1026
1041int wxJSONWriter::WriteInvalid(wxOutputStream& os) {
1042 wxFAIL_MSG(
1043 "wxJSONWriter::WriteInvalid() cannot be called (not a valid JSON "
1044 "text");
1045 int lastChar = 0;
1046 os.Write("<invalid JSON value>", 9);
1047 return lastChar;
1048}
1049
1051
1060int wxJSONWriter::WriteMemoryBuff(wxOutputStream& os,
1061 const wxMemoryBuffer& buff) {
1062#define MAX_BYTES_PER_ROW 20
1063 char str[16];
1064
1065 // if STYLED and SPLIT_STRING flags are set, the function writes 20 bytes on
1066 // every row the following is the counter of bytes written. the string is
1067 // splitted only for the special meory buffer type, not for array of INTs
1068 int bytesWritten = 0;
1069 bool splitString = false;
1070 if ((m_style & wxJSONWRITER_STYLED) &&
1071 (m_style & wxJSONWRITER_SPLIT_STRING)) {
1072 splitString = true;
1073 }
1074
1075 size_t buffLen = buff.GetDataLen();
1076 unsigned char* ptr = (unsigned char*)buff.GetData();
1077 wxASSERT(ptr);
1078 char openChar = '\'';
1079 char closeChar = '\'';
1080 bool asArray = false;
1081
1082 if ((m_style & wxJSONWRITER_MEMORYBUFF) == 0) {
1083 // if the special flag is not specified, write as an array of INTs
1084 openChar = '[';
1085 closeChar = ']';
1086 asArray = true;
1087 }
1088 // write the open character
1089 os.PutC(openChar);
1090
1091 for (size_t i = 0; i < buffLen; i++) {
1092 unsigned char c = *ptr;
1093 ++ptr;
1094
1095 if (asArray) {
1096 snprintf(str, 14, "%d", c);
1097 size_t len = strlen(str);
1098 wxASSERT(len <= 3);
1099 wxASSERT(len >= 1);
1100 str[len] = ',';
1101 // do not write the comma char for the last element
1102 if (i < buffLen - 1) {
1103 ++len;
1104 }
1105 os.Write(str, len);
1106 if (os.GetLastError() != wxSTREAM_NO_ERROR) {
1107 return -1;
1108 }
1109 } else {
1110 // now convert the byte in two hex digits
1111 char c1 = c / 16;
1112 char c2 = c % 16;
1113 c1 += '0';
1114 c2 += '0';
1115 if (c1 > '9') {
1116 c1 += 7;
1117 }
1118 if (c2 > '9') {
1119 c2 += 7;
1120 }
1121 os.PutC(c1);
1122 os.PutC(c2);
1123 if (os.GetLastError() != wxSTREAM_NO_ERROR) {
1124 return -1;
1125 }
1126 if (splitString) {
1127 ++bytesWritten;
1128 }
1129
1130 if ((bytesWritten >= MAX_BYTES_PER_ROW) && ((buffLen - i) >= 5)) {
1131 // split the string if we wrote 20 bytes, but only is we have to
1132 // write at least 5 bytes
1133 os.Write("\'\n", 2);
1134 int lastChar = WriteIndent(os, m_level + 2); // write indentation
1135 os.PutC('\''); // reopen quotes
1136 if (lastChar < 0) {
1137 return lastChar;
1138 }
1139 bytesWritten = 0;
1140 }
1141 }
1142 }
1143
1144 // write the close character
1145 os.PutC(closeChar);
1146 return closeChar;
1147}
1148
1150
1160int wxJSONWriter::WriteSeparator(wxOutputStream& os) {
1161 int lastChar = '\n';
1162 if ((m_style & wxJSONWRITER_STYLED) &&
1163 !(m_style & wxJSONWRITER_NO_LINEFEEDS)) {
1164 os.PutC('\n');
1165 }
1166 return lastChar;
1167}
1168
1170bool wxJSONWriter::IsSpace(wxChar ch) {
1171 bool r = false;
1172 switch (ch) {
1173 case ' ':
1174 case '\t':
1175 case '\r':
1176 case '\f':
1177 case '\n':
1178 r = true;
1179 break;
1180 default:
1181 break;
1182 }
1183 return r;
1184}
1185
1188 bool r = false;
1189 switch (ch) {
1190 case '.':
1191 case ',':
1192 case ';':
1193 case ':':
1194 case '!':
1195 case '?':
1196 r = true;
1197 break;
1198 default:
1199 break;
1200 }
1201 return r;
1202}
1203
1204/*
1205{
1206}
1207*/
The reference counted JSON value data (internal use).
Definition jsonval.h:350
The JSON value class implementation.
Definition jsonval.h:84
wxJSONValue ItemAt(unsigned index) const
Return the item at the specified index.
Definition jsonval.cpp:1655
int WriteComment(wxOutputStream &os, const wxJSONValue &value, bool indent)
Write the comment strings, if any.
int WriteInvalid(wxOutputStream &os)
Write the invalid JSON value to the output stream.
int WriteUIntValue(wxOutputStream &os, const wxJSONValue &v)
Writes a value of type UNSIGNED INT.
bool IsPunctuation(wxChar ch)
Returns TRUE if the character if a puctuation character.
~wxJSONWriter()
Dtor - does nothing.
void Write(const wxJSONValue &value, wxString &str)
Write the JSONvalue object to a JSON text.
void SetDoubleFmtString(const char *fmt)
Set the format string for double values.
int WriteIntValue(wxOutputStream &os, const wxJSONValue &v)
Writes a value of type INT.
int WriteKey(wxOutputStream &os, const wxString &key)
Write the key of a key/value element to the output stream.
int WriteIndent(wxOutputStream &os)
Writes the indentation to the JSON text.
int WriteBoolValue(wxOutputStream &os, const wxJSONValue &v)
Writes a value of type BOOL.
bool IsSpace(wxChar ch)
Returns TRUE if the character is a space character.
int WriteNullValue(wxOutputStream &os)
Write the nullptr JSON value to the output stream.
int WriteStringValue(wxOutputStream &os, const wxString &str)
Write the provided string to the output object.
int WriteString(wxOutputStream &os, const wxString &str)
Write a generic string.
int WriteMemoryBuff(wxOutputStream &os, const wxMemoryBuffer &buff)
Write a JSON value of type memory buffer.
wxJSONWriter(int style=wxJSONWRITER_STYLED, int indent=0, int step=3)
Ctor.
int WriteDoubleValue(wxOutputStream &os, const wxJSONValue &v)
Writes a value of type DOUBLE.
int DoWrite(wxOutputStream &os, const wxJSONValue &value, const wxString *key, bool comma)
Perform the real write operation.
int WriteSeparator(wxOutputStream &os)
Writes the separator between values.