~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/json_server/json/value.h

  • Committer: Mark Atwood
  • Date: 2011-05-12 22:20:08 UTC
  • mfrom: (2283.4.17 json-interface)
  • Revision ID: me@mark.atwood.name-20110512222008-7facdn0qu7lsbm0g
mergeĀ lp:~stewart/drizzle/json-interface

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 
2
 * 
 
3
 *  JSON Library, originally from http://jsoncpp.sourceforge.net/
 
4
 *
 
5
 *  Copyright (C) 2011 Stewart Smith
 
6
 *  All rights reserved.
 
7
 *
 
8
 *  Redistribution and use in source and binary forms, with or without
 
9
 *  modification, are permitted provided that the following conditions are
 
10
 *  met:
 
11
 *
 
12
 *      * Redistributions of source code must retain the above copyright
 
13
 *  notice, this list of conditions and the following disclaimer.
 
14
 *
 
15
 *      * Redistributions in binary form must reproduce the above
 
16
 *  copyright notice, this list of conditions and the following disclaimer
 
17
 *  in the documentation and/or other materials provided with the
 
18
 *  distribution.
 
19
 *
 
20
 *      * The names of its contributors may not be used to endorse or
 
21
 *  promote products derived from this software without specific prior
 
22
 *  written permission.
 
23
 *
 
24
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
25
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
26
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 
27
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 
28
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
29
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
30
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
31
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
32
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
33
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
34
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
35
 *
 
36
 */
 
37
 
 
38
#pragma once
 
39
#ifndef CPPTL_JSON_H_INCLUDED
 
40
# define CPPTL_JSON_H_INCLUDED
 
41
 
 
42
# include "forwards.h"
 
43
# include <string>
 
44
# include <vector>
 
45
 
 
46
# ifndef JSON_USE_CPPTL_SMALLMAP
 
47
#  include <map>
 
48
# else
 
49
#  include <cpptl/smallmap.h>
 
50
# endif
 
51
# ifdef JSON_USE_CPPTL
 
52
#  include <cpptl/forwards.h>
 
53
# endif
 
54
 
 
55
/** \brief JSON (JavaScript Object Notation).
 
56
 */
 
57
namespace Json {
 
58
 
 
59
   /** \brief Type of the value held by a Value object.
 
60
    */
 
61
   enum ValueType
 
62
   {
 
63
      nullValue = 0, ///< 'null' value
 
64
      intValue,      ///< signed integer value
 
65
      uintValue,     ///< unsigned integer value
 
66
      realValue,     ///< double value
 
67
      stringValue,   ///< UTF-8 string value
 
68
      booleanValue,  ///< bool value
 
69
      arrayValue,    ///< array value (ordered list)
 
70
      objectValue    ///< object value (collection of name/value pairs).
 
71
   };
 
72
 
 
73
   enum CommentPlacement
 
74
   {
 
75
      commentBefore = 0,        ///< a comment placed on the line before a value
 
76
      commentAfterOnSameLine,   ///< a comment just after a value on the same line
 
77
      commentAfter,             ///< a comment on the line after a value (only make sense for root value)
 
78
      numberOfCommentPlacement
 
79
   };
 
80
 
 
81
//# ifdef JSON_USE_CPPTL
 
82
//   typedef CppTL::AnyEnumerator<const char *> EnumMemberNames;
 
83
//   typedef CppTL::AnyEnumerator<const Value &> EnumValues;
 
84
//# endif
 
85
 
 
86
   /** \brief Lightweight wrapper to tag static string.
 
87
    *
 
88
    * Value constructor and objectValue member assignement takes advantage of the
 
89
    * StaticString and avoid the cost of string duplication when storing the
 
90
    * string or the member name.
 
91
    *
 
92
    * Example of usage:
 
93
    * \code
 
94
    * Json::Value aValue( StaticString("some text") );
 
95
    * Json::Value object;
 
96
    * static const StaticString code("code");
 
97
    * object[code] = 1234;
 
98
    * \endcode
 
99
    */
 
100
   class JSON_API StaticString
 
101
   {
 
102
   public:
 
103
      explicit StaticString( const char *czstring )
 
104
         : str_( czstring )
 
105
      {
 
106
      }
 
107
 
 
108
      operator const char *() const
 
109
      {
 
110
         return str_;
 
111
      }
 
112
 
 
113
      const char *c_str() const
 
114
      {
 
115
         return str_;
 
116
      }
 
117
 
 
118
   private:
 
119
      const char *str_;
 
120
   };
 
121
 
 
122
   /** \brief Represents a <a HREF="http://www.json.org">JSON</a> value.
 
123
    *
 
124
    * This class is a discriminated union wrapper that can represents a:
 
125
    * - signed integer [range: Value::minInt - Value::maxInt]
 
126
    * - unsigned integer (range: 0 - Value::maxUInt)
 
127
    * - double
 
128
    * - UTF-8 string
 
129
    * - boolean
 
130
    * - 'null'
 
131
    * - an ordered list of Value
 
132
    * - collection of name/value pairs (javascript object)
 
133
    *
 
134
    * The type of the held value is represented by a #ValueType and 
 
135
    * can be obtained using type().
 
136
    *
 
137
    * values of an #objectValue or #arrayValue can be accessed using operator[]() methods. 
 
138
    * Non const methods will automatically create the a #nullValue element 
 
139
    * if it does not exist. 
 
140
    * The sequence of an #arrayValue will be automatically resize and initialized 
 
141
    * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue.
 
142
    *
 
143
    * The get() methods can be used to obtanis default value in the case the required element
 
144
    * does not exist.
 
145
    *
 
146
    * It is possible to iterate over the list of a #objectValue values using 
 
147
    * the getMemberNames() method.
 
148
    */
 
149
   class JSON_API Value 
 
150
   {
 
151
      friend class ValueIteratorBase;
 
152
# ifdef JSON_VALUE_USE_INTERNAL_MAP
 
153
      friend class ValueInternalLink;
 
154
      friend class ValueInternalMap;
 
155
# endif
 
156
   public:
 
157
      typedef std::vector<std::string> Members;
 
158
      typedef ValueIterator iterator;
 
159
      typedef ValueConstIterator const_iterator;
 
160
      typedef Json::UInt UInt;
 
161
      typedef Json::Int Int;
 
162
      typedef UInt ArrayIndex;
 
163
 
 
164
      static const Value null;
 
165
      static const Int minInt;
 
166
      static const Int maxInt;
 
167
      static const UInt maxUInt;
 
168
 
 
169
   private:
 
170
#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
 
171
# ifndef JSON_VALUE_USE_INTERNAL_MAP
 
172
      class CZString 
 
173
      {
 
174
      public:
 
175
         enum DuplicationPolicy 
 
176
         {
 
177
            noDuplication = 0,
 
178
            duplicate,
 
179
            duplicateOnCopy
 
180
         };
 
181
         CZString( int index );
 
182
         CZString( const char *cstr, DuplicationPolicy allocate );
 
183
         CZString( const CZString &other );
 
184
         ~CZString();
 
185
         CZString &operator =( const CZString &other );
 
186
         bool operator<( const CZString &other ) const;
 
187
         bool operator==( const CZString &other ) const;
 
188
         int index() const;
 
189
         const char *c_str() const;
 
190
         bool isStaticString() const;
 
191
      private:
 
192
         void swap( CZString &other );
 
193
         const char *cstr_;
 
194
         int index_;
 
195
      };
 
196
 
 
197
   public:
 
198
#  ifndef JSON_USE_CPPTL_SMALLMAP
 
199
      typedef std::map<CZString, Value> ObjectValues;
 
200
#  else
 
201
      typedef CppTL::SmallMap<CZString, Value> ObjectValues;
 
202
#  endif // ifndef JSON_USE_CPPTL_SMALLMAP
 
203
# endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
 
204
#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
 
205
 
 
206
   public:
 
207
      /** \brief Create a default Value of the given type.
 
208
 
 
209
        This is a very useful constructor.
 
210
        To create an empty array, pass arrayValue.
 
211
        To create an empty object, pass objectValue.
 
212
        Another Value can then be set to this one by assignment.
 
213
        This is useful since clear() and resize() will not alter types.
 
214
 
 
215
        Examples:
 
216
        \code
 
217
        Json::Value null_value; // null
 
218
        Json::Value arr_value(Json::arrayValue); // []
 
219
        Json::Value obj_value(Json::objectValue); // {}
 
220
        \endcode
 
221
      */
 
222
      Value( ValueType type = nullValue );
 
223
      Value( Int value );
 
224
      Value( UInt value );
 
225
      Value( double value );
 
226
      Value( const char *value );
 
227
      Value( const char *beginValue, const char *endValue );
 
228
      /** \brief Constructs a value from a static string.
 
229
 
 
230
       * Like other value string constructor but do not duplicate the string for
 
231
       * internal storage. The given string must remain alive after the call to this
 
232
       * constructor.
 
233
       * Example of usage:
 
234
       * \code
 
235
       * Json::Value aValue( StaticString("some text") );
 
236
       * \endcode
 
237
       */
 
238
      Value( const StaticString &value );
 
239
      Value( const std::string &value );
 
240
# ifdef JSON_USE_CPPTL
 
241
      Value( const CppTL::ConstString &value );
 
242
# endif
 
243
      Value( bool value );
 
244
      Value( const Value &other );
 
245
      ~Value();
 
246
 
 
247
      Value &operator=( const Value &other );
 
248
      /// Swap values.
 
249
      /// \note Currently, comments are intentionally not swapped, for
 
250
      /// both logic and efficiency.
 
251
      void swap( Value &other );
 
252
 
 
253
      ValueType type() const;
 
254
 
 
255
      bool operator <( const Value &other ) const;
 
256
      bool operator <=( const Value &other ) const;
 
257
      bool operator >=( const Value &other ) const;
 
258
      bool operator >( const Value &other ) const;
 
259
 
 
260
      bool operator ==( const Value &other ) const;
 
261
      bool operator !=( const Value &other ) const;
 
262
 
 
263
      int compare( const Value &other );
 
264
 
 
265
      const char *asCString() const;
 
266
      std::string asString() const;
 
267
# ifdef JSON_USE_CPPTL
 
268
      CppTL::ConstString asConstString() const;
 
269
# endif
 
270
      Int asInt() const;
 
271
      UInt asUInt() const;
 
272
      double asDouble() const;
 
273
      bool asBool() const;
 
274
 
 
275
      bool isNull() const;
 
276
      bool isBool() const;
 
277
      bool isInt() const;
 
278
      bool isUInt() const;
 
279
      bool isIntegral() const;
 
280
      bool isDouble() const;
 
281
      bool isNumeric() const;
 
282
      bool isString() const;
 
283
      bool isArray() const;
 
284
      bool isObject() const;
 
285
 
 
286
      bool isConvertibleTo( ValueType other ) const;
 
287
 
 
288
      /// Number of values in array or object
 
289
      UInt size() const;
 
290
 
 
291
      /// \brief Return true if empty array, empty object, or null;
 
292
      /// otherwise, false.
 
293
      bool empty() const;
 
294
 
 
295
      /// Return isNull()
 
296
      bool operator!() const;
 
297
 
 
298
      /// Remove all object members and array elements.
 
299
      /// \pre type() is arrayValue, objectValue, or nullValue
 
300
      /// \post type() is unchanged
 
301
      void clear();
 
302
 
 
303
      /// Resize the array to size elements. 
 
304
      /// New elements are initialized to null.
 
305
      /// May only be called on nullValue or arrayValue.
 
306
      /// \pre type() is arrayValue or nullValue
 
307
      /// \post type() is arrayValue
 
308
      void resize( UInt size );
 
309
 
 
310
      /// Access an array element (zero based index ).
 
311
      /// If the array contains less than index element, then null value are inserted
 
312
      /// in the array so that its size is index+1.
 
313
      /// (You may need to say 'value[0u]' to get your compiler to distinguish
 
314
      ///  this from the operator[] which takes a string.)
 
315
      Value &operator[]( UInt index );
 
316
      /// Access an array element (zero based index )
 
317
      /// (You may need to say 'value[0u]' to get your compiler to distinguish
 
318
      ///  this from the operator[] which takes a string.)
 
319
      const Value &operator[]( UInt index ) const;
 
320
      /// If the array contains at least index+1 elements, returns the element value, 
 
321
      /// otherwise returns defaultValue.
 
322
      Value get( UInt index, 
 
323
                 const Value &defaultValue ) const;
 
324
      /// Return true if index < size().
 
325
      bool isValidIndex( UInt index ) const;
 
326
      /// \brief Append value to array at the end.
 
327
      ///
 
328
      /// Equivalent to jsonvalue[jsonvalue.size()] = value;
 
329
      Value &append( const Value &value );
 
330
 
 
331
      /// Access an object value by name, create a null member if it does not exist.
 
332
      Value &operator[]( const char *key );
 
333
      /// Access an object value by name, returns null if there is no member with that name.
 
334
      const Value &operator[]( const char *key ) const;
 
335
      /// Access an object value by name, create a null member if it does not exist.
 
336
      Value &operator[]( const std::string &key );
 
337
      /// Access an object value by name, returns null if there is no member with that name.
 
338
      const Value &operator[]( const std::string &key ) const;
 
339
      /** \brief Access an object value by name, create a null member if it does not exist.
 
340
 
 
341
       * If the object as no entry for that name, then the member name used to store
 
342
       * the new entry is not duplicated.
 
343
       * Example of use:
 
344
       * \code
 
345
       * Json::Value object;
 
346
       * static const StaticString code("code");
 
347
       * object[code] = 1234;
 
348
       * \endcode
 
349
       */
 
350
      Value &operator[]( const StaticString &key );
 
351
# ifdef JSON_USE_CPPTL
 
352
      /// Access an object value by name, create a null member if it does not exist.
 
353
      Value &operator[]( const CppTL::ConstString &key );
 
354
      /// Access an object value by name, returns null if there is no member with that name.
 
355
      const Value &operator[]( const CppTL::ConstString &key ) const;
 
356
# endif
 
357
      /// Return the member named key if it exist, defaultValue otherwise.
 
358
      Value get( const char *key, 
 
359
                 const Value &defaultValue ) const;
 
360
      /// Return the member named key if it exist, defaultValue otherwise.
 
361
      Value get( const std::string &key,
 
362
                 const Value &defaultValue ) const;
 
363
# ifdef JSON_USE_CPPTL
 
364
      /// Return the member named key if it exist, defaultValue otherwise.
 
365
      Value get( const CppTL::ConstString &key,
 
366
                 const Value &defaultValue ) const;
 
367
# endif
 
368
      /// \brief Remove and return the named member.  
 
369
      ///
 
370
      /// Do nothing if it did not exist.
 
371
      /// \return the removed Value, or null.
 
372
      /// \pre type() is objectValue or nullValue
 
373
      /// \post type() is unchanged
 
374
      Value removeMember( const char* key );
 
375
      /// Same as removeMember(const char*)
 
376
      Value removeMember( const std::string &key );
 
377
 
 
378
      /// Return true if the object has a member named key.
 
379
      bool isMember( const char *key ) const;
 
380
      /// Return true if the object has a member named key.
 
381
      bool isMember( const std::string &key ) const;
 
382
# ifdef JSON_USE_CPPTL
 
383
      /// Return true if the object has a member named key.
 
384
      bool isMember( const CppTL::ConstString &key ) const;
 
385
# endif
 
386
 
 
387
      /// \brief Return a list of the member names.
 
388
      ///
 
389
      /// If null, return an empty list.
 
390
      /// \pre type() is objectValue or nullValue
 
391
      /// \post if type() was nullValue, it remains nullValue
 
392
      Members getMemberNames() const;
 
393
 
 
394
//# ifdef JSON_USE_CPPTL
 
395
//      EnumMemberNames enumMemberNames() const;
 
396
//      EnumValues enumValues() const;
 
397
//# endif
 
398
 
 
399
      /// Comments must be //... or /* ... */
 
400
      void setComment( const char *comment,
 
401
                       CommentPlacement placement );
 
402
      /// Comments must be //... or /* ... */
 
403
      void setComment( const std::string &comment,
 
404
                       CommentPlacement placement );
 
405
      bool hasComment( CommentPlacement placement ) const;
 
406
      /// Include delimiters and embedded newlines.
 
407
      std::string getComment( CommentPlacement placement ) const;
 
408
 
 
409
      std::string toStyledString() const;
 
410
 
 
411
      const_iterator begin() const;
 
412
      const_iterator end() const;
 
413
 
 
414
      iterator begin();
 
415
      iterator end();
 
416
 
 
417
   private:
 
418
      Value &resolveReference( const char *key, 
 
419
                               bool isStatic );
 
420
 
 
421
# ifdef JSON_VALUE_USE_INTERNAL_MAP
 
422
      inline bool isItemAvailable() const
 
423
      {
 
424
         return itemIsUsed_ == 0;
 
425
      }
 
426
 
 
427
      inline void setItemUsed( bool isUsed = true )
 
428
      {
 
429
         itemIsUsed_ = isUsed ? 1 : 0;
 
430
      }
 
431
 
 
432
      inline bool isMemberNameStatic() const
 
433
      {
 
434
         return memberNameIsStatic_ == 0;
 
435
      }
 
436
 
 
437
      inline void setMemberNameIsStatic( bool isStatic )
 
438
      {
 
439
         memberNameIsStatic_ = isStatic ? 1 : 0;
 
440
      }
 
441
# endif // # ifdef JSON_VALUE_USE_INTERNAL_MAP
 
442
 
 
443
   private:
 
444
      struct CommentInfo
 
445
      {
 
446
         CommentInfo();
 
447
         ~CommentInfo();
 
448
 
 
449
         void setComment( const char *text );
 
450
 
 
451
         char *comment_;
 
452
      };
 
453
 
 
454
      //struct MemberNamesTransform
 
455
      //{
 
456
      //   typedef const char *result_type;
 
457
      //   const char *operator()( const CZString &name ) const
 
458
      //   {
 
459
      //      return name.c_str();
 
460
      //   }
 
461
      //};
 
462
 
 
463
      union ValueHolder
 
464
      {
 
465
         Int int_;
 
466
         UInt uint_;
 
467
         double real_;
 
468
         bool bool_;
 
469
         char *string_;
 
470
# ifdef JSON_VALUE_USE_INTERNAL_MAP
 
471
         ValueInternalArray *array_;
 
472
         ValueInternalMap *map_;
 
473
#else
 
474
         ObjectValues *map_;
 
475
# endif
 
476
      } value_;
 
477
      ValueType type_;
 
478
      bool allocated_;     // Notes: if declared as bool, bitfield is useless.
 
479
# ifdef JSON_VALUE_USE_INTERNAL_MAP
 
480
      unsigned int itemIsUsed_ : 1;      // used by the ValueInternalMap container.
 
481
      int memberNameIsStatic_ : 1;       // used by the ValueInternalMap container.
 
482
# endif
 
483
      CommentInfo *comments_;
 
484
   };
 
485
 
 
486
 
 
487
   /** \brief Experimental and untested: represents an element of the "path" to access a node.
 
488
    */
 
489
   class PathArgument
 
490
   {
 
491
   public:
 
492
      friend class Path;
 
493
 
 
494
      PathArgument();
 
495
      PathArgument( UInt index );
 
496
      PathArgument( const char *key );
 
497
      PathArgument( const std::string &key );
 
498
 
 
499
   private:
 
500
      enum Kind
 
501
      {
 
502
         kindNone = 0,
 
503
         kindIndex,
 
504
         kindKey
 
505
      };
 
506
      std::string key_;
 
507
      UInt index_;
 
508
      Kind kind_;
 
509
   };
 
510
 
 
511
   /** \brief Experimental and untested: represents a "path" to access a node.
 
512
    *
 
513
    * Syntax:
 
514
    * - "." => root node
 
515
    * - ".[n]" => elements at index 'n' of root node (an array value)
 
516
    * - ".name" => member named 'name' of root node (an object value)
 
517
    * - ".name1.name2.name3"
 
518
    * - ".[0][1][2].name1[3]"
 
519
    * - ".%" => member name is provided as parameter
 
520
    * - ".[%]" => index is provied as parameter
 
521
    */
 
522
   class Path
 
523
   {
 
524
   public:
 
525
      Path( const std::string &path,
 
526
            const PathArgument &a1 = PathArgument(),
 
527
            const PathArgument &a2 = PathArgument(),
 
528
            const PathArgument &a3 = PathArgument(),
 
529
            const PathArgument &a4 = PathArgument(),
 
530
            const PathArgument &a5 = PathArgument() );
 
531
 
 
532
      const Value &resolve( const Value &root ) const;
 
533
      Value resolve( const Value &root, 
 
534
                     const Value &defaultValue ) const;
 
535
      /// Creates the "path" to access the specified node and returns a reference on the node.
 
536
      Value &make( Value &root ) const;
 
537
 
 
538
   private:
 
539
      typedef std::vector<const PathArgument *> InArgs;
 
540
      typedef std::vector<PathArgument> Args;
 
541
 
 
542
      void makePath( const std::string &path,
 
543
                     const InArgs &in );
 
544
      void addPathInArg( const std::string &path, 
 
545
                         const InArgs &in, 
 
546
                         InArgs::const_iterator &itInArg, 
 
547
                         PathArgument::Kind kind );
 
548
      void invalidPath( const std::string &path, 
 
549
                        int location );
 
550
 
 
551
      Args args_;
 
552
   };
 
553
 
 
554
   /** \brief Experimental do not use: Allocator to customize member name and string value memory management done by Value.
 
555
    *
 
556
    * - makeMemberName() and releaseMemberName() are called to respectively duplicate and
 
557
    *   free an Json::objectValue member name.
 
558
    * - duplicateStringValue() and releaseStringValue() are called similarly to
 
559
    *   duplicate and free a Json::stringValue value.
 
560
    */
 
561
   class ValueAllocator
 
562
   {
 
563
   public:
 
564
      enum { unknown = (unsigned)-1 };
 
565
 
 
566
      virtual ~ValueAllocator();
 
567
 
 
568
      virtual char *makeMemberName( const char *memberName ) = 0;
 
569
      virtual void releaseMemberName( char *memberName ) = 0;
 
570
      virtual char *duplicateStringValue( const char *value, 
 
571
                                          unsigned int length = unknown ) = 0;
 
572
      virtual void releaseStringValue( char *value ) = 0;
 
573
   };
 
574
 
 
575
#ifdef JSON_VALUE_USE_INTERNAL_MAP
 
576
   /** \brief Allocator to customize Value internal map.
 
577
    * Below is an example of a simple implementation (default implementation actually
 
578
    * use memory pool for speed).
 
579
    * \code
 
580
      class DefaultValueMapAllocator : public ValueMapAllocator
 
581
      {
 
582
      public: // overridden from ValueMapAllocator
 
583
         virtual ValueInternalMap *newMap()
 
584
         {
 
585
            return new ValueInternalMap();
 
586
         }
 
587
 
 
588
         virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
 
589
         {
 
590
            return new ValueInternalMap( other );
 
591
         }
 
592
 
 
593
         virtual void destructMap( ValueInternalMap *map )
 
594
         {
 
595
            delete map;
 
596
         }
 
597
 
 
598
         virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
 
599
         {
 
600
            return new ValueInternalLink[size];
 
601
         }
 
602
 
 
603
         virtual void releaseMapBuckets( ValueInternalLink *links )
 
604
         {
 
605
            delete [] links;
 
606
         }
 
607
 
 
608
         virtual ValueInternalLink *allocateMapLink()
 
609
         {
 
610
            return new ValueInternalLink();
 
611
         }
 
612
 
 
613
         virtual void releaseMapLink( ValueInternalLink *link )
 
614
         {
 
615
            delete link;
 
616
         }
 
617
      };
 
618
    * \endcode
 
619
    */ 
 
620
   class JSON_API ValueMapAllocator
 
621
   {
 
622
   public:
 
623
      virtual ~ValueMapAllocator();
 
624
      virtual ValueInternalMap *newMap() = 0;
 
625
      virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) = 0;
 
626
      virtual void destructMap( ValueInternalMap *map ) = 0;
 
627
      virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) = 0;
 
628
      virtual void releaseMapBuckets( ValueInternalLink *links ) = 0;
 
629
      virtual ValueInternalLink *allocateMapLink() = 0;
 
630
      virtual void releaseMapLink( ValueInternalLink *link ) = 0;
 
631
   };
 
632
 
 
633
   /** \brief ValueInternalMap hash-map bucket chain link (for internal use only).
 
634
    * \internal previous_ & next_ allows for bidirectional traversal.
 
635
    */
 
636
   class JSON_API ValueInternalLink
 
637
   {
 
638
   public:
 
639
      enum { itemPerLink = 6 };  // sizeof(ValueInternalLink) = 128 on 32 bits architecture.
 
640
      enum InternalFlags { 
 
641
         flagAvailable = 0,
 
642
         flagUsed = 1
 
643
      };
 
644
 
 
645
      ValueInternalLink();
 
646
 
 
647
      ~ValueInternalLink();
 
648
 
 
649
      Value items_[itemPerLink];
 
650
      char *keys_[itemPerLink];
 
651
      ValueInternalLink *previous_;
 
652
      ValueInternalLink *next_;
 
653
   };
 
654
 
 
655
 
 
656
   /** \brief A linked page based hash-table implementation used internally by Value.
 
657
    * \internal ValueInternalMap is a tradional bucket based hash-table, with a linked
 
658
    * list in each bucket to handle collision. There is an addional twist in that
 
659
    * each node of the collision linked list is a page containing a fixed amount of
 
660
    * value. This provides a better compromise between memory usage and speed.
 
661
    * 
 
662
    * Each bucket is made up of a chained list of ValueInternalLink. The last
 
663
    * link of a given bucket can be found in the 'previous_' field of the following bucket.
 
664
    * The last link of the last bucket is stored in tailLink_ as it has no following bucket.
 
665
    * Only the last link of a bucket may contains 'available' item. The last link always
 
666
    * contains at least one element unless is it the bucket one very first link.
 
667
    */
 
668
   class JSON_API ValueInternalMap
 
669
   {
 
670
      friend class ValueIteratorBase;
 
671
      friend class Value;
 
672
   public:
 
673
      typedef unsigned int HashKey;
 
674
      typedef unsigned int BucketIndex;
 
675
 
 
676
# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
 
677
      struct IteratorState
 
678
      {
 
679
         IteratorState() 
 
680
            : map_(0)
 
681
            , link_(0)
 
682
            , itemIndex_(0)
 
683
            , bucketIndex_(0) 
 
684
         {
 
685
         }
 
686
         ValueInternalMap *map_;
 
687
         ValueInternalLink *link_;
 
688
         BucketIndex itemIndex_;
 
689
         BucketIndex bucketIndex_;
 
690
      };
 
691
# endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
 
692
 
 
693
      ValueInternalMap();
 
694
      ValueInternalMap( const ValueInternalMap &other );
 
695
      ValueInternalMap &operator =( const ValueInternalMap &other );
 
696
      ~ValueInternalMap();
 
697
 
 
698
      void swap( ValueInternalMap &other );
 
699
 
 
700
      BucketIndex size() const;
 
701
 
 
702
      void clear();
 
703
 
 
704
      bool reserveDelta( BucketIndex growth );
 
705
 
 
706
      bool reserve( BucketIndex newItemCount );
 
707
 
 
708
      const Value *find( const char *key ) const;
 
709
 
 
710
      Value *find( const char *key );
 
711
 
 
712
      Value &resolveReference( const char *key, 
 
713
                               bool isStatic );
 
714
 
 
715
      void remove( const char *key );
 
716
 
 
717
      void doActualRemove( ValueInternalLink *link, 
 
718
                           BucketIndex index,
 
719
                           BucketIndex bucketIndex );
 
720
 
 
721
      ValueInternalLink *&getLastLinkInBucket( BucketIndex bucketIndex );
 
722
 
 
723
      Value &setNewItem( const char *key, 
 
724
                         bool isStatic, 
 
725
                         ValueInternalLink *link, 
 
726
                         BucketIndex index );
 
727
 
 
728
      Value &unsafeAdd( const char *key, 
 
729
                        bool isStatic, 
 
730
                        HashKey hashedKey );
 
731
 
 
732
      HashKey hash( const char *key ) const;
 
733
 
 
734
      int compare( const ValueInternalMap &other ) const;
 
735
 
 
736
   private:
 
737
      void makeBeginIterator( IteratorState &it ) const;
 
738
      void makeEndIterator( IteratorState &it ) const;
 
739
      static bool equals( const IteratorState &x, const IteratorState &other );
 
740
      static void increment( IteratorState &iterator );
 
741
      static void incrementBucket( IteratorState &iterator );
 
742
      static void decrement( IteratorState &iterator );
 
743
      static const char *key( const IteratorState &iterator );
 
744
      static const char *key( const IteratorState &iterator, bool &isStatic );
 
745
      static Value &value( const IteratorState &iterator );
 
746
      static int distance( const IteratorState &x, const IteratorState &y );
 
747
 
 
748
   private:
 
749
      ValueInternalLink *buckets_;
 
750
      ValueInternalLink *tailLink_;
 
751
      BucketIndex bucketsSize_;
 
752
      BucketIndex itemCount_;
 
753
   };
 
754
 
 
755
   /** \brief A simplified deque implementation used internally by Value.
 
756
   * \internal
 
757
   * It is based on a list of fixed "page", each page contains a fixed number of items.
 
758
   * Instead of using a linked-list, a array of pointer is used for fast item look-up.
 
759
   * Look-up for an element is as follow:
 
760
   * - compute page index: pageIndex = itemIndex / itemsPerPage
 
761
   * - look-up item in page: pages_[pageIndex][itemIndex % itemsPerPage]
 
762
   *
 
763
   * Insertion is amortized constant time (only the array containing the index of pointers
 
764
   * need to be reallocated when items are appended).
 
765
   */
 
766
   class JSON_API ValueInternalArray
 
767
   {
 
768
      friend class Value;
 
769
      friend class ValueIteratorBase;
 
770
   public:
 
771
      enum { itemsPerPage = 8 };    // should be a power of 2 for fast divide and modulo.
 
772
      typedef Value::ArrayIndex ArrayIndex;
 
773
      typedef unsigned int PageIndex;
 
774
 
 
775
# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
 
776
      struct IteratorState // Must be a POD
 
777
      {
 
778
         IteratorState() 
 
779
            : array_(0)
 
780
            , currentPageIndex_(0)
 
781
            , currentItemIndex_(0) 
 
782
         {
 
783
         }
 
784
         ValueInternalArray *array_;
 
785
         Value **currentPageIndex_;
 
786
         unsigned int currentItemIndex_;
 
787
      };
 
788
# endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
 
789
 
 
790
      ValueInternalArray();
 
791
      ValueInternalArray( const ValueInternalArray &other );
 
792
      ValueInternalArray &operator =( const ValueInternalArray &other );
 
793
      ~ValueInternalArray();
 
794
      void swap( ValueInternalArray &other );
 
795
 
 
796
      void clear();
 
797
      void resize( ArrayIndex newSize );
 
798
 
 
799
      Value &resolveReference( ArrayIndex index );
 
800
 
 
801
      Value *find( ArrayIndex index ) const;
 
802
 
 
803
      ArrayIndex size() const;
 
804
 
 
805
      int compare( const ValueInternalArray &other ) const;
 
806
 
 
807
   private:
 
808
      static bool equals( const IteratorState &x, const IteratorState &other );
 
809
      static void increment( IteratorState &iterator );
 
810
      static void decrement( IteratorState &iterator );
 
811
      static Value &dereference( const IteratorState &iterator );
 
812
      static Value &unsafeDereference( const IteratorState &iterator );
 
813
      static int distance( const IteratorState &x, const IteratorState &y );
 
814
      static ArrayIndex indexOf( const IteratorState &iterator );
 
815
      void makeBeginIterator( IteratorState &it ) const;
 
816
      void makeEndIterator( IteratorState &it ) const;
 
817
      void makeIterator( IteratorState &it, ArrayIndex index ) const;
 
818
 
 
819
      void makeIndexValid( ArrayIndex index );
 
820
 
 
821
      Value **pages_;
 
822
      ArrayIndex size_;
 
823
      PageIndex pageCount_;
 
824
   };
 
825
 
 
826
   /** \brief Experimental: do not use. Allocator to customize Value internal array.
 
827
    * Below is an example of a simple implementation (actual implementation use
 
828
    * memory pool).
 
829
      \code
 
830
class DefaultValueArrayAllocator : public ValueArrayAllocator
 
831
{
 
832
public: // overridden from ValueArrayAllocator
 
833
   virtual ~DefaultValueArrayAllocator()
 
834
   {
 
835
   }
 
836
 
 
837
   virtual ValueInternalArray *newArray()
 
838
   {
 
839
      return new ValueInternalArray();
 
840
   }
 
841
 
 
842
   virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
 
843
   {
 
844
      return new ValueInternalArray( other );
 
845
   }
 
846
 
 
847
   virtual void destruct( ValueInternalArray *array )
 
848
   {
 
849
      delete array;
 
850
   }
 
851
 
 
852
   virtual void reallocateArrayPageIndex( Value **&indexes, 
 
853
                                          ValueInternalArray::PageIndex &indexCount,
 
854
                                          ValueInternalArray::PageIndex minNewIndexCount )
 
855
   {
 
856
      ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
 
857
      if ( minNewIndexCount > newIndexCount )
 
858
         newIndexCount = minNewIndexCount;
 
859
      void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
 
860
      if ( !newIndexes )
 
861
         throw std::bad_alloc();
 
862
      indexCount = newIndexCount;
 
863
      indexes = static_cast<Value **>( newIndexes );
 
864
   }
 
865
   virtual void releaseArrayPageIndex( Value **indexes, 
 
866
                                       ValueInternalArray::PageIndex indexCount )
 
867
   {
 
868
      if ( indexes )
 
869
         free( indexes );
 
870
   }
 
871
 
 
872
   virtual Value *allocateArrayPage()
 
873
   {
 
874
      return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) );
 
875
   }
 
876
 
 
877
   virtual void releaseArrayPage( Value *value )
 
878
   {
 
879
      if ( value )
 
880
         free( value );
 
881
   }
 
882
};
 
883
      \endcode
 
884
    */ 
 
885
   class JSON_API ValueArrayAllocator
 
886
   {
 
887
   public:
 
888
      virtual ~ValueArrayAllocator();
 
889
      virtual ValueInternalArray *newArray() = 0;
 
890
      virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) = 0;
 
891
      virtual void destructArray( ValueInternalArray *array ) = 0;
 
892
      /** \brief Reallocate array page index.
 
893
       * Reallocates an array of pointer on each page.
 
894
       * \param indexes [input] pointer on the current index. May be \c NULL.
 
895
       *                [output] pointer on the new index of at least 
 
896
       *                         \a minNewIndexCount pages. 
 
897
       * \param indexCount [input] current number of pages in the index.
 
898
       *                   [output] number of page the reallocated index can handle.
 
899
       *                            \b MUST be >= \a minNewIndexCount.
 
900
       * \param minNewIndexCount Minimum number of page the new index must be able to
 
901
       *                         handle.
 
902
       */
 
903
      virtual void reallocateArrayPageIndex( Value **&indexes, 
 
904
                                             ValueInternalArray::PageIndex &indexCount,
 
905
                                             ValueInternalArray::PageIndex minNewIndexCount ) = 0;
 
906
      virtual void releaseArrayPageIndex( Value **indexes, 
 
907
                                          ValueInternalArray::PageIndex indexCount ) = 0;
 
908
      virtual Value *allocateArrayPage() = 0;
 
909
      virtual void releaseArrayPage( Value *value ) = 0;
 
910
   };
 
911
#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
 
912
 
 
913
 
 
914
   /** \brief base class for Value iterators.
 
915
    *
 
916
    */
 
917
   class ValueIteratorBase
 
918
   {
 
919
   public:
 
920
      typedef unsigned int size_t;
 
921
      typedef int difference_type;
 
922
      typedef ValueIteratorBase SelfType;
 
923
 
 
924
      ValueIteratorBase();
 
925
#ifndef JSON_VALUE_USE_INTERNAL_MAP
 
926
      explicit ValueIteratorBase( const Value::ObjectValues::iterator &current );
 
927
#else
 
928
      ValueIteratorBase( const ValueInternalArray::IteratorState &state );
 
929
      ValueIteratorBase( const ValueInternalMap::IteratorState &state );
 
930
#endif
 
931
 
 
932
      bool operator ==( const SelfType &other ) const
 
933
      {
 
934
         return isEqual( other );
 
935
      }
 
936
 
 
937
      bool operator !=( const SelfType &other ) const
 
938
      {
 
939
         return !isEqual( other );
 
940
      }
 
941
 
 
942
      difference_type operator -( const SelfType &other ) const
 
943
      {
 
944
         return computeDistance( other );
 
945
      }
 
946
 
 
947
      /// Return either the index or the member name of the referenced value as a Value.
 
948
      Value key() const;
 
949
 
 
950
      /// Return the index of the referenced Value. -1 if it is not an arrayValue.
 
951
      UInt index() const;
 
952
 
 
953
      /// Return the member name of the referenced Value. "" if it is not an objectValue.
 
954
      const char *memberName() const;
 
955
 
 
956
   protected:
 
957
      Value &deref() const;
 
958
 
 
959
      void increment();
 
960
 
 
961
      void decrement();
 
962
 
 
963
      difference_type computeDistance( const SelfType &other ) const;
 
964
 
 
965
      bool isEqual( const SelfType &other ) const;
 
966
 
 
967
      void copy( const SelfType &other );
 
968
 
 
969
   private:
 
970
#ifndef JSON_VALUE_USE_INTERNAL_MAP
 
971
      Value::ObjectValues::iterator current_;
 
972
      // Indicates that iterator is for a null value.
 
973
      bool isNull_;
 
974
#else
 
975
      union
 
976
      {
 
977
         ValueInternalArray::IteratorState array_;
 
978
         ValueInternalMap::IteratorState map_;
 
979
      } iterator_;
 
980
      bool isArray_;
 
981
#endif
 
982
   };
 
983
 
 
984
   /** \brief const iterator for object and array value.
 
985
    *
 
986
    */
 
987
   class ValueConstIterator : public ValueIteratorBase
 
988
   {
 
989
      friend class Value;
 
990
   public:
 
991
      typedef unsigned int size_t;
 
992
      typedef int difference_type;
 
993
      typedef const Value &reference;
 
994
      typedef const Value *pointer;
 
995
      typedef ValueConstIterator SelfType;
 
996
 
 
997
      ValueConstIterator();
 
998
   private:
 
999
      /*! \internal Use by Value to create an iterator.
 
1000
       */
 
1001
#ifndef JSON_VALUE_USE_INTERNAL_MAP
 
1002
      explicit ValueConstIterator( const Value::ObjectValues::iterator &current );
 
1003
#else
 
1004
      ValueConstIterator( const ValueInternalArray::IteratorState &state );
 
1005
      ValueConstIterator( const ValueInternalMap::IteratorState &state );
 
1006
#endif
 
1007
   public:
 
1008
      SelfType &operator =( const ValueIteratorBase &other );
 
1009
 
 
1010
      SelfType operator++( int )
 
1011
      {
 
1012
         SelfType temp( *this );
 
1013
         ++*this;
 
1014
         return temp;
 
1015
      }
 
1016
 
 
1017
      SelfType operator--( int )
 
1018
      {
 
1019
         SelfType temp( *this );
 
1020
         --*this;
 
1021
         return temp;
 
1022
      }
 
1023
 
 
1024
      SelfType &operator--()
 
1025
      {
 
1026
         decrement();
 
1027
         return *this;
 
1028
      }
 
1029
 
 
1030
      SelfType &operator++()
 
1031
      {
 
1032
         increment();
 
1033
         return *this;
 
1034
      }
 
1035
 
 
1036
      reference operator *() const
 
1037
      {
 
1038
         return deref();
 
1039
      }
 
1040
   };
 
1041
 
 
1042
 
 
1043
   /** \brief Iterator for object and array value.
 
1044
    */
 
1045
   class ValueIterator : public ValueIteratorBase
 
1046
   {
 
1047
      friend class Value;
 
1048
   public:
 
1049
      typedef unsigned int size_t;
 
1050
      typedef int difference_type;
 
1051
      typedef Value &reference;
 
1052
      typedef Value *pointer;
 
1053
      typedef ValueIterator SelfType;
 
1054
 
 
1055
      ValueIterator();
 
1056
      ValueIterator( const ValueConstIterator &other );
 
1057
      ValueIterator( const ValueIterator &other );
 
1058
   private:
 
1059
      /*! \internal Use by Value to create an iterator.
 
1060
       */
 
1061
#ifndef JSON_VALUE_USE_INTERNAL_MAP
 
1062
      explicit ValueIterator( const Value::ObjectValues::iterator &current );
 
1063
#else
 
1064
      ValueIterator( const ValueInternalArray::IteratorState &state );
 
1065
      ValueIterator( const ValueInternalMap::IteratorState &state );
 
1066
#endif
 
1067
   public:
 
1068
 
 
1069
      SelfType &operator =( const SelfType &other );
 
1070
 
 
1071
      SelfType operator++( int )
 
1072
      {
 
1073
         SelfType temp( *this );
 
1074
         ++*this;
 
1075
         return temp;
 
1076
      }
 
1077
 
 
1078
      SelfType operator--( int )
 
1079
      {
 
1080
         SelfType temp( *this );
 
1081
         --*this;
 
1082
         return temp;
 
1083
      }
 
1084
 
 
1085
      SelfType &operator--()
 
1086
      {
 
1087
         decrement();
 
1088
         return *this;
 
1089
      }
 
1090
 
 
1091
      SelfType &operator++()
 
1092
      {
 
1093
         increment();
 
1094
         return *this;
 
1095
      }
 
1096
 
 
1097
      reference operator *() const
 
1098
      {
 
1099
         return deref();
 
1100
      }
 
1101
   };
 
1102
 
 
1103
 
 
1104
} // namespace Json
 
1105
 
 
1106
 
 
1107
#endif // CPPTL_JSON_H_INCLUDED