annotate jsoncpp.mm @ 52:89944ab3e129 tip

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