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