1 /// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/).
2 /// It is intented to be used with #include <jellyfish/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 <jellyfish/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 *&current )
163 {
164    *--current = 0;
165    do
166    {
167       *--current = char(value % 10) + '0';
168       value /= 10;
169    }
170    while ( value != 0 );
171 }
172 
173 } // namespace Json {
174 
175 #endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED
176 
177 // //////////////////////////////////////////////////////////////////////
178 // End of content of file: src/lib_json/json_tool.h
179 // //////////////////////////////////////////////////////////////////////
180 
181 
182 
183 
184 
185 
186 // //////////////////////////////////////////////////////////////////////
187 // Beginning of content of file: src/lib_json/json_reader.cpp
188 // //////////////////////////////////////////////////////////////////////
189 
190 // Copyright 2007-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_ = &currentValue();
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 <= 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 &current,
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 &current,
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 &current )
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 &current )
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 &current )
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