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