ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/cbrown/Development/Plotting/Modules/JSON/jsoncpp.cpp
Revision: 1.1
Committed: Tue Oct 30 14:56:59 2012 UTC (12 years, 6 months ago) by buchmann
Branch: MAIN
CVS Tags: HEAD
Log Message:
Added development version of sample loading from JSON file. Not ready for prime time, but getting there. Uses amalgamated version of jsoncpp

File Contents

# Content
1 /// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/).
2 /// It is intented to be used with #include <json/json.h>
3
4 // //////////////////////////////////////////////////////////////////////
5 // Beginning of content of file: LICENSE
6 // //////////////////////////////////////////////////////////////////////
7
8 /*
9 The JsonCpp library's source code, including accompanying documentation,
10 tests and demonstration applications, are licensed under the following
11 conditions...
12
13 The author (Baptiste Lepilleur) explicitly disclaims copyright in all
14 jurisdictions which recognize such a disclaimer. In such jurisdictions,
15 this software is released into the Public Domain.
16
17 In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
18 2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is
19 released under the terms of the MIT License (see below).
20
21 In jurisdictions which recognize Public Domain property, the user of this
22 software may choose to accept it either as 1) Public Domain, 2) under the
23 conditions of the MIT License (see below), or 3) under the terms of dual
24 Public Domain/MIT License conditions described here, as they choose.
25
26 The MIT License is about as close to Public Domain as a license can get, and is
27 described in clear, concise terms at:
28
29 http://en.wikipedia.org/wiki/MIT_License
30
31 The full text of the MIT License follows:
32
33 ========================================================================
34 Copyright (c) 2007-2010 Baptiste Lepilleur
35
36 Permission is hereby granted, free of charge, to any person
37 obtaining a copy of this software and associated documentation
38 files (the "Software"), to deal in the Software without
39 restriction, including without limitation the rights to use, copy,
40 modify, merge, publish, distribute, sublicense, and/or sell copies
41 of the Software, and to permit persons to whom the Software is
42 furnished to do so, subject to the following conditions:
43
44 The above copyright notice and this permission notice shall be
45 included in all copies or substantial portions of the Software.
46
47 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
48 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
49 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
50 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
51 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
52 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
53 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
54 SOFTWARE.
55 ========================================================================
56 (END LICENSE TEXT)
57
58 The MIT license is compatible with both the GPL and commercial
59 software, affording one all of the rights of Public Domain with the
60 minor nuisance of being required to keep the above copyright notice
61 and license text in the source code. Note also that by accepting the
62 Public Domain "license" you can re-license your copy using whatever
63 license you like.
64
65 */
66
67 // //////////////////////////////////////////////////////////////////////
68 // End of content of file: LICENSE
69 // //////////////////////////////////////////////////////////////////////
70
71
72
73
74
75
76 #include "json.h"
77
78
79 // //////////////////////////////////////////////////////////////////////
80 // Beginning of content of file: src/lib_json/json_tool.h
81 // //////////////////////////////////////////////////////////////////////
82
83 // Copyright 2007-2010 Baptiste Lepilleur
84 // Distributed under MIT license, or public domain if desired and
85 // recognized in your jurisdiction.
86 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
87
88 #ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
89 # define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
90
91 /* This header provides common string manipulation support, such as UTF-8,
92 * portable conversion from/to string...
93 *
94 * It is an internal header that must not be exposed.
95 */
96
97 namespace Json {
98
99 /// Converts a unicode code-point to UTF-8.
100 static inline std::string
101 codePointToUTF8(unsigned int cp)
102 {
103 std::string result;
104
105 // based on description from http://en.wikipedia.org/wiki/UTF-8
106
107 if (cp <= 0x7f)
108 {
109 result.resize(1);
110 result[0] = static_cast<char>(cp);
111 }
112 else if (cp <= 0x7FF)
113 {
114 result.resize(2);
115 result[1] = static_cast<char>(0x80 | (0x3f & cp));
116 result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
117 }
118 else if (cp <= 0xFFFF)
119 {
120 result.resize(3);
121 result[2] = static_cast<char>(0x80 | (0x3f & cp));
122 result[1] = 0x80 | static_cast<char>((0x3f & (cp >> 6)));
123 result[0] = 0xE0 | static_cast<char>((0xf & (cp >> 12)));
124 }
125 else if (cp <= 0x10FFFF)
126 {
127 result.resize(4);
128 result[3] = static_cast<char>(0x80 | (0x3f & cp));
129 result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
130 result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
131 result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
132 }
133
134 return result;
135 }
136
137
138 /// Returns true if ch is a control character (in range [0,32[).
139 static inline bool
140 isControlCharacter(char ch)
141 {
142 return ch > 0 && ch <= 0x1F;
143 }
144
145
146 enum {
147 /// Constant that specify the size of the buffer that must be passed to uintToString.
148 uintToStringBufferSize = 3*sizeof(LargestUInt)+1
149 };
150
151 // Defines a char buffer for use with uintToString().
152 typedef char UIntToStringBuffer[uintToStringBufferSize];
153
154
155 /** Converts an unsigned integer to string.
156 * @param value Unsigned interger to convert to string
157 * @param current Input/Output string buffer.
158 * Must have at least uintToStringBufferSize chars free.
159 */
160 static inline void
161 uintToString( LargestUInt value,
162 char *&current )
163 {
164 *--current = 0;
165 do
166 {
167 *--current = char(value % 10) + '0';
168 value /= 10;
169 }
170 while ( value != 0 );
171 }
172
173 } // namespace Json {
174
175 #endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED
176
177 // //////////////////////////////////////////////////////////////////////
178 // End of content of file: src/lib_json/json_tool.h
179 // //////////////////////////////////////////////////////////////////////
180
181
182
183
184
185
186 // //////////////////////////////////////////////////////////////////////
187 // Beginning of content of file: src/lib_json/json_reader.cpp
188 // //////////////////////////////////////////////////////////////////////
189
190 // Copyright 2007-2011 Baptiste Lepilleur
191 // Distributed under MIT license, or public domain if desired and
192 // recognized in your jurisdiction.
193 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
194
195 #if !defined(JSON_IS_AMALGAMATION)
196 # include <json/assertions.h>
197 # include <json/reader.h>
198 # include <json/value.h>
199 # include "json_tool.h"
200 #endif // if !defined(JSON_IS_AMALGAMATION)
201 #include <utility>
202 #include <cstdio>
203 #include <cassert>
204 #include <cstring>
205 #include <stdexcept>
206
207 #if _MSC_VER >= 1400 // VC++ 8.0
208 #pragma warning( disable : 4996 ) // disable warning about strdup being deprecated.
209 #endif
210
211 namespace Json {
212
213 // Implementation of class Features
214 // ////////////////////////////////
215
216 Features::Features()
217 : allowComments_( true )
218 , strictRoot_( false )
219 {
220 }
221
222
223 Features
224 Features::all()
225 {
226 return Features();
227 }
228
229
230 Features
231 Features::strictMode()
232 {
233 Features features;
234 features.allowComments_ = false;
235 features.strictRoot_ = true;
236 return features;
237 }
238
239 // Implementation of class Reader
240 // ////////////////////////////////
241
242
243 static inline bool
244 in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4 )
245 {
246 return c == c1 || c == c2 || c == c3 || c == c4;
247 }
248
249 static inline bool
250 in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4, Reader::Char c5 )
251 {
252 return c == c1 || c == c2 || c == c3 || c == c4 || c == c5;
253 }
254
255
256 static bool
257 containsNewLine( Reader::Location begin,
258 Reader::Location end )
259 {
260 for ( ;begin < end; ++begin )
261 if ( *begin == '\n' || *begin == '\r' )
262 return true;
263 return false;
264 }
265
266
267 // Class Reader
268 // //////////////////////////////////////////////////////////////////
269
270 Reader::Reader()
271 : errors_(),
272 document_(),
273 begin_(),
274 end_(),
275 current_(),
276 lastValueEnd_(),
277 lastValue_(),
278 commentsBefore_(),
279 features_( Features::all() ),
280 collectComments_()
281 {
282 }
283
284
285 Reader::Reader( const Features &features )
286 : errors_(),
287 document_(),
288 begin_(),
289 end_(),
290 current_(),
291 lastValueEnd_(),
292 lastValue_(),
293 commentsBefore_(),
294 features_( features ),
295 collectComments_()
296 {
297 }
298
299
300 bool
301 Reader::parse( const std::string &document,
302 Value &root,
303 bool collectComments )
304 {
305 document_ = document;
306 const char *begin = document_.c_str();
307 const char *end = begin + document_.length();
308 return parse( begin, end, root, collectComments );
309 }
310
311
312 bool
313 Reader::parse( std::istream& sin,
314 Value &root,
315 bool collectComments )
316 {
317 //std::istream_iterator<char> begin(sin);
318 //std::istream_iterator<char> end;
319 // Those would allow streamed input from a file, if parse() were a
320 // template function.
321
322 // Since std::string is reference-counted, this at least does not
323 // create an extra copy.
324 std::string doc;
325 std::getline(sin, doc, (char)EOF);
326 return parse( doc, root, collectComments );
327 }
328
329 bool
330 Reader::parse( const char *beginDoc, const char *endDoc,
331 Value &root,
332 bool collectComments )
333 {
334 if ( !features_.allowComments_ )
335 {
336 collectComments = false;
337 }
338
339 begin_ = beginDoc;
340 end_ = endDoc;
341 collectComments_ = collectComments;
342 current_ = begin_;
343 lastValueEnd_ = 0;
344 lastValue_ = 0;
345 commentsBefore_ = "";
346 errors_.clear();
347 while ( !nodes_.empty() )
348 nodes_.pop();
349 nodes_.push( &root );
350
351 bool successful = readValue();
352 Token token;
353 skipCommentTokens( token );
354 if ( collectComments_ && !commentsBefore_.empty() )
355 root.setComment( commentsBefore_, commentAfter );
356 if ( features_.strictRoot_ )
357 {
358 if ( !root.isArray() && !root.isObject() )
359 {
360 // Set error location to start of doc, ideally should be first token found in doc
361 token.type_ = tokenError;
362 token.start_ = beginDoc;
363 token.end_ = endDoc;
364 addError( "A valid JSON document must be either an array or an object value.",
365 token );
366 return false;
367 }
368 }
369 return successful;
370 }
371
372
373 bool
374 Reader::readValue()
375 {
376 Token token;
377 skipCommentTokens( token );
378 bool successful = true;
379
380 if ( collectComments_ && !commentsBefore_.empty() )
381 {
382 currentValue().setComment( commentsBefore_, commentBefore );
383 commentsBefore_ = "";
384 }
385
386
387 switch ( token.type_ )
388 {
389 case tokenObjectBegin:
390 successful = readObject( token );
391 break;
392 case tokenArrayBegin:
393 successful = readArray( token );
394 break;
395 case tokenNumber:
396 successful = decodeNumber( token );
397 break;
398 case tokenString:
399 successful = decodeString( token );
400 break;
401 case tokenTrue:
402 currentValue() = true;
403 break;
404 case tokenFalse:
405 currentValue() = false;
406 break;
407 case tokenNull:
408 currentValue() = Value();
409 break;
410 default:
411 return addError( "Syntax error: value, object or array expected.", token );
412 }
413
414 if ( collectComments_ )
415 {
416 lastValueEnd_ = current_;
417 lastValue_ = &currentValue();
418 }
419
420 return successful;
421 }
422
423
424 void
425 Reader::skipCommentTokens( Token &token )
426 {
427 if ( features_.allowComments_ )
428 {
429 do
430 {
431 readToken( token );
432 }
433 while ( token.type_ == tokenComment );
434 }
435 else
436 {
437 readToken( token );
438 }
439 }
440
441
442 bool
443 Reader::expectToken( TokenType type, Token &token, const char *message )
444 {
445 readToken( token );
446 if ( token.type_ != type )
447 return addError( message, token );
448 return true;
449 }
450
451
452 bool
453 Reader::readToken( Token &token )
454 {
455 skipSpaces();
456 token.start_ = current_;
457 Char c = getNextChar();
458 bool ok = true;
459 switch ( c )
460 {
461 case '{':
462 token.type_ = tokenObjectBegin;
463 break;
464 case '}':
465 token.type_ = tokenObjectEnd;
466 break;
467 case '[':
468 token.type_ = tokenArrayBegin;
469 break;
470 case ']':
471 token.type_ = tokenArrayEnd;
472 break;
473 case '"':
474 token.type_ = tokenString;
475 ok = readString();
476 break;
477 case '/':
478 token.type_ = tokenComment;
479 ok = readComment();
480 break;
481 case '0':
482 case '1':
483 case '2':
484 case '3':
485 case '4':
486 case '5':
487 case '6':
488 case '7':
489 case '8':
490 case '9':
491 case '-':
492 token.type_ = tokenNumber;
493 readNumber();
494 break;
495 case 't':
496 token.type_ = tokenTrue;
497 ok = match( "rue", 3 );
498 break;
499 case 'f':
500 token.type_ = tokenFalse;
501 ok = match( "alse", 4 );
502 break;
503 case 'n':
504 token.type_ = tokenNull;
505 ok = match( "ull", 3 );
506 break;
507 case ',':
508 token.type_ = tokenArraySeparator;
509 break;
510 case ':':
511 token.type_ = tokenMemberSeparator;
512 break;
513 case 0:
514 token.type_ = tokenEndOfStream;
515 break;
516 default:
517 ok = false;
518 break;
519 }
520 if ( !ok )
521 token.type_ = tokenError;
522 token.end_ = current_;
523 return true;
524 }
525
526
527 void
528 Reader::skipSpaces()
529 {
530 while ( current_ != end_ )
531 {
532 Char c = *current_;
533 if ( c == ' ' || c == '\t' || c == '\r' || c == '\n' )
534 ++current_;
535 else
536 break;
537 }
538 }
539
540
541 bool
542 Reader::match( Location pattern,
543 int patternLength )
544 {
545 if ( end_ - current_ < patternLength )
546 return false;
547 int index = patternLength;
548 while ( index-- )
549 if ( current_[index] != pattern[index] )
550 return false;
551 current_ += patternLength;
552 return true;
553 }
554
555
556 bool
557 Reader::readComment()
558 {
559 Location commentBegin = current_ - 1;
560 Char c = getNextChar();
561 bool successful = false;
562 if ( c == '*' )
563 successful = readCStyleComment();
564 else if ( c == '/' )
565 successful = readCppStyleComment();
566 if ( !successful )
567 return false;
568
569 if ( collectComments_ )
570 {
571 CommentPlacement placement = commentBefore;
572 if ( lastValueEnd_ && !containsNewLine( lastValueEnd_, commentBegin ) )
573 {
574 if ( c != '*' || !containsNewLine( commentBegin, current_ ) )
575 placement = commentAfterOnSameLine;
576 }
577
578 addComment( commentBegin, current_, placement );
579 }
580 return true;
581 }
582
583
584 void
585 Reader::addComment( Location begin,
586 Location end,
587 CommentPlacement placement )
588 {
589 assert( collectComments_ );
590 if ( placement == commentAfterOnSameLine )
591 {
592 assert( lastValue_ != 0 );
593 lastValue_->setComment( std::string( begin, end ), placement );
594 }
595 else
596 {
597 if ( !commentsBefore_.empty() )
598 commentsBefore_ += "\n";
599 commentsBefore_ += std::string( begin, end );
600 }
601 }
602
603
604 bool
605 Reader::readCStyleComment()
606 {
607 while ( current_ != end_ )
608 {
609 Char c = getNextChar();
610 if ( c == '*' && *current_ == '/' )
611 break;
612 }
613 return getNextChar() == '/';
614 }
615
616
617 bool
618 Reader::readCppStyleComment()
619 {
620 while ( current_ != end_ )
621 {
622 Char c = getNextChar();
623 if ( c == '\r' || c == '\n' )
624 break;
625 }
626 return true;
627 }
628
629
630 void
631 Reader::readNumber()
632 {
633 while ( current_ != end_ )
634 {
635 if ( !(*current_ >= '0' && *current_ <= '9') &&
636 !in( *current_, '.', 'e', 'E', '+', '-' ) )
637 break;
638 ++current_;
639 }
640 }
641
642 bool
643 Reader::readString()
644 {
645 Char c = 0;
646 while ( current_ != end_ )
647 {
648 c = getNextChar();
649 if ( c == '\\' )
650 getNextChar();
651 else if ( c == '"' )
652 break;
653 }
654 return c == '"';
655 }
656
657
658 bool
659 Reader::readObject( Token &/*tokenStart*/ )
660 {
661 Token tokenName;
662 std::string name;
663 currentValue() = Value( objectValue );
664 while ( readToken( tokenName ) )
665 {
666 bool initialTokenOk = true;
667 while ( tokenName.type_ == tokenComment && initialTokenOk )
668 initialTokenOk = readToken( tokenName );
669 if ( !initialTokenOk )
670 break;
671 if ( tokenName.type_ == tokenObjectEnd && name.empty() ) // empty object
672 return true;
673 if ( tokenName.type_ != tokenString )
674 break;
675
676 name = "";
677 if ( !decodeString( tokenName, name ) )
678 return recoverFromError( tokenObjectEnd );
679
680 Token colon;
681 if ( !readToken( colon ) || colon.type_ != tokenMemberSeparator )
682 {
683 return addErrorAndRecover( "Missing ':' after object member name",
684 colon,
685 tokenObjectEnd );
686 }
687 Value &value = currentValue()[ name ];
688 nodes_.push( &value );
689 bool ok = readValue();
690 nodes_.pop();
691 if ( !ok ) // error already set
692 return recoverFromError( tokenObjectEnd );
693
694 Token comma;
695 if ( !readToken( comma )
696 || ( comma.type_ != tokenObjectEnd &&
697 comma.type_ != tokenArraySeparator &&
698 comma.type_ != tokenComment ) )
699 {
700 return addErrorAndRecover( "Missing ',' or '}' in object declaration",
701 comma,
702 tokenObjectEnd );
703 }
704 bool finalizeTokenOk = true;
705 while ( comma.type_ == tokenComment &&
706 finalizeTokenOk )
707 finalizeTokenOk = readToken( comma );
708 if ( comma.type_ == tokenObjectEnd )
709 return true;
710 }
711 return addErrorAndRecover( "Missing '}' or object member name",
712 tokenName,
713 tokenObjectEnd );
714 }
715
716
717 bool
718 Reader::readArray( Token &/*tokenStart*/ )
719 {
720 currentValue() = Value( arrayValue );
721 skipSpaces();
722 if ( *current_ == ']' ) // empty array
723 {
724 Token endArray;
725 readToken( endArray );
726 return true;
727 }
728 int index = 0;
729 for (;;)
730 {
731 Value &value = currentValue()[ index++ ];
732 nodes_.push( &value );
733 bool ok = readValue();
734 nodes_.pop();
735 if ( !ok ) // error already set
736 return recoverFromError( tokenArrayEnd );
737
738 Token token;
739 // Accept Comment after last item in the array.
740 ok = readToken( token );
741 while ( token.type_ == tokenComment && ok )
742 {
743 ok = readToken( token );
744 }
745 bool badTokenType = ( token.type_ != tokenArraySeparator &&
746 token.type_ != tokenArrayEnd );
747 if ( !ok || badTokenType )
748 {
749 return addErrorAndRecover( "Missing ',' or ']' in array declaration",
750 token,
751 tokenArrayEnd );
752 }
753 if ( token.type_ == tokenArrayEnd )
754 break;
755 }
756 return true;
757 }
758
759
760 bool
761 Reader::decodeNumber( Token &token )
762 {
763 bool isDouble = false;
764 for ( Location inspect = token.start_; inspect != token.end_; ++inspect )
765 {
766 isDouble = isDouble
767 || in( *inspect, '.', 'e', 'E', '+' )
768 || ( *inspect == '-' && inspect != token.start_ );
769 }
770 if ( isDouble )
771 return decodeDouble( token );
772 // Attempts to parse the number as an integer. If the number is
773 // larger than the maximum supported value of an integer then
774 // we decode the number as a double.
775 Location current = token.start_;
776 bool isNegative = *current == '-';
777 if ( isNegative )
778 ++current;
779 Value::LargestUInt maxIntegerValue = isNegative ? Value::LargestUInt(-Value::minLargestInt)
780 : Value::maxLargestUInt;
781 Value::LargestUInt threshold = maxIntegerValue / 10;
782 Value::LargestUInt value = 0;
783 while ( current < token.end_ )
784 {
785 Char c = *current++;
786 if ( c < '0' || c > '9' )
787 return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
788 Value::UInt digit(c - '0');
789 if ( value >= threshold )
790 {
791 // We've hit or exceeded the max value divided by 10 (rounded down). If
792 // a) we've only just touched the limit, b) this is the last digit, and
793 // c) it's small enough to fit in that rounding delta, we're okay.
794 // Otherwise treat this number as a double to avoid overflow.
795 if (value > threshold ||
796 current != token.end_ ||
797 digit > maxIntegerValue % 10)
798 {
799 return decodeDouble( token );
800 }
801 }
802 value = value * 10 + digit;
803 }
804 if ( isNegative )
805 currentValue() = -Value::LargestInt( value );
806 else if ( value <= Value::LargestUInt(Value::maxInt) )
807 currentValue() = Value::LargestInt( value );
808 else
809 currentValue() = value;
810 return true;
811 }
812
813
814 bool
815 Reader::decodeDouble( Token &token )
816 {
817 double value = 0;
818 const int bufferSize = 32;
819 int count;
820 int length = int(token.end_ - token.start_);
821
822 // Sanity check to avoid buffer overflow exploits.
823 if (length < 0) {
824 return addError( "Unable to parse token length", token );
825 }
826
827 // Avoid using a string constant for the format control string given to
828 // sscanf, as this can cause hard to debug crashes on OS X. See here for more
829 // info:
830 //
831 // http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html
832 char format[] = "%lf";
833
834 if ( length <= bufferSize )
835 {
836 Char buffer[bufferSize+1];
837 memcpy( buffer, token.start_, length );
838 buffer[length] = 0;
839 count = sscanf( buffer, format, &value );
840 }
841 else
842 {
843 std::string buffer( token.start_, token.end_ );
844 count = sscanf( buffer.c_str(), format, &value );
845 }
846
847 if ( count != 1 )
848 return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
849 currentValue() = value;
850 return true;
851 }
852
853
854 bool
855 Reader::decodeString( Token &token )
856 {
857 std::string decoded;
858 if ( !decodeString( token, decoded ) )
859 return false;
860 currentValue() = decoded;
861 return true;
862 }
863
864
865 bool
866 Reader::decodeString( Token &token, std::string &decoded )
867 {
868 decoded.reserve( token.end_ - token.start_ - 2 );
869 Location current = token.start_ + 1; // skip '"'
870 Location end = token.end_ - 1; // do not include '"'
871 while ( current != end )
872 {
873 Char c = *current++;
874 if ( c == '"' )
875 break;
876 else if ( c == '\\' )
877 {
878 if ( current == end )
879 return addError( "Empty escape sequence in string", token, current );
880 Char escape = *current++;
881 switch ( escape )
882 {
883 case '"': decoded += '"'; break;
884 case '/': decoded += '/'; break;
885 case '\\': decoded += '\\'; break;
886 case 'b': decoded += '\b'; break;
887 case 'f': decoded += '\f'; break;
888 case 'n': decoded += '\n'; break;
889 case 'r': decoded += '\r'; break;
890 case 't': decoded += '\t'; break;
891 case 'u':
892 {
893 unsigned int unicode;
894 if ( !decodeUnicodeCodePoint( token, current, end, unicode ) )
895 return false;
896 decoded += codePointToUTF8(unicode);
897 }
898 break;
899 default:
900 return addError( "Bad escape sequence in string", token, current );
901 }
902 }
903 else
904 {
905 decoded += c;
906 }
907 }
908 return true;
909 }
910
911 bool
912 Reader::decodeUnicodeCodePoint( Token &token,
913 Location &current,
914 Location end,
915 unsigned int &unicode )
916 {
917
918 if ( !decodeUnicodeEscapeSequence( token, current, end, unicode ) )
919 return false;
920 if (unicode >= 0xD800 && unicode <= 0xDBFF)
921 {
922 // surrogate pairs
923 if (end - current < 6)
924 return addError( "additional six characters expected to parse unicode surrogate pair.", token, current );
925 unsigned int surrogatePair;
926 if (*(current++) == '\\' && *(current++)== 'u')
927 {
928 if (decodeUnicodeEscapeSequence( token, current, end, surrogatePair ))
929 {
930 unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
931 }
932 else
933 return false;
934 }
935 else
936 return addError( "expecting another \\u token to begin the second half of a unicode surrogate pair", token, current );
937 }
938 return true;
939 }
940
941 bool
942 Reader::decodeUnicodeEscapeSequence( Token &token,
943 Location &current,
944 Location end,
945 unsigned int &unicode )
946 {
947 if ( end - current < 4 )
948 return addError( "Bad unicode escape sequence in string: four digits expected.", token, current );
949 unicode = 0;
950 for ( int index =0; index < 4; ++index )
951 {
952 Char c = *current++;
953 unicode *= 16;
954 if ( c >= '0' && c <= '9' )
955 unicode += c - '0';
956 else if ( c >= 'a' && c <= 'f' )
957 unicode += c - 'a' + 10;
958 else if ( c >= 'A' && c <= 'F' )
959 unicode += c - 'A' + 10;
960 else
961 return addError( "Bad unicode escape sequence in string: hexadecimal digit expected.", token, current );
962 }
963 return true;
964 }
965
966
967 bool
968 Reader::addError( const std::string &message,
969 Token &token,
970 Location extra )
971 {
972 ErrorInfo info;
973 info.token_ = token;
974 info.message_ = message;
975 info.extra_ = extra;
976 errors_.push_back( info );
977 return false;
978 }
979
980
981 bool
982 Reader::recoverFromError( TokenType skipUntilToken )
983 {
984 int errorCount = int(errors_.size());
985 Token skip;
986 for (;;)
987 {
988 if ( !readToken(skip) )
989 errors_.resize( errorCount ); // discard errors caused by recovery
990 if ( skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream )
991 break;
992 }
993 errors_.resize( errorCount );
994 return false;
995 }
996
997
998 bool
999 Reader::addErrorAndRecover( const std::string &message,
1000 Token &token,
1001 TokenType skipUntilToken )
1002 {
1003 addError( message, token );
1004 return recoverFromError( skipUntilToken );
1005 }
1006
1007
1008 Value &
1009 Reader::currentValue()
1010 {
1011 return *(nodes_.top());
1012 }
1013
1014
1015 Reader::Char
1016 Reader::getNextChar()
1017 {
1018 if ( current_ == end_ )
1019 return 0;
1020 return *current_++;
1021 }
1022
1023
1024 void
1025 Reader::getLocationLineAndColumn( Location location,
1026 int &line,
1027 int &column ) const
1028 {
1029 Location current = begin_;
1030 Location lastLineStart = current;
1031 line = 0;
1032 while ( current < location && current != end_ )
1033 {
1034 Char c = *current++;
1035 if ( c == '\r' )
1036 {
1037 if ( *current == '\n' )
1038 ++current;
1039 lastLineStart = current;
1040 ++line;
1041 }
1042 else if ( c == '\n' )
1043 {
1044 lastLineStart = current;
1045 ++line;
1046 }
1047 }
1048 // column & line start at 1
1049 column = int(location - lastLineStart) + 1;
1050 ++line;
1051 }
1052
1053
1054 std::string
1055 Reader::getLocationLineAndColumn( Location location ) const
1056 {
1057 int line, column;
1058 getLocationLineAndColumn( location, line, column );
1059 char buffer[18+16+16+1];
1060 sprintf( buffer, "Line %d, Column %d", line, column );
1061 return buffer;
1062 }
1063
1064
1065 // Deprecated. Preserved for backward compatibility
1066 std::string
1067 Reader::getFormatedErrorMessages() const
1068 {
1069 return getFormattedErrorMessages();
1070 }
1071
1072
1073 std::string
1074 Reader::getFormattedErrorMessages() const
1075 {
1076 std::string formattedMessage;
1077 for ( Errors::const_iterator itError = errors_.begin();
1078 itError != errors_.end();
1079 ++itError )
1080 {
1081 const ErrorInfo &error = *itError;
1082 formattedMessage += "* " + getLocationLineAndColumn( error.token_.start_ ) + "\n";
1083 formattedMessage += " " + error.message_ + "\n";
1084 if ( error.extra_ )
1085 formattedMessage += "See " + getLocationLineAndColumn( error.extra_ ) + " for detail.\n";
1086 }
1087 return formattedMessage;
1088 }
1089
1090
1091 std::istream& operator>>( std::istream &sin, Value &root )
1092 {
1093 Json::Reader reader;
1094 bool ok = reader.parse(sin, root, true);
1095 if (!ok) {
1096 fprintf(
1097 stderr,
1098 "Error from reader: %s",
1099 reader.getFormattedErrorMessages().c_str());
1100
1101 JSON_FAIL_MESSAGE("reader error");
1102 }
1103 return sin;
1104 }
1105
1106
1107 } // namespace Json
1108
1109 // //////////////////////////////////////////////////////////////////////
1110 // End of content of file: src/lib_json/json_reader.cpp
1111 // //////////////////////////////////////////////////////////////////////
1112
1113
1114
1115
1116
1117
1118 // //////////////////////////////////////////////////////////////////////
1119 // Beginning of content of file: src/lib_json/json_batchallocator.h
1120 // //////////////////////////////////////////////////////////////////////
1121
1122 // Copyright 2007-2010 Baptiste Lepilleur
1123 // Distributed under MIT license, or public domain if desired and
1124 // recognized in your jurisdiction.
1125 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
1126
1127 #ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED
1128 # define JSONCPP_BATCHALLOCATOR_H_INCLUDED
1129
1130 # include <stdlib.h>
1131 # include <assert.h>
1132
1133 # ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
1134
1135 namespace Json {
1136
1137 /* Fast memory allocator.
1138 *
1139 * This memory allocator allocates memory for a batch of object (specified by
1140 * the page size, the number of object in each page).
1141 *
1142 * It does not allow the destruction of a single object. All the allocated objects
1143 * can be destroyed at once. The memory can be either released or reused for future
1144 * allocation.
1145 *
1146 * The in-place new operator must be used to construct the object using the pointer
1147 * returned by allocate.
1148 */
1149 template<typename AllocatedType
1150 ,const unsigned int objectPerAllocation>
1151 class BatchAllocator
1152 {
1153 public:
1154 BatchAllocator( unsigned int objectsPerPage = 255 )
1155 : freeHead_( 0 )
1156 , objectsPerPage_( objectsPerPage )
1157 {
1158 // printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() );
1159 assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space.
1160 assert( objectsPerPage >= 16 );
1161 batches_ = allocateBatch( 0 ); // allocated a dummy page
1162 currentBatch_ = batches_;
1163 }
1164
1165 ~BatchAllocator()
1166 {
1167 for ( BatchInfo *batch = batches_; batch; )
1168 {
1169 BatchInfo *nextBatch = batch->next_;
1170 free( batch );
1171 batch = nextBatch;
1172 }
1173 }
1174
1175 /// allocate space for an array of objectPerAllocation object.
1176 /// @warning it is the responsability of the caller to call objects constructors.
1177 AllocatedType *allocate()
1178 {
1179 if ( freeHead_ ) // returns node from free list.
1180 {
1181 AllocatedType *object = freeHead_;
1182 freeHead_ = *(AllocatedType **)object;
1183 return object;
1184 }
1185 if ( currentBatch_->used_ == currentBatch_->end_ )
1186 {
1187 currentBatch_ = currentBatch_->next_;
1188 while ( currentBatch_ && currentBatch_->used_ == currentBatch_->end_ )
1189 currentBatch_ = currentBatch_->next_;
1190
1191 if ( !currentBatch_ ) // no free batch found, allocate a new one
1192 {
1193 currentBatch_ = allocateBatch( objectsPerPage_ );
1194 currentBatch_->next_ = batches_; // insert at the head of the list
1195 batches_ = currentBatch_;
1196 }
1197 }
1198 AllocatedType *allocated = currentBatch_->used_;
1199 currentBatch_->used_ += objectPerAllocation;
1200 return allocated;
1201 }
1202
1203 /// Release the object.
1204 /// @warning it is the responsability of the caller to actually destruct the object.
1205 void release( AllocatedType *object )
1206 {
1207 assert( object != 0 );
1208 *(AllocatedType **)object = freeHead_;
1209 freeHead_ = object;
1210 }
1211
1212 private:
1213 struct BatchInfo
1214 {
1215 BatchInfo *next_;
1216 AllocatedType *used_;
1217 AllocatedType *end_;
1218 AllocatedType buffer_[objectPerAllocation];
1219 };
1220
1221 // disabled copy constructor and assignement operator.
1222 BatchAllocator( const BatchAllocator & );
1223 void operator =( const BatchAllocator &);
1224
1225 static BatchInfo *allocateBatch( unsigned int objectsPerPage )
1226 {
1227 const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation
1228 + sizeof(AllocatedType) * objectPerAllocation * objectsPerPage;
1229 BatchInfo *batch = static_cast<BatchInfo*>( malloc( mallocSize ) );
1230 batch->next_ = 0;
1231 batch->used_ = batch->buffer_;
1232 batch->end_ = batch->buffer_ + objectsPerPage;
1233 return batch;
1234 }
1235
1236 BatchInfo *batches_;
1237 BatchInfo *currentBatch_;
1238 /// Head of a single linked list within the allocated space of freeed object
1239 AllocatedType *freeHead_;
1240 unsigned int objectsPerPage_;
1241 };
1242
1243
1244 } // namespace Json
1245
1246 # endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION
1247
1248 #endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED
1249
1250 // //////////////////////////////////////////////////////////////////////
1251 // End of content of file: src/lib_json/json_batchallocator.h
1252 // //////////////////////////////////////////////////////////////////////
1253
1254
1255
1256
1257
1258
1259 // //////////////////////////////////////////////////////////////////////
1260 // Beginning of content of file: src/lib_json/json_valueiterator.inl
1261 // //////////////////////////////////////////////////////////////////////
1262
1263 // Copyright 2007-2010 Baptiste Lepilleur
1264 // Distributed under MIT license, or public domain if desired and
1265 // recognized in your jurisdiction.
1266 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
1267
1268 // included by json_value.cpp
1269
1270 namespace Json {
1271
1272 // //////////////////////////////////////////////////////////////////
1273 // //////////////////////////////////////////////////////////////////
1274 // //////////////////////////////////////////////////////////////////
1275 // class ValueIteratorBase
1276 // //////////////////////////////////////////////////////////////////
1277 // //////////////////////////////////////////////////////////////////
1278 // //////////////////////////////////////////////////////////////////
1279
1280 ValueIteratorBase::ValueIteratorBase()
1281 #ifndef JSON_VALUE_USE_INTERNAL_MAP
1282 : current_()
1283 , isNull_( true )
1284 {
1285 }
1286 #else
1287 : isArray_( true )
1288 , isNull_( true )
1289 {
1290 iterator_.array_ = ValueInternalArray::IteratorState();
1291 }
1292 #endif
1293
1294
1295 #ifndef JSON_VALUE_USE_INTERNAL_MAP
1296 ValueIteratorBase::ValueIteratorBase( const Value::ObjectValues::iterator &current )
1297 : current_( current )
1298 , isNull_( false )
1299 {
1300 }
1301 #else
1302 ValueIteratorBase::ValueIteratorBase( const ValueInternalArray::IteratorState &state )
1303 : isArray_( true )
1304 {
1305 iterator_.array_ = state;
1306 }
1307
1308
1309 ValueIteratorBase::ValueIteratorBase( const ValueInternalMap::IteratorState &state )
1310 : isArray_( false )
1311 {
1312 iterator_.map_ = state;
1313 }
1314 #endif
1315
1316 Value &
1317 ValueIteratorBase::deref() const
1318 {
1319 #ifndef JSON_VALUE_USE_INTERNAL_MAP
1320 return current_->second;
1321 #else
1322 if ( isArray_ )
1323 return ValueInternalArray::dereference( iterator_.array_ );
1324 return ValueInternalMap::value( iterator_.map_ );
1325 #endif
1326 }
1327
1328
1329 void
1330 ValueIteratorBase::increment()
1331 {
1332 #ifndef JSON_VALUE_USE_INTERNAL_MAP
1333 ++current_;
1334 #else
1335 if ( isArray_ )
1336 ValueInternalArray::increment( iterator_.array_ );
1337 ValueInternalMap::increment( iterator_.map_ );
1338 #endif
1339 }
1340
1341
1342 void
1343 ValueIteratorBase::decrement()
1344 {
1345 #ifndef JSON_VALUE_USE_INTERNAL_MAP
1346 --current_;
1347 #else
1348 if ( isArray_ )
1349 ValueInternalArray::decrement( iterator_.array_ );
1350 ValueInternalMap::decrement( iterator_.map_ );
1351 #endif
1352 }
1353
1354
1355 ValueIteratorBase::difference_type
1356 ValueIteratorBase::computeDistance( const SelfType &other ) const
1357 {
1358 #ifndef JSON_VALUE_USE_INTERNAL_MAP
1359 # ifdef JSON_USE_CPPTL_SMALLMAP
1360 return current_ - other.current_;
1361 # else
1362 // Iterator for null value are initialized using the default
1363 // constructor, which initialize current_ to the default
1364 // std::map::iterator. As begin() and end() are two instance
1365 // of the default std::map::iterator, they can not be compared.
1366 // To allow this, we handle this comparison specifically.
1367 if ( isNull_ && other.isNull_ )
1368 {
1369 return 0;
1370 }
1371
1372
1373 // Usage of std::distance is not portable (does not compile with Sun Studio 12 RogueWave STL,
1374 // which is the one used by default).
1375 // Using a portable hand-made version for non random iterator instead:
1376 // return difference_type( std::distance( current_, other.current_ ) );
1377 difference_type myDistance = 0;
1378 for ( Value::ObjectValues::iterator it = current_; it != other.current_; ++it )
1379 {
1380 ++myDistance;
1381 }
1382 return myDistance;
1383 # endif
1384 #else
1385 if ( isArray_ )
1386 return ValueInternalArray::distance( iterator_.array_, other.iterator_.array_ );
1387 return ValueInternalMap::distance( iterator_.map_, other.iterator_.map_ );
1388 #endif
1389 }
1390
1391
1392 bool
1393 ValueIteratorBase::isEqual( const SelfType &other ) const
1394 {
1395 #ifndef JSON_VALUE_USE_INTERNAL_MAP
1396 if ( isNull_ )
1397 {
1398 return other.isNull_;
1399 }
1400 return current_ == other.current_;
1401 #else
1402 if ( isArray_ )
1403 return ValueInternalArray::equals( iterator_.array_, other.iterator_.array_ );
1404 return ValueInternalMap::equals( iterator_.map_, other.iterator_.map_ );
1405 #endif
1406 }
1407
1408
1409 void
1410 ValueIteratorBase::copy( const SelfType &other )
1411 {
1412 #ifndef JSON_VALUE_USE_INTERNAL_MAP
1413 current_ = other.current_;
1414 #else
1415 if ( isArray_ )
1416 iterator_.array_ = other.iterator_.array_;
1417 iterator_.map_ = other.iterator_.map_;
1418 #endif
1419 }
1420
1421
1422 Value
1423 ValueIteratorBase::key() const
1424 {
1425 #ifndef JSON_VALUE_USE_INTERNAL_MAP
1426 const Value::CZString czstring = (*current_).first;
1427 if ( czstring.c_str() )
1428 {
1429 if ( czstring.isStaticString() )
1430 return Value( StaticString( czstring.c_str() ) );
1431 return Value( czstring.c_str() );
1432 }
1433 return Value( czstring.index() );
1434 #else
1435 if ( isArray_ )
1436 return Value( ValueInternalArray::indexOf( iterator_.array_ ) );
1437 bool isStatic;
1438 const char *memberName = ValueInternalMap::key( iterator_.map_, isStatic );
1439 if ( isStatic )
1440 return Value( StaticString( memberName ) );
1441 return Value( memberName );
1442 #endif
1443 }
1444
1445
1446 UInt
1447 ValueIteratorBase::index() const
1448 {
1449 #ifndef JSON_VALUE_USE_INTERNAL_MAP
1450 const Value::CZString czstring = (*current_).first;
1451 if ( !czstring.c_str() )
1452 return czstring.index();
1453 return Value::UInt( -1 );
1454 #else
1455 if ( isArray_ )
1456 return Value::UInt( ValueInternalArray::indexOf( iterator_.array_ ) );
1457 return Value::UInt( -1 );
1458 #endif
1459 }
1460
1461
1462 const char *
1463 ValueIteratorBase::memberName() const
1464 {
1465 #ifndef JSON_VALUE_USE_INTERNAL_MAP
1466 const char *name = (*current_).first.c_str();
1467 return name ? name : "";
1468 #else
1469 if ( !isArray_ )
1470 return ValueInternalMap::key( iterator_.map_ );
1471 return "";
1472 #endif
1473 }
1474
1475
1476 // //////////////////////////////////////////////////////////////////
1477 // //////////////////////////////////////////////////////////////////
1478 // //////////////////////////////////////////////////////////////////
1479 // class ValueConstIterator
1480 // //////////////////////////////////////////////////////////////////
1481 // //////////////////////////////////////////////////////////////////
1482 // //////////////////////////////////////////////////////////////////
1483
1484 ValueConstIterator::ValueConstIterator()
1485 {
1486 }
1487
1488
1489 #ifndef JSON_VALUE_USE_INTERNAL_MAP
1490 ValueConstIterator::ValueConstIterator( const Value::ObjectValues::iterator &current )
1491 : ValueIteratorBase( current )
1492 {
1493 }
1494 #else
1495 ValueConstIterator::ValueConstIterator( const ValueInternalArray::IteratorState &state )
1496 : ValueIteratorBase( state )
1497 {
1498 }
1499
1500 ValueConstIterator::ValueConstIterator( const ValueInternalMap::IteratorState &state )
1501 : ValueIteratorBase( state )
1502 {
1503 }
1504 #endif
1505
1506 ValueConstIterator &
1507 ValueConstIterator::operator =( const ValueIteratorBase &other )
1508 {
1509 copy( other );
1510 return *this;
1511 }
1512
1513
1514 // //////////////////////////////////////////////////////////////////
1515 // //////////////////////////////////////////////////////////////////
1516 // //////////////////////////////////////////////////////////////////
1517 // class ValueIterator
1518 // //////////////////////////////////////////////////////////////////
1519 // //////////////////////////////////////////////////////////////////
1520 // //////////////////////////////////////////////////////////////////
1521
1522 ValueIterator::ValueIterator()
1523 {
1524 }
1525
1526
1527 #ifndef JSON_VALUE_USE_INTERNAL_MAP
1528 ValueIterator::ValueIterator( const Value::ObjectValues::iterator &current )
1529 : ValueIteratorBase( current )
1530 {
1531 }
1532 #else
1533 ValueIterator::ValueIterator( const ValueInternalArray::IteratorState &state )
1534 : ValueIteratorBase( state )
1535 {
1536 }
1537
1538 ValueIterator::ValueIterator( const ValueInternalMap::IteratorState &state )
1539 : ValueIteratorBase( state )
1540 {
1541 }
1542 #endif
1543
1544 ValueIterator::ValueIterator( const ValueConstIterator &other )
1545 : ValueIteratorBase( other )
1546 {
1547 }
1548
1549 ValueIterator::ValueIterator( const ValueIterator &other )
1550 : ValueIteratorBase( other )
1551 {
1552 }
1553
1554 ValueIterator &
1555 ValueIterator::operator =( const SelfType &other )
1556 {
1557 copy( other );
1558 return *this;
1559 }
1560
1561 } // namespace Json
1562
1563 // //////////////////////////////////////////////////////////////////////
1564 // End of content of file: src/lib_json/json_valueiterator.inl
1565 // //////////////////////////////////////////////////////////////////////
1566
1567
1568
1569
1570
1571
1572 // //////////////////////////////////////////////////////////////////////
1573 // Beginning of content of file: src/lib_json/json_value.cpp
1574 // //////////////////////////////////////////////////////////////////////
1575
1576 // Copyright 2011 Baptiste Lepilleur
1577 // Distributed under MIT license, or public domain if desired and
1578 // recognized in your jurisdiction.
1579 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
1580
1581 #if !defined(JSON_IS_AMALGAMATION)
1582 # include <json/assertions.h>
1583 # include <json/value.h>
1584 # include <json/writer.h>
1585 # ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
1586 # include "json_batchallocator.h"
1587 # endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
1588 #endif // if !defined(JSON_IS_AMALGAMATION)
1589 #include <math.h>
1590 #include <sstream>
1591 #include <utility>
1592 #include <stdexcept>
1593 #include <cstring>
1594 #include <cassert>
1595 #ifdef JSON_USE_CPPTL
1596 # include <cpptl/conststring.h>
1597 #endif
1598 #include <cstddef> // size_t
1599
1600 #define JSON_ASSERT_UNREACHABLE assert( false )
1601
1602 namespace Json {
1603
1604 const Value Value::null;
1605 const Int Value::minInt = Int( ~(UInt(-1)/2) );
1606 const Int Value::maxInt = Int( UInt(-1)/2 );
1607 const UInt Value::maxUInt = UInt(-1);
1608 # if defined(JSON_HAS_INT64)
1609 const Int64 Value::minInt64 = Int64( ~(UInt64(-1)/2) );
1610 const Int64 Value::maxInt64 = Int64( UInt64(-1)/2 );
1611 const UInt64 Value::maxUInt64 = UInt64(-1);
1612 // The constant is hard-coded because some compiler have trouble
1613 // converting Value::maxUInt64 to a double correctly (AIX/xlC).
1614 // Assumes that UInt64 is a 64 bits integer.
1615 static const double maxUInt64AsDouble = 18446744073709551615.0;
1616 #endif // defined(JSON_HAS_INT64)
1617 const LargestInt Value::minLargestInt = LargestInt( ~(LargestUInt(-1)/2) );
1618 const LargestInt Value::maxLargestInt = LargestInt( LargestUInt(-1)/2 );
1619 const LargestUInt Value::maxLargestUInt = LargestUInt(-1);
1620
1621
1622 /// Unknown size marker
1623 static const unsigned int unknown = (unsigned)-1;
1624
1625 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
1626 template <typename T, typename U>
1627 static inline bool InRange(double d, T min, U max) {
1628 return d >= min && d <= max;
1629 }
1630 #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
1631 static inline double integerToDouble( Json::UInt64 value )
1632 {
1633 return static_cast<double>( Int64(value/2) ) * 2.0 + Int64(value & 1);
1634 }
1635
1636 template<typename T>
1637 static inline double integerToDouble( T value )
1638 {
1639 return static_cast<double>( value );
1640 }
1641
1642 template <typename T, typename U>
1643 static inline bool InRange(double d, T min, U max) {
1644 return d >= integerToDouble(min) && d <= integerToDouble(max);
1645 }
1646 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
1647
1648
1649 /** Duplicates the specified string value.
1650 * @param value Pointer to the string to duplicate. Must be zero-terminated if
1651 * length is "unknown".
1652 * @param length Length of the value. if equals to unknown, then it will be
1653 * computed using strlen(value).
1654 * @return Pointer on the duplicate instance of string.
1655 */
1656 static inline char *
1657 duplicateStringValue( const char *value,
1658 unsigned int length = unknown )
1659 {
1660 if ( length == unknown )
1661 length = (unsigned int)strlen(value);
1662
1663 // Avoid an integer overflow in the call to malloc below by limiting length
1664 // to a sane value.
1665 if (length >= (unsigned)Value::maxInt)
1666 length = Value::maxInt - 1;
1667
1668 char *newString = static_cast<char *>( malloc( length + 1 ) );
1669 JSON_ASSERT_MESSAGE( newString != 0, "Failed to allocate string value buffer" );
1670 memcpy( newString, value, length );
1671 newString[length] = 0;
1672 return newString;
1673 }
1674
1675
1676 /** Free the string duplicated by duplicateStringValue().
1677 */
1678 static inline void
1679 releaseStringValue( char *value )
1680 {
1681 if ( value )
1682 free( value );
1683 }
1684
1685 } // namespace Json
1686
1687
1688 // //////////////////////////////////////////////////////////////////
1689 // //////////////////////////////////////////////////////////////////
1690 // //////////////////////////////////////////////////////////////////
1691 // ValueInternals...
1692 // //////////////////////////////////////////////////////////////////
1693 // //////////////////////////////////////////////////////////////////
1694 // //////////////////////////////////////////////////////////////////
1695 #if !defined(JSON_IS_AMALGAMATION)
1696 # ifdef JSON_VALUE_USE_INTERNAL_MAP
1697 # include "json_internalarray.inl"
1698 # include "json_internalmap.inl"
1699 # endif // JSON_VALUE_USE_INTERNAL_MAP
1700
1701 # include "json_valueiterator.inl"
1702 #endif // if !defined(JSON_IS_AMALGAMATION)
1703
1704 namespace Json {
1705
1706 // //////////////////////////////////////////////////////////////////
1707 // //////////////////////////////////////////////////////////////////
1708 // //////////////////////////////////////////////////////////////////
1709 // class Value::CommentInfo
1710 // //////////////////////////////////////////////////////////////////
1711 // //////////////////////////////////////////////////////////////////
1712 // //////////////////////////////////////////////////////////////////
1713
1714
1715 Value::CommentInfo::CommentInfo()
1716 : comment_( 0 )
1717 {
1718 }
1719
1720 Value::CommentInfo::~CommentInfo()
1721 {
1722 if ( comment_ )
1723 releaseStringValue( comment_ );
1724 }
1725
1726
1727 void
1728 Value::CommentInfo::setComment( const char *text )
1729 {
1730 if ( comment_ )
1731 releaseStringValue( comment_ );
1732 JSON_ASSERT( text != 0 );
1733 JSON_ASSERT_MESSAGE( text[0]=='\0' || text[0]=='/', "Comments must start with /");
1734 // It seems that /**/ style comments are acceptable as well.
1735 comment_ = duplicateStringValue( text );
1736 }
1737
1738
1739 // //////////////////////////////////////////////////////////////////
1740 // //////////////////////////////////////////////////////////////////
1741 // //////////////////////////////////////////////////////////////////
1742 // class Value::CZString
1743 // //////////////////////////////////////////////////////////////////
1744 // //////////////////////////////////////////////////////////////////
1745 // //////////////////////////////////////////////////////////////////
1746 # ifndef JSON_VALUE_USE_INTERNAL_MAP
1747
1748 // Notes: index_ indicates if the string was allocated when
1749 // a string is stored.
1750
1751 Value::CZString::CZString( ArrayIndex index )
1752 : cstr_( 0 )
1753 , index_( index )
1754 {
1755 }
1756
1757 Value::CZString::CZString( const char *cstr, DuplicationPolicy allocate )
1758 : cstr_( allocate == duplicate ? duplicateStringValue(cstr)
1759 : cstr )
1760 , index_( allocate )
1761 {
1762 }
1763
1764 Value::CZString::CZString( const CZString &other )
1765 : cstr_( other.index_ != noDuplication && other.cstr_ != 0
1766 ? duplicateStringValue( other.cstr_ )
1767 : other.cstr_ )
1768 , index_( other.cstr_ ? (other.index_ == noDuplication ? noDuplication : duplicate)
1769 : other.index_ )
1770 {
1771 }
1772
1773 Value::CZString::~CZString()
1774 {
1775 if ( cstr_ && index_ == duplicate )
1776 releaseStringValue( const_cast<char *>( cstr_ ) );
1777 }
1778
1779 void
1780 Value::CZString::swap( CZString &other )
1781 {
1782 std::swap( cstr_, other.cstr_ );
1783 std::swap( index_, other.index_ );
1784 }
1785
1786 Value::CZString &
1787 Value::CZString::operator =( const CZString &other )
1788 {
1789 CZString temp( other );
1790 swap( temp );
1791 return *this;
1792 }
1793
1794 bool
1795 Value::CZString::operator<( const CZString &other ) const
1796 {
1797 if ( cstr_ )
1798 return strcmp( cstr_, other.cstr_ ) < 0;
1799 return index_ < other.index_;
1800 }
1801
1802 bool
1803 Value::CZString::operator==( const CZString &other ) const
1804 {
1805 if ( cstr_ )
1806 return strcmp( cstr_, other.cstr_ ) == 0;
1807 return index_ == other.index_;
1808 }
1809
1810
1811 ArrayIndex
1812 Value::CZString::index() const
1813 {
1814 return index_;
1815 }
1816
1817
1818 const char *
1819 Value::CZString::c_str() const
1820 {
1821 return cstr_;
1822 }
1823
1824 bool
1825 Value::CZString::isStaticString() const
1826 {
1827 return index_ == noDuplication;
1828 }
1829
1830 #endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
1831
1832
1833 // //////////////////////////////////////////////////////////////////
1834 // //////////////////////////////////////////////////////////////////
1835 // //////////////////////////////////////////////////////////////////
1836 // class Value::Value
1837 // //////////////////////////////////////////////////////////////////
1838 // //////////////////////////////////////////////////////////////////
1839 // //////////////////////////////////////////////////////////////////
1840
1841 /*! \internal Default constructor initialization must be equivalent to:
1842 * memset( this, 0, sizeof(Value) )
1843 * This optimization is used in ValueInternalMap fast allocator.
1844 */
1845 Value::Value( ValueType type )
1846 : type_( type )
1847 , allocated_( false )
1848 # ifdef JSON_VALUE_USE_INTERNAL_MAP
1849 , itemIsUsed_( 0 )
1850 #endif
1851 , comments_( 0 )
1852 {
1853 switch ( type )
1854 {
1855 case nullValue:
1856 break;
1857 case intValue:
1858 case uintValue:
1859 value_.int_ = 0;
1860 break;
1861 case realValue:
1862 value_.real_ = 0.0;
1863 break;
1864 case stringValue:
1865 value_.string_ = 0;
1866 break;
1867 #ifndef JSON_VALUE_USE_INTERNAL_MAP
1868 case arrayValue:
1869 case objectValue:
1870 value_.map_ = new ObjectValues();
1871 break;
1872 #else
1873 case arrayValue:
1874 value_.array_ = arrayAllocator()->newArray();
1875 break;
1876 case objectValue:
1877 value_.map_ = mapAllocator()->newMap();
1878 break;
1879 #endif
1880 case booleanValue:
1881 value_.bool_ = false;
1882 break;
1883 default:
1884 JSON_ASSERT_UNREACHABLE;
1885 }
1886 }
1887
1888
1889 Value::Value( UInt value )
1890 : type_( uintValue )
1891 , allocated_( false )
1892 # ifdef JSON_VALUE_USE_INTERNAL_MAP
1893 , itemIsUsed_( 0 )
1894 #endif
1895 , comments_( 0 )
1896 {
1897 value_.uint_ = value;
1898 }
1899
1900 Value::Value( Int value )
1901 : type_( intValue )
1902 , allocated_( false )
1903 # ifdef JSON_VALUE_USE_INTERNAL_MAP
1904 , itemIsUsed_( 0 )
1905 #endif
1906 , comments_( 0 )
1907 {
1908 value_.int_ = value;
1909 }
1910
1911
1912 # if defined(JSON_HAS_INT64)
1913 Value::Value( Int64 value )
1914 : type_( intValue )
1915 , allocated_( false )
1916 # ifdef JSON_VALUE_USE_INTERNAL_MAP
1917 , itemIsUsed_( 0 )
1918 #endif
1919 , comments_( 0 )
1920 {
1921 value_.int_ = value;
1922 }
1923
1924
1925 Value::Value( UInt64 value )
1926 : type_( uintValue )
1927 , allocated_( false )
1928 # ifdef JSON_VALUE_USE_INTERNAL_MAP
1929 , itemIsUsed_( 0 )
1930 #endif
1931 , comments_( 0 )
1932 {
1933 value_.uint_ = value;
1934 }
1935 #endif // defined(JSON_HAS_INT64)
1936
1937 Value::Value( double value )
1938 : type_( realValue )
1939 , allocated_( false )
1940 # ifdef JSON_VALUE_USE_INTERNAL_MAP
1941 , itemIsUsed_( 0 )
1942 #endif
1943 , comments_( 0 )
1944 {
1945 value_.real_ = value;
1946 }
1947
1948 Value::Value( const char *value )
1949 : type_( stringValue )
1950 , allocated_( true )
1951 # ifdef JSON_VALUE_USE_INTERNAL_MAP
1952 , itemIsUsed_( 0 )
1953 #endif
1954 , comments_( 0 )
1955 {
1956 value_.string_ = duplicateStringValue( value );
1957 }
1958
1959
1960 Value::Value( const char *beginValue,
1961 const char *endValue )
1962 : type_( stringValue )
1963 , allocated_( true )
1964 # ifdef JSON_VALUE_USE_INTERNAL_MAP
1965 , itemIsUsed_( 0 )
1966 #endif
1967 , comments_( 0 )
1968 {
1969 value_.string_ = duplicateStringValue( beginValue,
1970 (unsigned int)(endValue - beginValue) );
1971 }
1972
1973
1974 Value::Value( const std::string &value )
1975 : type_( stringValue )
1976 , allocated_( true )
1977 # ifdef JSON_VALUE_USE_INTERNAL_MAP
1978 , itemIsUsed_( 0 )
1979 #endif
1980 , comments_( 0 )
1981 {
1982 value_.string_ = duplicateStringValue( value.c_str(),
1983 (unsigned int)value.length() );
1984
1985 }
1986
1987 Value::Value( const StaticString &value )
1988 : type_( stringValue )
1989 , allocated_( false )
1990 # ifdef JSON_VALUE_USE_INTERNAL_MAP
1991 , itemIsUsed_( 0 )
1992 #endif
1993 , comments_( 0 )
1994 {
1995 value_.string_ = const_cast<char *>( value.c_str() );
1996 }
1997
1998
1999 # ifdef JSON_USE_CPPTL
2000 Value::Value( const CppTL::ConstString &value )
2001 : type_( stringValue )
2002 , allocated_( true )
2003 # ifdef JSON_VALUE_USE_INTERNAL_MAP
2004 , itemIsUsed_( 0 )
2005 #endif
2006 , comments_( 0 )
2007 {
2008 value_.string_ = duplicateStringValue( value, value.length() );
2009 }
2010 # endif
2011
2012 Value::Value( bool value )
2013 : type_( booleanValue )
2014 , allocated_( false )
2015 # ifdef JSON_VALUE_USE_INTERNAL_MAP
2016 , itemIsUsed_( 0 )
2017 #endif
2018 , comments_( 0 )
2019 {
2020 value_.bool_ = value;
2021 }
2022
2023
2024 Value::Value( const Value &other )
2025 : type_( other.type_ )
2026 , allocated_( false )
2027 # ifdef JSON_VALUE_USE_INTERNAL_MAP
2028 , itemIsUsed_( 0 )
2029 #endif
2030 , comments_( 0 )
2031 {
2032 switch ( type_ )
2033 {
2034 case nullValue:
2035 case intValue:
2036 case uintValue:
2037 case realValue:
2038 case booleanValue:
2039 value_ = other.value_;
2040 break;
2041 case stringValue:
2042 if ( other.value_.string_ )
2043 {
2044 value_.string_ = duplicateStringValue( other.value_.string_ );
2045 allocated_ = true;
2046 }
2047 else
2048 value_.string_ = 0;
2049 break;
2050 #ifndef JSON_VALUE_USE_INTERNAL_MAP
2051 case arrayValue:
2052 case objectValue:
2053 value_.map_ = new ObjectValues( *other.value_.map_ );
2054 break;
2055 #else
2056 case arrayValue:
2057 value_.array_ = arrayAllocator()->newArrayCopy( *other.value_.array_ );
2058 break;
2059 case objectValue:
2060 value_.map_ = mapAllocator()->newMapCopy( *other.value_.map_ );
2061 break;
2062 #endif
2063 default:
2064 JSON_ASSERT_UNREACHABLE;
2065 }
2066 if ( other.comments_ )
2067 {
2068 comments_ = new CommentInfo[numberOfCommentPlacement];
2069 for ( int comment =0; comment < numberOfCommentPlacement; ++comment )
2070 {
2071 const CommentInfo &otherComment = other.comments_[comment];
2072 if ( otherComment.comment_ )
2073 comments_[comment].setComment( otherComment.comment_ );
2074 }
2075 }
2076 }
2077
2078
2079 Value::~Value()
2080 {
2081 switch ( type_ )
2082 {
2083 case nullValue:
2084 case intValue:
2085 case uintValue:
2086 case realValue:
2087 case booleanValue:
2088 break;
2089 case stringValue:
2090 if ( allocated_ )
2091 releaseStringValue( value_.string_ );
2092 break;
2093 #ifndef JSON_VALUE_USE_INTERNAL_MAP
2094 case arrayValue:
2095 case objectValue:
2096 delete value_.map_;
2097 break;
2098 #else
2099 case arrayValue:
2100 arrayAllocator()->destructArray( value_.array_ );
2101 break;
2102 case objectValue:
2103 mapAllocator()->destructMap( value_.map_ );
2104 break;
2105 #endif
2106 default:
2107 JSON_ASSERT_UNREACHABLE;
2108 }
2109
2110 if ( comments_ )
2111 delete[] comments_;
2112 }
2113
2114 Value &
2115 Value::operator=( const Value &other )
2116 {
2117 Value temp( other );
2118 swap( temp );
2119 return *this;
2120 }
2121
2122 void
2123 Value::swap( Value &other )
2124 {
2125 ValueType temp = type_;
2126 type_ = other.type_;
2127 other.type_ = temp;
2128 std::swap( value_, other.value_ );
2129 int temp2 = allocated_;
2130 allocated_ = other.allocated_;
2131 other.allocated_ = temp2;
2132 }
2133
2134 ValueType
2135 Value::type() const
2136 {
2137 return type_;
2138 }
2139
2140
2141 int
2142 Value::compare( const Value &other ) const
2143 {
2144 if ( *this < other )
2145 return -1;
2146 if ( *this > other )
2147 return 1;
2148 return 0;
2149 }
2150
2151
2152 bool
2153 Value::operator <( const Value &other ) const
2154 {
2155 int typeDelta = type_ - other.type_;
2156 if ( typeDelta )
2157 return typeDelta < 0 ? true : false;
2158 switch ( type_ )
2159 {
2160 case nullValue:
2161 return false;
2162 case intValue:
2163 return value_.int_ < other.value_.int_;
2164 case uintValue:
2165 return value_.uint_ < other.value_.uint_;
2166 case realValue:
2167 return value_.real_ < other.value_.real_;
2168 case booleanValue:
2169 return value_.bool_ < other.value_.bool_;
2170 case stringValue:
2171 return ( value_.string_ == 0 && other.value_.string_ )
2172 || ( other.value_.string_
2173 && value_.string_
2174 && strcmp( value_.string_, other.value_.string_ ) < 0 );
2175 #ifndef JSON_VALUE_USE_INTERNAL_MAP
2176 case arrayValue:
2177 case objectValue:
2178 {
2179 int delta = int( value_.map_->size() - other.value_.map_->size() );
2180 if ( delta )
2181 return delta < 0;
2182 return (*value_.map_) < (*other.value_.map_);
2183 }
2184 #else
2185 case arrayValue:
2186 return value_.array_->compare( *(other.value_.array_) ) < 0;
2187 case objectValue:
2188 return value_.map_->compare( *(other.value_.map_) ) < 0;
2189 #endif
2190 default:
2191 JSON_ASSERT_UNREACHABLE;
2192 }
2193 return false; // unreachable
2194 }
2195
2196 bool
2197 Value::operator <=( const Value &other ) const
2198 {
2199 return !(other < *this);
2200 }
2201
2202 bool
2203 Value::operator >=( const Value &other ) const
2204 {
2205 return !(*this < other);
2206 }
2207
2208 bool
2209 Value::operator >( const Value &other ) const
2210 {
2211 return other < *this;
2212 }
2213
2214 bool
2215 Value::operator ==( const Value &other ) const
2216 {
2217 //if ( type_ != other.type_ )
2218 // GCC 2.95.3 says:
2219 // attempt to take address of bit-field structure member `Json::Value::type_'
2220 // Beats me, but a temp solves the problem.
2221 int temp = other.type_;
2222 if ( type_ != temp )
2223 return false;
2224 switch ( type_ )
2225 {
2226 case nullValue:
2227 return true;
2228 case intValue:
2229 return value_.int_ == other.value_.int_;
2230 case uintValue:
2231 return value_.uint_ == other.value_.uint_;
2232 case realValue:
2233 return value_.real_ == other.value_.real_;
2234 case booleanValue:
2235 return value_.bool_ == other.value_.bool_;
2236 case stringValue:
2237 return ( value_.string_ == other.value_.string_ )
2238 || ( other.value_.string_
2239 && value_.string_
2240 && strcmp( value_.string_, other.value_.string_ ) == 0 );
2241 #ifndef JSON_VALUE_USE_INTERNAL_MAP
2242 case arrayValue:
2243 case objectValue:
2244 return value_.map_->size() == other.value_.map_->size()
2245 && (*value_.map_) == (*other.value_.map_);
2246 #else
2247 case arrayValue:
2248 return value_.array_->compare( *(other.value_.array_) ) == 0;
2249 case objectValue:
2250 return value_.map_->compare( *(other.value_.map_) ) == 0;
2251 #endif
2252 default:
2253 JSON_ASSERT_UNREACHABLE;
2254 }
2255 return false; // unreachable
2256 }
2257
2258 bool
2259 Value::operator !=( const Value &other ) const
2260 {
2261 return !( *this == other );
2262 }
2263
2264 const char *
2265 Value::asCString() const
2266 {
2267 JSON_ASSERT( type_ == stringValue );
2268 return value_.string_;
2269 }
2270
2271
2272 std::string
2273 Value::asString() const
2274 {
2275 switch ( type_ )
2276 {
2277 case nullValue:
2278 return "";
2279 case stringValue:
2280 return value_.string_ ? value_.string_ : "";
2281 case booleanValue:
2282 return value_.bool_ ? "true" : "false";
2283 case intValue:
2284 return valueToString( value_.int_ );
2285 case uintValue:
2286 return valueToString( value_.uint_ );
2287 case realValue:
2288 return valueToString( value_.real_ );
2289 default:
2290 JSON_FAIL_MESSAGE( "Type is not convertible to string" );
2291 }
2292 }
2293
2294 # ifdef JSON_USE_CPPTL
2295 CppTL::ConstString
2296 Value::asConstString() const
2297 {
2298 return CppTL::ConstString( asString().c_str() );
2299 }
2300 # endif
2301
2302
2303 Value::Int
2304 Value::asInt() const
2305 {
2306 switch ( type_ )
2307 {
2308 case intValue:
2309 JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range");
2310 return Int(value_.int_);
2311 case uintValue:
2312 JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range");
2313 return Int(value_.uint_);
2314 case realValue:
2315 JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt), "double out of Int range");
2316 return Int(value_.real_);
2317 case nullValue:
2318 return 0;
2319 case booleanValue:
2320 return value_.bool_ ? 1 : 0;
2321 default:
2322 break;
2323 }
2324 JSON_FAIL_MESSAGE("Value is not convertible to Int.");
2325 }
2326
2327
2328 Value::UInt
2329 Value::asUInt() const
2330 {
2331 switch ( type_ )
2332 {
2333 case intValue:
2334 JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range");
2335 return UInt(value_.int_);
2336 case uintValue:
2337 JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
2338 return UInt(value_.uint_);
2339 case realValue:
2340 JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt), "double out of UInt range");
2341 return UInt( value_.real_ );
2342 case nullValue:
2343 return 0;
2344 case booleanValue:
2345 return value_.bool_ ? 1 : 0;
2346 default:
2347 break;
2348 }
2349 JSON_FAIL_MESSAGE("Value is not convertible to UInt.");
2350 }
2351
2352
2353 # if defined(JSON_HAS_INT64)
2354
2355 Value::Int64
2356 Value::asInt64() const
2357 {
2358 switch ( type_ )
2359 {
2360 case intValue:
2361 return Int64(value_.int_);
2362 case uintValue:
2363 JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
2364 return Int64(value_.uint_);
2365 case realValue:
2366 JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64), "double out of Int64 range");
2367 return Int64(value_.real_);
2368 case nullValue:
2369 return 0;
2370 case booleanValue:
2371 return value_.bool_ ? 1 : 0;
2372 default:
2373 break;
2374 }
2375 JSON_FAIL_MESSAGE("Value is not convertible to Int64.");
2376 }
2377
2378
2379 Value::UInt64
2380 Value::asUInt64() const
2381 {
2382 switch ( type_ )
2383 {
2384 case intValue:
2385 JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range");
2386 return UInt64(value_.int_);
2387 case uintValue:
2388 return UInt64(value_.uint_);
2389 case realValue:
2390 JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64), "double out of UInt64 range");
2391 return UInt64( value_.real_ );
2392 case nullValue:
2393 return 0;
2394 case booleanValue:
2395 return value_.bool_ ? 1 : 0;
2396 default:
2397 break;
2398 }
2399 JSON_FAIL_MESSAGE("Value is not convertible to UInt64.");
2400 }
2401 # endif // if defined(JSON_HAS_INT64)
2402
2403
2404 LargestInt
2405 Value::asLargestInt() const
2406 {
2407 #if defined(JSON_NO_INT64)
2408 return asInt();
2409 #else
2410 return asInt64();
2411 #endif
2412 }
2413
2414
2415 LargestUInt
2416 Value::asLargestUInt() const
2417 {
2418 #if defined(JSON_NO_INT64)
2419 return asUInt();
2420 #else
2421 return asUInt64();
2422 #endif
2423 }
2424
2425
2426 double
2427 Value::asDouble() const
2428 {
2429 switch ( type_ )
2430 {
2431 case intValue:
2432 return static_cast<double>( value_.int_ );
2433 case uintValue:
2434 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2435 return static_cast<double>( value_.uint_ );
2436 #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2437 return integerToDouble( value_.uint_ );
2438 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2439 case realValue:
2440 return value_.real_;
2441 case nullValue:
2442 return 0.0;
2443 case booleanValue:
2444 return value_.bool_ ? 1.0 : 0.0;
2445 default:
2446 break;
2447 }
2448 JSON_FAIL_MESSAGE("Value is not convertible to double.");
2449 }
2450
2451 float
2452 Value::asFloat() const
2453 {
2454 switch ( type_ )
2455 {
2456 case intValue:
2457 return static_cast<float>( value_.int_ );
2458 case uintValue:
2459 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2460 return static_cast<float>( value_.uint_ );
2461 #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2462 return integerToDouble( value_.uint_ );
2463 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2464 case realValue:
2465 return static_cast<float>( value_.real_ );
2466 case nullValue:
2467 return 0.0;
2468 case booleanValue:
2469 return value_.bool_ ? 1.0f : 0.0f;
2470 default:
2471 break;
2472 }
2473 JSON_FAIL_MESSAGE("Value is not convertible to float.");
2474 }
2475
2476 bool
2477 Value::asBool() const
2478 {
2479 switch ( type_ )
2480 {
2481 case booleanValue:
2482 return value_.bool_;
2483 case nullValue:
2484 return false;
2485 case intValue:
2486 return value_.int_ ? true : false;
2487 case uintValue:
2488 return value_.uint_ ? true : false;
2489 case realValue:
2490 return value_.real_ ? true : false;
2491 default:
2492 break;
2493 }
2494 JSON_FAIL_MESSAGE("Value is not convertible to bool.");
2495 }
2496
2497
2498 bool
2499 Value::isConvertibleTo( ValueType other ) const
2500 {
2501 switch ( other )
2502 {
2503 case nullValue:
2504 return ( isNumeric() && asDouble() == 0.0 )
2505 || ( type_ == booleanValue && value_.bool_ == false )
2506 || ( type_ == stringValue && asString() == "" )
2507 || ( type_ == arrayValue && value_.map_->size() == 0 )
2508 || ( type_ == objectValue && value_.map_->size() == 0 )
2509 || type_ == nullValue;
2510 case intValue:
2511 return isInt()
2512 || (type_ == realValue && InRange(value_.real_, minInt, maxInt))
2513 || type_ == booleanValue
2514 || type_ == nullValue;
2515 case uintValue:
2516 return isUInt()
2517 || (type_ == realValue && InRange(value_.real_, 0, maxUInt))
2518 || type_ == booleanValue
2519 || type_ == nullValue;
2520 case realValue:
2521 return isNumeric()
2522 || type_ == booleanValue
2523 || type_ == nullValue;
2524 case booleanValue:
2525 return isNumeric()
2526 || type_ == booleanValue
2527 || type_ == nullValue;
2528 case stringValue:
2529 return isNumeric()
2530 || type_ == booleanValue
2531 || type_ == stringValue
2532 || type_ == nullValue;
2533 case arrayValue:
2534 return type_ == arrayValue
2535 || type_ == nullValue;
2536 case objectValue:
2537 return type_ == objectValue
2538 || type_ == nullValue;
2539 }
2540 JSON_ASSERT_UNREACHABLE;
2541 return false;
2542 }
2543
2544
2545 /// Number of values in array or object
2546 ArrayIndex
2547 Value::size() const
2548 {
2549 switch ( type_ )
2550 {
2551 case nullValue:
2552 case intValue:
2553 case uintValue:
2554 case realValue:
2555 case booleanValue:
2556 case stringValue:
2557 return 0;
2558 #ifndef JSON_VALUE_USE_INTERNAL_MAP
2559 case arrayValue: // size of the array is highest index + 1
2560 if ( !value_.map_->empty() )
2561 {
2562 ObjectValues::const_iterator itLast = value_.map_->end();
2563 --itLast;
2564 return (*itLast).first.index()+1;
2565 }
2566 return 0;
2567 case objectValue:
2568 return ArrayIndex( value_.map_->size() );
2569 #else
2570 case arrayValue:
2571 return Int( value_.array_->size() );
2572 case objectValue:
2573 return Int( value_.map_->size() );
2574 #endif
2575 }
2576 JSON_ASSERT_UNREACHABLE;
2577 return 0; // unreachable;
2578 }
2579
2580
2581 bool
2582 Value::empty() const
2583 {
2584 if ( isNull() || isArray() || isObject() )
2585 return size() == 0u;
2586 else
2587 return false;
2588 }
2589
2590
2591 bool
2592 Value::operator!() const
2593 {
2594 return isNull();
2595 }
2596
2597
2598 void
2599 Value::clear()
2600 {
2601 JSON_ASSERT( type_ == nullValue || type_ == arrayValue || type_ == objectValue );
2602
2603 switch ( type_ )
2604 {
2605 #ifndef JSON_VALUE_USE_INTERNAL_MAP
2606 case arrayValue:
2607 case objectValue:
2608 value_.map_->clear();
2609 break;
2610 #else
2611 case arrayValue:
2612 value_.array_->clear();
2613 break;
2614 case objectValue:
2615 value_.map_->clear();
2616 break;
2617 #endif
2618 default:
2619 break;
2620 }
2621 }
2622
2623 void
2624 Value::resize( ArrayIndex newSize )
2625 {
2626 JSON_ASSERT( type_ == nullValue || type_ == arrayValue );
2627 if ( type_ == nullValue )
2628 *this = Value( arrayValue );
2629 #ifndef JSON_VALUE_USE_INTERNAL_MAP
2630 ArrayIndex oldSize = size();
2631 if ( newSize == 0 )
2632 clear();
2633 else if ( newSize > oldSize )
2634 (*this)[ newSize - 1 ];
2635 else
2636 {
2637 for ( ArrayIndex index = newSize; index < oldSize; ++index )
2638 {
2639 value_.map_->erase( index );
2640 }
2641 assert( size() == newSize );
2642 }
2643 #else
2644 value_.array_->resize( newSize );
2645 #endif
2646 }
2647
2648
2649 Value &
2650 Value::operator[]( ArrayIndex index )
2651 {
2652 JSON_ASSERT( type_ == nullValue || type_ == arrayValue );
2653 if ( type_ == nullValue )
2654 *this = Value( arrayValue );
2655 #ifndef JSON_VALUE_USE_INTERNAL_MAP
2656 CZString key( index );
2657 ObjectValues::iterator it = value_.map_->lower_bound( key );
2658 if ( it != value_.map_->end() && (*it).first == key )
2659 return (*it).second;
2660
2661 ObjectValues::value_type defaultValue( key, null );
2662 it = value_.map_->insert( it, defaultValue );
2663 return (*it).second;
2664 #else
2665 return value_.array_->resolveReference( index );
2666 #endif
2667 }
2668
2669
2670 Value &
2671 Value::operator[]( int index )
2672 {
2673 JSON_ASSERT( index >= 0 );
2674 return (*this)[ ArrayIndex(index) ];
2675 }
2676
2677
2678 const Value &
2679 Value::operator[]( ArrayIndex index ) const
2680 {
2681 JSON_ASSERT( type_ == nullValue || type_ == arrayValue );
2682 if ( type_ == nullValue )
2683 return null;
2684 #ifndef JSON_VALUE_USE_INTERNAL_MAP
2685 CZString key( index );
2686 ObjectValues::const_iterator it = value_.map_->find( key );
2687 if ( it == value_.map_->end() )
2688 return null;
2689 return (*it).second;
2690 #else
2691 Value *value = value_.array_->find( index );
2692 return value ? *value : null;
2693 #endif
2694 }
2695
2696
2697 const Value &
2698 Value::operator[]( int index ) const
2699 {
2700 JSON_ASSERT( index >= 0 );
2701 return (*this)[ ArrayIndex(index) ];
2702 }
2703
2704
2705 Value &
2706 Value::operator[]( const char *key )
2707 {
2708 return resolveReference( key, false );
2709 }
2710
2711
2712 Value &
2713 Value::resolveReference( const char *key,
2714 bool isStatic )
2715 {
2716 JSON_ASSERT( type_ == nullValue || type_ == objectValue );
2717 if ( type_ == nullValue )
2718 *this = Value( objectValue );
2719 #ifndef JSON_VALUE_USE_INTERNAL_MAP
2720 CZString actualKey( key, isStatic ? CZString::noDuplication
2721 : CZString::duplicateOnCopy );
2722 ObjectValues::iterator it = value_.map_->lower_bound( actualKey );
2723 if ( it != value_.map_->end() && (*it).first == actualKey )
2724 return (*it).second;
2725
2726 ObjectValues::value_type defaultValue( actualKey, null );
2727 it = value_.map_->insert( it, defaultValue );
2728 Value &value = (*it).second;
2729 return value;
2730 #else
2731 return value_.map_->resolveReference( key, isStatic );
2732 #endif
2733 }
2734
2735
2736 Value
2737 Value::get( ArrayIndex index,
2738 const Value &defaultValue ) const
2739 {
2740 const Value *value = &((*this)[index]);
2741 return value == &null ? defaultValue : *value;
2742 }
2743
2744
2745 bool
2746 Value::isValidIndex( ArrayIndex index ) const
2747 {
2748 return index < size();
2749 }
2750
2751
2752
2753 const Value &
2754 Value::operator[]( const char *key ) const
2755 {
2756 JSON_ASSERT( type_ == nullValue || type_ == objectValue );
2757 if ( type_ == nullValue )
2758 return null;
2759 #ifndef JSON_VALUE_USE_INTERNAL_MAP
2760 CZString actualKey( key, CZString::noDuplication );
2761 ObjectValues::const_iterator it = value_.map_->find( actualKey );
2762 if ( it == value_.map_->end() )
2763 return null;
2764 return (*it).second;
2765 #else
2766 const Value *value = value_.map_->find( key );
2767 return value ? *value : null;
2768 #endif
2769 }
2770
2771
2772 Value &
2773 Value::operator[]( const std::string &key )
2774 {
2775 return (*this)[ key.c_str() ];
2776 }
2777
2778
2779 const Value &
2780 Value::operator[]( const std::string &key ) const
2781 {
2782 return (*this)[ key.c_str() ];
2783 }
2784
2785 Value &
2786 Value::operator[]( const StaticString &key )
2787 {
2788 return resolveReference( key, true );
2789 }
2790
2791
2792 # ifdef JSON_USE_CPPTL
2793 Value &
2794 Value::operator[]( const CppTL::ConstString &key )
2795 {
2796 return (*this)[ key.c_str() ];
2797 }
2798
2799
2800 const Value &
2801 Value::operator[]( const CppTL::ConstString &key ) const
2802 {
2803 return (*this)[ key.c_str() ];
2804 }
2805 # endif
2806
2807
2808 Value &
2809 Value::append( const Value &value )
2810 {
2811 return (*this)[size()] = value;
2812 }
2813
2814
2815 Value
2816 Value::get( const char *key,
2817 const Value &defaultValue ) const
2818 {
2819 const Value *value = &((*this)[key]);
2820 return value == &null ? defaultValue : *value;
2821 }
2822
2823
2824 Value
2825 Value::get( const std::string &key,
2826 const Value &defaultValue ) const
2827 {
2828 return get( key.c_str(), defaultValue );
2829 }
2830
2831 Value
2832 Value::removeMember( const char* key )
2833 {
2834 JSON_ASSERT( type_ == nullValue || type_ == objectValue );
2835 if ( type_ == nullValue )
2836 return null;
2837 #ifndef JSON_VALUE_USE_INTERNAL_MAP
2838 CZString actualKey( key, CZString::noDuplication );
2839 ObjectValues::iterator it = value_.map_->find( actualKey );
2840 if ( it == value_.map_->end() )
2841 return null;
2842 Value old(it->second);
2843 value_.map_->erase(it);
2844 return old;
2845 #else
2846 Value *value = value_.map_->find( key );
2847 if (value){
2848 Value old(*value);
2849 value_.map_.remove( key );
2850 return old;
2851 } else {
2852 return null;
2853 }
2854 #endif
2855 }
2856
2857 Value
2858 Value::removeMember( const std::string &key )
2859 {
2860 return removeMember( key.c_str() );
2861 }
2862
2863 # ifdef JSON_USE_CPPTL
2864 Value
2865 Value::get( const CppTL::ConstString &key,
2866 const Value &defaultValue ) const
2867 {
2868 return get( key.c_str(), defaultValue );
2869 }
2870 # endif
2871
2872 bool
2873 Value::isMember( const char *key ) const
2874 {
2875 const Value *value = &((*this)[key]);
2876 return value != &null;
2877 }
2878
2879
2880 bool
2881 Value::isMember( const std::string &key ) const
2882 {
2883 return isMember( key.c_str() );
2884 }
2885
2886
2887 # ifdef JSON_USE_CPPTL
2888 bool
2889 Value::isMember( const CppTL::ConstString &key ) const
2890 {
2891 return isMember( key.c_str() );
2892 }
2893 #endif
2894
2895 Value::Members
2896 Value::getMemberNames() const
2897 {
2898 JSON_ASSERT( type_ == nullValue || type_ == objectValue );
2899 if ( type_ == nullValue )
2900 return Value::Members();
2901 Members members;
2902 members.reserve( value_.map_->size() );
2903 #ifndef JSON_VALUE_USE_INTERNAL_MAP
2904 ObjectValues::const_iterator it = value_.map_->begin();
2905 ObjectValues::const_iterator itEnd = value_.map_->end();
2906 for ( ; it != itEnd; ++it )
2907 members.push_back( std::string( (*it).first.c_str() ) );
2908 #else
2909 ValueInternalMap::IteratorState it;
2910 ValueInternalMap::IteratorState itEnd;
2911 value_.map_->makeBeginIterator( it );
2912 value_.map_->makeEndIterator( itEnd );
2913 for ( ; !ValueInternalMap::equals( it, itEnd ); ValueInternalMap::increment(it) )
2914 members.push_back( std::string( ValueInternalMap::key( it ) ) );
2915 #endif
2916 return members;
2917 }
2918 //
2919 //# ifdef JSON_USE_CPPTL
2920 //EnumMemberNames
2921 //Value::enumMemberNames() const
2922 //{
2923 // if ( type_ == objectValue )
2924 // {
2925 // return CppTL::Enum::any( CppTL::Enum::transform(
2926 // CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
2927 // MemberNamesTransform() ) );
2928 // }
2929 // return EnumMemberNames();
2930 //}
2931 //
2932 //
2933 //EnumValues
2934 //Value::enumValues() const
2935 //{
2936 // if ( type_ == objectValue || type_ == arrayValue )
2937 // return CppTL::Enum::anyValues( *(value_.map_),
2938 // CppTL::Type<const Value &>() );
2939 // return EnumValues();
2940 //}
2941 //
2942 //# endif
2943
2944 static bool IsIntegral(double d) {
2945 double integral_part;
2946 return modf(d, &integral_part) == 0.0;
2947 }
2948
2949
2950 bool
2951 Value::isNull() const
2952 {
2953 return type_ == nullValue;
2954 }
2955
2956
2957 bool
2958 Value::isBool() const
2959 {
2960 return type_ == booleanValue;
2961 }
2962
2963
2964 bool
2965 Value::isInt() const
2966 {
2967 switch ( type_ )
2968 {
2969 case intValue:
2970 return value_.int_ >= minInt && value_.int_ <= maxInt;
2971 case uintValue:
2972 return value_.uint_ <= UInt(maxInt);
2973 case realValue:
2974 return value_.real_ >= minInt &&
2975 value_.real_ <= maxInt &&
2976 IsIntegral(value_.real_);
2977 default:
2978 break;
2979 }
2980 return false;
2981 }
2982
2983
2984 bool
2985 Value::isUInt() const
2986 {
2987 switch ( type_ )
2988 {
2989 case intValue:
2990 return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);
2991 case uintValue:
2992 return value_.uint_ <= maxUInt;
2993 case realValue:
2994 return value_.real_ >= 0 &&
2995 value_.real_ <= maxUInt &&
2996 IsIntegral(value_.real_);
2997 default:
2998 break;
2999 }
3000 return false;
3001 }
3002
3003 bool
3004 Value::isInt64() const
3005 {
3006 # if defined(JSON_HAS_INT64)
3007 switch ( type_ )
3008 {
3009 case intValue:
3010 return true;
3011 case uintValue:
3012 return value_.uint_ <= UInt64(maxInt64);
3013 case realValue:
3014 // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
3015 // double, so double(maxInt64) will be rounded up to 2^63. Therefore we
3016 // require the value to be strictly less than the limit.
3017 return value_.real_ >= double(minInt64) &&
3018 value_.real_ < double(maxInt64) &&
3019 IsIntegral(value_.real_);
3020 default:
3021 break;
3022 }
3023 # endif // JSON_HAS_INT64
3024 return false;
3025 }
3026
3027 bool
3028 Value::isUInt64() const
3029 {
3030 # if defined(JSON_HAS_INT64)
3031 switch ( type_ )
3032 {
3033 case intValue:
3034 return value_.int_ >= 0;
3035 case uintValue:
3036 return true;
3037 case realValue:
3038 // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
3039 // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
3040 // require the value to be strictly less than the limit.
3041 return value_.real_ >= 0 &&
3042 value_.real_ < maxUInt64AsDouble &&
3043 IsIntegral(value_.real_);
3044 default:
3045 break;
3046 }
3047 # endif // JSON_HAS_INT64
3048 return false;
3049 }
3050
3051
3052 bool
3053 Value::isIntegral() const
3054 {
3055 #if defined(JSON_HAS_INT64)
3056 return isInt64() || isUInt64();
3057 #else
3058 return isInt() || isUInt();
3059 #endif
3060 }
3061
3062
3063 bool
3064 Value::isDouble() const
3065 {
3066 return type_ == realValue || isIntegral();
3067 }
3068
3069
3070 bool
3071 Value::isNumeric() const
3072 {
3073 return isIntegral() || isDouble();
3074 }
3075
3076
3077 bool
3078 Value::isString() const
3079 {
3080 return type_ == stringValue;
3081 }
3082
3083
3084 bool
3085 Value::isArray() const
3086 {
3087 return type_ == arrayValue;
3088 }
3089
3090
3091 bool
3092 Value::isObject() const
3093 {
3094 return type_ == objectValue;
3095 }
3096
3097
3098 void
3099 Value::setComment( const char *comment,
3100 CommentPlacement placement )
3101 {
3102 if ( !comments_ )
3103 comments_ = new CommentInfo[numberOfCommentPlacement];
3104 comments_[placement].setComment( comment );
3105 }
3106
3107
3108 void
3109 Value::setComment( const std::string &comment,
3110 CommentPlacement placement )
3111 {
3112 setComment( comment.c_str(), placement );
3113 }
3114
3115
3116 bool
3117 Value::hasComment( CommentPlacement placement ) const
3118 {
3119 return comments_ != 0 && comments_[placement].comment_ != 0;
3120 }
3121
3122 std::string
3123 Value::getComment( CommentPlacement placement ) const
3124 {
3125 if ( hasComment(placement) )
3126 return comments_[placement].comment_;
3127 return "";
3128 }
3129
3130
3131 std::string
3132 Value::toStyledString() const
3133 {
3134 StyledWriter writer;
3135 return writer.write( *this );
3136 }
3137
3138
3139 Value::const_iterator
3140 Value::begin() const
3141 {
3142 switch ( type_ )
3143 {
3144 #ifdef JSON_VALUE_USE_INTERNAL_MAP
3145 case arrayValue:
3146 if ( value_.array_ )
3147 {
3148 ValueInternalArray::IteratorState it;
3149 value_.array_->makeBeginIterator( it );
3150 return const_iterator( it );
3151 }
3152 break;
3153 case objectValue:
3154 if ( value_.map_ )
3155 {
3156 ValueInternalMap::IteratorState it;
3157 value_.map_->makeBeginIterator( it );
3158 return const_iterator( it );
3159 }
3160 break;
3161 #else
3162 case arrayValue:
3163 case objectValue:
3164 if ( value_.map_ )
3165 return const_iterator( value_.map_->begin() );
3166 break;
3167 #endif
3168 default:
3169 break;
3170 }
3171 return const_iterator();
3172 }
3173
3174 Value::const_iterator
3175 Value::end() const
3176 {
3177 switch ( type_ )
3178 {
3179 #ifdef JSON_VALUE_USE_INTERNAL_MAP
3180 case arrayValue:
3181 if ( value_.array_ )
3182 {
3183 ValueInternalArray::IteratorState it;
3184 value_.array_->makeEndIterator( it );
3185 return const_iterator( it );
3186 }
3187 break;
3188 case objectValue:
3189 if ( value_.map_ )
3190 {
3191 ValueInternalMap::IteratorState it;
3192 value_.map_->makeEndIterator( it );
3193 return const_iterator( it );
3194 }
3195 break;
3196 #else
3197 case arrayValue:
3198 case objectValue:
3199 if ( value_.map_ )
3200 return const_iterator( value_.map_->end() );
3201 break;
3202 #endif
3203 default:
3204 break;
3205 }
3206 return const_iterator();
3207 }
3208
3209
3210 Value::iterator
3211 Value::begin()
3212 {
3213 switch ( type_ )
3214 {
3215 #ifdef JSON_VALUE_USE_INTERNAL_MAP
3216 case arrayValue:
3217 if ( value_.array_ )
3218 {
3219 ValueInternalArray::IteratorState it;
3220 value_.array_->makeBeginIterator( it );
3221 return iterator( it );
3222 }
3223 break;
3224 case objectValue:
3225 if ( value_.map_ )
3226 {
3227 ValueInternalMap::IteratorState it;
3228 value_.map_->makeBeginIterator( it );
3229 return iterator( it );
3230 }
3231 break;
3232 #else
3233 case arrayValue:
3234 case objectValue:
3235 if ( value_.map_ )
3236 return iterator( value_.map_->begin() );
3237 break;
3238 #endif
3239 default:
3240 break;
3241 }
3242 return iterator();
3243 }
3244
3245 Value::iterator
3246 Value::end()
3247 {
3248 switch ( type_ )
3249 {
3250 #ifdef JSON_VALUE_USE_INTERNAL_MAP
3251 case arrayValue:
3252 if ( value_.array_ )
3253 {
3254 ValueInternalArray::IteratorState it;
3255 value_.array_->makeEndIterator( it );
3256 return iterator( it );
3257 }
3258 break;
3259 case objectValue:
3260 if ( value_.map_ )
3261 {
3262 ValueInternalMap::IteratorState it;
3263 value_.map_->makeEndIterator( it );
3264 return iterator( it );
3265 }
3266 break;
3267 #else
3268 case arrayValue:
3269 case objectValue:
3270 if ( value_.map_ )
3271 return iterator( value_.map_->end() );
3272 break;
3273 #endif
3274 default:
3275 break;
3276 }
3277 return iterator();
3278 }
3279
3280
3281 // class PathArgument
3282 // //////////////////////////////////////////////////////////////////
3283
3284 PathArgument::PathArgument()
3285 : key_()
3286 , index_()
3287 , kind_( kindNone )
3288 {
3289 }
3290
3291
3292 PathArgument::PathArgument( ArrayIndex index )
3293 : key_()
3294 , index_( index )
3295 , kind_( kindIndex )
3296 {
3297 }
3298
3299
3300 PathArgument::PathArgument( const char *key )
3301 : key_( key )
3302 , index_()
3303 , kind_( kindKey )
3304 {
3305 }
3306
3307
3308 PathArgument::PathArgument( const std::string &key )
3309 : key_( key.c_str() )
3310 , index_()
3311 , kind_( kindKey )
3312 {
3313 }
3314
3315 // class Path
3316 // //////////////////////////////////////////////////////////////////
3317
3318 Path::Path( const std::string &path,
3319 const PathArgument &a1,
3320 const PathArgument &a2,
3321 const PathArgument &a3,
3322 const PathArgument &a4,
3323 const PathArgument &a5 )
3324 {
3325 InArgs in;
3326 in.push_back( &a1 );
3327 in.push_back( &a2 );
3328 in.push_back( &a3 );
3329 in.push_back( &a4 );
3330 in.push_back( &a5 );
3331 makePath( path, in );
3332 }
3333
3334
3335 void
3336 Path::makePath( const std::string &path,
3337 const InArgs &in )
3338 {
3339 const char *current = path.c_str();
3340 const char *end = current + path.length();
3341 InArgs::const_iterator itInArg = in.begin();
3342 while ( current != end )
3343 {
3344 if ( *current == '[' )
3345 {
3346 ++current;
3347 if ( *current == '%' )
3348 addPathInArg( path, in, itInArg, PathArgument::kindIndex );
3349 else
3350 {
3351 ArrayIndex index = 0;
3352 for ( ; current != end && *current >= '0' && *current <= '9'; ++current )
3353 index = index * 10 + ArrayIndex(*current - '0');
3354 args_.push_back( index );
3355 }
3356 if ( current == end || *current++ != ']' )
3357 invalidPath( path, int(current - path.c_str()) );
3358 }
3359 else if ( *current == '%' )
3360 {
3361 addPathInArg( path, in, itInArg, PathArgument::kindKey );
3362 ++current;
3363 }
3364 else if ( *current == '.' )
3365 {
3366 ++current;
3367 }
3368 else
3369 {
3370 const char *beginName = current;
3371 while ( current != end && !strchr( "[.", *current ) )
3372 ++current;
3373 args_.push_back( std::string( beginName, current ) );
3374 }
3375 }
3376 }
3377
3378
3379 void
3380 Path::addPathInArg( const std::string &path,
3381 const InArgs &in,
3382 InArgs::const_iterator &itInArg,
3383 PathArgument::Kind kind )
3384 {
3385 if ( itInArg == in.end() )
3386 {
3387 // Error: missing argument %d
3388 }
3389 else if ( (*itInArg)->kind_ != kind )
3390 {
3391 // Error: bad argument type
3392 }
3393 else
3394 {
3395 args_.push_back( **itInArg );
3396 }
3397 }
3398
3399
3400 void
3401 Path::invalidPath( const std::string &path,
3402 int location )
3403 {
3404 // Error: invalid path.
3405 }
3406
3407
3408 const Value &
3409 Path::resolve( const Value &root ) const
3410 {
3411 const Value *node = &root;
3412 for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
3413 {
3414 const PathArgument &arg = *it;
3415 if ( arg.kind_ == PathArgument::kindIndex )
3416 {
3417 if ( !node->isArray() || !node->isValidIndex( arg.index_ ) )
3418 {
3419 // Error: unable to resolve path (array value expected at position...
3420 }
3421 node = &((*node)[arg.index_]);
3422 }
3423 else if ( arg.kind_ == PathArgument::kindKey )
3424 {
3425 if ( !node->isObject() )
3426 {
3427 // Error: unable to resolve path (object value expected at position...)
3428 }
3429 node = &((*node)[arg.key_]);
3430 if ( node == &Value::null )
3431 {
3432 // Error: unable to resolve path (object has no member named '' at position...)
3433 }
3434 }
3435 }
3436 return *node;
3437 }
3438
3439
3440 Value
3441 Path::resolve( const Value &root,
3442 const Value &defaultValue ) const
3443 {
3444 const Value *node = &root;
3445 for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
3446 {
3447 const PathArgument &arg = *it;
3448 if ( arg.kind_ == PathArgument::kindIndex )
3449 {
3450 if ( !node->isArray() || !node->isValidIndex( arg.index_ ) )
3451 return defaultValue;
3452 node = &((*node)[arg.index_]);
3453 }
3454 else if ( arg.kind_ == PathArgument::kindKey )
3455 {
3456 if ( !node->isObject() )
3457 return defaultValue;
3458 node = &((*node)[arg.key_]);
3459 if ( node == &Value::null )
3460 return defaultValue;
3461 }
3462 }
3463 return *node;
3464 }
3465
3466
3467 Value &
3468 Path::make( Value &root ) const
3469 {
3470 Value *node = &root;
3471 for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
3472 {
3473 const PathArgument &arg = *it;
3474 if ( arg.kind_ == PathArgument::kindIndex )
3475 {
3476 if ( !node->isArray() )
3477 {
3478 // Error: node is not an array at position ...
3479 }
3480 node = &((*node)[arg.index_]);
3481 }
3482 else if ( arg.kind_ == PathArgument::kindKey )
3483 {
3484 if ( !node->isObject() )
3485 {
3486 // Error: node is not an object at position...
3487 }
3488 node = &((*node)[arg.key_]);
3489 }
3490 }
3491 return *node;
3492 }
3493
3494
3495 } // namespace Json
3496
3497 // //////////////////////////////////////////////////////////////////////
3498 // End of content of file: src/lib_json/json_value.cpp
3499 // //////////////////////////////////////////////////////////////////////
3500
3501
3502
3503
3504
3505
3506 // //////////////////////////////////////////////////////////////////////
3507 // Beginning of content of file: src/lib_json/json_writer.cpp
3508 // //////////////////////////////////////////////////////////////////////
3509
3510 // Copyright 2011 Baptiste Lepilleur
3511 // Distributed under MIT license, or public domain if desired and
3512 // recognized in your jurisdiction.
3513 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
3514
3515 #if !defined(JSON_IS_AMALGAMATION)
3516 # include <json/writer.h>
3517 # include "json_tool.h"
3518 #endif // if !defined(JSON_IS_AMALGAMATION)
3519 #include <utility>
3520 #include <assert.h>
3521 #include <stdio.h>
3522 #include <string.h>
3523 #include <sstream>
3524 #include <iomanip>
3525
3526 #if _MSC_VER >= 1400 // VC++ 8.0
3527 #pragma warning( disable : 4996 ) // disable warning about strdup being deprecated.
3528 #endif
3529
3530 namespace Json {
3531
3532 static bool containsControlCharacter( const char* str )
3533 {
3534 while ( *str )
3535 {
3536 if ( isControlCharacter( *(str++) ) )
3537 return true;
3538 }
3539 return false;
3540 }
3541
3542
3543 std::string valueToString( LargestInt value )
3544 {
3545 UIntToStringBuffer buffer;
3546 char *current = buffer + sizeof(buffer);
3547 bool isNegative = value < 0;
3548 if ( isNegative )
3549 value = -value;
3550 uintToString( LargestUInt(value), current );
3551 if ( isNegative )
3552 *--current = '-';
3553 assert( current >= buffer );
3554 return current;
3555 }
3556
3557
3558 std::string valueToString( LargestUInt value )
3559 {
3560 UIntToStringBuffer buffer;
3561 char *current = buffer + sizeof(buffer);
3562 uintToString( value, current );
3563 assert( current >= buffer );
3564 return current;
3565 }
3566
3567 #if defined(JSON_HAS_INT64)
3568
3569 std::string valueToString( Int value )
3570 {
3571 return valueToString( LargestInt(value) );
3572 }
3573
3574
3575 std::string valueToString( UInt value )
3576 {
3577 return valueToString( LargestUInt(value) );
3578 }
3579
3580 #endif // # if defined(JSON_HAS_INT64)
3581
3582
3583 std::string valueToString( double value )
3584 {
3585 char buffer[32];
3586 #if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with visual studio 2005 to avoid warning.
3587 sprintf_s(buffer, sizeof(buffer), "%#.16g", value);
3588 #else
3589 sprintf(buffer, "%#.16g", value);
3590 #endif
3591 char* ch = buffer + strlen(buffer) - 1;
3592 if (*ch != '0') return buffer; // nothing to truncate, so save time
3593 while(ch > buffer && *ch == '0'){
3594 --ch;
3595 }
3596 char* last_nonzero = ch;
3597 while(ch >= buffer){
3598 switch(*ch){
3599 case '0':
3600 case '1':
3601 case '2':
3602 case '3':
3603 case '4':
3604 case '5':
3605 case '6':
3606 case '7':
3607 case '8':
3608 case '9':
3609 --ch;
3610 continue;
3611 case '.':
3612 // Truncate zeroes to save bytes in output, but keep one.
3613 *(last_nonzero+2) = '\0';
3614 return buffer;
3615 default:
3616 return buffer;
3617 }
3618 }
3619 return buffer;
3620 }
3621
3622
3623 std::string valueToString( bool value )
3624 {
3625 return value ? "true" : "false";
3626 }
3627
3628 std::string valueToQuotedString( const char *value )
3629 {
3630 if (value == NULL)
3631 return "";
3632 // Not sure how to handle unicode...
3633 if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && !containsControlCharacter( value ))
3634 return std::string("\"") + value + "\"";
3635 // We have to walk value and escape any special characters.
3636 // Appending to std::string is not efficient, but this should be rare.
3637 // (Note: forward slashes are *not* rare, but I am not escaping them.)
3638 std::string::size_type maxsize = strlen(value)*2 + 3; // allescaped+quotes+NULL
3639 std::string result;
3640 result.reserve(maxsize); // to avoid lots of mallocs
3641 result += "\"";
3642 for (const char* c=value; *c != 0; ++c)
3643 {
3644 switch(*c)
3645 {
3646 case '\"':
3647 result += "\\\"";
3648 break;
3649 case '\\':
3650 result += "\\\\";
3651 break;
3652 case '\b':
3653 result += "\\b";
3654 break;
3655 case '\f':
3656 result += "\\f";
3657 break;
3658 case '\n':
3659 result += "\\n";
3660 break;
3661 case '\r':
3662 result += "\\r";
3663 break;
3664 case '\t':
3665 result += "\\t";
3666 break;
3667 //case '/':
3668 // Even though \/ is considered a legal escape in JSON, a bare
3669 // slash is also legal, so I see no reason to escape it.
3670 // (I hope I am not misunderstanding something.
3671 // blep notes: actually escaping \/ may be useful in javascript to avoid </
3672 // sequence.
3673 // Should add a flag to allow this compatibility mode and prevent this
3674 // sequence from occurring.
3675 default:
3676 if ( isControlCharacter( *c ) )
3677 {
3678 std::ostringstream oss;
3679 oss << "\\u" << std::hex << std::uppercase << std::setfill('0') << std::setw(4) << static_cast<int>(*c);
3680 result += oss.str();
3681 }
3682 else
3683 {
3684 result += *c;
3685 }
3686 break;
3687 }
3688 }
3689 result += "\"";
3690 return result;
3691 }
3692
3693 // Class Writer
3694 // //////////////////////////////////////////////////////////////////
3695 Writer::~Writer()
3696 {
3697 }
3698
3699
3700 // Class FastWriter
3701 // //////////////////////////////////////////////////////////////////
3702
3703 FastWriter::FastWriter()
3704 : yamlCompatiblityEnabled_( false ),
3705 dropNullPlaceholders_( false )
3706 {
3707 }
3708
3709
3710 void
3711 FastWriter::enableYAMLCompatibility()
3712 {
3713 yamlCompatiblityEnabled_ = true;
3714 }
3715
3716
3717 void
3718 FastWriter::dropNullPlaceholders()
3719 {
3720 dropNullPlaceholders_ = true;
3721 }
3722
3723
3724 std::string
3725 FastWriter::write( const Value &root )
3726 {
3727 document_ = "";
3728 writeValue( root );
3729 document_ += "\n";
3730 return document_;
3731 }
3732
3733
3734 void
3735 FastWriter::writeValue( const Value &value )
3736 {
3737 switch ( value.type() )
3738 {
3739 case nullValue:
3740 if (!dropNullPlaceholders_) document_ += "null";
3741 break;
3742 case intValue:
3743 document_ += valueToString( value.asLargestInt() );
3744 break;
3745 case uintValue:
3746 document_ += valueToString( value.asLargestUInt() );
3747 break;
3748 case realValue:
3749 document_ += valueToString( value.asDouble() );
3750 break;
3751 case stringValue:
3752 document_ += valueToQuotedString( value.asCString() );
3753 break;
3754 case booleanValue:
3755 document_ += valueToString( value.asBool() );
3756 break;
3757 case arrayValue:
3758 {
3759 document_ += "[";
3760 int size = value.size();
3761 for ( int index =0; index < size; ++index )
3762 {
3763 if ( index > 0 )
3764 document_ += ",";
3765 writeValue( value[index] );
3766 }
3767 document_ += "]";
3768 }
3769 break;
3770 case objectValue:
3771 {
3772 Value::Members members( value.getMemberNames() );
3773 document_ += "{";
3774 for ( Value::Members::iterator it = members.begin();
3775 it != members.end();
3776 ++it )
3777 {
3778 const std::string &name = *it;
3779 if ( it != members.begin() )
3780 document_ += ",";
3781 document_ += valueToQuotedString( name.c_str() );
3782 document_ += yamlCompatiblityEnabled_ ? ": "
3783 : ":";
3784 writeValue( value[name] );
3785 }
3786 document_ += "}";
3787 }
3788 break;
3789 }
3790 }
3791
3792
3793 // Class StyledWriter
3794 // //////////////////////////////////////////////////////////////////
3795
3796 StyledWriter::StyledWriter()
3797 : rightMargin_( 74 )
3798 , indentSize_( 3 )
3799 , addChildValues_()
3800 {
3801 }
3802
3803
3804 std::string
3805 StyledWriter::write( const Value &root )
3806 {
3807 document_ = "";
3808 addChildValues_ = false;
3809 indentString_ = "";
3810 writeCommentBeforeValue( root );
3811 writeValue( root );
3812 writeCommentAfterValueOnSameLine( root );
3813 document_ += "\n";
3814 return document_;
3815 }
3816
3817
3818 void
3819 StyledWriter::writeValue( const Value &value )
3820 {
3821 switch ( value.type() )
3822 {
3823 case nullValue:
3824 pushValue( "null" );
3825 break;
3826 case intValue:
3827 pushValue( valueToString( value.asLargestInt() ) );
3828 break;
3829 case uintValue:
3830 pushValue( valueToString( value.asLargestUInt() ) );
3831 break;
3832 case realValue:
3833 pushValue( valueToString( value.asDouble() ) );
3834 break;
3835 case stringValue:
3836 pushValue( valueToQuotedString( value.asCString() ) );
3837 break;
3838 case booleanValue:
3839 pushValue( valueToString( value.asBool() ) );
3840 break;
3841 case arrayValue:
3842 writeArrayValue( value);
3843 break;
3844 case objectValue:
3845 {
3846 Value::Members members( value.getMemberNames() );
3847 if ( members.empty() )
3848 pushValue( "{}" );
3849 else
3850 {
3851 writeWithIndent( "{" );
3852 indent();
3853 Value::Members::iterator it = members.begin();
3854 for (;;)
3855 {
3856 const std::string &name = *it;
3857 const Value &childValue = value[name];
3858 writeCommentBeforeValue( childValue );
3859 writeWithIndent( valueToQuotedString( name.c_str() ) );
3860 document_ += " : ";
3861 writeValue( childValue );
3862 if ( ++it == members.end() )
3863 {
3864 writeCommentAfterValueOnSameLine( childValue );
3865 break;
3866 }
3867 document_ += ",";
3868 writeCommentAfterValueOnSameLine( childValue );
3869 }
3870 unindent();
3871 writeWithIndent( "}" );
3872 }
3873 }
3874 break;
3875 }
3876 }
3877
3878
3879 void
3880 StyledWriter::writeArrayValue( const Value &value )
3881 {
3882 unsigned size = value.size();
3883 if ( size == 0 )
3884 pushValue( "[]" );
3885 else
3886 {
3887 bool isArrayMultiLine = isMultineArray( value );
3888 if ( isArrayMultiLine )
3889 {
3890 writeWithIndent( "[" );
3891 indent();
3892 bool hasChildValue = !childValues_.empty();
3893 unsigned index =0;
3894 for (;;)
3895 {
3896 const Value &childValue = value[index];
3897 writeCommentBeforeValue( childValue );
3898 if ( hasChildValue )
3899 writeWithIndent( childValues_[index] );
3900 else
3901 {
3902 writeIndent();
3903 writeValue( childValue );
3904 }
3905 if ( ++index == size )
3906 {
3907 writeCommentAfterValueOnSameLine( childValue );
3908 break;
3909 }
3910 document_ += ",";
3911 writeCommentAfterValueOnSameLine( childValue );
3912 }
3913 unindent();
3914 writeWithIndent( "]" );
3915 }
3916 else // output on a single line
3917 {
3918 assert( childValues_.size() == size );
3919 document_ += "[ ";
3920 for ( unsigned index =0; index < size; ++index )
3921 {
3922 if ( index > 0 )
3923 document_ += ", ";
3924 document_ += childValues_[index];
3925 }
3926 document_ += " ]";
3927 }
3928 }
3929 }
3930
3931
3932 bool
3933 StyledWriter::isMultineArray( const Value &value )
3934 {
3935 int size = value.size();
3936 bool isMultiLine = size*3 >= rightMargin_ ;
3937 childValues_.clear();
3938 for ( int index =0; index < size && !isMultiLine; ++index )
3939 {
3940 const Value &childValue = value[index];
3941 isMultiLine = isMultiLine ||
3942 ( (childValue.isArray() || childValue.isObject()) &&
3943 childValue.size() > 0 );
3944 }
3945 if ( !isMultiLine ) // check if line length > max line length
3946 {
3947 childValues_.reserve( size );
3948 addChildValues_ = true;
3949 int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]'
3950 for ( int index =0; index < size && !isMultiLine; ++index )
3951 {
3952 writeValue( value[index] );
3953 lineLength += int( childValues_[index].length() );
3954 isMultiLine = isMultiLine && hasCommentForValue( value[index] );
3955 }
3956 addChildValues_ = false;
3957 isMultiLine = isMultiLine || lineLength >= rightMargin_;
3958 }
3959 return isMultiLine;
3960 }
3961
3962
3963 void
3964 StyledWriter::pushValue( const std::string &value )
3965 {
3966 if ( addChildValues_ )
3967 childValues_.push_back( value );
3968 else
3969 document_ += value;
3970 }
3971
3972
3973 void
3974 StyledWriter::writeIndent()
3975 {
3976 if ( !document_.empty() )
3977 {
3978 char last = document_[document_.length()-1];
3979 if ( last == ' ' ) // already indented
3980 return;
3981 if ( last != '\n' ) // Comments may add new-line
3982 document_ += '\n';
3983 }
3984 document_ += indentString_;
3985 }
3986
3987
3988 void
3989 StyledWriter::writeWithIndent( const std::string &value )
3990 {
3991 writeIndent();
3992 document_ += value;
3993 }
3994
3995
3996 void
3997 StyledWriter::indent()
3998 {
3999 indentString_ += std::string( indentSize_, ' ' );
4000 }
4001
4002
4003 void
4004 StyledWriter::unindent()
4005 {
4006 assert( int(indentString_.size()) >= indentSize_ );
4007 indentString_.resize( indentString_.size() - indentSize_ );
4008 }
4009
4010
4011 void
4012 StyledWriter::writeCommentBeforeValue( const Value &root )
4013 {
4014 if ( !root.hasComment( commentBefore ) )
4015 return;
4016 document_ += normalizeEOL( root.getComment( commentBefore ) );
4017 document_ += "\n";
4018 }
4019
4020
4021 void
4022 StyledWriter::writeCommentAfterValueOnSameLine( const Value &root )
4023 {
4024 if ( root.hasComment( commentAfterOnSameLine ) )
4025 document_ += " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) );
4026
4027 if ( root.hasComment( commentAfter ) )
4028 {
4029 document_ += "\n";
4030 document_ += normalizeEOL( root.getComment( commentAfter ) );
4031 document_ += "\n";
4032 }
4033 }
4034
4035
4036 bool
4037 StyledWriter::hasCommentForValue( const Value &value )
4038 {
4039 return value.hasComment( commentBefore )
4040 || value.hasComment( commentAfterOnSameLine )
4041 || value.hasComment( commentAfter );
4042 }
4043
4044
4045 std::string
4046 StyledWriter::normalizeEOL( const std::string &text )
4047 {
4048 std::string normalized;
4049 normalized.reserve( text.length() );
4050 const char *begin = text.c_str();
4051 const char *end = begin + text.length();
4052 const char *current = begin;
4053 while ( current != end )
4054 {
4055 char c = *current++;
4056 if ( c == '\r' ) // mac or dos EOL
4057 {
4058 if ( *current == '\n' ) // convert dos EOL
4059 ++current;
4060 normalized += '\n';
4061 }
4062 else // handle unix EOL & other char
4063 normalized += c;
4064 }
4065 return normalized;
4066 }
4067
4068
4069 // Class StyledStreamWriter
4070 // //////////////////////////////////////////////////////////////////
4071
4072 StyledStreamWriter::StyledStreamWriter( std::string indentation )
4073 : document_(NULL)
4074 , rightMargin_( 74 )
4075 , indentation_( indentation )
4076 , addChildValues_()
4077 {
4078 }
4079
4080
4081 void
4082 StyledStreamWriter::write( std::ostream &out, const Value &root )
4083 {
4084 document_ = &out;
4085 addChildValues_ = false;
4086 indentString_ = "";
4087 writeCommentBeforeValue( root );
4088 writeValue( root );
4089 writeCommentAfterValueOnSameLine( root );
4090 *document_ << "\n";
4091 document_ = NULL; // Forget the stream, for safety.
4092 }
4093
4094
4095 void
4096 StyledStreamWriter::writeValue( const Value &value )
4097 {
4098 switch ( value.type() )
4099 {
4100 case nullValue:
4101 pushValue( "null" );
4102 break;
4103 case intValue:
4104 pushValue( valueToString( value.asLargestInt() ) );
4105 break;
4106 case uintValue:
4107 pushValue( valueToString( value.asLargestUInt() ) );
4108 break;
4109 case realValue:
4110 pushValue( valueToString( value.asDouble() ) );
4111 break;
4112 case stringValue:
4113 pushValue( valueToQuotedString( value.asCString() ) );
4114 break;
4115 case booleanValue:
4116 pushValue( valueToString( value.asBool() ) );
4117 break;
4118 case arrayValue:
4119 writeArrayValue( value);
4120 break;
4121 case objectValue:
4122 {
4123 Value::Members members( value.getMemberNames() );
4124 if ( members.empty() )
4125 pushValue( "{}" );
4126 else
4127 {
4128 writeWithIndent( "{" );
4129 indent();
4130 Value::Members::iterator it = members.begin();
4131 for (;;)
4132 {
4133 const std::string &name = *it;
4134 const Value &childValue = value[name];
4135 writeCommentBeforeValue( childValue );
4136 writeWithIndent( valueToQuotedString( name.c_str() ) );
4137 *document_ << " : ";
4138 writeValue( childValue );
4139 if ( ++it == members.end() )
4140 {
4141 writeCommentAfterValueOnSameLine( childValue );
4142 break;
4143 }
4144 *document_ << ",";
4145 writeCommentAfterValueOnSameLine( childValue );
4146 }
4147 unindent();
4148 writeWithIndent( "}" );
4149 }
4150 }
4151 break;
4152 }
4153 }
4154
4155
4156 void
4157 StyledStreamWriter::writeArrayValue( const Value &value )
4158 {
4159 unsigned size = value.size();
4160 if ( size == 0 )
4161 pushValue( "[]" );
4162 else
4163 {
4164 bool isArrayMultiLine = isMultineArray( value );
4165 if ( isArrayMultiLine )
4166 {
4167 writeWithIndent( "[" );
4168 indent();
4169 bool hasChildValue = !childValues_.empty();
4170 unsigned index =0;
4171 for (;;)
4172 {
4173 const Value &childValue = value[index];
4174 writeCommentBeforeValue( childValue );
4175 if ( hasChildValue )
4176 writeWithIndent( childValues_[index] );
4177 else
4178 {
4179 writeIndent();
4180 writeValue( childValue );
4181 }
4182 if ( ++index == size )
4183 {
4184 writeCommentAfterValueOnSameLine( childValue );
4185 break;
4186 }
4187 *document_ << ",";
4188 writeCommentAfterValueOnSameLine( childValue );
4189 }
4190 unindent();
4191 writeWithIndent( "]" );
4192 }
4193 else // output on a single line
4194 {
4195 assert( childValues_.size() == size );
4196 *document_ << "[ ";
4197 for ( unsigned index =0; index < size; ++index )
4198 {
4199 if ( index > 0 )
4200 *document_ << ", ";
4201 *document_ << childValues_[index];
4202 }
4203 *document_ << " ]";
4204 }
4205 }
4206 }
4207
4208
4209 bool
4210 StyledStreamWriter::isMultineArray( const Value &value )
4211 {
4212 int size = value.size();
4213 bool isMultiLine = size*3 >= rightMargin_ ;
4214 childValues_.clear();
4215 for ( int index =0; index < size && !isMultiLine; ++index )
4216 {
4217 const Value &childValue = value[index];
4218 isMultiLine = isMultiLine ||
4219 ( (childValue.isArray() || childValue.isObject()) &&
4220 childValue.size() > 0 );
4221 }
4222 if ( !isMultiLine ) // check if line length > max line length
4223 {
4224 childValues_.reserve( size );
4225 addChildValues_ = true;
4226 int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]'
4227 for ( int index =0; index < size && !isMultiLine; ++index )
4228 {
4229 writeValue( value[index] );
4230 lineLength += int( childValues_[index].length() );
4231 isMultiLine = isMultiLine && hasCommentForValue( value[index] );
4232 }
4233 addChildValues_ = false;
4234 isMultiLine = isMultiLine || lineLength >= rightMargin_;
4235 }
4236 return isMultiLine;
4237 }
4238
4239
4240 void
4241 StyledStreamWriter::pushValue( const std::string &value )
4242 {
4243 if ( addChildValues_ )
4244 childValues_.push_back( value );
4245 else
4246 *document_ << value;
4247 }
4248
4249
4250 void
4251 StyledStreamWriter::writeIndent()
4252 {
4253 /*
4254 Some comments in this method would have been nice. ;-)
4255
4256 if ( !document_.empty() )
4257 {
4258 char last = document_[document_.length()-1];
4259 if ( last == ' ' ) // already indented
4260 return;
4261 if ( last != '\n' ) // Comments may add new-line
4262 *document_ << '\n';
4263 }
4264 */
4265 *document_ << '\n' << indentString_;
4266 }
4267
4268
4269 void
4270 StyledStreamWriter::writeWithIndent( const std::string &value )
4271 {
4272 writeIndent();
4273 *document_ << value;
4274 }
4275
4276
4277 void
4278 StyledStreamWriter::indent()
4279 {
4280 indentString_ += indentation_;
4281 }
4282
4283
4284 void
4285 StyledStreamWriter::unindent()
4286 {
4287 assert( indentString_.size() >= indentation_.size() );
4288 indentString_.resize( indentString_.size() - indentation_.size() );
4289 }
4290
4291
4292 void
4293 StyledStreamWriter::writeCommentBeforeValue( const Value &root )
4294 {
4295 if ( !root.hasComment( commentBefore ) )
4296 return;
4297 *document_ << normalizeEOL( root.getComment( commentBefore ) );
4298 *document_ << "\n";
4299 }
4300
4301
4302 void
4303 StyledStreamWriter::writeCommentAfterValueOnSameLine( const Value &root )
4304 {
4305 if ( root.hasComment( commentAfterOnSameLine ) )
4306 *document_ << " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) );
4307
4308 if ( root.hasComment( commentAfter ) )
4309 {
4310 *document_ << "\n";
4311 *document_ << normalizeEOL( root.getComment( commentAfter ) );
4312 *document_ << "\n";
4313 }
4314 }
4315
4316
4317 bool
4318 StyledStreamWriter::hasCommentForValue( const Value &value )
4319 {
4320 return value.hasComment( commentBefore )
4321 || value.hasComment( commentAfterOnSameLine )
4322 || value.hasComment( commentAfter );
4323 }
4324
4325
4326 std::string
4327 StyledStreamWriter::normalizeEOL( const std::string &text )
4328 {
4329 std::string normalized;
4330 normalized.reserve( text.length() );
4331 const char *begin = text.c_str();
4332 const char *end = begin + text.length();
4333 const char *current = begin;
4334 while ( current != end )
4335 {
4336 char c = *current++;
4337 if ( c == '\r' ) // mac or dos EOL
4338 {
4339 if ( *current == '\n' ) // convert dos EOL
4340 ++current;
4341 normalized += '\n';
4342 }
4343 else // handle unix EOL & other char
4344 normalized += c;
4345 }
4346 return normalized;
4347 }
4348
4349
4350 std::ostream& operator<<( std::ostream &sout, const Value &root )
4351 {
4352 Json::StyledStreamWriter writer;
4353 writer.write(sout, root);
4354 return sout;
4355 }
4356
4357
4358 } // namespace Json
4359
4360 // //////////////////////////////////////////////////////////////////////
4361 // End of content of file: src/lib_json/json_writer.cpp
4362 // //////////////////////////////////////////////////////////////////////
4363
4364
4365
4366
4367