~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty Taylor
  • Date: 2011-02-13 17:26:39 UTC
  • mfrom: (2157.2.2 give-in-to-pkg-config)
  • mto: This revision was merged to the branch mainline in revision 2166.
  • Revision ID: mordred@inaugust.com-20110213172639-nhy7i72sfhoq13ms
Merged in pkg-config fixes.

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