annotate jsoncpp.mm @ 49:178642d134a7 tip

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