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