annotate jsoncpp.cpp @ 9:346807b47860

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