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 = _T("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 _T("wxJSONWriter::WriteEmpty() cannot be called (not a valid JSON ")
386 _T("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(_T("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, _T("(%s) string to write=%s"),
815 __PRETTY_FUNCTION__, 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, _T("(%s) result=%d"), __PRETTY_FUNCTION__,
850 lastChar);
851 return lastChar;
852}
853
855
858int wxJSONWriter::WriteNullValue(wxOutputStream& os) {
859 os.Write("null", 4);
860 if (os.GetLastError() != wxSTREAM_NO_ERROR) {
861 return -1;
862 }
863 return 0;
864}
865
867
873int wxJSONWriter::WriteIntValue(wxOutputStream& os, const wxJSONValue& value) {
874 int r = 0;
875 char buffer[32]; // need to store 64-bits integers (max 20 digits)
876 size_t len;
877
878 wxJSONRefData* data = value.GetRefData();
879 wxASSERT(data);
880
881#if defined(wxJSON_64BIT_INT)
882#if wxCHECK_VERSION(2, 9, 0) || !defined(wxJSON_USE_UNICODE)
883 // this is fine for wxW 2.9 and for wxW 2.8 ANSI
884 snprintf(buffer, 32, "%" wxLongLongFmtSpec "d", data->m_value.m_valInt64);
885#else
886 // this is for wxW 2.8 Unicode: in order to use the cross-platform
887 // format specifier, we use the wxString's sprintf() function and then
888 // convert to UTF-8 before writing to the stream
889 wxString s;
890 s.Printf(_T("%") wxLongLongFmtSpec _T("d"), data->m_value.m_valInt64);
891 wxCharBuffer cb = s.ToUTF8();
892 const char* cbData = cb.data();
893 len = strlen(cbData);
894 wxASSERT(len < 32);
895 memcpy(buffer, cbData, len);
896 buffer[len] = 0;
897#endif
898#else
899 snprintf(buffer, 32, "%ld", data->m_value.m_valLong);
900#endif
901 len = strlen(buffer);
902 os.Write(buffer, len);
903 if (os.GetLastError() != wxSTREAM_NO_ERROR) {
904 r = -1;
905 }
906 return r;
907}
908
910
918int wxJSONWriter::WriteUIntValue(wxOutputStream& os, const wxJSONValue& value) {
919 int r = 0;
920 size_t len;
921
922 // prepend a plus sign if the style specifies that unsigned integers
923 // have to be recognized by the JSON reader
924 if (m_style & wxJSONWRITER_RECOGNIZE_UNSIGNED) {
925 os.PutC('+');
926 }
927
928 char buffer[32]; // need to store 64-bits integers (max 20 digits)
929 wxJSONRefData* data = value.GetRefData();
930 wxASSERT(data);
931
932#if defined(wxJSON_64BIT_INT)
933#if wxCHECK_VERSION(2, 9, 0) || !defined(wxJSON_USE_UNICODE)
934 // this is fine for wxW 2.9 and for wxW 2.8 ANSI
935 snprintf(buffer, 32, "%" wxLongLongFmtSpec "u", data->m_value.m_valUInt64);
936#else
937 // this is for wxW 2.8 Unicode: in order to use the cross-platform
938 // format specifier, we use the wxString's sprintf() function and then
939 // convert to UTF-8 before writing to the stream
940 wxString s;
941 s.Printf(_T("%") wxLongLongFmtSpec _T("u"), data->m_value.m_valInt64);
942 wxCharBuffer cb = s.ToUTF8();
943 const char* cbData = cb.data();
944 len = strlen(cbData);
945 wxASSERT(len < 32);
946 memcpy(buffer, cbData, len);
947 buffer[len] = 0;
948#endif
949#else
950 snprintf(buffer, 32, "%lu", data->m_value.m_valULong);
951#endif
952 len = strlen(buffer);
953 os.Write(buffer, len);
954 if (os.GetLastError() != wxSTREAM_NO_ERROR) {
955 r = -1;
956 }
957 return r;
958}
959
961
972int wxJSONWriter::WriteDoubleValue(wxOutputStream& os,
973 const wxJSONValue& value) {
974 int r = 0;
975
976 char buffer[32];
977 wxJSONRefData* data = value.GetRefData();
978 wxASSERT(data);
979 snprintf(buffer, 32, m_fmt, data->m_value.m_valDouble);
980 size_t len = strlen(buffer);
981 os.Write(buffer, len);
982 if (os.GetLastError() != wxSTREAM_NO_ERROR) {
983 r = -1;
984 }
985 return r;
986}
987
989
995int wxJSONWriter::WriteBoolValue(wxOutputStream& os, const wxJSONValue& value) {
996 int r = 0;
997 const char* f = "false";
998 const char* t = "true";
999 wxJSONRefData* data = value.GetRefData();
1000 wxASSERT(data);
1001
1002 const char* c = f; // defaults to FALSE
1003
1004 if (data->m_value.m_valBool) {
1005 c = t;
1006 }
1007
1008 size_t len = strlen(c);
1009 os.Write(c, len);
1010 if (os.GetLastError() != wxSTREAM_NO_ERROR) {
1011 r = -1;
1012 }
1013 return r;
1014}
1015
1017int wxJSONWriter::WriteKey(wxOutputStream& os, const wxString& key) {
1018 wxLogTrace(writerTraceMask, _T("(%s) key write=%s"), __PRETTY_FUNCTION__,
1019 key.c_str());
1020
1021 int lastChar = WriteStringValue(os, key);
1022 os.Write(" : ", 3);
1023 return lastChar;
1024}
1025
1027
1042int wxJSONWriter::WriteInvalid(wxOutputStream& os) {
1043 wxFAIL_MSG(
1044 _T("wxJSONWriter::WriteInvalid() cannot be called (not a valid JSON ")
1045 _T("text"));
1046 int lastChar = 0;
1047 os.Write("<invalid JSON value>", 9);
1048 return lastChar;
1049}
1050
1052
1061int wxJSONWriter::WriteMemoryBuff(wxOutputStream& os,
1062 const wxMemoryBuffer& buff) {
1063#define MAX_BYTES_PER_ROW 20
1064 char str[16];
1065
1066 // if STYLED and SPLIT_STRING flags are set, the function writes 20 bytes on
1067 // every row the following is the counter of bytes written. the string is
1068 // splitted only for the special meory buffer type, not for array of INTs
1069 int bytesWritten = 0;
1070 bool splitString = false;
1071 if ((m_style & wxJSONWRITER_STYLED) &&
1072 (m_style & wxJSONWRITER_SPLIT_STRING)) {
1073 splitString = true;
1074 }
1075
1076 size_t buffLen = buff.GetDataLen();
1077 unsigned char* ptr = (unsigned char*)buff.GetData();
1078 wxASSERT(ptr);
1079 char openChar = '\'';
1080 char closeChar = '\'';
1081 bool asArray = false;
1082
1083 if ((m_style & wxJSONWRITER_MEMORYBUFF) == 0) {
1084 // if the special flag is not specified, write as an array of INTs
1085 openChar = '[';
1086 closeChar = ']';
1087 asArray = true;
1088 }
1089 // write the open character
1090 os.PutC(openChar);
1091
1092 for (size_t i = 0; i < buffLen; i++) {
1093 unsigned char c = *ptr;
1094 ++ptr;
1095
1096 if (asArray) {
1097 snprintf(str, 14, "%d", c);
1098 size_t len = strlen(str);
1099 wxASSERT(len <= 3);
1100 wxASSERT(len >= 1);
1101 str[len] = ',';
1102 // do not write the comma char for the last element
1103 if (i < buffLen - 1) {
1104 ++len;
1105 }
1106 os.Write(str, len);
1107 if (os.GetLastError() != wxSTREAM_NO_ERROR) {
1108 return -1;
1109 }
1110 } else {
1111 // now convert the byte in two hex digits
1112 char c1 = c / 16;
1113 char c2 = c % 16;
1114 c1 += '0';
1115 c2 += '0';
1116 if (c1 > '9') {
1117 c1 += 7;
1118 }
1119 if (c2 > '9') {
1120 c2 += 7;
1121 }
1122 os.PutC(c1);
1123 os.PutC(c2);
1124 if (os.GetLastError() != wxSTREAM_NO_ERROR) {
1125 return -1;
1126 }
1127 if (splitString) {
1128 ++bytesWritten;
1129 }
1130
1131 if ((bytesWritten >= MAX_BYTES_PER_ROW) && ((buffLen - i) >= 5)) {
1132 // split the string if we wrote 20 bytes, but only is we have to
1133 // write at least 5 bytes
1134 os.Write("\'\n", 2);
1135 int lastChar = WriteIndent(os, m_level + 2); // write indentation
1136 os.PutC('\''); // reopen quotes
1137 if (lastChar < 0) {
1138 return lastChar;
1139 }
1140 bytesWritten = 0;
1141 }
1142 }
1143 }
1144
1145 // write the close character
1146 os.PutC(closeChar);
1147 return closeChar;
1148}
1149
1151
1161int wxJSONWriter::WriteSeparator(wxOutputStream& os) {
1162 int lastChar = '\n';
1163 if ((m_style & wxJSONWRITER_STYLED) &&
1164 !(m_style & wxJSONWRITER_NO_LINEFEEDS)) {
1165 os.PutC('\n');
1166 }
1167 return lastChar;
1168}
1169
1171bool wxJSONWriter::IsSpace(wxChar ch) {
1172 bool r = false;
1173 switch (ch) {
1174 case ' ':
1175 case '\t':
1176 case '\r':
1177 case '\f':
1178 case '\n':
1179 r = true;
1180 break;
1181 default:
1182 break;
1183 }
1184 return r;
1185}
1186
1189 bool r = false;
1190 switch (ch) {
1191 case '.':
1192 case ',':
1193 case ';':
1194 case ':':
1195 case '!':
1196 case '?':
1197 r = true;
1198 break;
1199 default:
1200 break;
1201 }
1202 return r;
1203}
1204
1205/*
1206{
1207}
1208*/
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:1657
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.