annotate jsoncpp.mm @ 15:d5758530a039 tip

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