1 /// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/).
2 /// It is intented to be used with #include <json/json.h>
4 // //////////////////////////////////////////////////////////////////////
5 // Beginning of content of file: LICENSE
6 // //////////////////////////////////////////////////////////////////////
9 The JsonCpp library's source code, including accompanying documentation,
10 tests and demonstration applications, are licensed under the following
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.
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).
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.
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:
29 http://en.wikipedia.org/wiki/MIT_License
31 The full text of the MIT License follows:
33 ========================================================================
34 Copyright (c) 2007-2010 Baptiste Lepilleur
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:
44 The above copyright notice and this permission notice shall be
45 included in all copies or substantial portions of the Software.
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
55 ========================================================================
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
67 // //////////////////////////////////////////////////////////////////////
68 // End of content of file: LICENSE
69 // //////////////////////////////////////////////////////////////////////
79 // //////////////////////////////////////////////////////////////////////
80 // Beginning of content of file: src/lib_json/json_tool.h
81 // //////////////////////////////////////////////////////////////////////
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
88 #ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
89 # define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
91 /* This header provides common string manipulation support, such as UTF-8,
92 * portable conversion from/to string...
94 * It is an internal header that must not be exposed.
99 /// Converts a unicode code-point to UTF-8.
100 static inline std::string
101 codePointToUTF8(unsigned int cp)
105 // based on description from http://en.wikipedia.org/wiki/UTF-8
110 result[0] = static_cast<char>(cp);
112 else if (cp <= 0x7FF)
115 result[1] = static_cast<char>(0x80 | (0x3f & cp));
116 result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
118 else if (cp <= 0xFFFF)
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)));
125 else if (cp <= 0x10FFFF)
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)));
138 /// Returns true if ch is a control character (in range [0,32[).
140 isControlCharacter(char ch)
142 return ch > 0 && ch <= 0x1F;
147 /// Constant that specify the size of the buffer that must be passed to uintToString.
148 uintToStringBufferSize = 3*sizeof(LargestUInt)+1
151 // Defines a char buffer for use with uintToString().
152 typedef char UIntToStringBuffer[uintToStringBufferSize];
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.
161 uintToString( LargestUInt value,
167 *--current = char(value % 10) + '0';
170 while ( value != 0 );
173 } // namespace Json {
175 #endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED
177 // //////////////////////////////////////////////////////////////////////
178 // End of content of file: src/lib_json/json_tool.h
179 // //////////////////////////////////////////////////////////////////////
186 // //////////////////////////////////////////////////////////////////////
187 // Beginning of content of file: src/lib_json/json_reader.cpp
188 // //////////////////////////////////////////////////////////////////////
190 // Copyright 2007-2011 Baptiste Lepilleur
191 // Distributed under MIT license, or public domain if desired and
192 // recognized in your jurisdiction.
193 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
195 #if !defined(JSON_IS_AMALGAMATION)
196 # include <json/assertions.h>
197 # include <json/reader.h>
198 # include <json/value.h>
199 # include "json_tool.h"
200 #endif // if !defined(JSON_IS_AMALGAMATION)
207 #if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
208 #pragma warning( disable : 4996 ) // disable warning about strdup being deprecated.
213 // Implementation of class Features
214 // ////////////////////////////////
217 : allowComments_( true )
218 , strictRoot_( false )
231 Features::strictMode()
234 features.allowComments_ = false;
235 features.strictRoot_ = true;
239 // Implementation of class Reader
240 // ////////////////////////////////
244 in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4 )
246 return c == c1 || c == c2 || c == c3 || c == c4;
250 in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4, Reader::Char c5 )
252 return c == c1 || c == c2 || c == c3 || c == c4 || c == c5;
257 containsNewLine( Reader::Location begin,
258 Reader::Location end )
260 for ( ;begin < end; ++begin )
261 if ( *begin == '\n' || *begin == '\r' )
268 // //////////////////////////////////////////////////////////////////
279 features_( Features::all() ),
285 Reader::Reader( const Features &features )
294 features_( features ),
301 Reader::parse( const std::string &document,
303 bool collectComments )
305 document_ = document;
306 const char *begin = document_.c_str();
307 const char *end = begin + document_.length();
308 return parse( begin, end, root, collectComments );
313 Reader::parse( std::istream& sin,
315 bool collectComments )
317 //std::istream_iterator<char> begin(sin);
318 //std::istream_iterator<char> end;
319 // Those would allow streamed input from a file, if parse() were a
320 // template function.
322 // Since std::string is reference-counted, this at least does not
323 // create an extra copy.
325 std::getline(sin, doc, (char)EOF);
326 return parse( doc, root, collectComments );
330 Reader::parse( const char *beginDoc, const char *endDoc,
332 bool collectComments )
334 if ( !features_.allowComments_ )
336 collectComments = false;
341 collectComments_ = collectComments;
345 commentsBefore_ = "";
347 while ( !nodes_.empty() )
349 nodes_.push( &root );
351 bool successful = readValue();
353 skipCommentTokens( token );
354 if ( collectComments_ && !commentsBefore_.empty() )
355 root.setComment( commentsBefore_, commentAfter );
356 if ( features_.strictRoot_ )
358 if ( !root.isArray() && !root.isObject() )
360 // Set error location to start of doc, ideally should be first token found in doc
361 token.type_ = tokenError;
362 token.start_ = beginDoc;
364 addError( "A valid JSON document must be either an array or an object value.",
377 skipCommentTokens( token );
378 bool successful = true;
380 if ( collectComments_ && !commentsBefore_.empty() )
382 currentValue().setComment( commentsBefore_, commentBefore );
383 commentsBefore_ = "";
387 switch ( token.type_ )
389 case tokenObjectBegin:
390 successful = readObject( token );
392 case tokenArrayBegin:
393 successful = readArray( token );
396 successful = decodeNumber( token );
399 successful = decodeString( token );
402 currentValue() = true;
405 currentValue() = false;
408 currentValue() = Value();
411 return addError( "Syntax error: value, object or array expected.", token );
414 if ( collectComments_ )
416 lastValueEnd_ = current_;
417 lastValue_ = ¤tValue();
425 Reader::skipCommentTokens( Token &token )
427 if ( features_.allowComments_ )
433 while ( token.type_ == tokenComment );
443 Reader::expectToken( TokenType type, Token &token, const char *message )
446 if ( token.type_ != type )
447 return addError( message, token );
453 Reader::readToken( Token &token )
456 token.start_ = current_;
457 Char c = getNextChar();
462 token.type_ = tokenObjectBegin;
465 token.type_ = tokenObjectEnd;
468 token.type_ = tokenArrayBegin;
471 token.type_ = tokenArrayEnd;
474 token.type_ = tokenString;
478 token.type_ = tokenComment;
492 token.type_ = tokenNumber;
496 token.type_ = tokenTrue;
497 ok = match( "rue", 3 );
500 token.type_ = tokenFalse;
501 ok = match( "alse", 4 );
504 token.type_ = tokenNull;
505 ok = match( "ull", 3 );
508 token.type_ = tokenArraySeparator;
511 token.type_ = tokenMemberSeparator;
514 token.type_ = tokenEndOfStream;
521 token.type_ = tokenError;
522 token.end_ = current_;
530 while ( current_ != end_ )
533 if ( c == ' ' || c == '\t' || c == '\r' || c == '\n' )
542 Reader::match( Location pattern,
545 if ( end_ - current_ < patternLength )
547 int index = patternLength;
549 if ( current_[index] != pattern[index] )
551 current_ += patternLength;
557 Reader::readComment()
559 Location commentBegin = current_ - 1;
560 Char c = getNextChar();
561 bool successful = false;
563 successful = readCStyleComment();
565 successful = readCppStyleComment();
569 if ( collectComments_ )
571 CommentPlacement placement = commentBefore;
572 if ( lastValueEnd_ && !containsNewLine( lastValueEnd_, commentBegin ) )
574 if ( c != '*' || !containsNewLine( commentBegin, current_ ) )
575 placement = commentAfterOnSameLine;
578 addComment( commentBegin, current_, placement );
585 Reader::addComment( Location begin,
587 CommentPlacement placement )
589 assert( collectComments_ );
590 if ( placement == commentAfterOnSameLine )
592 assert( lastValue_ != 0 );
593 lastValue_->setComment( std::string( begin, end ), placement );
597 if ( !commentsBefore_.empty() )
598 commentsBefore_ += "\n";
599 commentsBefore_ += std::string( begin, end );
605 Reader::readCStyleComment()
607 while ( current_ != end_ )
609 Char c = getNextChar();
610 if ( c == '*' && *current_ == '/' )
613 return getNextChar() == '/';
618 Reader::readCppStyleComment()
620 while ( current_ != end_ )
622 Char c = getNextChar();
623 if ( c == '\r' || c == '\n' )
633 while ( current_ != end_ )
635 if ( !(*current_ >= '0' && *current_ <= '9') &&
636 !in( *current_, '.', 'e', 'E', '+', '-' ) )
646 while ( current_ != end_ )
659 Reader::readObject( Token &/*tokenStart*/ )
663 currentValue() = Value( objectValue );
664 while ( readToken( tokenName ) )
666 bool initialTokenOk = true;
667 while ( tokenName.type_ == tokenComment && initialTokenOk )
668 initialTokenOk = readToken( tokenName );
669 if ( !initialTokenOk )
671 if ( tokenName.type_ == tokenObjectEnd && name.empty() ) // empty object
673 if ( tokenName.type_ != tokenString )
677 if ( !decodeString( tokenName, name ) )
678 return recoverFromError( tokenObjectEnd );
681 if ( !readToken( colon ) || colon.type_ != tokenMemberSeparator )
683 return addErrorAndRecover( "Missing ':' after object member name",
687 Value &value = currentValue()[ name ];
688 nodes_.push( &value );
689 bool ok = readValue();
691 if ( !ok ) // error already set
692 return recoverFromError( tokenObjectEnd );
695 if ( !readToken( comma )
696 || ( comma.type_ != tokenObjectEnd &&
697 comma.type_ != tokenArraySeparator &&
698 comma.type_ != tokenComment ) )
700 return addErrorAndRecover( "Missing ',' or '}' in object declaration",
704 bool finalizeTokenOk = true;
705 while ( comma.type_ == tokenComment &&
707 finalizeTokenOk = readToken( comma );
708 if ( comma.type_ == tokenObjectEnd )
711 return addErrorAndRecover( "Missing '}' or object member name",
718 Reader::readArray( Token &/*tokenStart*/ )
720 currentValue() = Value( arrayValue );
722 if ( *current_ == ']' ) // empty array
725 readToken( endArray );
731 Value &value = currentValue()[ index++ ];
732 nodes_.push( &value );
733 bool ok = readValue();
735 if ( !ok ) // error already set
736 return recoverFromError( tokenArrayEnd );
739 // Accept Comment after last item in the array.
740 ok = readToken( token );
741 while ( token.type_ == tokenComment && ok )
743 ok = readToken( token );
745 bool badTokenType = ( token.type_ != tokenArraySeparator &&
746 token.type_ != tokenArrayEnd );
747 if ( !ok || badTokenType )
749 return addErrorAndRecover( "Missing ',' or ']' in array declaration",
753 if ( token.type_ == tokenArrayEnd )
761 Reader::decodeNumber( Token &token )
763 bool isDouble = false;
764 for ( Location inspect = token.start_; inspect != token.end_; ++inspect )
767 || in( *inspect, '.', 'e', 'E', '+' )
768 || ( *inspect == '-' && inspect != token.start_ );
771 return decodeDouble( token );
772 // Attempts to parse the number as an integer. If the number is
773 // larger than the maximum supported value of an integer then
774 // we decode the number as a double.
775 Location current = token.start_;
776 bool isNegative = *current == '-';
779 Value::LargestUInt maxIntegerValue = isNegative ? Value::LargestUInt(-Value::minLargestInt)
780 : Value::maxLargestUInt;
781 Value::LargestUInt threshold = maxIntegerValue / 10;
782 Value::LargestUInt value = 0;
783 while ( current < token.end_ )
786 if ( c < '0' || c > '9' )
787 return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
788 Value::UInt digit(c - '0');
789 if ( value >= threshold )
791 // We've hit or exceeded the max value divided by 10 (rounded down). If
792 // a) we've only just touched the limit, b) this is the last digit, and
793 // c) it's small enough to fit in that rounding delta, we're okay.
794 // Otherwise treat this number as a double to avoid overflow.
795 if (value > threshold ||
796 current != token.end_ ||
797 digit > maxIntegerValue % 10)
799 return decodeDouble( token );
802 value = value * 10 + digit;
805 currentValue() = -Value::LargestInt( value );
806 else if ( value <= Value::LargestUInt(Value::maxInt) )
807 currentValue() = Value::LargestInt( value );
809 currentValue() = value;
815 Reader::decodeDouble( Token &token )
818 const int bufferSize = 32;
820 int length = int(token.end_ - token.start_);
822 // Sanity check to avoid buffer overflow exploits.
824 return addError( "Unable to parse token length", token );
827 // Avoid using a string constant for the format control string given to
828 // sscanf, as this can cause hard to debug crashes on OS X. See here for more
831 // http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html
832 char format[] = "%lf";
834 if ( length <= bufferSize )
836 Char buffer[bufferSize+1];
837 memcpy( buffer, token.start_, length );
839 count = sscanf( buffer, format, &value );
843 std::string buffer( token.start_, token.end_ );
844 count = sscanf( buffer.c_str(), format, &value );
848 return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
849 currentValue() = value;
855 Reader::decodeString( Token &token )
858 if ( !decodeString( token, decoded ) )
860 currentValue() = decoded;
866 Reader::decodeString( Token &token, std::string &decoded )
868 decoded.reserve( token.end_ - token.start_ - 2 );
869 Location current = token.start_ + 1; // skip '"'
870 Location end = token.end_ - 1; // do not include '"'
871 while ( current != end )
876 else if ( c == '\\' )
878 if ( current == end )
879 return addError( "Empty escape sequence in string", token, current );
880 Char escape = *current++;
883 case '"': decoded += '"'; break;
884 case '/': decoded += '/'; break;
885 case '\\': decoded += '\\'; break;
886 case 'b': decoded += '\b'; break;
887 case 'f': decoded += '\f'; break;
888 case 'n': decoded += '\n'; break;
889 case 'r': decoded += '\r'; break;
890 case 't': decoded += '\t'; break;
893 unsigned int unicode;
894 if ( !decodeUnicodeCodePoint( token, current, end, unicode ) )
896 decoded += codePointToUTF8(unicode);
900 return addError( "Bad escape sequence in string", token, current );
912 Reader::decodeUnicodeCodePoint( Token &token,
915 unsigned int &unicode )
918 if ( !decodeUnicodeEscapeSequence( token, current, end, unicode ) )
920 if (unicode >= 0xD800 && unicode <= 0xDBFF)
923 if (end - current < 6)
924 return addError( "additional six characters expected to parse unicode surrogate pair.", token, current );
925 unsigned int surrogatePair;
926 if (*(current++) == '\\' && *(current++)== 'u')
928 if (decodeUnicodeEscapeSequence( token, current, end, surrogatePair ))
930 unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
936 return addError( "expecting another \\u token to begin the second half of a unicode surrogate pair", token, current );
942 Reader::decodeUnicodeEscapeSequence( Token &token,
945 unsigned int &unicode )
947 if ( end - current < 4 )
948 return addError( "Bad unicode escape sequence in string: four digits expected.", token, current );
950 for ( int index =0; index < 4; ++index )
954 if ( c >= '0' && c <= '9' )
956 else if ( c >= 'a' && c <= 'f' )
957 unicode += c - 'a' + 10;
958 else if ( c >= 'A' && c <= 'F' )
959 unicode += c - 'A' + 10;
961 return addError( "Bad unicode escape sequence in string: hexadecimal digit expected.", token, current );
968 Reader::addError( const std::string &message,
974 info.message_ = message;
976 errors_.push_back( info );
982 Reader::recoverFromError( TokenType skipUntilToken )
984 int errorCount = int(errors_.size());
988 if ( !readToken(skip) )
989 errors_.resize( errorCount ); // discard errors caused by recovery
990 if ( skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream )
993 errors_.resize( errorCount );
999 Reader::addErrorAndRecover( const std::string &message,
1001 TokenType skipUntilToken )
1003 addError( message, token );
1004 return recoverFromError( skipUntilToken );
1009 Reader::currentValue()
1011 return *(nodes_.top());
1016 Reader::getNextChar()
1018 if ( current_ == end_ )
1025 Reader::getLocationLineAndColumn( Location location,
1029 Location current = begin_;
1030 Location lastLineStart = current;
1032 while ( current < location && current != end_ )
1034 Char c = *current++;
1037 if ( *current == '\n' )
1039 lastLineStart = current;
1042 else if ( c == '\n' )
1044 lastLineStart = current;
1048 // column & line start at 1
1049 column = int(location - lastLineStart) + 1;
1055 Reader::getLocationLineAndColumn( Location location ) const
1058 getLocationLineAndColumn( location, line, column );
1059 char buffer[18+16+16+1];
1060 sprintf( buffer, "Line %d, Column %d", line, column );
1065 // Deprecated. Preserved for backward compatibility
1067 Reader::getFormatedErrorMessages() const
1069 return getFormattedErrorMessages();
1074 Reader::getFormattedErrorMessages() const
1076 std::string formattedMessage;
1077 for ( Errors::const_iterator itError = errors_.begin();
1078 itError != errors_.end();
1081 const ErrorInfo &error = *itError;
1082 formattedMessage += "* " + getLocationLineAndColumn( error.token_.start_ ) + "\n";
1083 formattedMessage += " " + error.message_ + "\n";
1085 formattedMessage += "See " + getLocationLineAndColumn( error.extra_ ) + " for detail.\n";
1087 return formattedMessage;
1091 std::istream& operator>>( std::istream &sin, Value &root )
1093 Json::Reader reader;
1094 bool ok = reader.parse(sin, root, true);
1098 "Error from reader: %s",
1099 reader.getFormattedErrorMessages().c_str());
1101 JSON_FAIL_MESSAGE("reader error");
1109 // //////////////////////////////////////////////////////////////////////
1110 // End of content of file: src/lib_json/json_reader.cpp
1111 // //////////////////////////////////////////////////////////////////////
1118 // //////////////////////////////////////////////////////////////////////
1119 // Beginning of content of file: src/lib_json/json_batchallocator.h
1120 // //////////////////////////////////////////////////////////////////////
1122 // Copyright 2007-2010 Baptiste Lepilleur
1123 // Distributed under MIT license, or public domain if desired and
1124 // recognized in your jurisdiction.
1125 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
1127 #ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED
1128 # define JSONCPP_BATCHALLOCATOR_H_INCLUDED
1130 # include <stdlib.h>
1131 # include <assert.h>
1133 # ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
1137 /* Fast memory allocator.
1139 * This memory allocator allocates memory for a batch of object (specified by
1140 * the page size, the number of object in each page).
1142 * It does not allow the destruction of a single object. All the allocated objects
1143 * can be destroyed at once. The memory can be either released or reused for future
1146 * The in-place new operator must be used to construct the object using the pointer
1147 * returned by allocate.
1149 template<typename AllocatedType
1150 ,const unsigned int objectPerAllocation>
1151 class BatchAllocator
1154 BatchAllocator( unsigned int objectsPerPage = 255 )
1156 , objectsPerPage_( objectsPerPage )
1158 // printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() );
1159 assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space.
1160 assert( objectsPerPage >= 16 );
1161 batches_ = allocateBatch( 0 ); // allocated a dummy page
1162 currentBatch_ = batches_;
1167 for ( BatchInfo *batch = batches_; batch; )
1169 BatchInfo *nextBatch = batch->next_;
1175 /// allocate space for an array of objectPerAllocation object.
1176 /// @warning it is the responsability of the caller to call objects constructors.
1177 AllocatedType *allocate()
1179 if ( freeHead_ ) // returns node from free list.
1181 AllocatedType *object = freeHead_;
1182 freeHead_ = *(AllocatedType **)object;
1185 if ( currentBatch_->used_ == currentBatch_->end_ )
1187 currentBatch_ = currentBatch_->next_;
1188 while ( currentBatch_ && currentBatch_->used_ == currentBatch_->end_ )
1189 currentBatch_ = currentBatch_->next_;
1191 if ( !currentBatch_ ) // no free batch found, allocate a new one
1193 currentBatch_ = allocateBatch( objectsPerPage_ );
1194 currentBatch_->next_ = batches_; // insert at the head of the list
1195 batches_ = currentBatch_;
1198 AllocatedType *allocated = currentBatch_->used_;
1199 currentBatch_->used_ += objectPerAllocation;
1203 /// Release the object.
1204 /// @warning it is the responsability of the caller to actually destruct the object.
1205 void release( AllocatedType *object )
1207 assert( object != 0 );
1208 *(AllocatedType **)object = freeHead_;
1216 AllocatedType *used_;
1217 AllocatedType *end_;
1218 AllocatedType buffer_[objectPerAllocation];
1221 // disabled copy constructor and assignement operator.
1222 BatchAllocator( const BatchAllocator & );
1223 void operator =( const BatchAllocator &);
1225 static BatchInfo *allocateBatch( unsigned int objectsPerPage )
1227 const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation
1228 + sizeof(AllocatedType) * objectPerAllocation * objectsPerPage;
1229 BatchInfo *batch = static_cast<BatchInfo*>( malloc( mallocSize ) );
1231 batch->used_ = batch->buffer_;
1232 batch->end_ = batch->buffer_ + objectsPerPage;
1236 BatchInfo *batches_;
1237 BatchInfo *currentBatch_;
1238 /// Head of a single linked list within the allocated space of freeed object
1239 AllocatedType *freeHead_;
1240 unsigned int objectsPerPage_;
1246 # endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION
1248 #endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED
1250 // //////////////////////////////////////////////////////////////////////
1251 // End of content of file: src/lib_json/json_batchallocator.h
1252 // //////////////////////////////////////////////////////////////////////
1259 // //////////////////////////////////////////////////////////////////////
1260 // Beginning of content of file: src/lib_json/json_valueiterator.inl
1261 // //////////////////////////////////////////////////////////////////////
1263 // Copyright 2007-2010 Baptiste Lepilleur
1264 // Distributed under MIT license, or public domain if desired and
1265 // recognized in your jurisdiction.
1266 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
1268 // included by json_value.cpp
1272 // //////////////////////////////////////////////////////////////////
1273 // //////////////////////////////////////////////////////////////////
1274 // //////////////////////////////////////////////////////////////////
1275 // class ValueIteratorBase
1276 // //////////////////////////////////////////////////////////////////
1277 // //////////////////////////////////////////////////////////////////
1278 // //////////////////////////////////////////////////////////////////
1280 ValueIteratorBase::ValueIteratorBase()
1281 #ifndef JSON_VALUE_USE_INTERNAL_MAP
1290 iterator_.array_ = ValueInternalArray::IteratorState();
1295 #ifndef JSON_VALUE_USE_INTERNAL_MAP
1296 ValueIteratorBase::ValueIteratorBase( const Value::ObjectValues::iterator ¤t )
1297 : current_( current )
1302 ValueIteratorBase::ValueIteratorBase( const ValueInternalArray::IteratorState &state )
1305 iterator_.array_ = state;
1309 ValueIteratorBase::ValueIteratorBase( const ValueInternalMap::IteratorState &state )
1312 iterator_.map_ = state;
1317 ValueIteratorBase::deref() const
1319 #ifndef JSON_VALUE_USE_INTERNAL_MAP
1320 return current_->second;
1323 return ValueInternalArray::dereference( iterator_.array_ );
1324 return ValueInternalMap::value( iterator_.map_ );
1330 ValueIteratorBase::increment()
1332 #ifndef JSON_VALUE_USE_INTERNAL_MAP
1336 ValueInternalArray::increment( iterator_.array_ );
1337 ValueInternalMap::increment( iterator_.map_ );
1343 ValueIteratorBase::decrement()
1345 #ifndef JSON_VALUE_USE_INTERNAL_MAP
1349 ValueInternalArray::decrement( iterator_.array_ );
1350 ValueInternalMap::decrement( iterator_.map_ );
1355 ValueIteratorBase::difference_type
1356 ValueIteratorBase::computeDistance( const SelfType &other ) const
1358 #ifndef JSON_VALUE_USE_INTERNAL_MAP
1359 # ifdef JSON_USE_CPPTL_SMALLMAP
1360 return current_ - other.current_;
1362 // Iterator for null value are initialized using the default
1363 // constructor, which initialize current_ to the default
1364 // std::map::iterator. As begin() and end() are two instance
1365 // of the default std::map::iterator, they can not be compared.
1366 // To allow this, we handle this comparison specifically.
1367 if ( isNull_ && other.isNull_ )
1373 // Usage of std::distance is not portable (does not compile with Sun Studio 12 RogueWave STL,
1374 // which is the one used by default).
1375 // Using a portable hand-made version for non random iterator instead:
1376 // return difference_type( std::distance( current_, other.current_ ) );
1377 difference_type myDistance = 0;
1378 for ( Value::ObjectValues::iterator it = current_; it != other.current_; ++it )
1386 return ValueInternalArray::distance( iterator_.array_, other.iterator_.array_ );
1387 return ValueInternalMap::distance( iterator_.map_, other.iterator_.map_ );
1393 ValueIteratorBase::isEqual( const SelfType &other ) const
1395 #ifndef JSON_VALUE_USE_INTERNAL_MAP
1398 return other.isNull_;
1400 return current_ == other.current_;
1403 return ValueInternalArray::equals( iterator_.array_, other.iterator_.array_ );
1404 return ValueInternalMap::equals( iterator_.map_, other.iterator_.map_ );
1410 ValueIteratorBase::copy( const SelfType &other )
1412 #ifndef JSON_VALUE_USE_INTERNAL_MAP
1413 current_ = other.current_;
1416 iterator_.array_ = other.iterator_.array_;
1417 iterator_.map_ = other.iterator_.map_;
1423 ValueIteratorBase::key() const
1425 #ifndef JSON_VALUE_USE_INTERNAL_MAP
1426 const Value::CZString czstring = (*current_).first;
1427 if ( czstring.c_str() )
1429 if ( czstring.isStaticString() )
1430 return Value( StaticString( czstring.c_str() ) );
1431 return Value( czstring.c_str() );
1433 return Value( czstring.index() );
1436 return Value( ValueInternalArray::indexOf( iterator_.array_ ) );
1438 const char *memberName = ValueInternalMap::key( iterator_.map_, isStatic );
1440 return Value( StaticString( memberName ) );
1441 return Value( memberName );
1447 ValueIteratorBase::index() const
1449 #ifndef JSON_VALUE_USE_INTERNAL_MAP
1450 const Value::CZString czstring = (*current_).first;
1451 if ( !czstring.c_str() )
1452 return czstring.index();
1453 return Value::UInt( -1 );
1456 return Value::UInt( ValueInternalArray::indexOf( iterator_.array_ ) );
1457 return Value::UInt( -1 );
1463 ValueIteratorBase::memberName() const
1465 #ifndef JSON_VALUE_USE_INTERNAL_MAP
1466 const char *name = (*current_).first.c_str();
1467 return name ? name : "";
1470 return ValueInternalMap::key( iterator_.map_ );
1476 // //////////////////////////////////////////////////////////////////
1477 // //////////////////////////////////////////////////////////////////
1478 // //////////////////////////////////////////////////////////////////
1479 // class ValueConstIterator
1480 // //////////////////////////////////////////////////////////////////
1481 // //////////////////////////////////////////////////////////////////
1482 // //////////////////////////////////////////////////////////////////
1484 ValueConstIterator::ValueConstIterator()
1489 #ifndef JSON_VALUE_USE_INTERNAL_MAP
1490 ValueConstIterator::ValueConstIterator( const Value::ObjectValues::iterator ¤t )
1491 : ValueIteratorBase( current )
1495 ValueConstIterator::ValueConstIterator( const ValueInternalArray::IteratorState &state )
1496 : ValueIteratorBase( state )
1500 ValueConstIterator::ValueConstIterator( const ValueInternalMap::IteratorState &state )
1501 : ValueIteratorBase( state )
1506 ValueConstIterator &
1507 ValueConstIterator::operator =( const ValueIteratorBase &other )
1514 // //////////////////////////////////////////////////////////////////
1515 // //////////////////////////////////////////////////////////////////
1516 // //////////////////////////////////////////////////////////////////
1517 // class ValueIterator
1518 // //////////////////////////////////////////////////////////////////
1519 // //////////////////////////////////////////////////////////////////
1520 // //////////////////////////////////////////////////////////////////
1522 ValueIterator::ValueIterator()
1527 #ifndef JSON_VALUE_USE_INTERNAL_MAP
1528 ValueIterator::ValueIterator( const Value::ObjectValues::iterator ¤t )
1529 : ValueIteratorBase( current )
1533 ValueIterator::ValueIterator( const ValueInternalArray::IteratorState &state )
1534 : ValueIteratorBase( state )
1538 ValueIterator::ValueIterator( const ValueInternalMap::IteratorState &state )
1539 : ValueIteratorBase( state )
1544 ValueIterator::ValueIterator( const ValueConstIterator &other )
1545 : ValueIteratorBase( other )
1549 ValueIterator::ValueIterator( const ValueIterator &other )
1550 : ValueIteratorBase( other )
1555 ValueIterator::operator =( const SelfType &other )
1563 // //////////////////////////////////////////////////////////////////////
1564 // End of content of file: src/lib_json/json_valueiterator.inl
1565 // //////////////////////////////////////////////////////////////////////
1572 // //////////////////////////////////////////////////////////////////////
1573 // Beginning of content of file: src/lib_json/json_value.cpp
1574 // //////////////////////////////////////////////////////////////////////
1576 // Copyright 2011 Baptiste Lepilleur
1577 // Distributed under MIT license, or public domain if desired and
1578 // recognized in your jurisdiction.
1579 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
1581 #if !defined(JSON_IS_AMALGAMATION)
1582 # include <json/assertions.h>
1583 # include <json/value.h>
1584 # include <json/writer.h>
1585 # ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
1586 # include "json_batchallocator.h"
1587 # endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
1588 #endif // if !defined(JSON_IS_AMALGAMATION)
1592 #include <stdexcept>
1595 #ifdef JSON_USE_CPPTL
1596 # include <cpptl/conststring.h>
1598 #include <cstddef> // size_t
1600 #define JSON_ASSERT_UNREACHABLE assert( false )
1604 const Value Value::null;
1605 const Int Value::minInt = Int( ~(UInt(-1)/2) );
1606 const Int Value::maxInt = Int( UInt(-1)/2 );
1607 const UInt Value::maxUInt = UInt(-1);
1608 # if defined(JSON_HAS_INT64)
1609 const Int64 Value::minInt64 = Int64( ~(UInt64(-1)/2) );
1610 const Int64 Value::maxInt64 = Int64( UInt64(-1)/2 );
1611 const UInt64 Value::maxUInt64 = UInt64(-1);
1612 // The constant is hard-coded because some compiler have trouble
1613 // converting Value::maxUInt64 to a double correctly (AIX/xlC).
1614 // Assumes that UInt64 is a 64 bits integer.
1615 static const double maxUInt64AsDouble = 18446744073709551615.0;
1616 #endif // defined(JSON_HAS_INT64)
1617 const LargestInt Value::minLargestInt = LargestInt( ~(LargestUInt(-1)/2) );
1618 const LargestInt Value::maxLargestInt = LargestInt( LargestUInt(-1)/2 );
1619 const LargestUInt Value::maxLargestUInt = LargestUInt(-1);
1622 /// Unknown size marker
1623 static const unsigned int unknown = (unsigned)-1;
1625 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
1626 template <typename T, typename U>
1627 static inline bool InRange(double d, T min, U max) {
1628 return d >= min && d <= max;
1630 #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
1631 static inline double integerToDouble( Json::UInt64 value )
1633 return static_cast<double>( Int64(value/2) ) * 2.0 + Int64(value & 1);
1636 template<typename T>
1637 static inline double integerToDouble( T value )
1639 return static_cast<double>( value );
1642 template <typename T, typename U>
1643 static inline bool InRange(double d, T min, U max) {
1644 return d >= integerToDouble(min) && d <= integerToDouble(max);
1646 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
1649 /** Duplicates the specified string value.
1650 * @param value Pointer to the string to duplicate. Must be zero-terminated if
1651 * length is "unknown".
1652 * @param length Length of the value. if equals to unknown, then it will be
1653 * computed using strlen(value).
1654 * @return Pointer on the duplicate instance of string.
1656 static inline char *
1657 duplicateStringValue( const char *value,
1658 unsigned int length = unknown )
1660 if ( length == unknown )
1661 length = (unsigned int)strlen(value);
1663 // Avoid an integer overflow in the call to malloc below by limiting length
1665 if (length >= (unsigned)Value::maxInt)
1666 length = Value::maxInt - 1;
1668 char *newString = static_cast<char *>( malloc( length + 1 ) );
1669 JSON_ASSERT_MESSAGE( newString != 0, "Failed to allocate string value buffer" );
1670 memcpy( newString, value, length );
1671 newString[length] = 0;
1676 /** Free the string duplicated by duplicateStringValue().
1679 releaseStringValue( char *value )
1688 // //////////////////////////////////////////////////////////////////
1689 // //////////////////////////////////////////////////////////////////
1690 // //////////////////////////////////////////////////////////////////
1691 // ValueInternals...
1692 // //////////////////////////////////////////////////////////////////
1693 // //////////////////////////////////////////////////////////////////
1694 // //////////////////////////////////////////////////////////////////
1695 #if !defined(JSON_IS_AMALGAMATION)
1696 # ifdef JSON_VALUE_USE_INTERNAL_MAP
1697 # include "json_internalarray.inl"
1698 # include "json_internalmap.inl"
1699 # endif // JSON_VALUE_USE_INTERNAL_MAP
1701 # include "json_valueiterator.inl"
1702 #endif // if !defined(JSON_IS_AMALGAMATION)
1706 // //////////////////////////////////////////////////////////////////
1707 // //////////////////////////////////////////////////////////////////
1708 // //////////////////////////////////////////////////////////////////
1709 // class Value::CommentInfo
1710 // //////////////////////////////////////////////////////////////////
1711 // //////////////////////////////////////////////////////////////////
1712 // //////////////////////////////////////////////////////////////////
1715 Value::CommentInfo::CommentInfo()
1720 Value::CommentInfo::~CommentInfo()
1723 releaseStringValue( comment_ );
1728 Value::CommentInfo::setComment( const char *text )
1731 releaseStringValue( comment_ );
1732 JSON_ASSERT( text != 0 );
1733 JSON_ASSERT_MESSAGE( text[0]=='\0' || text[0]=='/', "Comments must start with /");
1734 // It seems that /**/ style comments are acceptable as well.
1735 comment_ = duplicateStringValue( text );
1739 // //////////////////////////////////////////////////////////////////
1740 // //////////////////////////////////////////////////////////////////
1741 // //////////////////////////////////////////////////////////////////
1742 // class Value::CZString
1743 // //////////////////////////////////////////////////////////////////
1744 // //////////////////////////////////////////////////////////////////
1745 // //////////////////////////////////////////////////////////////////
1746 # ifndef JSON_VALUE_USE_INTERNAL_MAP
1748 // Notes: index_ indicates if the string was allocated when
1749 // a string is stored.
1751 Value::CZString::CZString( ArrayIndex index )
1757 Value::CZString::CZString( const char *cstr, DuplicationPolicy allocate )
1758 : cstr_( allocate == duplicate ? duplicateStringValue(cstr)
1760 , index_( allocate )
1764 Value::CZString::CZString( const CZString &other )
1765 : cstr_( other.index_ != noDuplication && other.cstr_ != 0
1766 ? duplicateStringValue( other.cstr_ )
1768 , index_( other.cstr_ ? (other.index_ == noDuplication ? noDuplication : duplicate)
1773 Value::CZString::~CZString()
1775 if ( cstr_ && index_ == duplicate )
1776 releaseStringValue( const_cast<char *>( cstr_ ) );
1780 Value::CZString::swap( CZString &other )
1782 std::swap( cstr_, other.cstr_ );
1783 std::swap( index_, other.index_ );
1787 Value::CZString::operator =( const CZString &other )
1789 CZString temp( other );
1795 Value::CZString::operator<( const CZString &other ) const
1798 return strcmp( cstr_, other.cstr_ ) < 0;
1799 return index_ < other.index_;
1803 Value::CZString::operator==( const CZString &other ) const
1806 return strcmp( cstr_, other.cstr_ ) == 0;
1807 return index_ == other.index_;
1812 Value::CZString::index() const
1819 Value::CZString::c_str() const
1825 Value::CZString::isStaticString() const
1827 return index_ == noDuplication;
1830 #endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
1833 // //////////////////////////////////////////////////////////////////
1834 // //////////////////////////////////////////////////////////////////
1835 // //////////////////////////////////////////////////////////////////
1836 // class Value::Value
1837 // //////////////////////////////////////////////////////////////////
1838 // //////////////////////////////////////////////////////////////////
1839 // //////////////////////////////////////////////////////////////////
1841 /*! \internal Default constructor initialization must be equivalent to:
1842 * memset( this, 0, sizeof(Value) )
1843 * This optimization is used in ValueInternalMap fast allocator.
1845 Value::Value( ValueType type )
1847 , allocated_( false )
1848 # ifdef JSON_VALUE_USE_INTERNAL_MAP
1867 #ifndef JSON_VALUE_USE_INTERNAL_MAP
1870 value_.map_ = new ObjectValues();
1874 value_.array_ = arrayAllocator()->newArray();
1877 value_.map_ = mapAllocator()->newMap();
1881 value_.bool_ = false;
1884 JSON_ASSERT_UNREACHABLE;
1889 Value::Value( UInt value )
1890 : type_( uintValue )
1891 , allocated_( false )
1892 # ifdef JSON_VALUE_USE_INTERNAL_MAP
1897 value_.uint_ = value;
1900 Value::Value( Int value )
1902 , allocated_( false )
1903 # ifdef JSON_VALUE_USE_INTERNAL_MAP
1908 value_.int_ = value;
1912 # if defined(JSON_HAS_INT64)
1913 Value::Value( Int64 value )
1915 , allocated_( false )
1916 # ifdef JSON_VALUE_USE_INTERNAL_MAP
1921 value_.int_ = value;
1925 Value::Value( UInt64 value )
1926 : type_( uintValue )
1927 , allocated_( false )
1928 # ifdef JSON_VALUE_USE_INTERNAL_MAP
1933 value_.uint_ = value;
1935 #endif // defined(JSON_HAS_INT64)
1937 Value::Value( double value )
1938 : type_( realValue )
1939 , allocated_( false )
1940 # ifdef JSON_VALUE_USE_INTERNAL_MAP
1945 value_.real_ = value;
1948 Value::Value( const char *value )
1949 : type_( stringValue )
1950 , allocated_( true )
1951 # ifdef JSON_VALUE_USE_INTERNAL_MAP
1956 value_.string_ = duplicateStringValue( value );
1960 Value::Value( const char *beginValue,
1961 const char *endValue )
1962 : type_( stringValue )
1963 , allocated_( true )
1964 # ifdef JSON_VALUE_USE_INTERNAL_MAP
1969 value_.string_ = duplicateStringValue( beginValue,
1970 (unsigned int)(endValue - beginValue) );
1974 Value::Value( const std::string &value )
1975 : type_( stringValue )
1976 , allocated_( true )
1977 # ifdef JSON_VALUE_USE_INTERNAL_MAP
1982 value_.string_ = duplicateStringValue( value.c_str(),
1983 (unsigned int)value.length() );
1987 Value::Value( const StaticString &value )
1988 : type_( stringValue )
1989 , allocated_( false )
1990 # ifdef JSON_VALUE_USE_INTERNAL_MAP
1995 value_.string_ = const_cast<char *>( value.c_str() );
1999 # ifdef JSON_USE_CPPTL
2000 Value::Value( const CppTL::ConstString &value )
2001 : type_( stringValue )
2002 , allocated_( true )
2003 # ifdef JSON_VALUE_USE_INTERNAL_MAP
2008 value_.string_ = duplicateStringValue( value, value.length() );
2012 Value::Value( bool value )
2013 : type_( booleanValue )
2014 , allocated_( false )
2015 # ifdef JSON_VALUE_USE_INTERNAL_MAP
2020 value_.bool_ = value;
2024 Value::Value( const Value &other )
2025 : type_( other.type_ )
2026 , allocated_( false )
2027 # ifdef JSON_VALUE_USE_INTERNAL_MAP
2039 value_ = other.value_;
2042 if ( other.value_.string_ )
2044 value_.string_ = duplicateStringValue( other.value_.string_ );
2050 #ifndef JSON_VALUE_USE_INTERNAL_MAP
2053 value_.map_ = new ObjectValues( *other.value_.map_ );
2057 value_.array_ = arrayAllocator()->newArrayCopy( *other.value_.array_ );
2060 value_.map_ = mapAllocator()->newMapCopy( *other.value_.map_ );
2064 JSON_ASSERT_UNREACHABLE;
2066 if ( other.comments_ )
2068 comments_ = new CommentInfo[numberOfCommentPlacement];
2069 for ( int comment =0; comment < numberOfCommentPlacement; ++comment )
2071 const CommentInfo &otherComment = other.comments_[comment];
2072 if ( otherComment.comment_ )
2073 comments_[comment].setComment( otherComment.comment_ );
2091 releaseStringValue( value_.string_ );
2093 #ifndef JSON_VALUE_USE_INTERNAL_MAP
2100 arrayAllocator()->destructArray( value_.array_ );
2103 mapAllocator()->destructMap( value_.map_ );
2107 JSON_ASSERT_UNREACHABLE;
2115 Value::operator=( const Value &other )
2117 Value temp( other );
2123 Value::swap( Value &other )
2125 ValueType temp = type_;
2126 type_ = other.type_;
2128 std::swap( value_, other.value_ );
2129 int temp2 = allocated_;
2130 allocated_ = other.allocated_;
2131 other.allocated_ = temp2;
2142 Value::compare( const Value &other ) const
2144 if ( *this < other )
2146 if ( *this > other )
2153 Value::operator <( const Value &other ) const
2155 int typeDelta = type_ - other.type_;
2157 return typeDelta < 0 ? true : false;
2163 return value_.int_ < other.value_.int_;
2165 return value_.uint_ < other.value_.uint_;
2167 return value_.real_ < other.value_.real_;
2169 return value_.bool_ < other.value_.bool_;
2171 return ( value_.string_ == 0 && other.value_.string_ )
2172 || ( other.value_.string_
2174 && strcmp( value_.string_, other.value_.string_ ) < 0 );
2175 #ifndef JSON_VALUE_USE_INTERNAL_MAP
2179 int delta = int( value_.map_->size() - other.value_.map_->size() );
2182 return (*value_.map_) < (*other.value_.map_);
2186 return value_.array_->compare( *(other.value_.array_) ) < 0;
2188 return value_.map_->compare( *(other.value_.map_) ) < 0;
2191 JSON_ASSERT_UNREACHABLE;
2193 return false; // unreachable
2197 Value::operator <=( const Value &other ) const
2199 return !(other < *this);
2203 Value::operator >=( const Value &other ) const
2205 return !(*this < other);
2209 Value::operator >( const Value &other ) const
2211 return other < *this;
2215 Value::operator ==( const Value &other ) const
2217 //if ( type_ != other.type_ )
2219 // attempt to take address of bit-field structure member `Json::Value::type_'
2220 // Beats me, but a temp solves the problem.
2221 int temp = other.type_;
2222 if ( type_ != temp )
2229 return value_.int_ == other.value_.int_;
2231 return value_.uint_ == other.value_.uint_;
2233 return value_.real_ == other.value_.real_;
2235 return value_.bool_ == other.value_.bool_;
2237 return ( value_.string_ == other.value_.string_ )
2238 || ( other.value_.string_
2240 && strcmp( value_.string_, other.value_.string_ ) == 0 );
2241 #ifndef JSON_VALUE_USE_INTERNAL_MAP
2244 return value_.map_->size() == other.value_.map_->size()
2245 && (*value_.map_) == (*other.value_.map_);
2248 return value_.array_->compare( *(other.value_.array_) ) == 0;
2250 return value_.map_->compare( *(other.value_.map_) ) == 0;
2253 JSON_ASSERT_UNREACHABLE;
2255 return false; // unreachable
2259 Value::operator !=( const Value &other ) const
2261 return !( *this == other );
2265 Value::asCString() const
2267 JSON_ASSERT( type_ == stringValue );
2268 return value_.string_;
2273 Value::asString() const
2280 return value_.string_ ? value_.string_ : "";
2282 return value_.bool_ ? "true" : "false";
2284 return valueToString( value_.int_ );
2286 return valueToString( value_.uint_ );
2288 return valueToString( value_.real_ );
2290 JSON_FAIL_MESSAGE( "Type is not convertible to string" );
2294 # ifdef JSON_USE_CPPTL
2296 Value::asConstString() const
2298 return CppTL::ConstString( asString().c_str() );
2304 Value::asInt() const
2309 JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range");
2310 return Int(value_.int_);
2312 JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range");
2313 return Int(value_.uint_);
2315 JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt), "double out of Int range");
2316 return Int(value_.real_);
2320 return value_.bool_ ? 1 : 0;
2324 JSON_FAIL_MESSAGE("Value is not convertible to Int.");
2329 Value::asUInt() const
2334 JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range");
2335 return UInt(value_.int_);
2337 JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
2338 return UInt(value_.uint_);
2340 JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt), "double out of UInt range");
2341 return UInt( value_.real_ );
2345 return value_.bool_ ? 1 : 0;
2349 JSON_FAIL_MESSAGE("Value is not convertible to UInt.");
2353 # if defined(JSON_HAS_INT64)
2356 Value::asInt64() const
2361 return Int64(value_.int_);
2363 JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
2364 return Int64(value_.uint_);
2366 JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64), "double out of Int64 range");
2367 return Int64(value_.real_);
2371 return value_.bool_ ? 1 : 0;
2375 JSON_FAIL_MESSAGE("Value is not convertible to Int64.");
2380 Value::asUInt64() const
2385 JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range");
2386 return UInt64(value_.int_);
2388 return UInt64(value_.uint_);
2390 JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64), "double out of UInt64 range");
2391 return UInt64( value_.real_ );
2395 return value_.bool_ ? 1 : 0;
2399 JSON_FAIL_MESSAGE("Value is not convertible to UInt64.");
2401 # endif // if defined(JSON_HAS_INT64)
2405 Value::asLargestInt() const
2407 #if defined(JSON_NO_INT64)
2416 Value::asLargestUInt() const
2418 #if defined(JSON_NO_INT64)
2427 Value::asDouble() const
2432 return static_cast<double>( value_.int_ );
2434 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2435 return static_cast<double>( value_.uint_ );
2436 #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2437 return integerToDouble( value_.uint_ );
2438 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2440 return value_.real_;
2444 return value_.bool_ ? 1.0 : 0.0;
2448 JSON_FAIL_MESSAGE("Value is not convertible to double.");
2452 Value::asFloat() const
2457 return static_cast<float>( value_.int_ );
2459 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2460 return static_cast<float>( value_.uint_ );
2461 #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2462 return integerToDouble( value_.uint_ );
2463 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2465 return static_cast<float>( value_.real_ );
2469 return value_.bool_ ? 1.0f : 0.0f;
2473 JSON_FAIL_MESSAGE("Value is not convertible to float.");
2477 Value::asBool() const
2482 return value_.bool_;
2486 return value_.int_ ? true : false;
2488 return value_.uint_ ? true : false;
2490 return value_.real_ ? true : false;
2494 JSON_FAIL_MESSAGE("Value is not convertible to bool.");
2499 Value::isConvertibleTo( ValueType other ) const
2504 return ( isNumeric() && asDouble() == 0.0 )
2505 || ( type_ == booleanValue && value_.bool_ == false )
2506 || ( type_ == stringValue && asString() == "" )
2507 || ( type_ == arrayValue && value_.map_->size() == 0 )
2508 || ( type_ == objectValue && value_.map_->size() == 0 )
2509 || type_ == nullValue;
2512 || (type_ == realValue && InRange(value_.real_, minInt, maxInt))
2513 || type_ == booleanValue
2514 || type_ == nullValue;
2517 || (type_ == realValue && InRange(value_.real_, 0, maxUInt))
2518 || type_ == booleanValue
2519 || type_ == nullValue;
2522 || type_ == booleanValue
2523 || type_ == nullValue;
2526 || type_ == booleanValue
2527 || type_ == nullValue;
2530 || type_ == booleanValue
2531 || type_ == stringValue
2532 || type_ == nullValue;
2534 return type_ == arrayValue
2535 || type_ == nullValue;
2537 return type_ == objectValue
2538 || type_ == nullValue;
2540 JSON_ASSERT_UNREACHABLE;
2545 /// Number of values in array or object
2558 #ifndef JSON_VALUE_USE_INTERNAL_MAP
2559 case arrayValue: // size of the array is highest index + 1
2560 if ( !value_.map_->empty() )
2562 ObjectValues::const_iterator itLast = value_.map_->end();
2564 return (*itLast).first.index()+1;
2568 return ArrayIndex( value_.map_->size() );
2571 return Int( value_.array_->size() );
2573 return Int( value_.map_->size() );
2576 JSON_ASSERT_UNREACHABLE;
2577 return 0; // unreachable;
2582 Value::empty() const
2584 if ( isNull() || isArray() || isObject() )
2585 return size() == 0u;
2592 Value::operator!() const
2601 JSON_ASSERT( type_ == nullValue || type_ == arrayValue || type_ == objectValue );
2605 #ifndef JSON_VALUE_USE_INTERNAL_MAP
2608 value_.map_->clear();
2612 value_.array_->clear();
2615 value_.map_->clear();
2624 Value::resize( ArrayIndex newSize )
2626 JSON_ASSERT( type_ == nullValue || type_ == arrayValue );
2627 if ( type_ == nullValue )
2628 *this = Value( arrayValue );
2629 #ifndef JSON_VALUE_USE_INTERNAL_MAP
2630 ArrayIndex oldSize = size();
2633 else if ( newSize > oldSize )
2634 (*this)[ newSize - 1 ];
2637 for ( ArrayIndex index = newSize; index < oldSize; ++index )
2639 value_.map_->erase( index );
2641 assert( size() == newSize );
2644 value_.array_->resize( newSize );
2650 Value::operator[]( ArrayIndex index )
2652 JSON_ASSERT( type_ == nullValue || type_ == arrayValue );
2653 if ( type_ == nullValue )
2654 *this = Value( arrayValue );
2655 #ifndef JSON_VALUE_USE_INTERNAL_MAP
2656 CZString key( index );
2657 ObjectValues::iterator it = value_.map_->lower_bound( key );
2658 if ( it != value_.map_->end() && (*it).first == key )
2659 return (*it).second;
2661 ObjectValues::value_type defaultValue( key, null );
2662 it = value_.map_->insert( it, defaultValue );
2663 return (*it).second;
2665 return value_.array_->resolveReference( index );
2671 Value::operator[]( int index )
2673 JSON_ASSERT( index >= 0 );
2674 return (*this)[ ArrayIndex(index) ];
2679 Value::operator[]( ArrayIndex index ) const
2681 JSON_ASSERT( type_ == nullValue || type_ == arrayValue );
2682 if ( type_ == nullValue )
2684 #ifndef JSON_VALUE_USE_INTERNAL_MAP
2685 CZString key( index );
2686 ObjectValues::const_iterator it = value_.map_->find( key );
2687 if ( it == value_.map_->end() )
2689 return (*it).second;
2691 Value *value = value_.array_->find( index );
2692 return value ? *value : null;
2698 Value::operator[]( int index ) const
2700 JSON_ASSERT( index >= 0 );
2701 return (*this)[ ArrayIndex(index) ];
2706 Value::operator[]( const char *key )
2708 return resolveReference( key, false );
2713 Value::resolveReference( const char *key,
2716 JSON_ASSERT( type_ == nullValue || type_ == objectValue );
2717 if ( type_ == nullValue )
2718 *this = Value( objectValue );
2719 #ifndef JSON_VALUE_USE_INTERNAL_MAP
2720 CZString actualKey( key, isStatic ? CZString::noDuplication
2721 : CZString::duplicateOnCopy );
2722 ObjectValues::iterator it = value_.map_->lower_bound( actualKey );
2723 if ( it != value_.map_->end() && (*it).first == actualKey )
2724 return (*it).second;
2726 ObjectValues::value_type defaultValue( actualKey, null );
2727 it = value_.map_->insert( it, defaultValue );
2728 Value &value = (*it).second;
2731 return value_.map_->resolveReference( key, isStatic );
2737 Value::get( ArrayIndex index,
2738 const Value &defaultValue ) const
2740 const Value *value = &((*this)[index]);
2741 return value == &null ? defaultValue : *value;
2746 Value::isValidIndex( ArrayIndex index ) const
2748 return index < size();
2754 Value::operator[]( const char *key ) const
2756 JSON_ASSERT( type_ == nullValue || type_ == objectValue );
2757 if ( type_ == nullValue )
2759 #ifndef JSON_VALUE_USE_INTERNAL_MAP
2760 CZString actualKey( key, CZString::noDuplication );
2761 ObjectValues::const_iterator it = value_.map_->find( actualKey );
2762 if ( it == value_.map_->end() )
2764 return (*it).second;
2766 const Value *value = value_.map_->find( key );
2767 return value ? *value : null;
2773 Value::operator[]( const std::string &key )
2775 return (*this)[ key.c_str() ];
2780 Value::operator[]( const std::string &key ) const
2782 return (*this)[ key.c_str() ];
2786 Value::operator[]( const StaticString &key )
2788 return resolveReference( key, true );
2792 # ifdef JSON_USE_CPPTL
2794 Value::operator[]( const CppTL::ConstString &key )
2796 return (*this)[ key.c_str() ];
2801 Value::operator[]( const CppTL::ConstString &key ) const
2803 return (*this)[ key.c_str() ];
2809 Value::append( const Value &value )
2811 return (*this)[size()] = value;
2816 Value::get( const char *key,
2817 const Value &defaultValue ) const
2819 const Value *value = &((*this)[key]);
2820 return value == &null ? defaultValue : *value;
2825 Value::get( const std::string &key,
2826 const Value &defaultValue ) const
2828 return get( key.c_str(), defaultValue );
2832 Value::removeMember( const char* key )
2834 JSON_ASSERT( type_ == nullValue || type_ == objectValue );
2835 if ( type_ == nullValue )
2837 #ifndef JSON_VALUE_USE_INTERNAL_MAP
2838 CZString actualKey( key, CZString::noDuplication );
2839 ObjectValues::iterator it = value_.map_->find( actualKey );
2840 if ( it == value_.map_->end() )
2842 Value old(it->second);
2843 value_.map_->erase(it);
2846 Value *value = value_.map_->find( key );
2849 value_.map_.remove( key );
2858 Value::removeMember( const std::string &key )
2860 return removeMember( key.c_str() );
2863 # ifdef JSON_USE_CPPTL
2865 Value::get( const CppTL::ConstString &key,
2866 const Value &defaultValue ) const
2868 return get( key.c_str(), defaultValue );
2873 Value::isMember( const char *key ) const
2875 const Value *value = &((*this)[key]);
2876 return value != &null;
2881 Value::isMember( const std::string &key ) const
2883 return isMember( key.c_str() );
2887 # ifdef JSON_USE_CPPTL
2889 Value::isMember( const CppTL::ConstString &key ) const
2891 return isMember( key.c_str() );
2896 Value::getMemberNames() const
2898 JSON_ASSERT( type_ == nullValue || type_ == objectValue );
2899 if ( type_ == nullValue )
2900 return Value::Members();
2902 members.reserve( value_.map_->size() );
2903 #ifndef JSON_VALUE_USE_INTERNAL_MAP
2904 ObjectValues::const_iterator it = value_.map_->begin();
2905 ObjectValues::const_iterator itEnd = value_.map_->end();
2906 for ( ; it != itEnd; ++it )
2907 members.push_back( std::string( (*it).first.c_str() ) );
2909 ValueInternalMap::IteratorState it;
2910 ValueInternalMap::IteratorState itEnd;
2911 value_.map_->makeBeginIterator( it );
2912 value_.map_->makeEndIterator( itEnd );
2913 for ( ; !ValueInternalMap::equals( it, itEnd ); ValueInternalMap::increment(it) )
2914 members.push_back( std::string( ValueInternalMap::key( it ) ) );
2919 //# ifdef JSON_USE_CPPTL
2921 //Value::enumMemberNames() const
2923 // if ( type_ == objectValue )
2925 // return CppTL::Enum::any( CppTL::Enum::transform(
2926 // CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
2927 // MemberNamesTransform() ) );
2929 // return EnumMemberNames();
2934 //Value::enumValues() const
2936 // if ( type_ == objectValue || type_ == arrayValue )
2937 // return CppTL::Enum::anyValues( *(value_.map_),
2938 // CppTL::Type<const Value &>() );
2939 // return EnumValues();
2944 static bool IsIntegral(double d) {
2945 double integral_part;
2946 return modf(d, &integral_part) == 0.0;
2951 Value::isNull() const
2953 return type_ == nullValue;
2958 Value::isBool() const
2960 return type_ == booleanValue;
2965 Value::isInt() const
2970 return value_.int_ >= minInt && value_.int_ <= maxInt;
2972 return value_.uint_ <= UInt(maxInt);
2974 return value_.real_ >= minInt &&
2975 value_.real_ <= maxInt &&
2976 IsIntegral(value_.real_);
2985 Value::isUInt() const
2990 return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);
2992 return value_.uint_ <= maxUInt;
2994 return value_.real_ >= 0 &&
2995 value_.real_ <= maxUInt &&
2996 IsIntegral(value_.real_);
3004 Value::isInt64() const
3006 # if defined(JSON_HAS_INT64)
3012 return value_.uint_ <= UInt64(maxInt64);
3014 // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
3015 // double, so double(maxInt64) will be rounded up to 2^63. Therefore we
3016 // require the value to be strictly less than the limit.
3017 return value_.real_ >= double(minInt64) &&
3018 value_.real_ < double(maxInt64) &&
3019 IsIntegral(value_.real_);
3023 # endif // JSON_HAS_INT64
3028 Value::isUInt64() const
3030 # if defined(JSON_HAS_INT64)
3034 return value_.int_ >= 0;
3038 // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
3039 // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
3040 // require the value to be strictly less than the limit.
3041 return value_.real_ >= 0 &&
3042 value_.real_ < maxUInt64AsDouble &&
3043 IsIntegral(value_.real_);
3047 # endif // JSON_HAS_INT64
3053 Value::isIntegral() const
3055 #if defined(JSON_HAS_INT64)
3056 return isInt64() || isUInt64();
3058 return isInt() || isUInt();
3064 Value::isDouble() const
3066 return type_ == realValue || isIntegral();
3071 Value::isNumeric() const
3073 return isIntegral() || isDouble();
3078 Value::isString() const
3080 return type_ == stringValue;
3085 Value::isArray() const
3087 return type_ == arrayValue;
3092 Value::isObject() const
3094 return type_ == objectValue;
3099 Value::setComment( const char *comment,
3100 CommentPlacement placement )
3103 comments_ = new CommentInfo[numberOfCommentPlacement];
3104 comments_[placement].setComment( comment );
3109 Value::setComment( const std::string &comment,
3110 CommentPlacement placement )
3112 setComment( comment.c_str(), placement );
3117 Value::hasComment( CommentPlacement placement ) const
3119 return comments_ != 0 && comments_[placement].comment_ != 0;
3123 Value::getComment( CommentPlacement placement ) const
3125 if ( hasComment(placement) )
3126 return comments_[placement].comment_;
3132 Value::toStyledString() const
3134 StyledWriter writer;
3135 return writer.write( *this );
3139 Value::const_iterator
3140 Value::begin() const
3144 #ifdef JSON_VALUE_USE_INTERNAL_MAP
3146 if ( value_.array_ )
3148 ValueInternalArray::IteratorState it;
3149 value_.array_->makeBeginIterator( it );
3150 return const_iterator( it );
3156 ValueInternalMap::IteratorState it;
3157 value_.map_->makeBeginIterator( it );
3158 return const_iterator( it );
3165 return const_iterator( value_.map_->begin() );
3171 return const_iterator();
3174 Value::const_iterator
3179 #ifdef JSON_VALUE_USE_INTERNAL_MAP
3181 if ( value_.array_ )
3183 ValueInternalArray::IteratorState it;
3184 value_.array_->makeEndIterator( it );
3185 return const_iterator( it );
3191 ValueInternalMap::IteratorState it;
3192 value_.map_->makeEndIterator( it );
3193 return const_iterator( it );
3200 return const_iterator( value_.map_->end() );
3206 return const_iterator();
3215 #ifdef JSON_VALUE_USE_INTERNAL_MAP
3217 if ( value_.array_ )
3219 ValueInternalArray::IteratorState it;
3220 value_.array_->makeBeginIterator( it );
3221 return iterator( it );
3227 ValueInternalMap::IteratorState it;
3228 value_.map_->makeBeginIterator( it );
3229 return iterator( it );
3236 return iterator( value_.map_->begin() );
3250 #ifdef JSON_VALUE_USE_INTERNAL_MAP
3252 if ( value_.array_ )
3254 ValueInternalArray::IteratorState it;
3255 value_.array_->makeEndIterator( it );
3256 return iterator( it );
3262 ValueInternalMap::IteratorState it;
3263 value_.map_->makeEndIterator( it );
3264 return iterator( it );
3271 return iterator( value_.map_->end() );
3281 // class PathArgument
3282 // //////////////////////////////////////////////////////////////////
3284 PathArgument::PathArgument()
3292 PathArgument::PathArgument( ArrayIndex index )
3295 , kind_( kindIndex )
3300 PathArgument::PathArgument( const char *key )
3308 PathArgument::PathArgument( const std::string &key )
3309 : key_( key.c_str() )
3316 // //////////////////////////////////////////////////////////////////
3318 Path::Path( const std::string &path,
3319 const PathArgument &a1,
3320 const PathArgument &a2,
3321 const PathArgument &a3,
3322 const PathArgument &a4,
3323 const PathArgument &a5 )
3326 in.push_back( &a1 );
3327 in.push_back( &a2 );
3328 in.push_back( &a3 );
3329 in.push_back( &a4 );
3330 in.push_back( &a5 );
3331 makePath( path, in );
3336 Path::makePath( const std::string &path,
3339 const char *current = path.c_str();
3340 const char *end = current + path.length();
3341 InArgs::const_iterator itInArg = in.begin();
3342 while ( current != end )
3344 if ( *current == '[' )
3347 if ( *current == '%' )
3348 addPathInArg( path, in, itInArg, PathArgument::kindIndex );
3351 ArrayIndex index = 0;
3352 for ( ; current != end && *current >= '0' && *current <= '9'; ++current )
3353 index = index * 10 + ArrayIndex(*current - '0');
3354 args_.push_back( index );
3356 if ( current == end || *current++ != ']' )
3357 invalidPath( path, int(current - path.c_str()) );
3359 else if ( *current == '%' )
3361 addPathInArg( path, in, itInArg, PathArgument::kindKey );
3364 else if ( *current == '.' )
3370 const char *beginName = current;
3371 while ( current != end && !strchr( "[.", *current ) )
3373 args_.push_back( std::string( beginName, current ) );
3380 Path::addPathInArg( const std::string &path,
3382 InArgs::const_iterator &itInArg,
3383 PathArgument::Kind kind )
3385 if ( itInArg == in.end() )
3387 // Error: missing argument %d
3389 else if ( (*itInArg)->kind_ != kind )
3391 // Error: bad argument type
3395 args_.push_back( **itInArg );
3401 Path::invalidPath( const std::string &path,
3404 // Error: invalid path.
3409 Path::resolve( const Value &root ) const
3411 const Value *node = &root;
3412 for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
3414 const PathArgument &arg = *it;
3415 if ( arg.kind_ == PathArgument::kindIndex )
3417 if ( !node->isArray() || !node->isValidIndex( arg.index_ ) )
3419 // Error: unable to resolve path (array value expected at position...
3421 node = &((*node)[arg.index_]);
3423 else if ( arg.kind_ == PathArgument::kindKey )
3425 if ( !node->isObject() )
3427 // Error: unable to resolve path (object value expected at position...)
3429 node = &((*node)[arg.key_]);
3430 if ( node == &Value::null )
3432 // Error: unable to resolve path (object has no member named '' at position...)
3441 Path::resolve( const Value &root,
3442 const Value &defaultValue ) const
3444 const Value *node = &root;
3445 for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
3447 const PathArgument &arg = *it;
3448 if ( arg.kind_ == PathArgument::kindIndex )
3450 if ( !node->isArray() || !node->isValidIndex( arg.index_ ) )
3451 return defaultValue;
3452 node = &((*node)[arg.index_]);
3454 else if ( arg.kind_ == PathArgument::kindKey )
3456 if ( !node->isObject() )
3457 return defaultValue;
3458 node = &((*node)[arg.key_]);
3459 if ( node == &Value::null )
3460 return defaultValue;
3468 Path::make( Value &root ) const
3470 Value *node = &root;
3471 for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
3473 const PathArgument &arg = *it;
3474 if ( arg.kind_ == PathArgument::kindIndex )
3476 if ( !node->isArray() )
3478 // Error: node is not an array at position ...
3480 node = &((*node)[arg.index_]);
3482 else if ( arg.kind_ == PathArgument::kindKey )
3484 if ( !node->isObject() )
3486 // Error: node is not an object at position...
3488 node = &((*node)[arg.key_]);
3497 // //////////////////////////////////////////////////////////////////////
3498 // End of content of file: src/lib_json/json_value.cpp
3499 // //////////////////////////////////////////////////////////////////////
3506 // //////////////////////////////////////////////////////////////////////
3507 // Beginning of content of file: src/lib_json/json_writer.cpp
3508 // //////////////////////////////////////////////////////////////////////
3510 // Copyright 2011 Baptiste Lepilleur
3511 // Distributed under MIT license, or public domain if desired and
3512 // recognized in your jurisdiction.
3513 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
3515 #if !defined(JSON_IS_AMALGAMATION)
3516 # include <json/writer.h>
3517 # include "json_tool.h"
3518 #endif // if !defined(JSON_IS_AMALGAMATION)
3526 #if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
3527 #pragma warning( disable : 4996 ) // disable warning about strdup being deprecated.
3532 static bool containsControlCharacter( const char* str )
3536 if ( isControlCharacter( *(str++) ) )
3543 std::string valueToString( LargestInt value )
3545 UIntToStringBuffer buffer;
3546 char *current = buffer + sizeof(buffer);
3547 bool isNegative = value < 0;
3550 uintToString( LargestUInt(value), current );
3553 assert( current >= buffer );
3558 std::string valueToString( LargestUInt value )
3560 UIntToStringBuffer buffer;
3561 char *current = buffer + sizeof(buffer);
3562 uintToString( value, current );
3563 assert( current >= buffer );
3567 #if defined(JSON_HAS_INT64)
3569 std::string valueToString( Int value )
3571 return valueToString( LargestInt(value) );
3575 std::string valueToString( UInt value )
3577 return valueToString( LargestUInt(value) );
3580 #endif // # if defined(JSON_HAS_INT64)
3583 std::string valueToString( double value )
3586 #if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with visual studio 2005 to avoid warning.
3587 sprintf_s(buffer, sizeof(buffer), "%#.16g", value);
3589 sprintf(buffer, "%#.16g", value);
3591 char* ch = buffer + strlen(buffer) - 1;
3592 if (*ch != '0') return buffer; // nothing to truncate, so save time
3593 while(ch > buffer && *ch == '0'){
3596 char* last_nonzero = ch;
3597 while(ch >= buffer){
3612 // Truncate zeroes to save bytes in output, but keep one.
3613 *(last_nonzero+2) = '\0';
3623 std::string valueToString( bool value )
3625 return value ? "true" : "false";
3628 std::string valueToQuotedString( const char *value )
3632 // Not sure how to handle unicode...
3633 if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && !containsControlCharacter( value ))
3634 return std::string("\"") + value + "\"";
3635 // We have to walk value and escape any special characters.
3636 // Appending to std::string is not efficient, but this should be rare.
3637 // (Note: forward slashes are *not* rare, but I am not escaping them.)
3638 std::string::size_type maxsize = strlen(value)*2 + 3; // allescaped+quotes+NULL
3640 result.reserve(maxsize); // to avoid lots of mallocs
3642 for (const char* c=value; *c != 0; ++c)
3668 // Even though \/ is considered a legal escape in JSON, a bare
3669 // slash is also legal, so I see no reason to escape it.
3670 // (I hope I am not misunderstanding something.
3671 // blep notes: actually escaping \/ may be useful in javascript to avoid </
3673 // Should add a flag to allow this compatibility mode and prevent this
3674 // sequence from occurring.
3676 if ( isControlCharacter( *c ) )
3678 std::ostringstream oss;
3679 oss << "\\u" << std::hex << std::uppercase << std::setfill('0') << std::setw(4) << static_cast<int>(*c);
3680 result += oss.str();
3694 // //////////////////////////////////////////////////////////////////
3701 // //////////////////////////////////////////////////////////////////
3703 FastWriter::FastWriter()
3704 : yamlCompatiblityEnabled_( false ),
3705 dropNullPlaceholders_( false )
3711 FastWriter::enableYAMLCompatibility()
3713 yamlCompatiblityEnabled_ = true;
3718 FastWriter::dropNullPlaceholders()
3720 dropNullPlaceholders_ = true;
3725 FastWriter::write( const Value &root )
3735 FastWriter::writeValue( const Value &value )
3737 switch ( value.type() )
3740 if (!dropNullPlaceholders_) document_ += "null";
3743 document_ += valueToString( value.asLargestInt() );
3746 document_ += valueToString( value.asLargestUInt() );
3749 document_ += valueToString( value.asDouble() );
3752 document_ += valueToQuotedString( value.asCString() );
3755 document_ += valueToString( value.asBool() );
3760 int size = value.size();
3761 for ( int index =0; index < size; ++index )
3765 writeValue( value[index] );
3772 Value::Members members( value.getMemberNames() );
3774 for ( Value::Members::iterator it = members.begin();
3775 it != members.end();
3778 const std::string &name = *it;
3779 if ( it != members.begin() )
3781 document_ += valueToQuotedString( name.c_str() );
3782 document_ += yamlCompatiblityEnabled_ ? ": "
3784 writeValue( value[name] );
3793 // Class StyledWriter
3794 // //////////////////////////////////////////////////////////////////
3796 StyledWriter::StyledWriter()
3797 : rightMargin_( 74 )
3805 StyledWriter::write( const Value &root )
3808 addChildValues_ = false;
3810 writeCommentBeforeValue( root );
3812 writeCommentAfterValueOnSameLine( root );
3819 StyledWriter::writeValue( const Value &value )
3821 switch ( value.type() )
3824 pushValue( "null" );
3827 pushValue( valueToString( value.asLargestInt() ) );
3830 pushValue( valueToString( value.asLargestUInt() ) );
3833 pushValue( valueToString( value.asDouble() ) );
3836 pushValue( valueToQuotedString( value.asCString() ) );
3839 pushValue( valueToString( value.asBool() ) );
3842 writeArrayValue( value);
3846 Value::Members members( value.getMemberNames() );
3847 if ( members.empty() )
3851 writeWithIndent( "{" );
3853 Value::Members::iterator it = members.begin();
3856 const std::string &name = *it;
3857 const Value &childValue = value[name];
3858 writeCommentBeforeValue( childValue );
3859 writeWithIndent( valueToQuotedString( name.c_str() ) );
3861 writeValue( childValue );
3862 if ( ++it == members.end() )
3864 writeCommentAfterValueOnSameLine( childValue );
3868 writeCommentAfterValueOnSameLine( childValue );
3871 writeWithIndent( "}" );
3880 StyledWriter::writeArrayValue( const Value &value )
3882 unsigned size = value.size();
3887 bool isArrayMultiLine = isMultineArray( value );
3888 if ( isArrayMultiLine )
3890 writeWithIndent( "[" );
3892 bool hasChildValue = !childValues_.empty();
3896 const Value &childValue = value[index];
3897 writeCommentBeforeValue( childValue );
3898 if ( hasChildValue )
3899 writeWithIndent( childValues_[index] );
3903 writeValue( childValue );
3905 if ( ++index == size )
3907 writeCommentAfterValueOnSameLine( childValue );
3911 writeCommentAfterValueOnSameLine( childValue );
3914 writeWithIndent( "]" );
3916 else // output on a single line
3918 assert( childValues_.size() == size );
3920 for ( unsigned index =0; index < size; ++index )
3924 document_ += childValues_[index];
3933 StyledWriter::isMultineArray( const Value &value )
3935 int size = value.size();
3936 bool isMultiLine = size*3 >= rightMargin_ ;
3937 childValues_.clear();
3938 for ( int index =0; index < size && !isMultiLine; ++index )
3940 const Value &childValue = value[index];
3941 isMultiLine = isMultiLine ||
3942 ( (childValue.isArray() || childValue.isObject()) &&
3943 childValue.size() > 0 );
3945 if ( !isMultiLine ) // check if line length > max line length
3947 childValues_.reserve( size );
3948 addChildValues_ = true;
3949 int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]'
3950 for ( int index =0; index < size && !isMultiLine; ++index )
3952 writeValue( value[index] );
3953 lineLength += int( childValues_[index].length() );
3954 isMultiLine = isMultiLine && hasCommentForValue( value[index] );
3956 addChildValues_ = false;
3957 isMultiLine = isMultiLine || lineLength >= rightMargin_;
3964 StyledWriter::pushValue( const std::string &value )
3966 if ( addChildValues_ )
3967 childValues_.push_back( value );
3974 StyledWriter::writeIndent()
3976 if ( !document_.empty() )
3978 char last = document_[document_.length()-1];
3979 if ( last == ' ' ) // already indented
3981 if ( last != '\n' ) // Comments may add new-line
3984 document_ += indentString_;
3989 StyledWriter::writeWithIndent( const std::string &value )
3997 StyledWriter::indent()
3999 indentString_ += std::string( indentSize_, ' ' );
4004 StyledWriter::unindent()
4006 assert( int(indentString_.size()) >= indentSize_ );
4007 indentString_.resize( indentString_.size() - indentSize_ );
4012 StyledWriter::writeCommentBeforeValue( const Value &root )
4014 if ( !root.hasComment( commentBefore ) )
4016 document_ += normalizeEOL( root.getComment( commentBefore ) );
4022 StyledWriter::writeCommentAfterValueOnSameLine( const Value &root )
4024 if ( root.hasComment( commentAfterOnSameLine ) )
4025 document_ += " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) );
4027 if ( root.hasComment( commentAfter ) )
4030 document_ += normalizeEOL( root.getComment( commentAfter ) );
4037 StyledWriter::hasCommentForValue( const Value &value )
4039 return value.hasComment( commentBefore )
4040 || value.hasComment( commentAfterOnSameLine )
4041 || value.hasComment( commentAfter );
4046 StyledWriter::normalizeEOL( const std::string &text )
4048 std::string normalized;
4049 normalized.reserve( text.length() );
4050 const char *begin = text.c_str();
4051 const char *end = begin + text.length();
4052 const char *current = begin;
4053 while ( current != end )
4055 char c = *current++;
4056 if ( c == '\r' ) // mac or dos EOL
4058 if ( *current == '\n' ) // convert dos EOL
4062 else // handle unix EOL & other char
4069 // Class StyledStreamWriter
4070 // //////////////////////////////////////////////////////////////////
4072 StyledStreamWriter::StyledStreamWriter( std::string indentation )
4074 , rightMargin_( 74 )
4075 , indentation_( indentation )
4082 StyledStreamWriter::write( std::ostream &out, const Value &root )
4085 addChildValues_ = false;
4087 writeCommentBeforeValue( root );
4089 writeCommentAfterValueOnSameLine( root );
4091 document_ = NULL; // Forget the stream, for safety.
4096 StyledStreamWriter::writeValue( const Value &value )
4098 switch ( value.type() )
4101 pushValue( "null" );
4104 pushValue( valueToString( value.asLargestInt() ) );
4107 pushValue( valueToString( value.asLargestUInt() ) );
4110 pushValue( valueToString( value.asDouble() ) );
4113 pushValue( valueToQuotedString( value.asCString() ) );
4116 pushValue( valueToString( value.asBool() ) );
4119 writeArrayValue( value);
4123 Value::Members members( value.getMemberNames() );
4124 if ( members.empty() )
4128 writeWithIndent( "{" );
4130 Value::Members::iterator it = members.begin();
4133 const std::string &name = *it;
4134 const Value &childValue = value[name];
4135 writeCommentBeforeValue( childValue );
4136 writeWithIndent( valueToQuotedString( name.c_str() ) );
4137 *document_ << " : ";
4138 writeValue( childValue );
4139 if ( ++it == members.end() )
4141 writeCommentAfterValueOnSameLine( childValue );
4145 writeCommentAfterValueOnSameLine( childValue );
4148 writeWithIndent( "}" );
4157 StyledStreamWriter::writeArrayValue( const Value &value )
4159 unsigned size = value.size();
4164 bool isArrayMultiLine = isMultineArray( value );
4165 if ( isArrayMultiLine )
4167 writeWithIndent( "[" );
4169 bool hasChildValue = !childValues_.empty();
4173 const Value &childValue = value[index];
4174 writeCommentBeforeValue( childValue );
4175 if ( hasChildValue )
4176 writeWithIndent( childValues_[index] );
4180 writeValue( childValue );
4182 if ( ++index == size )
4184 writeCommentAfterValueOnSameLine( childValue );
4188 writeCommentAfterValueOnSameLine( childValue );
4191 writeWithIndent( "]" );
4193 else // output on a single line
4195 assert( childValues_.size() == size );
4197 for ( unsigned index =0; index < size; ++index )
4201 *document_ << childValues_[index];
4210 StyledStreamWriter::isMultineArray( const Value &value )
4212 int size = value.size();
4213 bool isMultiLine = size*3 >= rightMargin_ ;
4214 childValues_.clear();
4215 for ( int index =0; index < size && !isMultiLine; ++index )
4217 const Value &childValue = value[index];
4218 isMultiLine = isMultiLine ||
4219 ( (childValue.isArray() || childValue.isObject()) &&
4220 childValue.size() > 0 );
4222 if ( !isMultiLine ) // check if line length > max line length
4224 childValues_.reserve( size );
4225 addChildValues_ = true;
4226 int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]'
4227 for ( int index =0; index < size && !isMultiLine; ++index )
4229 writeValue( value[index] );
4230 lineLength += int( childValues_[index].length() );
4231 isMultiLine = isMultiLine && hasCommentForValue( value[index] );
4233 addChildValues_ = false;
4234 isMultiLine = isMultiLine || lineLength >= rightMargin_;
4241 StyledStreamWriter::pushValue( const std::string &value )
4243 if ( addChildValues_ )
4244 childValues_.push_back( value );
4246 *document_ << value;
4251 StyledStreamWriter::writeIndent()
4254 Some comments in this method would have been nice. ;-)
4256 if ( !document_.empty() )
4258 char last = document_[document_.length()-1];
4259 if ( last == ' ' ) // already indented
4261 if ( last != '\n' ) // Comments may add new-line
4265 *document_ << '\n' << indentString_;
4270 StyledStreamWriter::writeWithIndent( const std::string &value )
4273 *document_ << value;
4278 StyledStreamWriter::indent()
4280 indentString_ += indentation_;
4285 StyledStreamWriter::unindent()
4287 assert( indentString_.size() >= indentation_.size() );
4288 indentString_.resize( indentString_.size() - indentation_.size() );
4293 StyledStreamWriter::writeCommentBeforeValue( const Value &root )
4295 if ( !root.hasComment( commentBefore ) )
4297 *document_ << normalizeEOL( root.getComment( commentBefore ) );
4303 StyledStreamWriter::writeCommentAfterValueOnSameLine( const Value &root )
4305 if ( root.hasComment( commentAfterOnSameLine ) )
4306 *document_ << " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) );
4308 if ( root.hasComment( commentAfter ) )
4311 *document_ << normalizeEOL( root.getComment( commentAfter ) );
4318 StyledStreamWriter::hasCommentForValue( const Value &value )
4320 return value.hasComment( commentBefore )
4321 || value.hasComment( commentAfterOnSameLine )
4322 || value.hasComment( commentAfter );
4327 StyledStreamWriter::normalizeEOL( const std::string &text )
4329 std::string normalized;
4330 normalized.reserve( text.length() );
4331 const char *begin = text.c_str();
4332 const char *end = begin + text.length();
4333 const char *current = begin;
4334 while ( current != end )
4336 char c = *current++;
4337 if ( c == '\r' ) // mac or dos EOL
4339 if ( *current == '\n' ) // convert dos EOL
4343 else // handle unix EOL & other char
4350 std::ostream& operator<<( std::ostream &sout, const Value &root )
4352 Json::StyledStreamWriter writer;
4353 writer.write(sout, root);
4360 // //////////////////////////////////////////////////////////////////////
4361 // End of content of file: src/lib_json/json_writer.cpp
4362 // //////////////////////////////////////////////////////////////////////