Previous 199869 Revisions Next

r24796 Wednesday 7th August, 2013 at 17:29:19 UTC by Miodrag Milanović
added json library and working example (nw)
[src/emu]mame.c
[src/lib]lib.mak
[src/lib/web/json]autolink.h* config.h* features.h* forwards.h* json.h* json_batchallocator.h* json_internalarray.inl* json_internalmap.inl* json_reader.cpp* json_tool.h* json_value.cpp* json_valueiterator.inl* json_writer.cpp* reader.h* value.h* writer.h*

trunk/src/lib/lib.mak
r24795r24796
2525   $(LIBOBJ)/portmidi \
2626   $(LIBOBJ)/lua \
2727   $(LIBOBJ)/web \
28   $(LIBOBJ)/web/json \
2829
2930
3031#-------------------------------------------------
r24795r24796
493494
494495WEBOBJS = \
495496   $(LIBOBJ)/web/mongoose.o \
497   $(LIBOBJ)/web/json/json_reader.o \
498   $(LIBOBJ)/web/json/json_value.o \
499   $(LIBOBJ)/web/json/json_writer.o \
496500
497$(OBJ)/libweb.a: $(WEBOBJS)
No newline at end of file
501$(OBJ)/libweb.a: $(WEBOBJS)
502
503$(LIBOBJ)/web/%.o: $(LIBSRC)/web/%.cpp | $(OSPREBUILD)
504   @echo Compiling $<...
505   $(CC) $(CDEFS) $(CFLAGS) -I$(LIBSRC)/web -c $< -o $@
trunk/src/lib/web/json/json.h
r0r24796
1// Copyright 2007-2010 Baptiste Lepilleur
2// Distributed under MIT license, or public domain if desired and
3// recognized in your jurisdiction.
4// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
5
6#ifndef JSON_JSON_H_INCLUDED
7# define JSON_JSON_H_INCLUDED
8
9# include "autolink.h"
10# include "value.h"
11# include "reader.h"
12# include "writer.h"
13# include "features.h"
14
15#endif // JSON_JSON_H_INCLUDED
Property changes on: trunk/src/lib/web/json/json.h
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/lib/web/json/json_valueiterator.inl
r0r24796
1// Copyright 2007-2010 Baptiste Lepilleur
2// Distributed under MIT license, or public domain if desired and
3// recognized in your jurisdiction.
4// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
5
6// included by json_value.cpp
7
8namespace Json {
9
10// //////////////////////////////////////////////////////////////////
11// //////////////////////////////////////////////////////////////////
12// //////////////////////////////////////////////////////////////////
13// class ValueIteratorBase
14// //////////////////////////////////////////////////////////////////
15// //////////////////////////////////////////////////////////////////
16// //////////////////////////////////////////////////////////////////
17
18ValueIteratorBase::ValueIteratorBase()
19#ifndef JSON_VALUE_USE_INTERNAL_MAP
20   : current_()
21   , isNull_( true )
22{
23}
24#else
25   : isArray_( true )
26   , isNull_( true )
27{
28   iterator_.array_ = ValueInternalArray::IteratorState();
29}
30#endif
31
32
33#ifndef JSON_VALUE_USE_INTERNAL_MAP
34ValueIteratorBase::ValueIteratorBase( const Value::ObjectValues::iterator &current )
35   : current_( current )
36   , isNull_( false )
37{
38}
39#else
40ValueIteratorBase::ValueIteratorBase( const ValueInternalArray::IteratorState &state )
41   : isArray_( true )
42{
43   iterator_.array_ = state;
44}
45
46
47ValueIteratorBase::ValueIteratorBase( const ValueInternalMap::IteratorState &state )
48   : isArray_( false )
49{
50   iterator_.map_ = state;
51}
52#endif
53
54Value &
55ValueIteratorBase::deref() const
56{
57#ifndef JSON_VALUE_USE_INTERNAL_MAP
58   return current_->second;
59#else
60   if ( isArray_ )
61      return ValueInternalArray::dereference( iterator_.array_ );
62   return ValueInternalMap::value( iterator_.map_ );
63#endif
64}
65
66
67void
68ValueIteratorBase::increment()
69{
70#ifndef JSON_VALUE_USE_INTERNAL_MAP
71   ++current_;
72#else
73   if ( isArray_ )
74      ValueInternalArray::increment( iterator_.array_ );
75   ValueInternalMap::increment( iterator_.map_ );
76#endif
77}
78
79
80void
81ValueIteratorBase::decrement()
82{
83#ifndef JSON_VALUE_USE_INTERNAL_MAP
84   --current_;
85#else
86   if ( isArray_ )
87      ValueInternalArray::decrement( iterator_.array_ );
88   ValueInternalMap::decrement( iterator_.map_ );
89#endif
90}
91
92
93ValueIteratorBase::difference_type
94ValueIteratorBase::computeDistance( const SelfType &other ) const
95{
96#ifndef JSON_VALUE_USE_INTERNAL_MAP
97# ifdef JSON_USE_CPPTL_SMALLMAP
98   return current_ - other.current_;
99# else
100   // Iterator for null value are initialized using the default
101   // constructor, which initialize current_ to the default
102   // std::map::iterator. As begin() and end() are two instance
103   // of the default std::map::iterator, they can not be compared.
104   // To allow this, we handle this comparison specifically.
105   if ( isNull_  &&  other.isNull_ )
106   {
107      return 0;
108   }
109
110
111   // Usage of std::distance is not portable (does not compile with Sun Studio 12 RogueWave STL,
112   // which is the one used by default).
113   // Using a portable hand-made version for non random iterator instead:
114   //   return difference_type( std::distance( current_, other.current_ ) );
115   difference_type myDistance = 0;
116   for ( Value::ObjectValues::iterator it = current_; it != other.current_; ++it )
117   {
118      ++myDistance;
119   }
120   return myDistance;
121# endif
122#else
123   if ( isArray_ )
124      return ValueInternalArray::distance( iterator_.array_, other.iterator_.array_ );
125   return ValueInternalMap::distance( iterator_.map_, other.iterator_.map_ );
126#endif
127}
128
129
130bool
131ValueIteratorBase::isEqual( const SelfType &other ) const
132{
133#ifndef JSON_VALUE_USE_INTERNAL_MAP
134   if ( isNull_ )
135   {
136      return other.isNull_;
137   }
138   return current_ == other.current_;
139#else
140   if ( isArray_ )
141      return ValueInternalArray::equals( iterator_.array_, other.iterator_.array_ );
142   return ValueInternalMap::equals( iterator_.map_, other.iterator_.map_ );
143#endif
144}
145
146
147void
148ValueIteratorBase::copy( const SelfType &other )
149{
150#ifndef JSON_VALUE_USE_INTERNAL_MAP
151   current_ = other.current_;
152#else
153   if ( isArray_ )
154      iterator_.array_ = other.iterator_.array_;
155   iterator_.map_ = other.iterator_.map_;
156#endif
157}
158
159
160Value
161ValueIteratorBase::key() const
162{
163#ifndef JSON_VALUE_USE_INTERNAL_MAP
164   const Value::CZString czstring = (*current_).first;
165   if ( czstring.c_str() )
166   {
167      if ( czstring.isStaticString() )
168         return Value( StaticString( czstring.c_str() ) );
169      return Value( czstring.c_str() );
170   }
171   return Value( czstring.index() );
172#else
173   if ( isArray_ )
174      return Value( ValueInternalArray::indexOf( iterator_.array_ ) );
175   bool isStatic;
176   const char *memberName = ValueInternalMap::key( iterator_.map_, isStatic );
177   if ( isStatic )
178      return Value( StaticString( memberName ) );
179   return Value( memberName );
180#endif
181}
182
183
184UInt
185ValueIteratorBase::index() const
186{
187#ifndef JSON_VALUE_USE_INTERNAL_MAP
188   const Value::CZString czstring = (*current_).first;
189   if ( !czstring.c_str() )
190      return czstring.index();
191   return Value::UInt( -1 );
192#else
193   if ( isArray_ )
194      return Value::UInt( ValueInternalArray::indexOf( iterator_.array_ ) );
195   return Value::UInt( -1 );
196#endif
197}
198
199
200const char *
201ValueIteratorBase::memberName() const
202{
203#ifndef JSON_VALUE_USE_INTERNAL_MAP
204   const char *name = (*current_).first.c_str();
205   return name ? name : "";
206#else
207   if ( !isArray_ )
208      return ValueInternalMap::key( iterator_.map_ );
209   return "";
210#endif
211}
212
213
214// //////////////////////////////////////////////////////////////////
215// //////////////////////////////////////////////////////////////////
216// //////////////////////////////////////////////////////////////////
217// class ValueConstIterator
218// //////////////////////////////////////////////////////////////////
219// //////////////////////////////////////////////////////////////////
220// //////////////////////////////////////////////////////////////////
221
222ValueConstIterator::ValueConstIterator()
223{
224}
225
226
227#ifndef JSON_VALUE_USE_INTERNAL_MAP
228ValueConstIterator::ValueConstIterator( const Value::ObjectValues::iterator &current )
229   : ValueIteratorBase( current )
230{
231}
232#else
233ValueConstIterator::ValueConstIterator( const ValueInternalArray::IteratorState &state )
234   : ValueIteratorBase( state )
235{
236}
237
238ValueConstIterator::ValueConstIterator( const ValueInternalMap::IteratorState &state )
239   : ValueIteratorBase( state )
240{
241}
242#endif
243
244ValueConstIterator &
245ValueConstIterator::operator =( const ValueIteratorBase &other )
246{
247   copy( other );
248   return *this;
249}
250
251
252// //////////////////////////////////////////////////////////////////
253// //////////////////////////////////////////////////////////////////
254// //////////////////////////////////////////////////////////////////
255// class ValueIterator
256// //////////////////////////////////////////////////////////////////
257// //////////////////////////////////////////////////////////////////
258// //////////////////////////////////////////////////////////////////
259
260ValueIterator::ValueIterator()
261{
262}
263
264
265#ifndef JSON_VALUE_USE_INTERNAL_MAP
266ValueIterator::ValueIterator( const Value::ObjectValues::iterator &current )
267   : ValueIteratorBase( current )
268{
269}
270#else
271ValueIterator::ValueIterator( const ValueInternalArray::IteratorState &state )
272   : ValueIteratorBase( state )
273{
274}
275
276ValueIterator::ValueIterator( const ValueInternalMap::IteratorState &state )
277   : ValueIteratorBase( state )
278{
279}
280#endif
281
282ValueIterator::ValueIterator( const ValueConstIterator &other )
283   : ValueIteratorBase( other )
284{
285}
286
287ValueIterator::ValueIterator( const ValueIterator &other )
288   : ValueIteratorBase( other )
289{
290}
291
292ValueIterator &
293ValueIterator::operator =( const SelfType &other )
294{
295   copy( other );
296   return *this;
297}
298
299} // namespace Json
Property changes on: trunk/src/lib/web/json/json_valueiterator.inl
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/lib/web/json/json_batchallocator.h
r0r24796
1// Copyright 2007-2010 Baptiste Lepilleur
2// Distributed under MIT license, or public domain if desired and
3// recognized in your jurisdiction.
4// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
5
6#ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED
7# define JSONCPP_BATCHALLOCATOR_H_INCLUDED
8
9# include <stdlib.h>
10# include <assert.h>
11
12# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
13
14namespace Json {
15
16/* Fast memory allocator.
17 *
18 * This memory allocator allocates memory for a batch of object (specified by
19 * the page size, the number of object in each page).
20 *
21 * It does not allow the destruction of a single object. All the allocated objects
22 * can be destroyed at once. The memory can be either released or reused for future
23 * allocation.
24 *
25 * The in-place new operator must be used to construct the object using the pointer
26 * returned by allocate.
27 */
28template<typename AllocatedType
29        ,const unsigned int objectPerAllocation>
30class BatchAllocator
31{
32public:
33   typedef AllocatedType Type;
34
35   BatchAllocator( unsigned int objectsPerPage = 255 )
36      : freeHead_( 0 )
37      , objectsPerPage_( objectsPerPage )
38   {
39//      printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() );
40      assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space.
41      assert( objectsPerPage >= 16 );
42      batches_ = allocateBatch( 0 );   // allocated a dummy page
43      currentBatch_ = batches_;
44   }
45
46   ~BatchAllocator()
47   {
48      for ( BatchInfo *batch = batches_; batch;  )
49      {
50         BatchInfo *nextBatch = batch->next_;
51         free( batch );
52         batch = nextBatch;
53      }
54   }
55
56   /// allocate space for an array of objectPerAllocation object.
57   /// @warning it is the responsability of the caller to call objects constructors.
58   AllocatedType *allocate()
59   {
60      if ( freeHead_ ) // returns node from free list.
61      {
62         AllocatedType *object = freeHead_;
63         freeHead_ = *(AllocatedType **)object;
64         return object;
65      }
66      if ( currentBatch_->used_ == currentBatch_->end_ )
67      {
68         currentBatch_ = currentBatch_->next_;
69         while ( currentBatch_  &&  currentBatch_->used_ == currentBatch_->end_ )
70            currentBatch_ = currentBatch_->next_;
71
72         if ( !currentBatch_  ) // no free batch found, allocate a new one
73         {
74            currentBatch_ = allocateBatch( objectsPerPage_ );
75            currentBatch_->next_ = batches_; // insert at the head of the list
76            batches_ = currentBatch_;
77         }
78      }
79      AllocatedType *allocated = currentBatch_->used_;
80      currentBatch_->used_ += objectPerAllocation;
81      return allocated;
82   }
83
84   /// Release the object.
85   /// @warning it is the responsability of the caller to actually destruct the object.
86   void release( AllocatedType *object )
87   {
88      assert( object != 0 );
89      *(AllocatedType **)object = freeHead_;
90      freeHead_ = object;
91   }
92
93private:
94   struct BatchInfo
95   {
96      BatchInfo *next_;
97      AllocatedType *used_;
98      AllocatedType *end_;
99      AllocatedType buffer_[objectPerAllocation];
100   };
101
102   // disabled copy constructor and assignement operator.
103   BatchAllocator( const BatchAllocator & );
104   void operator =( const BatchAllocator &);
105
106   static BatchInfo *allocateBatch( unsigned int objectsPerPage )
107   {
108      const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation
109                                + sizeof(AllocatedType) * objectPerAllocation * objectsPerPage;
110      BatchInfo *batch = static_cast<BatchInfo*>( malloc( mallocSize ) );
111      batch->next_ = 0;
112      batch->used_ = batch->buffer_;
113      batch->end_ = batch->buffer_ + objectsPerPage;
114      return batch;
115   }
116
117   BatchInfo *batches_;
118   BatchInfo *currentBatch_;
119   /// Head of a single linked list within the allocated space of freeed object
120   AllocatedType *freeHead_;
121   unsigned int objectsPerPage_;
122};
123
124
125} // namespace Json
126
127# endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION
128
129#endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED
130
Property changes on: trunk/src/lib/web/json/json_batchallocator.h
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/lib/web/json/value.h
r0r24796
1// Copyright 2007-2010 Baptiste Lepilleur
2// Distributed under MIT license, or public domain if desired and
3// recognized in your jurisdiction.
4// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
5
6#ifndef CPPTL_JSON_H_INCLUDED
7# define CPPTL_JSON_H_INCLUDED
8
9#if !defined(JSON_IS_AMALGAMATION)
10# include "forwards.h"
11#endif // if !defined(JSON_IS_AMALGAMATION)
12# include <string>
13# include <vector>
14
15# ifndef JSON_USE_CPPTL_SMALLMAP
16#  include <map>
17# else
18#  include <cpptl/smallmap.h>
19# endif
20# ifdef JSON_USE_CPPTL
21#  include <cpptl/forwards.h>
22# endif
23
24/** \brief JSON (JavaScript Object Notation).
25 */
26namespace Json {
27
28   /** \brief Type of the value held by a Value object.
29    */
30   enum ValueType
31   {
32      nullValue = 0, ///< 'null' value
33      intValue,      ///< signed integer value
34      uintValue,     ///< unsigned integer value
35      realValue,     ///< double value
36      stringValue,   ///< UTF-8 string value
37      booleanValue,  ///< bool value
38      arrayValue,    ///< array value (ordered list)
39      objectValue    ///< object value (collection of name/value pairs).
40   };
41
42   enum CommentPlacement
43   {
44      commentBefore = 0,        ///< a comment placed on the line before a value
45      commentAfterOnSameLine,   ///< a comment just after a value on the same line
46      commentAfter,             ///< a comment on the line after a value (only make sense for root value)
47      numberOfCommentPlacement
48   };
49
50//# ifdef JSON_USE_CPPTL
51//   typedef CppTL::AnyEnumerator<const char *> EnumMemberNames;
52//   typedef CppTL::AnyEnumerator<const Value &> EnumValues;
53//# endif
54
55   /** \brief Lightweight wrapper to tag static string.
56    *
57    * Value constructor and objectValue member assignement takes advantage of the
58    * StaticString and avoid the cost of string duplication when storing the
59    * string or the member name.
60    *
61    * Example of usage:
62    * \code
63    * Json::Value aValue( StaticString("some text") );
64    * Json::Value object;
65    * static const StaticString code("code");
66    * object[code] = 1234;
67    * \endcode
68    */
69   class JSON_API StaticString
70   {
71   public:
72      explicit StaticString( const char *czstring )
73         : str_( czstring )
74      {
75      }
76
77      operator const char *() const
78      {
79         return str_;
80      }
81
82      const char *c_str() const
83      {
84         return str_;
85      }
86
87   private:
88      const char *str_;
89   };
90
91   /** \brief Represents a <a HREF="http://www.json.org">JSON</a> value.
92    *
93    * This class is a discriminated union wrapper that can represents a:
94    * - signed integer [range: Value::minInt - Value::maxInt]
95    * - unsigned integer (range: 0 - Value::maxUInt)
96    * - double
97    * - UTF-8 string
98    * - boolean
99    * - 'null'
100    * - an ordered list of Value
101    * - collection of name/value pairs (javascript object)
102    *
103    * The type of the held value is represented by a #ValueType and
104    * can be obtained using type().
105    *
106    * values of an #objectValue or #arrayValue can be accessed using operator[]() methods.
107    * Non const methods will automatically create the a #nullValue element
108    * if it does not exist.
109    * The sequence of an #arrayValue will be automatically resize and initialized
110    * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue.
111    *
112    * The get() methods can be used to obtanis default value in the case the required element
113    * does not exist.
114    *
115    * It is possible to iterate over the list of a #objectValue values using
116    * the getMemberNames() method.
117    */
118   class JSON_API Value
119   {
120      friend class ValueIteratorBase;
121# ifdef JSON_VALUE_USE_INTERNAL_MAP
122      friend class ValueInternalLink;
123      friend class ValueInternalMap;
124# endif
125   public:
126      typedef std::vector<std::string> Members;
127      typedef ValueIterator iterator;
128      typedef ValueConstIterator const_iterator;
129      typedef Json::UInt UInt;
130      typedef Json::Int Int;
131# if defined(JSON_HAS_INT64)
132      typedef Json::UInt64 UInt64;
133      typedef Json::Int64 Int64;
134#endif // defined(JSON_HAS_INT64)
135      typedef Json::LargestInt LargestInt;
136      typedef Json::LargestUInt LargestUInt;
137      typedef Json::ArrayIndex ArrayIndex;
138
139      static const Value null;
140      /// Minimum signed integer value that can be stored in a Json::Value.
141      static const LargestInt minLargestInt;
142      /// Maximum signed integer value that can be stored in a Json::Value.
143      static const LargestInt maxLargestInt;
144      /// Maximum unsigned integer value that can be stored in a Json::Value.
145      static const LargestUInt maxLargestUInt;
146
147      /// Minimum signed int value that can be stored in a Json::Value.
148      static const Int minInt;
149      /// Maximum signed int value that can be stored in a Json::Value.
150      static const Int maxInt;
151      /// Maximum unsigned int value that can be stored in a Json::Value.
152      static const UInt maxUInt;
153
154      /// Minimum signed 64 bits int value that can be stored in a Json::Value.
155      static const Int64 minInt64;
156      /// Maximum signed 64 bits int value that can be stored in a Json::Value.
157      static const Int64 maxInt64;
158      /// Maximum unsigned 64 bits int value that can be stored in a Json::Value.
159      static const UInt64 maxUInt64;
160
161   private:
162#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
163# ifndef JSON_VALUE_USE_INTERNAL_MAP
164      class CZString
165      {
166      public:
167         enum DuplicationPolicy
168         {
169            noDuplication = 0,
170            duplicate,
171            duplicateOnCopy
172         };
173         CZString( ArrayIndex index );
174         CZString( const char *cstr, DuplicationPolicy allocate );
175         CZString( const CZString &other );
176         ~CZString();
177         CZString &operator =( const CZString &other );
178         bool operator<( const CZString &other ) const;
179         bool operator==( const CZString &other ) const;
180         ArrayIndex index() const;
181         const char *c_str() const;
182         bool isStaticString() const;
183      private:
184         void swap( CZString &other );
185         const char *cstr_;
186         ArrayIndex index_;
187      };
188
189   public:
190#  ifndef JSON_USE_CPPTL_SMALLMAP
191      typedef std::map<CZString, Value> ObjectValues;
192#  else
193      typedef CppTL::SmallMap<CZString, Value> ObjectValues;
194#  endif // ifndef JSON_USE_CPPTL_SMALLMAP
195# endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
196#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
197
198   public:
199      /** \brief Create a default Value of the given type.
200
201        This is a very useful constructor.
202        To create an empty array, pass arrayValue.
203        To create an empty object, pass objectValue.
204        Another Value can then be set to this one by assignment.
205    This is useful since clear() and resize() will not alter types.
206
207        Examples:
208    \code
209    Json::Value null_value; // null
210    Json::Value arr_value(Json::arrayValue); // []
211    Json::Value obj_value(Json::objectValue); // {}
212    \endcode
213      */
214      Value( ValueType type = nullValue );
215      Value( Int value );
216      Value( UInt value );
217#if defined(JSON_HAS_INT64)
218      Value( Int64 value );
219      Value( UInt64 value );
220#endif // if defined(JSON_HAS_INT64)
221      Value( double value );
222      Value( const char *value );
223      Value( const char *beginValue, const char *endValue );
224      /** \brief Constructs a value from a static string.
225
226       * Like other value string constructor but do not duplicate the string for
227       * internal storage. The given string must remain alive after the call to this
228       * constructor.
229       * Example of usage:
230       * \code
231       * Json::Value aValue( StaticString("some text") );
232       * \endcode
233       */
234      Value( const StaticString &value );
235      Value( const std::string &value );
236# ifdef JSON_USE_CPPTL
237      Value( const CppTL::ConstString &value );
238# endif
239      Value( bool value );
240      Value( const Value &other );
241      ~Value();
242
243      Value &operator=( const Value &other );
244      /// Swap values.
245      /// \note Currently, comments are intentionally not swapped, for
246      /// both logic and efficiency.
247      void swap( Value &other );
248
249      ValueType type() const;
250
251      bool operator <( const Value &other ) const;
252      bool operator <=( const Value &other ) const;
253      bool operator >=( const Value &other ) const;
254      bool operator >( const Value &other ) const;
255
256      bool operator ==( const Value &other ) const;
257      bool operator !=( const Value &other ) const;
258
259      int compare( const Value &other ) const;
260
261      const char *asCString() const;
262      std::string asString() const;
263# ifdef JSON_USE_CPPTL
264      CppTL::ConstString asConstString() const;
265# endif
266      Int asInt() const;
267      UInt asUInt() const;
268      Int64 asInt64() const;
269      UInt64 asUInt64() const;
270      LargestInt asLargestInt() const;
271      LargestUInt asLargestUInt() const;
272      float asFloat() const;
273      double asDouble() const;
274      bool asBool() const;
275
276      bool isNull() const;
277      bool isBool() const;
278      bool isInt() const;
279      bool isUInt() const;
280      bool isIntegral() const;
281      bool isDouble() const;
282      bool isNumeric() const;
283      bool isString() const;
284      bool isArray() const;
285      bool isObject() const;
286
287      bool isConvertibleTo( ValueType other ) const;
288
289      /// Number of values in array or object
290      ArrayIndex size() const;
291
292      /// \brief Return true if empty array, empty object, or null;
293      /// otherwise, false.
294      bool empty() const;
295
296      /// Return isNull()
297      bool operator!() const;
298
299      /// Remove all object members and array elements.
300      /// \pre type() is arrayValue, objectValue, or nullValue
301      /// \post type() is unchanged
302      void clear();
303
304      /// Resize the array to size elements.
305      /// New elements are initialized to null.
306      /// May only be called on nullValue or arrayValue.
307      /// \pre type() is arrayValue or nullValue
308      /// \post type() is arrayValue
309      void resize( ArrayIndex size );
310
311      /// Access an array element (zero based index ).
312      /// If the array contains less than index element, then null value are inserted
313      /// in the array so that its size is index+1.
314      /// (You may need to say 'value[0u]' to get your compiler to distinguish
315      ///  this from the operator[] which takes a string.)
316      Value &operator[]( ArrayIndex index );
317
318      /// Access an array element (zero based index ).
319      /// If the array contains less than index element, then null value are inserted
320      /// in the array so that its size is index+1.
321      /// (You may need to say 'value[0u]' to get your compiler to distinguish
322      ///  this from the operator[] which takes a string.)
323      Value &operator[]( int index );
324
325      /// Access an array element (zero based index )
326      /// (You may need to say 'value[0u]' to get your compiler to distinguish
327      ///  this from the operator[] which takes a string.)
328      const Value &operator[]( ArrayIndex index ) const;
329
330      /// Access an array element (zero based index )
331      /// (You may need to say 'value[0u]' to get your compiler to distinguish
332      ///  this from the operator[] which takes a string.)
333      const Value &operator[]( int index ) const;
334
335      /// If the array contains at least index+1 elements, returns the element value,
336      /// otherwise returns defaultValue.
337      Value get( ArrayIndex index,
338                 const Value &defaultValue ) const;
339      /// Return true if index < size().
340      bool isValidIndex( ArrayIndex index ) const;
341      /// \brief Append value to array at the end.
342      ///
343      /// Equivalent to jsonvalue[jsonvalue.size()] = value;
344      Value &append( const Value &value );
345
346      /// Access an object value by name, create a null member if it does not exist.
347      Value &operator[]( const char *key );
348      /// Access an object value by name, returns null if there is no member with that name.
349      const Value &operator[]( const char *key ) const;
350      /// Access an object value by name, create a null member if it does not exist.
351      Value &operator[]( const std::string &key );
352      /// Access an object value by name, returns null if there is no member with that name.
353      const Value &operator[]( const std::string &key ) const;
354      /** \brief Access an object value by name, create a null member if it does not exist.
355
356       * If the object as no entry for that name, then the member name used to store
357       * the new entry is not duplicated.
358       * Example of use:
359       * \code
360       * Json::Value object;
361       * static const StaticString code("code");
362       * object[code] = 1234;
363       * \endcode
364       */
365      Value &operator[]( const StaticString &key );
366# ifdef JSON_USE_CPPTL
367      /// Access an object value by name, create a null member if it does not exist.
368      Value &operator[]( const CppTL::ConstString &key );
369      /// Access an object value by name, returns null if there is no member with that name.
370      const Value &operator[]( const CppTL::ConstString &key ) const;
371# endif
372      /// Return the member named key if it exist, defaultValue otherwise.
373      Value get( const char *key,
374                 const Value &defaultValue ) const;
375      /// Return the member named key if it exist, defaultValue otherwise.
376      Value get( const std::string &key,
377                 const Value &defaultValue ) const;
378# ifdef JSON_USE_CPPTL
379      /// Return the member named key if it exist, defaultValue otherwise.
380      Value get( const CppTL::ConstString &key,
381                 const Value &defaultValue ) const;
382# endif
383      /// \brief Remove and return the named member. 
384      ///
385      /// Do nothing if it did not exist.
386      /// \return the removed Value, or null.
387      /// \pre type() is objectValue or nullValue
388      /// \post type() is unchanged
389      Value removeMember( const char* key );
390      /// Same as removeMember(const char*)
391      Value removeMember( const std::string &key );
392
393      /// Return true if the object has a member named key.
394      bool isMember( const char *key ) const;
395      /// Return true if the object has a member named key.
396      bool isMember( const std::string &key ) const;
397# ifdef JSON_USE_CPPTL
398      /// Return true if the object has a member named key.
399      bool isMember( const CppTL::ConstString &key ) const;
400# endif
401
402      /// \brief Return a list of the member names.
403      ///
404      /// If null, return an empty list.
405      /// \pre type() is objectValue or nullValue
406      /// \post if type() was nullValue, it remains nullValue
407      Members getMemberNames() const;
408
409//# ifdef JSON_USE_CPPTL
410//      EnumMemberNames enumMemberNames() const;
411//      EnumValues enumValues() const;
412//# endif
413
414      /// Comments must be //... or /* ... */
415      void setComment( const char *comment,
416                       CommentPlacement placement );
417      /// Comments must be //... or /* ... */
418      void setComment( const std::string &comment,
419                       CommentPlacement placement );
420      bool hasComment( CommentPlacement placement ) const;
421      /// Include delimiters and embedded newlines.
422      std::string getComment( CommentPlacement placement ) const;
423
424      std::string toStyledString() const;
425
426      const_iterator begin() const;
427      const_iterator end() const;
428
429      iterator begin();
430      iterator end();
431
432   private:
433      Value &resolveReference( const char *key,
434                               bool isStatic );
435
436# ifdef JSON_VALUE_USE_INTERNAL_MAP
437      inline bool isItemAvailable() const
438      {
439         return itemIsUsed_ == 0;
440      }
441
442      inline void setItemUsed( bool isUsed = true )
443      {
444         itemIsUsed_ = isUsed ? 1 : 0;
445      }
446
447      inline bool isMemberNameStatic() const
448      {
449         return memberNameIsStatic_ == 0;
450      }
451
452      inline void setMemberNameIsStatic( bool isStatic )
453      {
454         memberNameIsStatic_ = isStatic ? 1 : 0;
455      }
456# endif // # ifdef JSON_VALUE_USE_INTERNAL_MAP
457
458   private:
459      struct CommentInfo
460      {
461         CommentInfo();
462         ~CommentInfo();
463
464         void setComment( const char *text );
465
466         char *comment_;
467      };
468
469      //struct MemberNamesTransform
470      //{
471      //   typedef const char *result_type;
472      //   const char *operator()( const CZString &name ) const
473      //   {
474      //      return name.c_str();
475      //   }
476      //};
477
478      union ValueHolder
479      {
480         LargestInt int_;
481         LargestUInt uint_;
482         double real_;
483         bool bool_;
484         char *string_;
485# ifdef JSON_VALUE_USE_INTERNAL_MAP
486         ValueInternalArray *array_;
487         ValueInternalMap *map_;
488#else
489         ObjectValues *map_;
490# endif
491      } value_;
492      ValueType type_ : 8;
493      int allocated_ : 1;     // Notes: if declared as bool, bitfield is useless.
494# ifdef JSON_VALUE_USE_INTERNAL_MAP
495      unsigned int itemIsUsed_ : 1;      // used by the ValueInternalMap container.
496      int memberNameIsStatic_ : 1;       // used by the ValueInternalMap container.
497# endif
498      CommentInfo *comments_;
499   };
500
501
502   /** \brief Experimental and untested: represents an element of the "path" to access a node.
503    */
504   class PathArgument
505   {
506   public:
507      friend class Path;
508
509      PathArgument();
510      PathArgument( ArrayIndex index );
511      PathArgument( const char *key );
512      PathArgument( const std::string &key );
513
514   private:
515      enum Kind
516      {
517         kindNone = 0,
518         kindIndex,
519         kindKey
520      };
521      std::string key_;
522      ArrayIndex index_;
523      Kind kind_;
524   };
525
526   /** \brief Experimental and untested: represents a "path" to access a node.
527    *
528    * Syntax:
529    * - "." => root node
530    * - ".[n]" => elements at index 'n' of root node (an array value)
531    * - ".name" => member named 'name' of root node (an object value)
532    * - ".name1.name2.name3"
533    * - ".[0][1][2].name1[3]"
534    * - ".%" => member name is provided as parameter
535    * - ".[%]" => index is provied as parameter
536    */
537   class Path
538   {
539   public:
540      Path( const std::string &path,
541            const PathArgument &a1 = PathArgument(),
542            const PathArgument &a2 = PathArgument(),
543            const PathArgument &a3 = PathArgument(),
544            const PathArgument &a4 = PathArgument(),
545            const PathArgument &a5 = PathArgument() );
546
547      const Value &resolve( const Value &root ) const;
548      Value resolve( const Value &root,
549                     const Value &defaultValue ) const;
550      /// Creates the "path" to access the specified node and returns a reference on the node.
551      Value &make( Value &root ) const;
552
553   private:
554      typedef std::vector<const PathArgument *> InArgs;
555      typedef std::vector<PathArgument> Args;
556
557      void makePath( const std::string &path,
558                     const InArgs &in );
559      void addPathInArg( const std::string &path,
560                         const InArgs &in,
561                         InArgs::const_iterator &itInArg,
562                         PathArgument::Kind kind );
563      void invalidPath( const std::string &path,
564                        int location );
565
566      Args args_;
567   };
568
569
570
571#ifdef JSON_VALUE_USE_INTERNAL_MAP
572   /** \brief Allocator to customize Value internal map.
573    * Below is an example of a simple implementation (default implementation actually
574    * use memory pool for speed).
575    * \code
576      class DefaultValueMapAllocator : public ValueMapAllocator
577      {
578      public: // overridden from ValueMapAllocator
579         virtual ValueInternalMap *newMap()
580         {
581            return new ValueInternalMap();
582         }
583
584         virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
585         {
586            return new ValueInternalMap( other );
587         }
588
589         virtual void destructMap( ValueInternalMap *map )
590         {
591            delete map;
592         }
593
594         virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
595         {
596            return new ValueInternalLink[size];
597         }
598
599         virtual void releaseMapBuckets( ValueInternalLink *links )
600         {
601            delete [] links;
602         }
603
604         virtual ValueInternalLink *allocateMapLink()
605         {
606            return new ValueInternalLink();
607         }
608
609         virtual void releaseMapLink( ValueInternalLink *link )
610         {
611            delete link;
612         }
613      };
614    * \endcode
615    */
616   class JSON_API ValueMapAllocator
617   {
618   public:
619      virtual ~ValueMapAllocator();
620      virtual ValueInternalMap *newMap() = 0;
621      virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) = 0;
622      virtual void destructMap( ValueInternalMap *map ) = 0;
623      virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) = 0;
624      virtual void releaseMapBuckets( ValueInternalLink *links ) = 0;
625      virtual ValueInternalLink *allocateMapLink() = 0;
626      virtual void releaseMapLink( ValueInternalLink *link ) = 0;
627   };
628
629   /** \brief ValueInternalMap hash-map bucket chain link (for internal use only).
630    * \internal previous_ & next_ allows for bidirectional traversal.
631    */
632   class JSON_API ValueInternalLink
633   {
634   public:
635      enum { itemPerLink = 6 };  // sizeof(ValueInternalLink) = 128 on 32 bits architecture.
636      enum InternalFlags {
637         flagAvailable = 0,
638         flagUsed = 1
639      };
640
641      ValueInternalLink();
642
643      ~ValueInternalLink();
644
645      Value items_[itemPerLink];
646      char *keys_[itemPerLink];
647      ValueInternalLink *previous_;
648      ValueInternalLink *next_;
649   };
650
651
652   /** \brief A linked page based hash-table implementation used internally by Value.
653    * \internal ValueInternalMap is a tradional bucket based hash-table, with a linked
654    * list in each bucket to handle collision. There is an addional twist in that
655    * each node of the collision linked list is a page containing a fixed amount of
656    * value. This provides a better compromise between memory usage and speed.
657    *
658    * Each bucket is made up of a chained list of ValueInternalLink. The last
659    * link of a given bucket can be found in the 'previous_' field of the following bucket.
660    * The last link of the last bucket is stored in tailLink_ as it has no following bucket.
661    * Only the last link of a bucket may contains 'available' item. The last link always
662    * contains at least one element unless is it the bucket one very first link.
663    */
664   class JSON_API ValueInternalMap
665   {
666      friend class ValueIteratorBase;
667      friend class Value;
668   public:
669      typedef unsigned int HashKey;
670      typedef unsigned int BucketIndex;
671
672# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
673      struct IteratorState
674      {
675         IteratorState()
676            : map_(0)
677            , link_(0)
678            , itemIndex_(0)
679            , bucketIndex_(0)
680         {
681         }
682         ValueInternalMap *map_;
683         ValueInternalLink *link_;
684         BucketIndex itemIndex_;
685         BucketIndex bucketIndex_;
686      };
687# endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
688
689      ValueInternalMap();
690      ValueInternalMap( const ValueInternalMap &other );
691      ValueInternalMap &operator =( const ValueInternalMap &other );
692      ~ValueInternalMap();
693
694      void swap( ValueInternalMap &other );
695
696      BucketIndex size() const;
697
698      void clear();
699
700      bool reserveDelta( BucketIndex growth );
701
702      bool reserve( BucketIndex newItemCount );
703
704      const Value *find( const char *key ) const;
705
706      Value *find( const char *key );
707
708      Value &resolveReference( const char *key,
709                               bool isStatic );
710
711      void remove( const char *key );
712
713      void doActualRemove( ValueInternalLink *link,
714                           BucketIndex index,
715                           BucketIndex bucketIndex );
716
717      ValueInternalLink *&getLastLinkInBucket( BucketIndex bucketIndex );
718
719      Value &setNewItem( const char *key,
720                         bool isStatic,
721                         ValueInternalLink *link,
722                         BucketIndex index );
723
724      Value &unsafeAdd( const char *key,
725                        bool isStatic,
726                        HashKey hashedKey );
727
728      HashKey hash( const char *key ) const;
729
730      int compare( const ValueInternalMap &other ) const;
731
732   private:
733      void makeBeginIterator( IteratorState &it ) const;
734      void makeEndIterator( IteratorState &it ) const;
735      static bool equals( const IteratorState &x, const IteratorState &other );
736      static void increment( IteratorState &iterator );
737      static void incrementBucket( IteratorState &iterator );
738      static void decrement( IteratorState &iterator );
739      static const char *key( const IteratorState &iterator );
740      static const char *key( const IteratorState &iterator, bool &isStatic );
741      static Value &value( const IteratorState &iterator );
742      static int distance( const IteratorState &x, const IteratorState &y );
743
744   private:
745      ValueInternalLink *buckets_;
746      ValueInternalLink *tailLink_;
747      BucketIndex bucketsSize_;
748      BucketIndex itemCount_;
749   };
750
751   /** \brief A simplified deque implementation used internally by Value.
752   * \internal
753   * It is based on a list of fixed "page", each page contains a fixed number of items.
754   * Instead of using a linked-list, a array of pointer is used for fast item look-up.
755   * Look-up for an element is as follow:
756   * - compute page index: pageIndex = itemIndex / itemsPerPage
757   * - look-up item in page: pages_[pageIndex][itemIndex % itemsPerPage]
758   *
759   * Insertion is amortized constant time (only the array containing the index of pointers
760   * need to be reallocated when items are appended).
761   */
762   class JSON_API ValueInternalArray
763   {
764      friend class Value;
765      friend class ValueIteratorBase;
766   public:
767      enum { itemsPerPage = 8 };    // should be a power of 2 for fast divide and modulo.
768      typedef Value::ArrayIndex ArrayIndex;
769      typedef unsigned int PageIndex;
770
771# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
772      struct IteratorState // Must be a POD
773      {
774         IteratorState()
775            : array_(0)
776            , currentPageIndex_(0)
777            , currentItemIndex_(0)
778         {
779         }
780         ValueInternalArray *array_;
781         Value **currentPageIndex_;
782         unsigned int currentItemIndex_;
783      };
784# endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
785
786      ValueInternalArray();
787      ValueInternalArray( const ValueInternalArray &other );
788      ValueInternalArray &operator =( const ValueInternalArray &other );
789      ~ValueInternalArray();
790      void swap( ValueInternalArray &other );
791
792      void clear();
793      void resize( ArrayIndex newSize );
794
795      Value &resolveReference( ArrayIndex index );
796
797      Value *find( ArrayIndex index ) const;
798
799      ArrayIndex size() const;
800
801      int compare( const ValueInternalArray &other ) const;
802
803   private:
804      static bool equals( const IteratorState &x, const IteratorState &other );
805      static void increment( IteratorState &iterator );
806      static void decrement( IteratorState &iterator );
807      static Value &dereference( const IteratorState &iterator );
808      static Value &unsafeDereference( const IteratorState &iterator );
809      static int distance( const IteratorState &x, const IteratorState &y );
810      static ArrayIndex indexOf( const IteratorState &iterator );
811      void makeBeginIterator( IteratorState &it ) const;
812      void makeEndIterator( IteratorState &it ) const;
813      void makeIterator( IteratorState &it, ArrayIndex index ) const;
814
815      void makeIndexValid( ArrayIndex index );
816
817      Value **pages_;
818      ArrayIndex size_;
819      PageIndex pageCount_;
820   };
821
822   /** \brief Experimental: do not use. Allocator to customize Value internal array.
823    * Below is an example of a simple implementation (actual implementation use
824    * memory pool).
825      \code
826class DefaultValueArrayAllocator : public ValueArrayAllocator
827{
828public: // overridden from ValueArrayAllocator
829   virtual ~DefaultValueArrayAllocator()
830   {
831   }
832
833   virtual ValueInternalArray *newArray()
834   {
835      return new ValueInternalArray();
836   }
837
838   virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
839   {
840      return new ValueInternalArray( other );
841   }
842
843   virtual void destruct( ValueInternalArray *array )
844   {
845      delete array;
846   }
847
848   virtual void reallocateArrayPageIndex( Value **&indexes,
849                                          ValueInternalArray::PageIndex &indexCount,
850                                          ValueInternalArray::PageIndex minNewIndexCount )
851   {
852      ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
853      if ( minNewIndexCount > newIndexCount )
854         newIndexCount = minNewIndexCount;
855      void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
856      if ( !newIndexes )
857         throw std::bad_alloc();
858      indexCount = newIndexCount;
859      indexes = static_cast<Value **>( newIndexes );
860   }
861   virtual void releaseArrayPageIndex( Value **indexes,
862                                       ValueInternalArray::PageIndex indexCount )
863   {
864      if ( indexes )
865         free( indexes );
866   }
867
868   virtual Value *allocateArrayPage()
869   {
870      return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) );
871   }
872
873   virtual void releaseArrayPage( Value *value )
874   {
875      if ( value )
876         free( value );
877   }
878};
879      \endcode
880    */
881   class JSON_API ValueArrayAllocator
882   {
883   public:
884      virtual ~ValueArrayAllocator();
885      virtual ValueInternalArray *newArray() = 0;
886      virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) = 0;
887      virtual void destructArray( ValueInternalArray *array ) = 0;
888      /** \brief Reallocate array page index.
889       * Reallocates an array of pointer on each page.
890       * \param indexes [input] pointer on the current index. May be \c NULL.
891       *                [output] pointer on the new index of at least
892       *                         \a minNewIndexCount pages.
893       * \param indexCount [input] current number of pages in the index.
894       *                   [output] number of page the reallocated index can handle.
895       *                            \b MUST be >= \a minNewIndexCount.
896       * \param minNewIndexCount Minimum number of page the new index must be able to
897       *                         handle.
898       */
899      virtual void reallocateArrayPageIndex( Value **&indexes,
900                                             ValueInternalArray::PageIndex &indexCount,
901                                             ValueInternalArray::PageIndex minNewIndexCount ) = 0;
902      virtual void releaseArrayPageIndex( Value **indexes,
903                                          ValueInternalArray::PageIndex indexCount ) = 0;
904      virtual Value *allocateArrayPage() = 0;
905      virtual void releaseArrayPage( Value *value ) = 0;
906   };
907#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
908
909
910   /** \brief base class for Value iterators.
911    *
912    */
913   class ValueIteratorBase
914   {
915   public:
916      typedef unsigned int size_t;
917      typedef int difference_type;
918      typedef ValueIteratorBase SelfType;
919
920      ValueIteratorBase();
921#ifndef JSON_VALUE_USE_INTERNAL_MAP
922      explicit ValueIteratorBase( const Value::ObjectValues::iterator &current );
923#else
924      ValueIteratorBase( const ValueInternalArray::IteratorState &state );
925      ValueIteratorBase( const ValueInternalMap::IteratorState &state );
926#endif
927
928      bool operator ==( const SelfType &other ) const
929      {
930         return isEqual( other );
931      }
932
933      bool operator !=( const SelfType &other ) const
934      {
935         return !isEqual( other );
936      }
937
938      difference_type operator -( const SelfType &other ) const
939      {
940         return computeDistance( other );
941      }
942
943      /// Return either the index or the member name of the referenced value as a Value.
944      Value key() const;
945
946      /// Return the index of the referenced Value. -1 if it is not an arrayValue.
947      UInt index() const;
948
949      /// Return the member name of the referenced Value. "" if it is not an objectValue.
950      const char *memberName() const;
951
952   protected:
953      Value &deref() const;
954
955      void increment();
956
957      void decrement();
958
959      difference_type computeDistance( const SelfType &other ) const;
960
961      bool isEqual( const SelfType &other ) const;
962
963      void copy( const SelfType &other );
964
965   private:
966#ifndef JSON_VALUE_USE_INTERNAL_MAP
967      Value::ObjectValues::iterator current_;
968      // Indicates that iterator is for a null value.
969      bool isNull_;
970#else
971      union
972      {
973         ValueInternalArray::IteratorState array_;
974         ValueInternalMap::IteratorState map_;
975      } iterator_;
976      bool isArray_;
977#endif
978   };
979
980   /** \brief const iterator for object and array value.
981    *
982    */
983   class ValueConstIterator : public ValueIteratorBase
984   {
985      friend class Value;
986   public:
987      typedef unsigned int size_t;
988      typedef int difference_type;
989      typedef const Value &reference;
990      typedef const Value *pointer;
991      typedef ValueConstIterator SelfType;
992
993      ValueConstIterator();
994   private:
995      /*! \internal Use by Value to create an iterator.
996       */
997#ifndef JSON_VALUE_USE_INTERNAL_MAP
998      explicit ValueConstIterator( const Value::ObjectValues::iterator &current );
999#else
1000      ValueConstIterator( const ValueInternalArray::IteratorState &state );
1001      ValueConstIterator( const ValueInternalMap::IteratorState &state );
1002#endif
1003   public:
1004      SelfType &operator =( const ValueIteratorBase &other );
1005
1006      SelfType operator++( int )
1007      {
1008         SelfType temp( *this );
1009         ++*this;
1010         return temp;
1011      }
1012
1013      SelfType operator--( int )
1014      {
1015         SelfType temp( *this );
1016         --*this;
1017         return temp;
1018      }
1019
1020      SelfType &operator--()
1021      {
1022         decrement();
1023         return *this;
1024      }
1025
1026      SelfType &operator++()
1027      {
1028         increment();
1029         return *this;
1030      }
1031
1032      reference operator *() const
1033      {
1034         return deref();
1035      }
1036   };
1037
1038
1039   /** \brief Iterator for object and array value.
1040    */
1041   class ValueIterator : public ValueIteratorBase
1042   {
1043      friend class Value;
1044   public:
1045      typedef unsigned int size_t;
1046      typedef int difference_type;
1047      typedef Value &reference;
1048      typedef Value *pointer;
1049      typedef ValueIterator SelfType;
1050
1051      ValueIterator();
1052      ValueIterator( const ValueConstIterator &other );
1053      ValueIterator( const ValueIterator &other );
1054   private:
1055      /*! \internal Use by Value to create an iterator.
1056       */
1057#ifndef JSON_VALUE_USE_INTERNAL_MAP
1058      explicit ValueIterator( const Value::ObjectValues::iterator &current );
1059#else
1060      ValueIterator( const ValueInternalArray::IteratorState &state );
1061      ValueIterator( const ValueInternalMap::IteratorState &state );
1062#endif
1063   public:
1064
1065      SelfType &operator =( const SelfType &other );
1066
1067      SelfType operator++( int )
1068      {
1069         SelfType temp( *this );
1070         ++*this;
1071         return temp;
1072      }
1073
1074      SelfType operator--( int )
1075      {
1076         SelfType temp( *this );
1077         --*this;
1078         return temp;
1079      }
1080
1081      SelfType &operator--()
1082      {
1083         decrement();
1084         return *this;
1085      }
1086
1087      SelfType &operator++()
1088      {
1089         increment();
1090         return *this;
1091      }
1092
1093      reference operator *() const
1094      {
1095         return deref();
1096      }
1097   };
1098
1099
1100} // namespace Json
1101
1102
1103#endif // CPPTL_JSON_H_INCLUDED
Property changes on: trunk/src/lib/web/json/value.h
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/lib/web/json/writer.h
r0r24796
1// Copyright 2007-2010 Baptiste Lepilleur
2// Distributed under MIT license, or public domain if desired and
3// recognized in your jurisdiction.
4// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
5
6#ifndef JSON_WRITER_H_INCLUDED
7# define JSON_WRITER_H_INCLUDED
8
9#if !defined(JSON_IS_AMALGAMATION)
10# include "value.h"
11#endif // if !defined(JSON_IS_AMALGAMATION)
12# include <vector>
13# include <string>
14# include <iostream>
15
16namespace Json {
17
18   class Value;
19
20   /** \brief Abstract class for writers.
21    */
22   class JSON_API Writer
23   {
24   public:
25      virtual ~Writer();
26
27      virtual std::string write( const Value &root ) = 0;
28   };
29
30   /** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format without formatting (not human friendly).
31    *
32    * The JSON document is written in a single line. It is not intended for 'human' consumption,
33    * but may be usefull to support feature such as RPC where bandwith is limited.
34    * \sa Reader, Value
35    */
36   class JSON_API FastWriter : public Writer
37   {
38   public:
39      FastWriter();
40      virtual ~FastWriter(){}
41
42      void enableYAMLCompatibility();
43
44   public: // overridden from Writer
45      virtual std::string write( const Value &root );
46
47   private:
48      void writeValue( const Value &value );
49
50      std::string document_;
51      bool yamlCompatiblityEnabled_;
52   };
53
54   /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way.
55    *
56    * The rules for line break and indent are as follow:
57    * - Object value:
58    *     - if empty then print {} without indent and line break
59    *     - if not empty the print '{', line break & indent, print one value per line
60    *       and then unindent and line break and print '}'.
61    * - Array value:
62    *     - if empty then print [] without indent and line break
63    *     - if the array contains no object value, empty array or some other value types,
64    *       and all the values fit on one lines, then print the array on a single line.
65    *     - otherwise, it the values do not fit on one line, or the array contains
66    *       object or non empty array, then print one value per line.
67    *
68    * If the Value have comments then they are outputed according to their #CommentPlacement.
69    *
70    * \sa Reader, Value, Value::setComment()
71    */
72   class JSON_API StyledWriter: public Writer
73   {
74   public:
75      StyledWriter();
76      virtual ~StyledWriter(){}
77
78   public: // overridden from Writer
79      /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
80       * \param root Value to serialize.
81       * \return String containing the JSON document that represents the root value.
82       */
83      virtual std::string write( const Value &root );
84
85   private:
86      void writeValue( const Value &value );
87      void writeArrayValue( const Value &value );
88      bool isMultineArray( const Value &value );
89      void pushValue( const std::string &value );
90      void writeIndent();
91      void writeWithIndent( const std::string &value );
92      void indent();
93      void unindent();
94      void writeCommentBeforeValue( const Value &root );
95      void writeCommentAfterValueOnSameLine( const Value &root );
96      bool hasCommentForValue( const Value &value );
97      static std::string normalizeEOL( const std::string &text );
98
99      typedef std::vector<std::string> ChildValues;
100
101      ChildValues childValues_;
102      std::string document_;
103      std::string indentString_;
104      int rightMargin_;
105      int indentSize_;
106      bool addChildValues_;
107   };
108
109   /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way,
110        to a stream rather than to a string.
111    *
112    * The rules for line break and indent are as follow:
113    * - Object value:
114    *     - if empty then print {} without indent and line break
115    *     - if not empty the print '{', line break & indent, print one value per line
116    *       and then unindent and line break and print '}'.
117    * - Array value:
118    *     - if empty then print [] without indent and line break
119    *     - if the array contains no object value, empty array or some other value types,
120    *       and all the values fit on one lines, then print the array on a single line.
121    *     - otherwise, it the values do not fit on one line, or the array contains
122    *       object or non empty array, then print one value per line.
123    *
124    * If the Value have comments then they are outputed according to their #CommentPlacement.
125    *
126    * \param indentation Each level will be indented by this amount extra.
127    * \sa Reader, Value, Value::setComment()
128    */
129   class JSON_API StyledStreamWriter
130   {
131   public:
132      StyledStreamWriter( std::string indentation="\t" );
133      ~StyledStreamWriter(){}
134
135   public:
136      /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
137       * \param out Stream to write to. (Can be ostringstream, e.g.)
138       * \param root Value to serialize.
139       * \note There is no point in deriving from Writer, since write() should not return a value.
140       */
141      void write( std::ostream &out, const Value &root );
142
143   private:
144      void writeValue( const Value &value );
145      void writeArrayValue( const Value &value );
146      bool isMultineArray( const Value &value );
147      void pushValue( const std::string &value );
148      void writeIndent();
149      void writeWithIndent( const std::string &value );
150      void indent();
151      void unindent();
152      void writeCommentBeforeValue( const Value &root );
153      void writeCommentAfterValueOnSameLine( const Value &root );
154      bool hasCommentForValue( const Value &value );
155      static std::string normalizeEOL( const std::string &text );
156
157      typedef std::vector<std::string> ChildValues;
158
159      ChildValues childValues_;
160      std::ostream* document_;
161      std::string indentString_;
162      int rightMargin_;
163      std::string indentation_;
164      bool addChildValues_;
165   };
166
167# if defined(JSON_HAS_INT64)
168   std::string JSON_API valueToString( Int value );
169   std::string JSON_API valueToString( UInt value );
170# endif // if defined(JSON_HAS_INT64)
171   std::string JSON_API valueToString( LargestInt value );
172   std::string JSON_API valueToString( LargestUInt value );
173   std::string JSON_API valueToString( double value );
174   std::string JSON_API valueToString( bool value );
175   std::string JSON_API valueToQuotedString( const char *value );
176
177   /// \brief Output using the StyledStreamWriter.
178   /// \see Json::operator>>()
179   std::ostream& operator<<( std::ostream&, const Value &root );
180
181} // namespace Json
182
183
184
185#endif // JSON_WRITER_H_INCLUDED
Property changes on: trunk/src/lib/web/json/writer.h
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/lib/web/json/features.h
r0r24796
1// Copyright 2007-2010 Baptiste Lepilleur
2// Distributed under MIT license, or public domain if desired and
3// recognized in your jurisdiction.
4// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
5
6#ifndef CPPTL_JSON_FEATURES_H_INCLUDED
7# define CPPTL_JSON_FEATURES_H_INCLUDED
8
9#if !defined(JSON_IS_AMALGAMATION)
10# include "forwards.h"
11#endif // if !defined(JSON_IS_AMALGAMATION)
12
13namespace Json {
14
15   /** \brief Configuration passed to reader and writer.
16    * This configuration object can be used to force the Reader or Writer
17    * to behave in a standard conforming way.
18    */
19   class JSON_API Features
20   {
21   public:
22      /** \brief A configuration that allows all features and assumes all strings are UTF-8.
23       * - C & C++ comments are allowed
24       * - Root object can be any JSON value
25       * - Assumes Value strings are encoded in UTF-8
26       */
27      static Features all();
28
29      /** \brief A configuration that is strictly compatible with the JSON specification.
30       * - Comments are forbidden.
31       * - Root object must be either an array or an object value.
32       * - Assumes Value strings are encoded in UTF-8
33       */
34      static Features strictMode();
35
36      /** \brief Initialize the configuration like JsonConfig::allFeatures;
37       */
38      Features();
39
40      /// \c true if comments are allowed. Default: \c true.
41      bool allowComments_;
42
43      /// \c true if root must be either an array or an object value. Default: \c false.
44      bool strictRoot_;
45   };
46
47} // namespace Json
48
49#endif // CPPTL_JSON_FEATURES_H_INCLUDED
Property changes on: trunk/src/lib/web/json/features.h
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/lib/web/json/json_reader.cpp
r0r24796
1// Copyright 2007-2010 Baptiste Lepilleur
2// Distributed under MIT license, or public domain if desired and
3// recognized in your jurisdiction.
4// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
5#include "emu.h"
6#if !defined(JSON_IS_AMALGAMATION)
7# include <json/reader.h>
8# include <json/value.h>
9# include "json_tool.h"
10#endif // if !defined(JSON_IS_AMALGAMATION)
11#include <utility>
12#include <cstdio>
13#include <cassert>
14#include <cstring>
15#include <iostream>
16#include <stdexcept>
17
18#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
19#pragma warning( disable : 4996 )   // disable warning about strdup being deprecated.
20#endif
21
22namespace Json {
23
24// Implementation of class Features
25// ////////////////////////////////
26
27Features::Features()
28   : allowComments_( true )
29   , strictRoot_( false )
30{
31}
32
33
34Features
35Features::all()
36{
37   return Features();
38}
39
40
41Features
42Features::strictMode()
43{
44   Features features;
45   features.allowComments_ = false;
46   features.strictRoot_ = true;
47   return features;
48}
49
50// Implementation of class Reader
51// ////////////////////////////////
52
53
54static inline bool
55in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4 )
56{
57   return c == c1  ||  c == c2  ||  c == c3  ||  c == c4;
58}
59
60static inline bool
61in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4, Reader::Char c5 )
62{
63   return c == c1  ||  c == c2  ||  c == c3  ||  c == c4  ||  c == c5;
64}
65
66
67static bool
68containsNewLine( Reader::Location begin,
69                 Reader::Location end )
70{
71   for ( ;begin < end; ++begin )
72      if ( *begin == '\n'  ||  *begin == '\r' )
73         return true;
74   return false;
75}
76
77
78// Class Reader
79// //////////////////////////////////////////////////////////////////
80
81Reader::Reader()
82   : features_( Features::all() )
83{
84}
85
86
87Reader::Reader( const Features &features )
88   : features_( features )
89{
90}
91
92
93bool
94Reader::parse( const std::string &document,
95               Value &root,
96               bool collectComments )
97{
98   document_ = document;
99   const char *begin = document_.c_str();
100   const char *end = begin + document_.length();
101   return parse( begin, end, root, collectComments );
102}
103
104
105bool
106Reader::parse( std::istream& sin,
107               Value &root,
108               bool collectComments )
109{
110   //std::istream_iterator<char> begin(sin);
111   //std::istream_iterator<char> end;
112   // Those would allow streamed input from a file, if parse() were a
113   // template function.
114
115   // Since std::string is reference-counted, this at least does not
116   // create an extra copy.
117   std::string doc;
118   std::getline(sin, doc, (char)EOF);
119   return parse( doc, root, collectComments );
120}
121
122bool
123Reader::parse( const char *beginDoc, const char *endDoc,
124               Value &root,
125               bool collectComments )
126{
127   if ( !features_.allowComments_ )
128   {
129      collectComments = false;
130   }
131
132   begin_ = beginDoc;
133   end_ = endDoc;
134   collectComments_ = collectComments;
135   current_ = begin_;
136   lastValueEnd_ = 0;
137   lastValue_ = 0;
138   commentsBefore_ = "";
139   errors_.clear();
140   while ( !nodes_.empty() )
141      nodes_.pop();
142   nodes_.push( &root );
143   
144   bool successful = readValue();
145   Token token;
146   skipCommentTokens( token );
147   if ( collectComments_  &&  !commentsBefore_.empty() )
148      root.setComment( commentsBefore_, commentAfter );
149   if ( features_.strictRoot_ )
150   {
151      if ( !root.isArray()  &&  !root.isObject() )
152      {
153         // Set error location to start of doc, ideally should be first token found in doc
154         token.type_ = tokenError;
155         token.start_ = beginDoc;
156         token.end_ = endDoc;
157         addError( "A valid JSON document must be either an array or an object value.",
158                   token );
159         return false;
160      }
161   }
162   return successful;
163}
164
165
166bool
167Reader::readValue()
168{
169   Token token;
170   skipCommentTokens( token );
171   bool successful = true;
172
173   if ( collectComments_  &&  !commentsBefore_.empty() )
174   {
175      currentValue().setComment( commentsBefore_, commentBefore );
176      commentsBefore_ = "";
177   }
178
179
180   switch ( token.type_ )
181   {
182   case tokenObjectBegin:
183      successful = readObject( token );
184      break;
185   case tokenArrayBegin:
186      successful = readArray( token );
187      break;
188   case tokenNumber:
189      successful = decodeNumber( token );
190      break;
191   case tokenString:
192      successful = decodeString( token );
193      break;
194   case tokenTrue:
195      currentValue() = true;
196      break;
197   case tokenFalse:
198      currentValue() = false;
199      break;
200   case tokenNull:
201      currentValue() = Value();
202      break;
203   default:
204      return addError( "Syntax error: value, object or array expected.", token );
205   }
206
207   if ( collectComments_ )
208   {
209      lastValueEnd_ = current_;
210      lastValue_ = &currentValue();
211   }
212
213   return successful;
214}
215
216
217void
218Reader::skipCommentTokens( Token &token )
219{
220   if ( features_.allowComments_ )
221   {
222      do
223      {
224         readToken( token );
225      }
226      while ( token.type_ == tokenComment );
227   }
228   else
229   {
230      readToken( token );
231   }
232}
233
234
235bool
236Reader::expectToken( TokenType type, Token &token, const char *message )
237{
238   readToken( token );
239   if ( token.type_ != type )
240      return addError( message, token );
241   return true;
242}
243
244
245bool
246Reader::readToken( Token &token )
247{
248   skipSpaces();
249   token.start_ = current_;
250   Char c = getNextChar();
251   bool ok = true;
252   switch ( c )
253   {
254   case '{':
255      token.type_ = tokenObjectBegin;
256      break;
257   case '}':
258      token.type_ = tokenObjectEnd;
259      break;
260   case '[':
261      token.type_ = tokenArrayBegin;
262      break;
263   case ']':
264      token.type_ = tokenArrayEnd;
265      break;
266   case '"':
267      token.type_ = tokenString;
268      ok = readString();
269      break;
270   case '/':
271      token.type_ = tokenComment;
272      ok = readComment();
273      break;
274   case '0':
275   case '1':
276   case '2':
277   case '3':
278   case '4':
279   case '5':
280   case '6':
281   case '7':
282   case '8':
283   case '9':
284   case '-':
285      token.type_ = tokenNumber;
286      readNumber();
287      break;
288   case 't':
289      token.type_ = tokenTrue;
290      ok = match( "rue", 3 );
291      break;
292   case 'f':
293      token.type_ = tokenFalse;
294      ok = match( "alse", 4 );
295      break;
296   case 'n':
297      token.type_ = tokenNull;
298      ok = match( "ull", 3 );
299      break;
300   case ',':
301      token.type_ = tokenArraySeparator;
302      break;
303   case ':':
304      token.type_ = tokenMemberSeparator;
305      break;
306   case 0:
307      token.type_ = tokenEndOfStream;
308      break;
309   default:
310      ok = false;
311      break;
312   }
313   if ( !ok )
314      token.type_ = tokenError;
315   token.end_ = current_;
316   return true;
317}
318
319
320void
321Reader::skipSpaces()
322{
323   while ( current_ != end_ )
324   {
325      Char c = *current_;
326      if ( c == ' '  ||  c == '\t'  ||  c == '\r'  ||  c == '\n' )
327         ++current_;
328      else
329         break;
330   }
331}
332
333
334bool
335Reader::match( Location pattern,
336               int patternLength )
337{
338   if ( end_ - current_ < patternLength )
339      return false;
340   int index = patternLength;
341   while ( index-- )
342      if ( current_[index] != pattern[index] )
343         return false;
344   current_ += patternLength;
345   return true;
346}
347
348
349bool
350Reader::readComment()
351{
352   Location commentBegin = current_ - 1;
353   Char c = getNextChar();
354   bool successful = false;
355   if ( c == '*' )
356      successful = readCStyleComment();
357   else if ( c == '/' )
358      successful = readCppStyleComment();
359   if ( !successful )
360      return false;
361
362   if ( collectComments_ )
363   {
364      CommentPlacement placement = commentBefore;
365      if ( lastValueEnd_  &&  !containsNewLine( lastValueEnd_, commentBegin ) )
366      {
367         if ( c != '*'  ||  !containsNewLine( commentBegin, current_ ) )
368            placement = commentAfterOnSameLine;
369      }
370
371      addComment( commentBegin, current_, placement );
372   }
373   return true;
374}
375
376
377void
378Reader::addComment( Location begin,
379                    Location end,
380                    CommentPlacement placement )
381{
382   assert( collectComments_ );
383   if ( placement == commentAfterOnSameLine )
384   {
385      assert( lastValue_ != 0 );
386      lastValue_->setComment( std::string( begin, end ), placement );
387   }
388   else
389   {
390      if ( !commentsBefore_.empty() )
391         commentsBefore_ += "\n";
392      commentsBefore_ += std::string( begin, end );
393   }
394}
395
396
397bool
398Reader::readCStyleComment()
399{
400   while ( current_ != end_ )
401   {
402      Char c = getNextChar();
403      if ( c == '*'  &&  *current_ == '/' )
404         break;
405   }
406   return getNextChar() == '/';
407}
408
409
410bool
411Reader::readCppStyleComment()
412{
413   while ( current_ != end_ )
414   {
415      Char c = getNextChar();
416      if (  c == '\r'  ||  c == '\n' )
417         break;
418   }
419   return true;
420}
421
422
423void
424Reader::readNumber()
425{
426   while ( current_ != end_ )
427   {
428      if ( !(*current_ >= '0'  &&  *current_ <= '9')  &&
429           !in( *current_, '.', 'e', 'E', '+', '-' ) )
430         break;
431      ++current_;
432   }
433}
434
435bool
436Reader::readString()
437{
438   Char c = 0;
439   while ( current_ != end_ )
440   {
441      c = getNextChar();
442      if ( c == '\\' )
443         getNextChar();
444      else if ( c == '"' )
445         break;
446   }
447   return c == '"';
448}
449
450
451bool
452Reader::readObject( Token &/*tokenStart*/ )
453{
454   Token tokenName;
455   std::string name;
456   currentValue() = Value( objectValue );
457   while ( readToken( tokenName ) )
458   {
459      bool initialTokenOk = true;
460      while ( tokenName.type_ == tokenComment  &&  initialTokenOk )
461         initialTokenOk = readToken( tokenName );
462      if  ( !initialTokenOk )
463         break;
464      if ( tokenName.type_ == tokenObjectEnd  &&  name.empty() )  // empty object
465         return true;
466      if ( tokenName.type_ != tokenString )
467         break;
468     
469      name = "";
470      if ( !decodeString( tokenName, name ) )
471         return recoverFromError( tokenObjectEnd );
472
473      Token colon;
474      if ( !readToken( colon ) ||  colon.type_ != tokenMemberSeparator )
475      {
476         return addErrorAndRecover( "Missing ':' after object member name",
477                                    colon,
478                                    tokenObjectEnd );
479      }
480      Value &value = currentValue()[ name ];
481      nodes_.push( &value );
482      bool ok = readValue();
483      nodes_.pop();
484      if ( !ok ) // error already set
485         return recoverFromError( tokenObjectEnd );
486
487      Token comma;
488      if ( !readToken( comma )
489            ||  ( comma.type_ != tokenObjectEnd  && 
490                  comma.type_ != tokenArraySeparator &&
491                  comma.type_ != tokenComment ) )
492      {
493         return addErrorAndRecover( "Missing ',' or '}' in object declaration",
494                                    comma,
495                                    tokenObjectEnd );
496      }
497      bool finalizeTokenOk = true;
498      while ( comma.type_ == tokenComment &&
499              finalizeTokenOk )
500         finalizeTokenOk = readToken( comma );
501      if ( comma.type_ == tokenObjectEnd )
502         return true;
503   }
504   return addErrorAndRecover( "Missing '}' or object member name",
505                              tokenName,
506                              tokenObjectEnd );
507}
508
509
510bool
511Reader::readArray( Token &/*tokenStart*/ )
512{
513   currentValue() = Value( arrayValue );
514   skipSpaces();
515   if ( *current_ == ']' ) // empty array
516   {
517      Token endArray;
518      readToken( endArray );
519      return true;
520   }
521   int index = 0;
522   for (;;)
523   {
524      Value &value = currentValue()[ index++ ];
525      nodes_.push( &value );
526      bool ok = readValue();
527      nodes_.pop();
528      if ( !ok ) // error already set
529         return recoverFromError( tokenArrayEnd );
530
531      Token token;
532      // Accept Comment after last item in the array.
533      ok = readToken( token );
534      while ( token.type_ == tokenComment  &&  ok )
535      {
536         ok = readToken( token );
537      }
538      bool badTokenType = ( token.type_ != tokenArraySeparator  &&
539                            token.type_ != tokenArrayEnd );
540      if ( !ok  ||  badTokenType )
541      {
542         return addErrorAndRecover( "Missing ',' or ']' in array declaration",
543                                    token,
544                                    tokenArrayEnd );
545      }
546      if ( token.type_ == tokenArrayEnd )
547         break;
548   }
549   return true;
550}
551
552
553bool
554Reader::decodeNumber( Token &token )
555{
556   bool isDouble = false;
557   for ( Location inspect = token.start_; inspect != token.end_; ++inspect )
558   {
559      isDouble = isDouble 
560                 ||  in( *inspect, '.', 'e', 'E', '+' ) 
561                 ||  ( *inspect == '-'  &&  inspect != token.start_ );
562   }
563   if ( isDouble )
564      return decodeDouble( token );
565   // Attempts to parse the number as an integer. If the number is
566   // larger than the maximum supported value of an integer then
567   // we decode the number as a double.
568   Location current = token.start_;
569   bool isNegative = *current == '-';
570   if ( isNegative )
571      ++current;
572   Value::LargestUInt maxIntegerValue = isNegative ? Value::LargestUInt(-Value::minLargestInt)
573                                                   : Value::maxLargestUInt;
574   Value::LargestUInt threshold = maxIntegerValue / 10;
575   Value::UInt lastDigitThreshold = Value::UInt( maxIntegerValue % 10 );
576   assert( lastDigitThreshold >=0  &&  lastDigitThreshold <= 9 );
577   Value::LargestUInt value = 0;
578   while ( current < token.end_ )
579   {
580      Char c = *current++;
581      if ( c < '0'  ||  c > '9' )
582         return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
583      Value::UInt digit(c - '0');
584      if ( value >= threshold )
585      {
586         // If the current digit is not the last one, or if it is
587         // greater than the last digit of the maximum integer value,
588         // the parse the number as a double.
589         if ( current != token.end_  ||  digit > lastDigitThreshold )
590         {
591            return decodeDouble( token );
592         }
593      }
594      value = value * 10 + digit;
595   }
596   if ( isNegative )
597      currentValue() = -Value::LargestInt( value );
598   else if ( value <= Value::LargestUInt(Value::maxInt) )
599      currentValue() = Value::LargestInt( value );
600   else
601      currentValue() = value;
602   return true;
603}
604
605
606bool
607Reader::decodeDouble( Token &token )
608{
609   double value = 0;
610   const int bufferSize = 32;
611   int count;
612   int length = int(token.end_ - token.start_);
613   if ( length <= bufferSize )
614   {
615      Char buffer[bufferSize+1];
616      memcpy( buffer, token.start_, length );
617      buffer[length] = 0;
618      count = sscanf( buffer, "%lf", &value );
619   }
620   else
621   {
622      std::string buffer( token.start_, token.end_ );
623      count = sscanf( buffer.c_str(), "%lf", &value );
624   }
625
626   if ( count != 1 )
627      return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
628   currentValue() = value;
629   return true;
630}
631
632
633bool
634Reader::decodeString( Token &token )
635{
636   std::string decoded;
637   if ( !decodeString( token, decoded ) )
638      return false;
639   currentValue() = decoded;
640   return true;
641}
642
643
644bool
645Reader::decodeString( Token &token, std::string &decoded )
646{
647   decoded.reserve( token.end_ - token.start_ - 2 );
648   Location current = token.start_ + 1; // skip '"'
649   Location end = token.end_ - 1;      // do not include '"'
650   while ( current != end )
651   {
652      Char c = *current++;
653      if ( c == '"' )
654         break;
655      else if ( c == '\\' )
656      {
657         if ( current == end )
658            return addError( "Empty escape sequence in string", token, current );
659         Char escape = *current++;
660         switch ( escape )
661         {
662         case '"': decoded += '"'; break;
663         case '/': decoded += '/'; break;
664         case '\\': decoded += '\\'; break;
665         case 'b': decoded += '\b'; break;
666         case 'f': decoded += '\f'; break;
667         case 'n': decoded += '\n'; break;
668         case 'r': decoded += '\r'; break;
669         case 't': decoded += '\t'; break;
670         case 'u':
671            {
672               unsigned int unicode;
673               if ( !decodeUnicodeCodePoint( token, current, end, unicode ) )
674                  return false;
675               decoded += codePointToUTF8(unicode);
676            }
677            break;
678         default:
679            return addError( "Bad escape sequence in string", token, current );
680         }
681      }
682      else
683      {
684         decoded += c;
685      }
686   }
687   return true;
688}
689
690bool
691Reader::decodeUnicodeCodePoint( Token &token,
692                                     Location &current,
693                                     Location end,
694                                     unsigned int &unicode )
695{
696
697   if ( !decodeUnicodeEscapeSequence( token, current, end, unicode ) )
698      return false;
699   if (unicode >= 0xD800 && unicode <= 0xDBFF)
700   {
701      // surrogate pairs
702      if (end - current < 6)
703         return addError( "additional six characters expected to parse unicode surrogate pair.", token, current );
704      unsigned int surrogatePair;
705      if (*(current++) == '\\' && *(current++)== 'u')
706      {
707         if (decodeUnicodeEscapeSequence( token, current, end, surrogatePair ))
708         {
709            unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
710         }
711         else
712            return false;
713      }
714      else
715         return addError( "expecting another \\u token to begin the second half of a unicode surrogate pair", token, current );
716   }
717   return true;
718}
719
720bool
721Reader::decodeUnicodeEscapeSequence( Token &token,
722                                     Location &current,
723                                     Location end,
724                                     unsigned int &unicode )
725{
726   if ( end - current < 4 )
727      return addError( "Bad unicode escape sequence in string: four digits expected.", token, current );
728   unicode = 0;
729   for ( int index =0; index < 4; ++index )
730   {
731      Char c = *current++;
732      unicode *= 16;
733      if ( c >= '0'  &&  c <= '9' )
734         unicode += c - '0';
735      else if ( c >= 'a'  &&  c <= 'f' )
736         unicode += c - 'a' + 10;
737      else if ( c >= 'A'  &&  c <= 'F' )
738         unicode += c - 'A' + 10;
739      else
740         return addError( "Bad unicode escape sequence in string: hexadecimal digit expected.", token, current );
741   }
742   return true;
743}
744
745
746bool
747Reader::addError( const std::string &message,
748                  Token &token,
749                  Location extra )
750{
751   ErrorInfo info;
752   info.token_ = token;
753   info.message_ = message;
754   info.extra_ = extra;
755   errors_.push_back( info );
756   return false;
757}
758
759
760bool
761Reader::recoverFromError( TokenType skipUntilToken )
762{
763   int errorCount = int(errors_.size());
764   Token skip;
765   for (;;)
766   {
767      if ( !readToken(skip) )
768         errors_.resize( errorCount ); // discard errors caused by recovery
769      if ( skip.type_ == skipUntilToken  ||  skip.type_ == tokenEndOfStream )
770         break;
771   }
772   errors_.resize( errorCount );
773   return false;
774}
775
776
777bool
778Reader::addErrorAndRecover( const std::string &message,
779                            Token &token,
780                            TokenType skipUntilToken )
781{
782   addError( message, token );
783   return recoverFromError( skipUntilToken );
784}
785
786
787Value &
788Reader::currentValue()
789{
790   return *(nodes_.top());
791}
792
793
794Reader::Char
795Reader::getNextChar()
796{
797   if ( current_ == end_ )
798      return 0;
799   return *current_++;
800}
801
802
803void
804Reader::getLocationLineAndColumn( Location location,
805                                  int &line,
806                                  int &column ) const
807{
808   Location current = begin_;
809   Location lastLineStart = current;
810   line = 0;
811   while ( current < location  &&  current != end_ )
812   {
813      Char c = *current++;
814      if ( c == '\r' )
815      {
816         if ( *current == '\n' )
817            ++current;
818         lastLineStart = current;
819         ++line;
820      }
821      else if ( c == '\n' )
822      {
823         lastLineStart = current;
824         ++line;
825      }
826   }
827   // column & line start at 1
828   column = int(location - lastLineStart) + 1;
829   ++line;
830}
831
832
833std::string
834Reader::getLocationLineAndColumn( Location location ) const
835{
836   int line, column;
837   getLocationLineAndColumn( location, line, column );
838   char buffer[18+16+16+1];
839   sprintf( buffer, "Line %d, Column %d", line, column );
840   return buffer;
841}
842
843
844// Deprecated. Preserved for backward compatibility
845std::string
846Reader::getFormatedErrorMessages() const
847{
848    return getFormattedErrorMessages();
849}
850
851
852std::string
853Reader::getFormattedErrorMessages() const
854{
855   std::string formattedMessage;
856   for ( Errors::const_iterator itError = errors_.begin();
857         itError != errors_.end();
858         ++itError )
859   {
860      const ErrorInfo &error = *itError;
861      formattedMessage += "* " + getLocationLineAndColumn( error.token_.start_ ) + "\n";
862      formattedMessage += "  " + error.message_ + "\n";
863      if ( error.extra_ )
864         formattedMessage += "See " + getLocationLineAndColumn( error.extra_ ) + " for detail.\n";
865   }
866   return formattedMessage;
867}
868
869
870std::istream& operator>>( std::istream &sin, Value &root )
871{
872    Json::Reader reader;
873    bool ok = reader.parse(sin, root, true);
874    //JSON_ASSERT( ok );
875    if (!ok) throw std::runtime_error(reader.getFormattedErrorMessages());
876    return sin;
877}
878
879
880} // namespace Json
Property changes on: trunk/src/lib/web/json/json_reader.cpp
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/lib/web/json/autolink.h
r0r24796
1// Copyright 2007-2010 Baptiste Lepilleur
2// Distributed under MIT license, or public domain if desired and
3// recognized in your jurisdiction.
4// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
5
6#ifndef JSON_AUTOLINK_H_INCLUDED
7# define JSON_AUTOLINK_H_INCLUDED
8
9# include "config.h"
10
11# ifdef JSON_IN_CPPTL
12#  include <cpptl/cpptl_autolink.h>
13# endif
14
15# if !defined(JSON_NO_AUTOLINK)  &&  !defined(JSON_DLL_BUILD)  &&  !defined(JSON_IN_CPPTL)
16#  define CPPTL_AUTOLINK_NAME "json"
17#  undef CPPTL_AUTOLINK_DLL
18#  ifdef JSON_DLL
19#   define CPPTL_AUTOLINK_DLL
20#  endif
21#  include "autolink.h"
22# endif
23
24#endif // JSON_AUTOLINK_H_INCLUDED
Property changes on: trunk/src/lib/web/json/autolink.h
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/lib/web/json/forwards.h
r0r24796
1// Copyright 2007-2010 Baptiste Lepilleur
2// Distributed under MIT license, or public domain if desired and
3// recognized in your jurisdiction.
4// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
5
6#ifndef JSON_FORWARDS_H_INCLUDED
7# define JSON_FORWARDS_H_INCLUDED
8
9#if !defined(JSON_IS_AMALGAMATION)
10# include "config.h"
11#endif // if !defined(JSON_IS_AMALGAMATION)
12
13namespace Json {
14
15   // writer.h
16   class FastWriter;
17   class StyledWriter;
18
19   // reader.h
20   class Reader;
21
22   // features.h
23   class Features;
24
25   // value.h
26   typedef unsigned int ArrayIndex;
27   class StaticString;
28   class Path;
29   class PathArgument;
30   class Value;
31   class ValueIteratorBase;
32   class ValueIterator;
33   class ValueConstIterator;
34#ifdef JSON_VALUE_USE_INTERNAL_MAP
35   class ValueMapAllocator;
36   class ValueInternalLink;
37   class ValueInternalArray;
38   class ValueInternalMap;
39#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
40
41} // namespace Json
42
43
44#endif // JSON_FORWARDS_H_INCLUDED
Property changes on: trunk/src/lib/web/json/forwards.h
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/lib/web/json/json_internalmap.inl
r0r24796
1// Copyright 2007-2010 Baptiste Lepilleur
2// Distributed under MIT license, or public domain if desired and
3// recognized in your jurisdiction.
4// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
5
6// included by json_value.cpp
7
8namespace Json {
9
10// //////////////////////////////////////////////////////////////////
11// //////////////////////////////////////////////////////////////////
12// //////////////////////////////////////////////////////////////////
13// class ValueInternalMap
14// //////////////////////////////////////////////////////////////////
15// //////////////////////////////////////////////////////////////////
16// //////////////////////////////////////////////////////////////////
17
18/** \internal MUST be safely initialized using memset( this, 0, sizeof(ValueInternalLink) );
19   * This optimization is used by the fast allocator.
20   */
21ValueInternalLink::ValueInternalLink()
22   : previous_( 0 )
23   , next_( 0 )
24{
25}
26
27ValueInternalLink::~ValueInternalLink()
28{
29   for ( int index =0; index < itemPerLink; ++index )
30   {
31      if ( !items_[index].isItemAvailable() )
32      {
33         if ( !items_[index].isMemberNameStatic() )
34            free( keys_[index] );
35      }
36      else
37         break;
38   }
39}
40
41
42
43ValueMapAllocator::~ValueMapAllocator()
44{
45}
46
47#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
48class DefaultValueMapAllocator : public ValueMapAllocator
49{
50public: // overridden from ValueMapAllocator
51   virtual ValueInternalMap *newMap()
52   {
53      return new ValueInternalMap();
54   }
55
56   virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
57   {
58      return new ValueInternalMap( other );
59   }
60
61   virtual void destructMap( ValueInternalMap *map )
62   {
63      delete map;
64   }
65
66   virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
67   {
68      return new ValueInternalLink[size];
69   }
70
71   virtual void releaseMapBuckets( ValueInternalLink *links )
72   {
73      delete [] links;
74   }
75
76   virtual ValueInternalLink *allocateMapLink()
77   {
78      return new ValueInternalLink();
79   }
80
81   virtual void releaseMapLink( ValueInternalLink *link )
82   {
83      delete link;
84   }
85};
86#else
87/// @todo make this thread-safe (lock when accessign batch allocator)
88class DefaultValueMapAllocator : public ValueMapAllocator
89{
90public: // overridden from ValueMapAllocator
91   virtual ValueInternalMap *newMap()
92   {
93      ValueInternalMap *map = mapsAllocator_.allocate();
94      new (map) ValueInternalMap(); // placement new
95      return map;
96   }
97
98   virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
99   {
100      ValueInternalMap *map = mapsAllocator_.allocate();
101      new (map) ValueInternalMap( other ); // placement new
102      return map;
103   }
104
105   virtual void destructMap( ValueInternalMap *map )
106   {
107      if ( map )
108      {
109         map->~ValueInternalMap();
110         mapsAllocator_.release( map );
111      }
112   }
113
114   virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
115   {
116      return new ValueInternalLink[size];
117   }
118
119   virtual void releaseMapBuckets( ValueInternalLink *links )
120   {
121      delete [] links;
122   }
123
124   virtual ValueInternalLink *allocateMapLink()
125   {
126      ValueInternalLink *link = linksAllocator_.allocate();
127      memset( link, 0, sizeof(ValueInternalLink) );
128      return link;
129   }
130
131   virtual void releaseMapLink( ValueInternalLink *link )
132   {
133      link->~ValueInternalLink();
134      linksAllocator_.release( link );
135   }
136private:
137   BatchAllocator<ValueInternalMap,1> mapsAllocator_;
138   BatchAllocator<ValueInternalLink,1> linksAllocator_;
139};
140#endif
141
142static ValueMapAllocator *&mapAllocator()
143{
144   static DefaultValueMapAllocator defaultAllocator;
145   static ValueMapAllocator *mapAllocator = &defaultAllocator;
146   return mapAllocator;
147}
148
149static struct DummyMapAllocatorInitializer {
150   DummyMapAllocatorInitializer()
151   {
152      mapAllocator();      // ensure mapAllocator() statics are initialized before main().
153   }
154} dummyMapAllocatorInitializer;
155
156
157
158// h(K) = value * K >> w ; with w = 32 & K prime w.r.t. 2^32.
159
160/*
161use linked list hash map.
162buckets array is a container.
163linked list element contains 6 key/values. (memory = (16+4) * 6 + 4 = 124)
164value have extra state: valid, available, deleted
165*/
166
167
168ValueInternalMap::ValueInternalMap()
169   : buckets_( 0 )
170   , tailLink_( 0 )
171   , bucketsSize_( 0 )
172   , itemCount_( 0 )
173{
174}
175
176
177ValueInternalMap::ValueInternalMap( const ValueInternalMap &other )
178   : buckets_( 0 )
179   , tailLink_( 0 )
180   , bucketsSize_( 0 )
181   , itemCount_( 0 )
182{
183   reserve( other.itemCount_ );
184   IteratorState it;
185   IteratorState itEnd;
186   other.makeBeginIterator( it );
187   other.makeEndIterator( itEnd );
188   for ( ; !equals(it,itEnd); increment(it) )
189   {
190      bool isStatic;
191      const char *memberName = key( it, isStatic );
192      const Value &aValue = value( it );
193      resolveReference(memberName, isStatic) = aValue;
194   }
195}
196
197
198ValueInternalMap &
199ValueInternalMap::operator =( const ValueInternalMap &other )
200{
201   ValueInternalMap dummy( other );
202   swap( dummy );
203   return *this;
204}
205
206
207ValueInternalMap::~ValueInternalMap()
208{
209   if ( buckets_ )
210   {
211      for ( BucketIndex bucketIndex =0; bucketIndex < bucketsSize_; ++bucketIndex )
212      {
213         ValueInternalLink *link = buckets_[bucketIndex].next_;
214         while ( link )
215         {
216            ValueInternalLink *linkToRelease = link;
217            link = link->next_;
218            mapAllocator()->releaseMapLink( linkToRelease );
219         }
220      }
221      mapAllocator()->releaseMapBuckets( buckets_ );
222   }
223}
224
225
226void
227ValueInternalMap::swap( ValueInternalMap &other )
228{
229   ValueInternalLink *tempBuckets = buckets_;
230   buckets_ = other.buckets_;
231   other.buckets_ = tempBuckets;
232   ValueInternalLink *tempTailLink = tailLink_;
233   tailLink_ = other.tailLink_;
234   other.tailLink_ = tempTailLink;
235   BucketIndex tempBucketsSize = bucketsSize_;
236   bucketsSize_ = other.bucketsSize_;
237   other.bucketsSize_ = tempBucketsSize;
238   BucketIndex tempItemCount = itemCount_;
239   itemCount_ = other.itemCount_;
240   other.itemCount_ = tempItemCount;
241}
242
243
244void
245ValueInternalMap::clear()
246{
247   ValueInternalMap dummy;
248   swap( dummy );
249}
250
251
252ValueInternalMap::BucketIndex
253ValueInternalMap::size() const
254{
255   return itemCount_;
256}
257
258bool
259ValueInternalMap::reserveDelta( BucketIndex growth )
260{
261   return reserve( itemCount_ + growth );
262}
263
264bool
265ValueInternalMap::reserve( BucketIndex newItemCount )
266{
267   if ( !buckets_  &&  newItemCount > 0 )
268   {
269      buckets_ = mapAllocator()->allocateMapBuckets( 1 );
270      bucketsSize_ = 1;
271      tailLink_ = &buckets_[0];
272   }
273//   BucketIndex idealBucketCount = (newItemCount + ValueInternalLink::itemPerLink) / ValueInternalLink::itemPerLink;
274   return true;
275}
276
277
278const Value *
279ValueInternalMap::find( const char *key ) const
280{
281   if ( !bucketsSize_ )
282      return 0;
283   HashKey hashedKey = hash( key );
284   BucketIndex bucketIndex = hashedKey % bucketsSize_;
285   for ( const ValueInternalLink *current = &buckets_[bucketIndex];
286         current != 0;
287         current = current->next_ )
288   {
289      for ( BucketIndex index=0; index < ValueInternalLink::itemPerLink; ++index )
290      {
291         if ( current->items_[index].isItemAvailable() )
292            return 0;
293         if ( strcmp( key, current->keys_[index] ) == 0 )
294            return &current->items_[index];
295      }
296   }
297   return 0;
298}
299
300
301Value *
302ValueInternalMap::find( const char *key )
303{
304   const ValueInternalMap *constThis = this;
305   return const_cast<Value *>( constThis->find( key ) );
306}
307
308
309Value &
310ValueInternalMap::resolveReference( const char *key,
311                                    bool isStatic )
312{
313   HashKey hashedKey = hash( key );
314   if ( bucketsSize_ )
315   {
316      BucketIndex bucketIndex = hashedKey % bucketsSize_;
317      ValueInternalLink **previous = 0;
318      BucketIndex index;
319      for ( ValueInternalLink *current = &buckets_[bucketIndex];
320            current != 0;
321            previous = &current->next_, current = current->next_ )
322      {
323         for ( index=0; index < ValueInternalLink::itemPerLink; ++index )
324         {
325            if ( current->items_[index].isItemAvailable() )
326               return setNewItem( key, isStatic, current, index );
327            if ( strcmp( key, current->keys_[index] ) == 0 )
328               return current->items_[index];
329         }
330      }
331   }
332
333   reserveDelta( 1 );
334   return unsafeAdd( key, isStatic, hashedKey );
335}
336
337
338void
339ValueInternalMap::remove( const char *key )
340{
341   HashKey hashedKey = hash( key );
342   if ( !bucketsSize_ )
343      return;
344   BucketIndex bucketIndex = hashedKey % bucketsSize_;
345   for ( ValueInternalLink *link = &buckets_[bucketIndex];
346         link != 0;
347         link = link->next_ )
348   {
349      BucketIndex index;
350      for ( index =0; index < ValueInternalLink::itemPerLink; ++index )
351      {
352         if ( link->items_[index].isItemAvailable() )
353            return;
354         if ( strcmp( key, link->keys_[index] ) == 0 )
355         {
356            doActualRemove( link, index, bucketIndex );
357            return;
358         }
359      }
360   }
361}
362
363void
364ValueInternalMap::doActualRemove( ValueInternalLink *link,
365                                  BucketIndex index,
366                                  BucketIndex bucketIndex )
367{
368   // find last item of the bucket and swap it with the 'removed' one.
369   // set removed items flags to 'available'.
370   // if last page only contains 'available' items, then desallocate it (it's empty)
371   ValueInternalLink *&lastLink = getLastLinkInBucket( index );
372   BucketIndex lastItemIndex = 1; // a link can never be empty, so start at 1
373   for ( ;   
374         lastItemIndex < ValueInternalLink::itemPerLink;
375         ++lastItemIndex ) // may be optimized with dicotomic search
376   {
377      if ( lastLink->items_[lastItemIndex].isItemAvailable() )
378         break;
379   }
380   
381   BucketIndex lastUsedIndex = lastItemIndex - 1;
382   Value *valueToDelete = &link->items_[index];
383   Value *valueToPreserve = &lastLink->items_[lastUsedIndex];
384   if ( valueToDelete != valueToPreserve )
385      valueToDelete->swap( *valueToPreserve );
386   if ( lastUsedIndex == 0 )  // page is now empty
387   {  // remove it from bucket linked list and delete it.
388      ValueInternalLink *linkPreviousToLast = lastLink->previous_;
389      if ( linkPreviousToLast != 0 )   // can not deleted bucket link.
390      {
391         mapAllocator()->releaseMapLink( lastLink );
392         linkPreviousToLast->next_ = 0;
393         lastLink = linkPreviousToLast;
394      }
395   }
396   else
397   {
398      Value dummy;
399      valueToPreserve->swap( dummy ); // restore deleted to default Value.
400      valueToPreserve->setItemUsed( false );
401   }
402   --itemCount_;
403}
404
405
406ValueInternalLink *&
407ValueInternalMap::getLastLinkInBucket( BucketIndex bucketIndex )
408{
409   if ( bucketIndex == bucketsSize_ - 1 )
410      return tailLink_;
411   ValueInternalLink *&previous = buckets_[bucketIndex+1].previous_;
412   if ( !previous )
413      previous = &buckets_[bucketIndex];
414   return previous;
415}
416
417
418Value &
419ValueInternalMap::setNewItem( const char *key,
420                              bool isStatic,
421                              ValueInternalLink *link,
422                              BucketIndex index )
423{
424   char *duplicatedKey = makeMemberName( key );
425   ++itemCount_;
426   link->keys_[index] = duplicatedKey;
427   link->items_[index].setItemUsed();
428   link->items_[index].setMemberNameIsStatic( isStatic );
429   return link->items_[index]; // items already default constructed.
430}
431
432
433Value &
434ValueInternalMap::unsafeAdd( const char *key,
435                             bool isStatic,
436                             HashKey hashedKey )
437{
438   JSON_ASSERT_MESSAGE( bucketsSize_ > 0, "ValueInternalMap::unsafeAdd(): internal logic error." );
439   BucketIndex bucketIndex = hashedKey % bucketsSize_;
440   ValueInternalLink *&previousLink = getLastLinkInBucket( bucketIndex );
441   ValueInternalLink *link = previousLink;
442   BucketIndex index;
443   for ( index =0; index < ValueInternalLink::itemPerLink; ++index )
444   {
445      if ( link->items_[index].isItemAvailable() )
446         break;
447   }
448   if ( index == ValueInternalLink::itemPerLink ) // need to add a new page
449   {
450      ValueInternalLink *newLink = mapAllocator()->allocateMapLink();
451      index = 0;
452      link->next_ = newLink;
453      previousLink = newLink;
454      link = newLink;
455   }
456   return setNewItem( key, isStatic, link, index );
457}
458
459
460ValueInternalMap::HashKey
461ValueInternalMap::hash( const char *key ) const
462{
463   HashKey hash = 0;
464   while ( *key )
465      hash += *key++ * 37;
466   return hash;
467}
468
469
470int
471ValueInternalMap::compare( const ValueInternalMap &other ) const
472{
473   int sizeDiff( itemCount_ - other.itemCount_ );
474   if ( sizeDiff != 0 )
475      return sizeDiff;
476   // Strict order guaranty is required. Compare all keys FIRST, then compare values.
477   IteratorState it;
478   IteratorState itEnd;
479   makeBeginIterator( it );
480   makeEndIterator( itEnd );
481   for ( ; !equals(it,itEnd); increment(it) )
482   {
483      if ( !other.find( key( it ) ) )
484         return 1;
485   }
486
487   // All keys are equals, let's compare values
488   makeBeginIterator( it );
489   for ( ; !equals(it,itEnd); increment(it) )
490   {
491      const Value *otherValue = other.find( key( it ) );
492      int valueDiff = value(it).compare( *otherValue );
493      if ( valueDiff != 0 )
494         return valueDiff;
495   }
496   return 0;
497}
498
499
500void
501ValueInternalMap::makeBeginIterator( IteratorState &it ) const
502{
503   it.map_ = const_cast<ValueInternalMap *>( this );
504   it.bucketIndex_ = 0;
505   it.itemIndex_ = 0;
506   it.link_ = buckets_;
507}
508
509
510void
511ValueInternalMap::makeEndIterator( IteratorState &it ) const
512{
513   it.map_ = const_cast<ValueInternalMap *>( this );
514   it.bucketIndex_ = bucketsSize_;
515   it.itemIndex_ = 0;
516   it.link_ = 0;
517}
518
519
520bool
521ValueInternalMap::equals( const IteratorState &x, const IteratorState &other )
522{
523   return x.map_ == other.map_ 
524          &&  x.bucketIndex_ == other.bucketIndex_ 
525          &&  x.link_ == other.link_
526          &&  x.itemIndex_ == other.itemIndex_;
527}
528
529
530void
531ValueInternalMap::incrementBucket( IteratorState &iterator )
532{
533   ++iterator.bucketIndex_;
534   JSON_ASSERT_MESSAGE( iterator.bucketIndex_ <= iterator.map_->bucketsSize_,
535      "ValueInternalMap::increment(): attempting to iterate beyond end." );
536   if ( iterator.bucketIndex_ == iterator.map_->bucketsSize_ )
537      iterator.link_ = 0;
538   else
539      iterator.link_ = &(iterator.map_->buckets_[iterator.bucketIndex_]);
540   iterator.itemIndex_ = 0;
541}
542
543
544void
545ValueInternalMap::increment( IteratorState &iterator )
546{
547   JSON_ASSERT_MESSAGE( iterator.map_, "Attempting to iterator using invalid iterator." );
548   ++iterator.itemIndex_;
549   if ( iterator.itemIndex_ == ValueInternalLink::itemPerLink )
550   {
551      JSON_ASSERT_MESSAGE( iterator.link_ != 0,
552         "ValueInternalMap::increment(): attempting to iterate beyond end." );
553      iterator.link_ = iterator.link_->next_;
554      if ( iterator.link_ == 0 )
555         incrementBucket( iterator );
556   }
557   else if ( iterator.link_->items_[iterator.itemIndex_].isItemAvailable() )
558   {
559      incrementBucket( iterator );
560   }
561}
562
563
564void
565ValueInternalMap::decrement( IteratorState &iterator )
566{
567   if ( iterator.itemIndex_ == 0 )
568   {
569      JSON_ASSERT_MESSAGE( iterator.map_, "Attempting to iterate using invalid iterator." );
570      if ( iterator.link_ == &iterator.map_->buckets_[iterator.bucketIndex_] )
571      {
572         JSON_ASSERT_MESSAGE( iterator.bucketIndex_ > 0, "Attempting to iterate beyond beginning." );
573         --(iterator.bucketIndex_);
574      }
575      iterator.link_ = iterator.link_->previous_;
576      iterator.itemIndex_ = ValueInternalLink::itemPerLink - 1;
577   }
578}
579
580
581const char *
582ValueInternalMap::key( const IteratorState &iterator )
583{
584   JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
585   return iterator.link_->keys_[iterator.itemIndex_];
586}
587
588const char *
589ValueInternalMap::key( const IteratorState &iterator, bool &isStatic )
590{
591   JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
592   isStatic = iterator.link_->items_[iterator.itemIndex_].isMemberNameStatic();
593   return iterator.link_->keys_[iterator.itemIndex_];
594}
595
596
597Value &
598ValueInternalMap::value( const IteratorState &iterator )
599{
600   JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
601   return iterator.link_->items_[iterator.itemIndex_];
602}
603
604
605int
606ValueInternalMap::distance( const IteratorState &x, const IteratorState &y )
607{
608   int offset = 0;
609   IteratorState it = x;
610   while ( !equals( it, y ) )
611      increment( it );
612   return offset;
613}
614
615} // namespace Json
Property changes on: trunk/src/lib/web/json/json_internalmap.inl
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/lib/web/json/json_internalarray.inl
r0r24796
1// Copyright 2007-2010 Baptiste Lepilleur
2// Distributed under MIT license, or public domain if desired and
3// recognized in your jurisdiction.
4// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
5
6// included by json_value.cpp
7
8namespace Json {
9
10// //////////////////////////////////////////////////////////////////
11// //////////////////////////////////////////////////////////////////
12// //////////////////////////////////////////////////////////////////
13// class ValueInternalArray
14// //////////////////////////////////////////////////////////////////
15// //////////////////////////////////////////////////////////////////
16// //////////////////////////////////////////////////////////////////
17
18ValueArrayAllocator::~ValueArrayAllocator()
19{
20}
21
22// //////////////////////////////////////////////////////////////////
23// class DefaultValueArrayAllocator
24// //////////////////////////////////////////////////////////////////
25#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
26class DefaultValueArrayAllocator : public ValueArrayAllocator
27{
28public: // overridden from ValueArrayAllocator
29   virtual ~DefaultValueArrayAllocator()
30   {
31   }
32
33   virtual ValueInternalArray *newArray()
34   {
35      return new ValueInternalArray();
36   }
37
38   virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
39   {
40      return new ValueInternalArray( other );
41   }
42
43   virtual void destructArray( ValueInternalArray *array )
44   {
45      delete array;
46   }
47
48   virtual void reallocateArrayPageIndex( Value **&indexes,
49                                          ValueInternalArray::PageIndex &indexCount,
50                                          ValueInternalArray::PageIndex minNewIndexCount )
51   {
52      ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
53      if ( minNewIndexCount > newIndexCount )
54         newIndexCount = minNewIndexCount;
55      void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
56      if ( !newIndexes )
57         throw std::bad_alloc();
58      indexCount = newIndexCount;
59      indexes = static_cast<Value **>( newIndexes );
60   }
61   virtual void releaseArrayPageIndex( Value **indexes,
62                                       ValueInternalArray::PageIndex indexCount )
63   {
64      if ( indexes )
65         free( indexes );
66   }
67
68   virtual Value *allocateArrayPage()
69   {
70      return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) );
71   }
72
73   virtual void releaseArrayPage( Value *value )
74   {
75      if ( value )
76         free( value );
77   }
78};
79
80#else // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
81/// @todo make this thread-safe (lock when accessign batch allocator)
82class DefaultValueArrayAllocator : public ValueArrayAllocator
83{
84public: // overridden from ValueArrayAllocator
85   virtual ~DefaultValueArrayAllocator()
86   {
87   }
88
89   virtual ValueInternalArray *newArray()
90   {
91      ValueInternalArray *array = arraysAllocator_.allocate();
92      new (array) ValueInternalArray(); // placement new
93      return array;
94   }
95
96   virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
97   {
98      ValueInternalArray *array = arraysAllocator_.allocate();
99      new (array) ValueInternalArray( other ); // placement new
100      return array;
101   }
102
103   virtual void destructArray( ValueInternalArray *array )
104   {
105      if ( array )
106      {
107         array->~ValueInternalArray();
108         arraysAllocator_.release( array );
109      }
110   }
111
112   virtual void reallocateArrayPageIndex( Value **&indexes,
113                                          ValueInternalArray::PageIndex &indexCount,
114                                          ValueInternalArray::PageIndex minNewIndexCount )
115   {
116      ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
117      if ( minNewIndexCount > newIndexCount )
118         newIndexCount = minNewIndexCount;
119      void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
120      if ( !newIndexes )
121         throw std::bad_alloc();
122      indexCount = newIndexCount;
123      indexes = static_cast<Value **>( newIndexes );
124   }
125   virtual void releaseArrayPageIndex( Value **indexes,
126                                       ValueInternalArray::PageIndex indexCount )
127   {
128      if ( indexes )
129         free( indexes );
130   }
131
132   virtual Value *allocateArrayPage()
133   {
134      return static_cast<Value *>( pagesAllocator_.allocate() );
135   }
136
137   virtual void releaseArrayPage( Value *value )
138   {
139      if ( value )
140         pagesAllocator_.release( value );
141   }
142private:
143   BatchAllocator<ValueInternalArray,1> arraysAllocator_;
144   BatchAllocator<Value,ValueInternalArray::itemsPerPage> pagesAllocator_;
145};
146#endif // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
147
148static ValueArrayAllocator *&arrayAllocator()
149{
150   static DefaultValueArrayAllocator defaultAllocator;
151   static ValueArrayAllocator *arrayAllocator = &defaultAllocator;
152   return arrayAllocator;
153}
154
155static struct DummyArrayAllocatorInitializer {
156   DummyArrayAllocatorInitializer()
157   {
158      arrayAllocator();      // ensure arrayAllocator() statics are initialized before main().
159   }
160} dummyArrayAllocatorInitializer;
161
162// //////////////////////////////////////////////////////////////////
163// class ValueInternalArray
164// //////////////////////////////////////////////////////////////////
165bool
166ValueInternalArray::equals( const IteratorState &x,
167                            const IteratorState &other )
168{
169   return x.array_ == other.array_ 
170          &&  x.currentItemIndex_ == other.currentItemIndex_ 
171          &&  x.currentPageIndex_ == other.currentPageIndex_;
172}
173
174
175void
176ValueInternalArray::increment( IteratorState &it )
177{
178   JSON_ASSERT_MESSAGE( it.array_  &&
179      (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
180      != it.array_->size_,
181      "ValueInternalArray::increment(): moving iterator beyond end" );
182   ++(it.currentItemIndex_);
183   if ( it.currentItemIndex_ == itemsPerPage )
184   {
185      it.currentItemIndex_ = 0;
186      ++(it.currentPageIndex_);
187   }
188}
189
190
191void
192ValueInternalArray::decrement( IteratorState &it )
193{
194   JSON_ASSERT_MESSAGE( it.array_  &&  it.currentPageIndex_ == it.array_->pages_
195                        &&  it.currentItemIndex_ == 0,
196      "ValueInternalArray::decrement(): moving iterator beyond end" );
197   if ( it.currentItemIndex_ == 0 )
198   {
199      it.currentItemIndex_ = itemsPerPage-1;
200      --(it.currentPageIndex_);
201   }
202   else
203   {
204      --(it.currentItemIndex_);
205   }
206}
207
208
209Value &
210ValueInternalArray::unsafeDereference( const IteratorState &it )
211{
212   return (*(it.currentPageIndex_))[it.currentItemIndex_];
213}
214
215
216Value &
217ValueInternalArray::dereference( const IteratorState &it )
218{
219   JSON_ASSERT_MESSAGE( it.array_  &&
220      (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
221      < it.array_->size_,
222      "ValueInternalArray::dereference(): dereferencing invalid iterator" );
223   return unsafeDereference( it );
224}
225
226void
227ValueInternalArray::makeBeginIterator( IteratorState &it ) const
228{
229   it.array_ = const_cast<ValueInternalArray *>( this );
230   it.currentItemIndex_ = 0;
231   it.currentPageIndex_ = pages_;
232}
233
234
235void
236ValueInternalArray::makeIterator( IteratorState &it, ArrayIndex index ) const
237{
238   it.array_ = const_cast<ValueInternalArray *>( this );
239   it.currentItemIndex_ = index % itemsPerPage;
240   it.currentPageIndex_ = pages_ + index / itemsPerPage;
241}
242
243
244void
245ValueInternalArray::makeEndIterator( IteratorState &it ) const
246{
247   makeIterator( it, size_ );
248}
249
250
251ValueInternalArray::ValueInternalArray()
252   : pages_( 0 )
253   , size_( 0 )
254   , pageCount_( 0 )
255{
256}
257
258
259ValueInternalArray::ValueInternalArray( const ValueInternalArray &other )
260   : pages_( 0 )
261   , pageCount_( 0 )
262   , size_( other.size_ )
263{
264   PageIndex minNewPages = other.size_ / itemsPerPage;
265   arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
266   JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages,
267                        "ValueInternalArray::reserve(): bad reallocation" );
268   IteratorState itOther;
269   other.makeBeginIterator( itOther );
270   Value *value;
271   for ( ArrayIndex index = 0; index < size_; ++index, increment(itOther) )
272   {
273      if ( index % itemsPerPage == 0 )
274      {
275         PageIndex pageIndex = index / itemsPerPage;
276         value = arrayAllocator()->allocateArrayPage();
277         pages_[pageIndex] = value;
278      }
279      new (value) Value( dereference( itOther ) );
280   }
281}
282
283
284ValueInternalArray &
285ValueInternalArray::operator =( const ValueInternalArray &other )
286{
287   ValueInternalArray temp( other );
288   swap( temp );
289   return *this;
290}
291
292
293ValueInternalArray::~ValueInternalArray()
294{
295   // destroy all constructed items
296   IteratorState it;
297   IteratorState itEnd;
298   makeBeginIterator( it);
299   makeEndIterator( itEnd );
300   for ( ; !equals(it,itEnd); increment(it) )
301   {
302      Value *value = &dereference(it);
303      value->~Value();
304   }
305   // release all pages
306   PageIndex lastPageIndex = size_ / itemsPerPage;
307   for ( PageIndex pageIndex = 0; pageIndex < lastPageIndex; ++pageIndex )
308      arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
309   // release pages index
310   arrayAllocator()->releaseArrayPageIndex( pages_, pageCount_ );
311}
312
313
314void
315ValueInternalArray::swap( ValueInternalArray &other )
316{
317   Value **tempPages = pages_;
318   pages_ = other.pages_;
319   other.pages_ = tempPages;
320   ArrayIndex tempSize = size_;
321   size_ = other.size_;
322   other.size_ = tempSize;
323   PageIndex tempPageCount = pageCount_;
324   pageCount_ = other.pageCount_;
325   other.pageCount_ = tempPageCount;
326}
327
328void
329ValueInternalArray::clear()
330{
331   ValueInternalArray dummy;
332   swap( dummy );
333}
334
335
336void
337ValueInternalArray::resize( ArrayIndex newSize )
338{
339   if ( newSize == 0 )
340      clear();
341   else if ( newSize < size_ )
342   {
343      IteratorState it;
344      IteratorState itEnd;
345      makeIterator( it, newSize );
346      makeIterator( itEnd, size_ );
347      for ( ; !equals(it,itEnd); increment(it) )
348      {
349         Value *value = &dereference(it);
350         value->~Value();
351      }
352      PageIndex pageIndex = (newSize + itemsPerPage - 1) / itemsPerPage;
353      PageIndex lastPageIndex = size_ / itemsPerPage;
354      for ( ; pageIndex < lastPageIndex; ++pageIndex )
355         arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
356      size_ = newSize;
357   }
358   else if ( newSize > size_ )
359      resolveReference( newSize );
360}
361
362
363void
364ValueInternalArray::makeIndexValid( ArrayIndex index )
365{
366   // Need to enlarge page index ?
367   if ( index >= pageCount_ * itemsPerPage )
368   {
369      PageIndex minNewPages = (index + 1) / itemsPerPage;
370      arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
371      JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages, "ValueInternalArray::reserve(): bad reallocation" );
372   }
373
374   // Need to allocate new pages ?
375   ArrayIndex nextPageIndex =
376      (size_ % itemsPerPage) != 0 ? size_ - (size_%itemsPerPage) + itemsPerPage
377                                  : size_;
378   if ( nextPageIndex <= index )
379   {
380      PageIndex pageIndex = nextPageIndex / itemsPerPage;
381      PageIndex pageToAllocate = (index - nextPageIndex) / itemsPerPage + 1;
382      for ( ; pageToAllocate-- > 0; ++pageIndex )
383         pages_[pageIndex] = arrayAllocator()->allocateArrayPage();
384   }
385
386   // Initialize all new entries
387   IteratorState it;
388   IteratorState itEnd;
389   makeIterator( it, size_ );
390   size_ = index + 1;
391   makeIterator( itEnd, size_ );
392   for ( ; !equals(it,itEnd); increment(it) )
393   {
394      Value *value = &dereference(it);
395      new (value) Value(); // Construct a default value using placement new
396   }
397}
398
399Value &
400ValueInternalArray::resolveReference( ArrayIndex index )
401{
402   if ( index >= size_ )
403      makeIndexValid( index );
404   return pages_[index/itemsPerPage][index%itemsPerPage];
405}
406
407Value *
408ValueInternalArray::find( ArrayIndex index ) const
409{
410   if ( index >= size_ )
411      return 0;
412   return &(pages_[index/itemsPerPage][index%itemsPerPage]);
413}
414
415ValueInternalArray::ArrayIndex
416ValueInternalArray::size() const
417{
418   return size_;
419}
420
421int
422ValueInternalArray::distance( const IteratorState &x, const IteratorState &y )
423{
424   return indexOf(y) - indexOf(x);
425}
426
427
428ValueInternalArray::ArrayIndex
429ValueInternalArray::indexOf( const IteratorState &iterator )
430{
431   if ( !iterator.array_ )
432      return ArrayIndex(-1);
433   return ArrayIndex(
434      (iterator.currentPageIndex_ - iterator.array_->pages_) * itemsPerPage
435      + iterator.currentItemIndex_ );
436}
437
438
439int
440ValueInternalArray::compare( const ValueInternalArray &other ) const
441{
442   int sizeDiff( size_ - other.size_ );
443   if ( sizeDiff != 0 )
444      return sizeDiff;
445   
446   for ( ArrayIndex index =0; index < size_; ++index )
447   {
448      int diff = pages_[index/itemsPerPage][index%itemsPerPage].compare(
449         other.pages_[index/itemsPerPage][index%itemsPerPage] );
450      if ( diff != 0 )
451         return diff;
452   }
453   return 0;
454}
455
456} // namespace Json
Property changes on: trunk/src/lib/web/json/json_internalarray.inl
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/lib/web/json/json_writer.cpp
r0r24796
1// Copyright 2007-2010 Baptiste Lepilleur
2// Distributed under MIT license, or public domain if desired and
3// recognized in your jurisdiction.
4// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
5#include "emu.h"
6#if !defined(JSON_IS_AMALGAMATION)
7# include <json/writer.h>
8# include "json_tool.h"
9#endif // if !defined(JSON_IS_AMALGAMATION)
10#include <utility>
11#include <assert.h>
12#include <stdio.h>
13#include <string.h>
14#include <iostream>
15#include <sstream>
16#include <iomanip>
17
18#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
19#pragma warning( disable : 4996 )   // disable warning about strdup being deprecated.
20#endif
21
22namespace Json {
23
24static bool containsControlCharacter( const char* str )
25{
26   while ( *str )
27   {
28      if ( isControlCharacter( *(str++) ) )
29         return true;
30   }
31   return false;
32}
33
34
35std::string valueToString( LargestInt value )
36{
37   UIntToStringBuffer buffer;
38   char *current = buffer + sizeof(buffer);
39   bool isNegative = value < 0;
40   if ( isNegative )
41      value = -value;
42   uintToString( LargestUInt(value), current );
43   if ( isNegative )
44      *--current = '-';
45   assert( current >= buffer );
46   return current;
47}
48
49
50std::string valueToString( LargestUInt value )
51{
52   UIntToStringBuffer buffer;
53   char *current = buffer + sizeof(buffer);
54   uintToString( value, current );
55   assert( current >= buffer );
56   return current;
57}
58
59#if defined(JSON_HAS_INT64)
60
61std::string valueToString( Int value )
62{
63   return valueToString( LargestInt(value) );
64}
65
66
67std::string valueToString( UInt value )
68{
69   return valueToString( LargestUInt(value) );
70}
71
72#endif // # if defined(JSON_HAS_INT64)
73
74
75std::string valueToString( double value )
76{
77   char buffer[32];
78#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with visual studio 2005 to avoid warning.
79   sprintf_s(buffer, sizeof(buffer), "%#.16g", value);
80#else   
81   sprintf(buffer, "%#.16g", value);
82#endif
83   char* ch = buffer + strlen(buffer) - 1;
84   if (*ch != '0') return buffer; // nothing to truncate, so save time
85   while(ch > buffer && *ch == '0'){
86     --ch;
87   }
88   char* last_nonzero = ch;
89   while(ch >= buffer){
90     switch(*ch){
91     case '0':
92     case '1':
93     case '2':
94     case '3':
95     case '4':
96     case '5':
97     case '6':
98     case '7':
99     case '8':
100     case '9':
101       --ch;
102       continue;
103     case '.':
104       // Truncate zeroes to save bytes in output, but keep one.
105       *(last_nonzero+2) = '\0';
106       return buffer;
107     default:
108       return buffer;
109     }
110   }
111   return buffer;
112}
113
114
115std::string valueToString( bool value )
116{
117   return value ? "true" : "false";
118}
119
120std::string valueToQuotedString( const char *value )
121{
122   // Not sure how to handle unicode...
123   if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && !containsControlCharacter( value ))
124      return std::string("\"") + value + "\"";
125   // We have to walk value and escape any special characters.
126   // Appending to std::string is not efficient, but this should be rare.
127   // (Note: forward slashes are *not* rare, but I am not escaping them.)
128   std::string::size_type maxsize = strlen(value)*2 + 3; // allescaped+quotes+NULL
129   std::string result;
130   result.reserve(maxsize); // to avoid lots of mallocs
131   result += "\"";
132   for (const char* c=value; *c != 0; ++c)
133   {
134      switch(*c)
135      {
136         case '\"':
137            result += "\\\"";
138            break;
139         case '\\':
140            result += "\\\\";
141            break;
142         case '\b':
143            result += "\\b";
144            break;
145         case '\f':
146            result += "\\f";
147            break;
148         case '\n':
149            result += "\\n";
150            break;
151         case '\r':
152            result += "\\r";
153            break;
154         case '\t':
155            result += "\\t";
156            break;
157         //case '/':
158            // Even though \/ is considered a legal escape in JSON, a bare
159            // slash is also legal, so I see no reason to escape it.
160            // (I hope I am not misunderstanding something.
161            // blep notes: actually escaping \/ may be useful in javascript to avoid </
162            // sequence.
163            // Should add a flag to allow this compatibility mode and prevent this
164            // sequence from occurring.
165         default:
166            if ( isControlCharacter( *c ) )
167            {
168               std::ostringstream oss;
169               oss << "\\u" << std::hex << std::uppercase << std::setfill('0') << std::setw(4) << static_cast<int>(*c);
170               result += oss.str();
171            }
172            else
173            {
174               result += *c;
175            }
176            break;
177      }
178   }
179   result += "\"";
180   return result;
181}
182
183// Class Writer
184// //////////////////////////////////////////////////////////////////
185Writer::~Writer()
186{
187}
188
189
190// Class FastWriter
191// //////////////////////////////////////////////////////////////////
192
193FastWriter::FastWriter()
194   : yamlCompatiblityEnabled_( false )
195{
196}
197
198
199void
200FastWriter::enableYAMLCompatibility()
201{
202   yamlCompatiblityEnabled_ = true;
203}
204
205
206std::string
207FastWriter::write( const Value &root )
208{
209   document_ = "";
210   writeValue( root );
211   document_ += "\n";
212   return document_;
213}
214
215
216void
217FastWriter::writeValue( const Value &value )
218{
219   switch ( value.type() )
220   {
221   case nullValue:
222      document_ += "null";
223      break;
224   case intValue:
225      document_ += valueToString( value.asLargestInt() );
226      break;
227   case uintValue:
228      document_ += valueToString( value.asLargestUInt() );
229      break;
230   case realValue:
231      document_ += valueToString( value.asDouble() );
232      break;
233   case stringValue:
234      document_ += valueToQuotedString( value.asCString() );
235      break;
236   case booleanValue:
237      document_ += valueToString( value.asBool() );
238      break;
239   case arrayValue:
240      {
241         document_ += "[";
242         int size = value.size();
243         for ( int index =0; index < size; ++index )
244         {
245            if ( index > 0 )
246               document_ += ",";
247            writeValue( value[index] );
248         }
249         document_ += "]";
250      }
251      break;
252   case objectValue:
253      {
254         Value::Members members( value.getMemberNames() );
255         document_ += "{";
256         for ( Value::Members::iterator it = members.begin();
257               it != members.end();
258               ++it )
259         {
260            const std::string &name = *it;
261            if ( it != members.begin() )
262               document_ += ",";
263            document_ += valueToQuotedString( name.c_str() );
264            document_ += yamlCompatiblityEnabled_ ? ": "
265                                                  : ":";
266            writeValue( value[name] );
267         }
268         document_ += "}";
269      }
270      break;
271   }
272}
273
274
275// Class StyledWriter
276// //////////////////////////////////////////////////////////////////
277
278StyledWriter::StyledWriter()
279   : rightMargin_( 74 )
280   , indentSize_( 3 )
281{
282}
283
284
285std::string
286StyledWriter::write( const Value &root )
287{
288   document_ = "";
289   addChildValues_ = false;
290   indentString_ = "";
291   writeCommentBeforeValue( root );
292   writeValue( root );
293   writeCommentAfterValueOnSameLine( root );
294   document_ += "\n";
295   return document_;
296}
297
298
299void
300StyledWriter::writeValue( const Value &value )
301{
302   switch ( value.type() )
303   {
304   case nullValue:
305      pushValue( "null" );
306      break;
307   case intValue:
308      pushValue( valueToString( value.asLargestInt() ) );
309      break;
310   case uintValue:
311      pushValue( valueToString( value.asLargestUInt() ) );
312      break;
313   case realValue:
314      pushValue( valueToString( value.asDouble() ) );
315      break;
316   case stringValue:
317      pushValue( valueToQuotedString( value.asCString() ) );
318      break;
319   case booleanValue:
320      pushValue( valueToString( value.asBool() ) );
321      break;
322   case arrayValue:
323      writeArrayValue( value);
324      break;
325   case objectValue:
326      {
327         Value::Members members( value.getMemberNames() );
328         if ( members.empty() )
329            pushValue( "{}" );
330         else
331         {
332            writeWithIndent( "{" );
333            indent();
334            Value::Members::iterator it = members.begin();
335            for (;;)
336            {
337               const std::string &name = *it;
338               const Value &childValue = value[name];
339               writeCommentBeforeValue( childValue );
340               writeWithIndent( valueToQuotedString( name.c_str() ) );
341               document_ += " : ";
342               writeValue( childValue );
343               if ( ++it == members.end() )
344               {
345                  writeCommentAfterValueOnSameLine( childValue );
346                  break;
347               }
348               document_ += ",";
349               writeCommentAfterValueOnSameLine( childValue );
350            }
351            unindent();
352            writeWithIndent( "}" );
353         }
354      }
355      break;
356   }
357}
358
359
360void
361StyledWriter::writeArrayValue( const Value &value )
362{
363   unsigned size = value.size();
364   if ( size == 0 )
365      pushValue( "[]" );
366   else
367   {
368      bool isArrayMultiLine = isMultineArray( value );
369      if ( isArrayMultiLine )
370      {
371         writeWithIndent( "[" );
372         indent();
373         bool hasChildValue = !childValues_.empty();
374         unsigned index =0;
375         for (;;)
376         {
377            const Value &childValue = value[index];
378            writeCommentBeforeValue( childValue );
379            if ( hasChildValue )
380               writeWithIndent( childValues_[index] );
381            else
382            {
383               writeIndent();
384               writeValue( childValue );
385            }
386            if ( ++index == size )
387            {
388               writeCommentAfterValueOnSameLine( childValue );
389               break;
390            }
391            document_ += ",";
392            writeCommentAfterValueOnSameLine( childValue );
393         }
394         unindent();
395         writeWithIndent( "]" );
396      }
397      else // output on a single line
398      {
399         assert( childValues_.size() == size );
400         document_ += "[ ";
401         for ( unsigned index =0; index < size; ++index )
402         {
403            if ( index > 0 )
404               document_ += ", ";
405            document_ += childValues_[index];
406         }
407         document_ += " ]";
408      }
409   }
410}
411
412
413bool
414StyledWriter::isMultineArray( const Value &value )
415{
416   int size = value.size();
417   bool isMultiLine = size*3 >= rightMargin_ ;
418   childValues_.clear();
419   for ( int index =0; index < size  &&  !isMultiLine; ++index )
420   {
421      const Value &childValue = value[index];
422      isMultiLine = isMultiLine  ||
423                     ( (childValue.isArray()  ||  childValue.isObject())  && 
424                        childValue.size() > 0 );
425   }
426   if ( !isMultiLine ) // check if line length > max line length
427   {
428      childValues_.reserve( size );
429      addChildValues_ = true;
430      int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]'
431      for ( int index =0; index < size  &&  !isMultiLine; ++index )
432      {
433         writeValue( value[index] );
434         lineLength += int( childValues_[index].length() );
435         isMultiLine = isMultiLine  &&  hasCommentForValue( value[index] );
436      }
437      addChildValues_ = false;
438      isMultiLine = isMultiLine  ||  lineLength >= rightMargin_;
439   }
440   return isMultiLine;
441}
442
443
444void
445StyledWriter::pushValue( const std::string &value )
446{
447   if ( addChildValues_ )
448      childValues_.push_back( value );
449   else
450      document_ += value;
451}
452
453
454void
455StyledWriter::writeIndent()
456{
457   if ( !document_.empty() )
458   {
459      char last = document_[document_.length()-1];
460      if ( last == ' ' )     // already indented
461         return;
462      if ( last != '\n' )    // Comments may add new-line
463         document_ += '\n';
464   }
465   document_ += indentString_;
466}
467
468
469void
470StyledWriter::writeWithIndent( const std::string &value )
471{
472   writeIndent();
473   document_ += value;
474}
475
476
477void
478StyledWriter::indent()
479{
480   indentString_ += std::string( indentSize_, ' ' );
481}
482
483
484void
485StyledWriter::unindent()
486{
487   assert( int(indentString_.size()) >= indentSize_ );
488   indentString_.resize( indentString_.size() - indentSize_ );
489}
490
491
492void
493StyledWriter::writeCommentBeforeValue( const Value &root )
494{
495   if ( !root.hasComment( commentBefore ) )
496      return;
497   document_ += normalizeEOL( root.getComment( commentBefore ) );
498   document_ += "\n";
499}
500
501
502void
503StyledWriter::writeCommentAfterValueOnSameLine( const Value &root )
504{
505   if ( root.hasComment( commentAfterOnSameLine ) )
506      document_ += " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) );
507
508   if ( root.hasComment( commentAfter ) )
509   {
510      document_ += "\n";
511      document_ += normalizeEOL( root.getComment( commentAfter ) );
512      document_ += "\n";
513   }
514}
515
516
517bool
518StyledWriter::hasCommentForValue( const Value &value )
519{
520   return value.hasComment( commentBefore )
521          ||  value.hasComment( commentAfterOnSameLine )
522          ||  value.hasComment( commentAfter );
523}
524
525
526std::string
527StyledWriter::normalizeEOL( const std::string &text )
528{
529   std::string normalized;
530   normalized.reserve( text.length() );
531   const char *begin = text.c_str();
532   const char *end = begin + text.length();
533   const char *current = begin;
534   while ( current != end )
535   {
536      char c = *current++;
537      if ( c == '\r' ) // mac or dos EOL
538      {
539         if ( *current == '\n' ) // convert dos EOL
540            ++current;
541         normalized += '\n';
542      }
543      else // handle unix EOL & other char
544         normalized += c;
545   }
546   return normalized;
547}
548
549
550// Class StyledStreamWriter
551// //////////////////////////////////////////////////////////////////
552
553StyledStreamWriter::StyledStreamWriter( std::string indentation )
554   : document_(NULL)
555   , rightMargin_( 74 )
556   , indentation_( indentation )
557{
558}
559
560
561void
562StyledStreamWriter::write( std::ostream &out, const Value &root )
563{
564   document_ = &out;
565   addChildValues_ = false;
566   indentString_ = "";
567   writeCommentBeforeValue( root );
568   writeValue( root );
569   writeCommentAfterValueOnSameLine( root );
570   *document_ << "\n";
571   document_ = NULL; // Forget the stream, for safety.
572}
573
574
575void
576StyledStreamWriter::writeValue( const Value &value )
577{
578   switch ( value.type() )
579   {
580   case nullValue:
581      pushValue( "null" );
582      break;
583   case intValue:
584      pushValue( valueToString( value.asLargestInt() ) );
585      break;
586   case uintValue:
587      pushValue( valueToString( value.asLargestUInt() ) );
588      break;
589   case realValue:
590      pushValue( valueToString( value.asDouble() ) );
591      break;
592   case stringValue:
593      pushValue( valueToQuotedString( value.asCString() ) );
594      break;
595   case booleanValue:
596      pushValue( valueToString( value.asBool() ) );
597      break;
598   case arrayValue:
599      writeArrayValue( value);
600      break;
601   case objectValue:
602      {
603         Value::Members members( value.getMemberNames() );
604         if ( members.empty() )
605            pushValue( "{}" );
606         else
607         {
608            writeWithIndent( "{" );
609            indent();
610            Value::Members::iterator it = members.begin();
611            for (;;)
612            {
613               const std::string &name = *it;
614               const Value &childValue = value[name];
615               writeCommentBeforeValue( childValue );
616               writeWithIndent( valueToQuotedString( name.c_str() ) );
617               *document_ << " : ";
618               writeValue( childValue );
619               if ( ++it == members.end() )
620               {
621                  writeCommentAfterValueOnSameLine( childValue );
622                  break;
623               }
624               *document_ << ",";
625               writeCommentAfterValueOnSameLine( childValue );
626            }
627            unindent();
628            writeWithIndent( "}" );
629         }
630      }
631      break;
632   }
633}
634
635
636void
637StyledStreamWriter::writeArrayValue( const Value &value )
638{
639   unsigned size = value.size();
640   if ( size == 0 )
641      pushValue( "[]" );
642   else
643   {
644      bool isArrayMultiLine = isMultineArray( value );
645      if ( isArrayMultiLine )
646      {
647         writeWithIndent( "[" );
648         indent();
649         bool hasChildValue = !childValues_.empty();
650         unsigned index =0;
651         for (;;)
652         {
653            const Value &childValue = value[index];
654            writeCommentBeforeValue( childValue );
655            if ( hasChildValue )
656               writeWithIndent( childValues_[index] );
657            else
658            {
659               writeIndent();
660               writeValue( childValue );
661            }
662            if ( ++index == size )
663            {
664               writeCommentAfterValueOnSameLine( childValue );
665               break;
666            }
667            *document_ << ",";
668            writeCommentAfterValueOnSameLine( childValue );
669         }
670         unindent();
671         writeWithIndent( "]" );
672      }
673      else // output on a single line
674      {
675         assert( childValues_.size() == size );
676         *document_ << "[ ";
677         for ( unsigned index =0; index < size; ++index )
678         {
679            if ( index > 0 )
680               *document_ << ", ";
681            *document_ << childValues_[index];
682         }
683         *document_ << " ]";
684      }
685   }
686}
687
688
689bool
690StyledStreamWriter::isMultineArray( const Value &value )
691{
692   int size = value.size();
693   bool isMultiLine = size*3 >= rightMargin_ ;
694   childValues_.clear();
695   for ( int index =0; index < size  &&  !isMultiLine; ++index )
696   {
697      const Value &childValue = value[index];
698      isMultiLine = isMultiLine  ||
699                     ( (childValue.isArray()  ||  childValue.isObject())  && 
700                        childValue.size() > 0 );
701   }
702   if ( !isMultiLine ) // check if line length > max line length
703   {
704      childValues_.reserve( size );
705      addChildValues_ = true;
706      int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]'
707      for ( int index =0; index < size  &&  !isMultiLine; ++index )
708      {
709         writeValue( value[index] );
710         lineLength += int( childValues_[index].length() );
711         isMultiLine = isMultiLine  &&  hasCommentForValue( value[index] );
712      }
713      addChildValues_ = false;
714      isMultiLine = isMultiLine  ||  lineLength >= rightMargin_;
715   }
716   return isMultiLine;
717}
718
719
720void
721StyledStreamWriter::pushValue( const std::string &value )
722{
723   if ( addChildValues_ )
724      childValues_.push_back( value );
725   else
726      *document_ << value;
727}
728
729
730void
731StyledStreamWriter::writeIndent()
732{
733  /*
734    Some comments in this method would have been nice. ;-)
735
736   if ( !document_.empty() )
737   {
738      char last = document_[document_.length()-1];
739      if ( last == ' ' )     // already indented
740         return;
741      if ( last != '\n' )    // Comments may add new-line
742         *document_ << '\n';
743   }
744  */
745   *document_ << '\n' << indentString_;
746}
747
748
749void
750StyledStreamWriter::writeWithIndent( const std::string &value )
751{
752   writeIndent();
753   *document_ << value;
754}
755
756
757void
758StyledStreamWriter::indent()
759{
760   indentString_ += indentation_;
761}
762
763
764void
765StyledStreamWriter::unindent()
766{
767   assert( indentString_.size() >= indentation_.size() );
768   indentString_.resize( indentString_.size() - indentation_.size() );
769}
770
771
772void
773StyledStreamWriter::writeCommentBeforeValue( const Value &root )
774{
775   if ( !root.hasComment( commentBefore ) )
776      return;
777   *document_ << normalizeEOL( root.getComment( commentBefore ) );
778   *document_ << "\n";
779}
780
781
782void
783StyledStreamWriter::writeCommentAfterValueOnSameLine( const Value &root )
784{
785   if ( root.hasComment( commentAfterOnSameLine ) )
786      *document_ << " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) );
787
788   if ( root.hasComment( commentAfter ) )
789   {
790      *document_ << "\n";
791      *document_ << normalizeEOL( root.getComment( commentAfter ) );
792      *document_ << "\n";
793   }
794}
795
796
797bool
798StyledStreamWriter::hasCommentForValue( const Value &value )
799{
800   return value.hasComment( commentBefore )
801          ||  value.hasComment( commentAfterOnSameLine )
802          ||  value.hasComment( commentAfter );
803}
804
805
806std::string
807StyledStreamWriter::normalizeEOL( const std::string &text )
808{
809   std::string normalized;
810   normalized.reserve( text.length() );
811   const char *begin = text.c_str();
812   const char *end = begin + text.length();
813   const char *current = begin;
814   while ( current != end )
815   {
816      char c = *current++;
817      if ( c == '\r' ) // mac or dos EOL
818      {
819         if ( *current == '\n' ) // convert dos EOL
820            ++current;
821         normalized += '\n';
822      }
823      else // handle unix EOL & other char
824         normalized += c;
825   }
826   return normalized;
827}
828
829
830std::ostream& operator<<( std::ostream &sout, const Value &root )
831{
832   Json::StyledStreamWriter writer;
833   writer.write(sout, root);
834   return sout;
835}
836
837
838} // namespace Json
Property changes on: trunk/src/lib/web/json/json_writer.cpp
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/lib/web/json/json_value.cpp
r0r24796
1// Copyright 2007-2010 Baptiste Lepilleur
2// Distributed under MIT license, or public domain if desired and
3// recognized in your jurisdiction.
4// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
5#include "emu.h"
6#if !defined(JSON_IS_AMALGAMATION)
7# include <json/value.h>
8# include <json/writer.h>
9# ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
10#  include "json_batchallocator.h"
11# endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
12#endif // if !defined(JSON_IS_AMALGAMATION)
13#include <iostream>
14#include <utility>
15#include <stdexcept>
16#include <cstring>
17#include <cassert>
18#ifdef JSON_USE_CPPTL
19# include <cpptl/conststring.h>
20#endif
21#include <cstddef>    // size_t
22
23#define JSON_ASSERT_UNREACHABLE assert( false )
24#define JSON_ASSERT( condition ) assert( condition );  // @todo <= change this into an exception throw
25#define JSON_FAIL_MESSAGE( message ) throw std::runtime_error( message );
26#define JSON_ASSERT_MESSAGE( condition, message ) if (!( condition )) JSON_FAIL_MESSAGE( message )
27
28namespace Json {
29
30const Value Value::null;
31const Int Value::minInt = Int( ~(UInt(-1)/2) );
32const Int Value::maxInt = Int( UInt(-1)/2 );
33const UInt Value::maxUInt = UInt(-1);
34const Int64 Value::minInt64 = Int64( ~(UInt64(-1)/2) );
35const Int64 Value::maxInt64 = Int64( UInt64(-1)/2 );
36const UInt64 Value::maxUInt64 = UInt64(-1);
37const LargestInt Value::minLargestInt = LargestInt( ~(LargestUInt(-1)/2) );
38const LargestInt Value::maxLargestInt = LargestInt( LargestUInt(-1)/2 );
39const LargestUInt Value::maxLargestUInt = LargestUInt(-1);
40
41
42/// Unknown size marker
43static const unsigned int unknown = (unsigned)-1;
44
45
46/** Duplicates the specified string value.
47 * @param value Pointer to the string to duplicate. Must be zero-terminated if
48 *              length is "unknown".
49 * @param length Length of the value. if equals to unknown, then it will be
50 *               computed using strlen(value).
51 * @return Pointer on the duplicate instance of string.
52 */
53static inline char *
54duplicateStringValue( const char *value,
55                      unsigned int length = unknown )
56{
57   if ( length == unknown )
58      length = (unsigned int)strlen(value);
59   char *newString = static_cast<char *>( malloc( length + 1 ) );
60   JSON_ASSERT_MESSAGE( newString != 0, "Failed to allocate string value buffer" );
61   memcpy( newString, value, length );
62   newString[length] = 0;
63   return newString;
64}
65
66
67/** Free the string duplicated by duplicateStringValue().
68 */
69static inline void
70releaseStringValue( char *value )
71{
72   if ( value )
73      free( value );
74}
75
76} // namespace Json
77
78
79// //////////////////////////////////////////////////////////////////
80// //////////////////////////////////////////////////////////////////
81// //////////////////////////////////////////////////////////////////
82// ValueInternals...
83// //////////////////////////////////////////////////////////////////
84// //////////////////////////////////////////////////////////////////
85// //////////////////////////////////////////////////////////////////
86#if !defined(JSON_IS_AMALGAMATION)
87# ifdef JSON_VALUE_USE_INTERNAL_MAP
88#  include "json_internalarray.inl"
89#  include "json_internalmap.inl"
90# endif // JSON_VALUE_USE_INTERNAL_MAP
91
92# include "json_valueiterator.inl"
93#endif // if !defined(JSON_IS_AMALGAMATION)
94
95namespace Json {
96
97// //////////////////////////////////////////////////////////////////
98// //////////////////////////////////////////////////////////////////
99// //////////////////////////////////////////////////////////////////
100// class Value::CommentInfo
101// //////////////////////////////////////////////////////////////////
102// //////////////////////////////////////////////////////////////////
103// //////////////////////////////////////////////////////////////////
104
105
106Value::CommentInfo::CommentInfo()
107   : comment_( 0 )
108{
109}
110
111Value::CommentInfo::~CommentInfo()
112{
113   if ( comment_ )
114      releaseStringValue( comment_ );
115}
116
117
118void
119Value::CommentInfo::setComment( const char *text )
120{
121   if ( comment_ )
122      releaseStringValue( comment_ );
123   JSON_ASSERT( text != 0 );
124   JSON_ASSERT_MESSAGE( text[0]=='\0' || text[0]=='/', "Comments must start with /");
125   // It seems that /**/ style comments are acceptable as well.
126   comment_ = duplicateStringValue( text );
127}
128
129
130// //////////////////////////////////////////////////////////////////
131// //////////////////////////////////////////////////////////////////
132// //////////////////////////////////////////////////////////////////
133// class Value::CZString
134// //////////////////////////////////////////////////////////////////
135// //////////////////////////////////////////////////////////////////
136// //////////////////////////////////////////////////////////////////
137# ifndef JSON_VALUE_USE_INTERNAL_MAP
138
139// Notes: index_ indicates if the string was allocated when
140// a string is stored.
141
142Value::CZString::CZString( ArrayIndex index )
143   : cstr_( 0 )
144   , index_( index )
145{
146}
147
148Value::CZString::CZString( const char *cstr, DuplicationPolicy allocate )
149   : cstr_( allocate == duplicate ? duplicateStringValue(cstr)
150                                  : cstr )
151   , index_( allocate )
152{
153}
154
155Value::CZString::CZString( const CZString &other )
156: cstr_( other.index_ != noDuplication &&  other.cstr_ != 0
157                ?  duplicateStringValue( other.cstr_ )
158                : other.cstr_ )
159   , index_( other.cstr_ ? (other.index_ == noDuplication ? noDuplication : duplicate)
160                         : other.index_ )
161{
162}
163
164Value::CZString::~CZString()
165{
166   if ( cstr_  &&  index_ == duplicate )
167      releaseStringValue( const_cast<char *>( cstr_ ) );
168}
169
170void
171Value::CZString::swap( CZString &other )
172{
173   std::swap( cstr_, other.cstr_ );
174   std::swap( index_, other.index_ );
175}
176
177Value::CZString &
178Value::CZString::operator =( const CZString &other )
179{
180   CZString temp( other );
181   swap( temp );
182   return *this;
183}
184
185bool
186Value::CZString::operator<( const CZString &other ) const
187{
188   if ( cstr_ )
189      return strcmp( cstr_, other.cstr_ ) < 0;
190   return index_ < other.index_;
191}
192
193bool
194Value::CZString::operator==( const CZString &other ) const
195{
196   if ( cstr_ )
197      return strcmp( cstr_, other.cstr_ ) == 0;
198   return index_ == other.index_;
199}
200
201
202ArrayIndex
203Value::CZString::index() const
204{
205   return index_;
206}
207
208
209const char *
210Value::CZString::c_str() const
211{
212   return cstr_;
213}
214
215bool
216Value::CZString::isStaticString() const
217{
218   return index_ == noDuplication;
219}
220
221#endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
222
223
224// //////////////////////////////////////////////////////////////////
225// //////////////////////////////////////////////////////////////////
226// //////////////////////////////////////////////////////////////////
227// class Value::Value
228// //////////////////////////////////////////////////////////////////
229// //////////////////////////////////////////////////////////////////
230// //////////////////////////////////////////////////////////////////
231
232/*! \internal Default constructor initialization must be equivalent to:
233 * memset( this, 0, sizeof(Value) )
234 * This optimization is used in ValueInternalMap fast allocator.
235 */
236Value::Value( ValueType type )
237   : type_( type )
238   , allocated_( 0 )
239   , comments_( 0 )
240# ifdef JSON_VALUE_USE_INTERNAL_MAP
241   , itemIsUsed_( 0 )
242#endif
243{
244   switch ( type )
245   {
246   case nullValue:
247      break;
248   case intValue:
249   case uintValue:
250      value_.int_ = 0;
251      break;
252   case realValue:
253      value_.real_ = 0.0;
254      break;
255   case stringValue:
256      value_.string_ = 0;
257      break;
258#ifndef JSON_VALUE_USE_INTERNAL_MAP
259   case arrayValue:
260   case objectValue:
261      value_.map_ = new ObjectValues();
262      break;
263#else
264   case arrayValue:
265      value_.array_ = arrayAllocator()->newArray();
266      break;
267   case objectValue:
268      value_.map_ = mapAllocator()->newMap();
269      break;
270#endif
271   case booleanValue:
272      value_.bool_ = false;
273      break;
274   default:
275      JSON_ASSERT_UNREACHABLE;
276   }
277}
278
279
280#if defined(JSON_HAS_INT64)
281Value::Value( UInt value )
282   : type_( uintValue )
283   , comments_( 0 )
284# ifdef JSON_VALUE_USE_INTERNAL_MAP
285   , itemIsUsed_( 0 )
286#endif
287{
288   value_.uint_ = value;
289}
290
291Value::Value( Int value )
292   : type_( intValue )
293   , comments_( 0 )
294# ifdef JSON_VALUE_USE_INTERNAL_MAP
295   , itemIsUsed_( 0 )
296#endif
297{
298   value_.int_ = value;
299}
300
301#endif // if defined(JSON_HAS_INT64)
302
303
304Value::Value( Int64 value )
305   : type_( intValue )
306   , comments_( 0 )
307# ifdef JSON_VALUE_USE_INTERNAL_MAP
308   , itemIsUsed_( 0 )
309#endif
310{
311   value_.int_ = value;
312}
313
314
315Value::Value( UInt64 value )
316   : type_( uintValue )
317   , comments_( 0 )
318# ifdef JSON_VALUE_USE_INTERNAL_MAP
319   , itemIsUsed_( 0 )
320#endif
321{
322   value_.uint_ = value;
323}
324
325Value::Value( double value )
326   : type_( realValue )
327   , comments_( 0 )
328# ifdef JSON_VALUE_USE_INTERNAL_MAP
329   , itemIsUsed_( 0 )
330#endif
331{
332   value_.real_ = value;
333}
334
335Value::Value( const char *value )
336   : type_( stringValue )
337   , allocated_( true )
338   , comments_( 0 )
339# ifdef JSON_VALUE_USE_INTERNAL_MAP
340   , itemIsUsed_( 0 )
341#endif
342{
343   value_.string_ = duplicateStringValue( value );
344}
345
346
347Value::Value( const char *beginValue,
348              const char *endValue )
349   : type_( stringValue )
350   , allocated_( true )
351   , comments_( 0 )
352# ifdef JSON_VALUE_USE_INTERNAL_MAP
353   , itemIsUsed_( 0 )
354#endif
355{
356   value_.string_ = duplicateStringValue( beginValue,
357                                          (unsigned int)(endValue - beginValue) );
358}
359
360
361Value::Value( const std::string &value )
362   : type_( stringValue )
363   , allocated_( true )
364   , comments_( 0 )
365# ifdef JSON_VALUE_USE_INTERNAL_MAP
366   , itemIsUsed_( 0 )
367#endif
368{
369   value_.string_ = duplicateStringValue( value.c_str(),
370                                          (unsigned int)value.length() );
371
372}
373
374Value::Value( const StaticString &value )
375   : type_( stringValue )
376   , allocated_( false )
377   , comments_( 0 )
378# ifdef JSON_VALUE_USE_INTERNAL_MAP
379   , itemIsUsed_( 0 )
380#endif
381{
382   value_.string_ = const_cast<char *>( value.c_str() );
383}
384
385
386# ifdef JSON_USE_CPPTL
387Value::Value( const CppTL::ConstString &value )
388   : type_( stringValue )
389   , allocated_( true )
390   , comments_( 0 )
391# ifdef JSON_VALUE_USE_INTERNAL_MAP
392   , itemIsUsed_( 0 )
393#endif
394{
395   value_.string_ = duplicateStringValue( value, value.length() );
396}
397# endif
398
399Value::Value( bool value )
400   : type_( booleanValue )
401   , comments_( 0 )
402# ifdef JSON_VALUE_USE_INTERNAL_MAP
403   , itemIsUsed_( 0 )
404#endif
405{
406   value_.bool_ = value;
407}
408
409
410Value::Value( const Value &other )
411   : type_( other.type_ )
412   , comments_( 0 )
413# ifdef JSON_VALUE_USE_INTERNAL_MAP
414   , itemIsUsed_( 0 )
415#endif
416{
417   switch ( type_ )
418   {
419   case nullValue:
420   case intValue:
421   case uintValue:
422   case realValue:
423   case booleanValue:
424      value_ = other.value_;
425      break;
426   case stringValue:
427      if ( other.value_.string_ )
428      {
429         value_.string_ = duplicateStringValue( other.value_.string_ );
430         allocated_ = true;
431      }
432      else
433         value_.string_ = 0;
434      break;
435#ifndef JSON_VALUE_USE_INTERNAL_MAP
436   case arrayValue:
437   case objectValue:
438      value_.map_ = new ObjectValues( *other.value_.map_ );
439      break;
440#else
441   case arrayValue:
442      value_.array_ = arrayAllocator()->newArrayCopy( *other.value_.array_ );
443      break;
444   case objectValue:
445      value_.map_ = mapAllocator()->newMapCopy( *other.value_.map_ );
446      break;
447#endif
448   default:
449      JSON_ASSERT_UNREACHABLE;
450   }
451   if ( other.comments_ )
452   {
453      comments_ = new CommentInfo[numberOfCommentPlacement];
454      for ( int comment =0; comment < numberOfCommentPlacement; ++comment )
455      {
456         const CommentInfo &otherComment = other.comments_[comment];
457         if ( otherComment.comment_ )
458            comments_[comment].setComment( otherComment.comment_ );
459      }
460   }
461}
462
463
464Value::~Value()
465{
466   switch ( type_ )
467   {
468   case nullValue:
469   case intValue:
470   case uintValue:
471   case realValue:
472   case booleanValue:
473      break;
474   case stringValue:
475      if ( allocated_ )
476         releaseStringValue( value_.string_ );
477      break;
478#ifndef JSON_VALUE_USE_INTERNAL_MAP
479   case arrayValue:
480   case objectValue:
481      delete value_.map_;
482      break;
483#else
484   case arrayValue:
485      arrayAllocator()->destructArray( value_.array_ );
486      break;
487   case objectValue:
488      mapAllocator()->destructMap( value_.map_ );
489      break;
490#endif
491   default:
492      JSON_ASSERT_UNREACHABLE;
493   }
494
495   if ( comments_ )
496      delete[] comments_;
497}
498
499Value &
500Value::operator=( const Value &other )
501{
502   Value temp( other );
503   swap( temp );
504   return *this;
505}
506
507void
508Value::swap( Value &other )
509{
510   ValueType temp = type_;
511   type_ = other.type_;
512   other.type_ = temp;
513   std::swap( value_, other.value_ );
514   int temp2 = allocated_;
515   allocated_ = other.allocated_;
516   other.allocated_ = temp2;
517}
518
519ValueType
520Value::type() const
521{
522   return type_;
523}
524
525
526int
527Value::compare( const Value &other ) const
528{
529   if ( *this < other )
530      return -1;
531   if ( *this > other )
532      return 1;
533   return 0;
534}
535
536
537bool
538Value::operator <( const Value &other ) const
539{
540   int typeDelta = type_ - other.type_;
541   if ( typeDelta )
542      return typeDelta < 0 ? true : false;
543   switch ( type_ )
544   {
545   case nullValue:
546      return false;
547   case intValue:
548      return value_.int_ < other.value_.int_;
549   case uintValue:
550      return value_.uint_ < other.value_.uint_;
551   case realValue:
552      return value_.real_ < other.value_.real_;
553   case booleanValue:
554      return value_.bool_ < other.value_.bool_;
555   case stringValue:
556      return ( value_.string_ == 0  &&  other.value_.string_ )
557             || ( other.value_.string_ 
558                  &&  value_.string_ 
559                  && strcmp( value_.string_, other.value_.string_ ) < 0 );
560#ifndef JSON_VALUE_USE_INTERNAL_MAP
561   case arrayValue:
562   case objectValue:
563      {
564         int delta = int( value_.map_->size() - other.value_.map_->size() );
565         if ( delta )
566            return delta < 0;
567         return (*value_.map_) < (*other.value_.map_);
568      }
569#else
570   case arrayValue:
571      return value_.array_->compare( *(other.value_.array_) ) < 0;
572   case objectValue:
573      return value_.map_->compare( *(other.value_.map_) ) < 0;
574#endif
575   default:
576      JSON_ASSERT_UNREACHABLE;
577   }
578   return false;  // unreachable
579}
580
581bool
582Value::operator <=( const Value &other ) const
583{
584   return !(other < *this);
585}
586
587bool
588Value::operator >=( const Value &other ) const
589{
590   return !(*this < other);
591}
592
593bool
594Value::operator >( const Value &other ) const
595{
596   return other < *this;
597}
598
599bool
600Value::operator ==( const Value &other ) const
601{
602   //if ( type_ != other.type_ )
603   // GCC 2.95.3 says:
604   // attempt to take address of bit-field structure member `Json::Value::type_'
605   // Beats me, but a temp solves the problem.
606   int temp = other.type_;
607   if ( type_ != temp )
608      return false;
609   switch ( type_ )
610   {
611   case nullValue:
612      return true;
613   case intValue:
614      return value_.int_ == other.value_.int_;
615   case uintValue:
616      return value_.uint_ == other.value_.uint_;
617   case realValue:
618      return value_.real_ == other.value_.real_;
619   case booleanValue:
620      return value_.bool_ == other.value_.bool_;
621   case stringValue:
622      return ( value_.string_ == other.value_.string_ )
623             || ( other.value_.string_ 
624                  &&  value_.string_ 
625                  && strcmp( value_.string_, other.value_.string_ ) == 0 );
626#ifndef JSON_VALUE_USE_INTERNAL_MAP
627   case arrayValue:
628   case objectValue:
629      return value_.map_->size() == other.value_.map_->size()
630             && (*value_.map_) == (*other.value_.map_);
631#else
632   case arrayValue:
633      return value_.array_->compare( *(other.value_.array_) ) == 0;
634   case objectValue:
635      return value_.map_->compare( *(other.value_.map_) ) == 0;
636#endif
637   default:
638      JSON_ASSERT_UNREACHABLE;
639   }
640   return false;  // unreachable
641}
642
643bool
644Value::operator !=( const Value &other ) const
645{
646   return !( *this == other );
647}
648
649const char *
650Value::asCString() const
651{
652   JSON_ASSERT( type_ == stringValue );
653   return value_.string_;
654}
655
656
657std::string
658Value::asString() const
659{
660   switch ( type_ )
661   {
662   case nullValue:
663      return "";
664   case stringValue:
665      return value_.string_ ? value_.string_ : "";
666   case booleanValue:
667      return value_.bool_ ? "true" : "false";
668   case intValue:
669   case uintValue:
670   case realValue:
671   case arrayValue:
672   case objectValue:
673      JSON_FAIL_MESSAGE( "Type is not convertible to string" );
674   default:
675      JSON_ASSERT_UNREACHABLE;
676   }
677   return ""; // unreachable
678}
679
680# ifdef JSON_USE_CPPTL
681CppTL::ConstString
682Value::asConstString() const
683{
684   return CppTL::ConstString( asString().c_str() );
685}
686# endif
687
688
689Value::Int
690Value::asInt() const
691{
692   switch ( type_ )
693   {
694   case nullValue:
695      return 0;
696   case intValue:
697      JSON_ASSERT_MESSAGE( value_.int_ >= minInt  &&  value_.int_ <= maxInt, "unsigned integer out of signed int range" );
698      return Int(value_.int_);
699   case uintValue:
700      JSON_ASSERT_MESSAGE( value_.uint_ <= UInt(maxInt), "unsigned integer out of signed int range" );
701      return Int(value_.uint_);
702   case realValue:
703      JSON_ASSERT_MESSAGE( value_.real_ >= minInt  &&  value_.real_ <= maxInt, "Real out of signed integer range" );
704      return Int( value_.real_ );
705   case booleanValue:
706      return value_.bool_ ? 1 : 0;
707   case stringValue:
708   case arrayValue:
709   case objectValue:
710      JSON_FAIL_MESSAGE( "Type is not convertible to int" );
711   default:
712      JSON_ASSERT_UNREACHABLE;
713   }
714   return 0; // unreachable;
715}
716
717
718Value::UInt
719Value::asUInt() const
720{
721   switch ( type_ )
722   {
723   case nullValue:
724      return 0;
725   case intValue:
726      JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to unsigned integer" );
727      JSON_ASSERT_MESSAGE( value_.int_ <= maxUInt, "signed integer out of UInt range" );
728      return UInt(value_.int_);
729   case uintValue:
730      JSON_ASSERT_MESSAGE( value_.uint_ <= maxUInt, "unsigned integer out of UInt range" );
731      return UInt(value_.uint_);
732   case realValue:
733      JSON_ASSERT_MESSAGE( value_.real_ >= 0  &&  value_.real_ <= maxUInt,  "Real out of unsigned integer range" );
734      return UInt( value_.real_ );
735   case booleanValue:
736      return value_.bool_ ? 1 : 0;
737   case stringValue:
738   case arrayValue:
739   case objectValue:
740      JSON_FAIL_MESSAGE( "Type is not convertible to uint" );
741   default:
742      JSON_ASSERT_UNREACHABLE;
743   }
744   return 0; // unreachable;
745}
746
747
748# if defined(JSON_HAS_INT64)
749
750Value::Int64
751Value::asInt64() const
752{
753   switch ( type_ )
754   {
755   case nullValue:
756      return 0;
757   case intValue:
758      return value_.int_;
759   case uintValue:
760      JSON_ASSERT_MESSAGE( value_.uint_ <= UInt64(maxInt64), "unsigned integer out of Int64 range" );
761      return value_.uint_;
762   case realValue:
763      JSON_ASSERT_MESSAGE( value_.real_ >= minInt64  &&  value_.real_ <= maxInt64, "Real out of Int64 range" );
764      return Int( value_.real_ );
765   case booleanValue:
766      return value_.bool_ ? 1 : 0;
767   case stringValue:
768   case arrayValue:
769   case objectValue:
770      JSON_FAIL_MESSAGE( "Type is not convertible to Int64" );
771   default:
772      JSON_ASSERT_UNREACHABLE;
773   }
774   return 0; // unreachable;
775}
776
777
778Value::UInt64
779Value::asUInt64() const
780{
781   switch ( type_ )
782   {
783   case nullValue:
784      return 0;
785   case intValue:
786      JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to UInt64" );
787      return value_.int_;
788   case uintValue:
789      return value_.uint_;
790   case realValue:
791      JSON_ASSERT_MESSAGE( value_.real_ >= 0  &&  value_.real_ <= maxUInt64,  "Real out of UInt64 range" );
792      return UInt( value_.real_ );
793   case booleanValue:
794      return value_.bool_ ? 1 : 0;
795   case stringValue:
796   case arrayValue:
797   case objectValue:
798      JSON_FAIL_MESSAGE( "Type is not convertible to UInt64" );
799   default:
800      JSON_ASSERT_UNREACHABLE;
801   }
802   return 0; // unreachable;
803}
804# endif // if defined(JSON_HAS_INT64)
805
806
807LargestInt
808Value::asLargestInt() const
809{
810#if defined(JSON_NO_INT64)
811    return asInt();
812#else
813    return asInt64();
814#endif
815}
816
817
818LargestUInt
819Value::asLargestUInt() const
820{
821#if defined(JSON_NO_INT64)
822    return asUInt();
823#else
824    return asUInt64();
825#endif
826}
827
828
829double
830Value::asDouble() const
831{
832   switch ( type_ )
833   {
834   case nullValue:
835      return 0.0;
836   case intValue:
837      return static_cast<double>( value_.int_ );
838   case uintValue:
839#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
840      return static_cast<double>( value_.uint_ );
841#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
842      return static_cast<double>( Int(value_.uint_/2) ) * 2 + Int(value_.uint_ & 1);
843#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
844   case realValue:
845      return value_.real_;
846   case booleanValue:
847      return value_.bool_ ? 1.0 : 0.0;
848   case stringValue:
849   case arrayValue:
850   case objectValue:
851      JSON_FAIL_MESSAGE( "Type is not convertible to double" );
852   default:
853      JSON_ASSERT_UNREACHABLE;
854   }
855   return 0; // unreachable;
856}
857
858float
859Value::asFloat() const
860{
861   switch ( type_ )
862   {
863   case nullValue:
864      return 0.0f;
865   case intValue:
866      return static_cast<float>( value_.int_ );
867   case uintValue:
868#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
869      return static_cast<float>( value_.uint_ );
870#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
871      return static_cast<float>( Int(value_.uint_/2) ) * 2 + Int(value_.uint_ & 1);
872#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
873   case realValue:
874      return static_cast<float>( value_.real_ );
875   case booleanValue:
876      return value_.bool_ ? 1.0f : 0.0f;
877   case stringValue:
878   case arrayValue:
879   case objectValue:
880      JSON_FAIL_MESSAGE( "Type is not convertible to float" );
881   default:
882      JSON_ASSERT_UNREACHABLE;
883   }
884   return 0.0f; // unreachable;
885}
886
887bool
888Value::asBool() const
889{
890   switch ( type_ )
891   {
892   case nullValue:
893      return false;
894   case intValue:
895   case uintValue:
896      return value_.int_ != 0;
897   case realValue:
898      return value_.real_ != 0.0;
899   case booleanValue:
900      return value_.bool_;
901   case stringValue:
902      return value_.string_  &&  value_.string_[0] != 0;
903   case arrayValue:
904   case objectValue:
905      return value_.map_->size() != 0;
906   default:
907      JSON_ASSERT_UNREACHABLE;
908   }
909   return false; // unreachable;
910}
911
912
913bool
914Value::isConvertibleTo( ValueType other ) const
915{
916   switch ( type_ )
917   {
918   case nullValue:
919      return true;
920   case intValue:
921      return ( other == nullValue  &&  value_.int_ == 0 )
922             || other == intValue
923             || ( other == uintValue  && value_.int_ >= 0 )
924             || other == realValue
925             || other == stringValue
926             || other == booleanValue;
927   case uintValue:
928      return ( other == nullValue  &&  value_.uint_ == 0 )
929             || ( other == intValue  && value_.uint_ <= (unsigned)maxInt )
930             || other == uintValue
931             || other == realValue
932             || other == stringValue
933             || other == booleanValue;
934   case realValue:
935      return ( other == nullValue  &&  value_.real_ == 0.0 )
936             || ( other == intValue  &&  value_.real_ >= minInt  &&  value_.real_ <= maxInt )
937             || ( other == uintValue  &&  value_.real_ >= 0  &&  value_.real_ <= maxUInt )
938             || other == realValue
939             || other == stringValue
940             || other == booleanValue;
941   case booleanValue:
942      return ( other == nullValue  &&  value_.bool_ == false )
943             || other == intValue
944             || other == uintValue
945             || other == realValue
946             || other == stringValue
947             || other == booleanValue;
948   case stringValue:
949      return other == stringValue
950             || ( other == nullValue  &&  (!value_.string_  ||  value_.string_[0] == 0) );
951   case arrayValue:
952      return other == arrayValue
953             ||  ( other == nullValue  &&  value_.map_->size() == 0 );
954   case objectValue:
955      return other == objectValue
956             ||  ( other == nullValue  &&  value_.map_->size() == 0 );
957   default:
958      JSON_ASSERT_UNREACHABLE;
959   }
960   return false; // unreachable;
961}
962
963
964/// Number of values in array or object
965ArrayIndex
966Value::size() const
967{
968   switch ( type_ )
969   {
970   case nullValue:
971   case intValue:
972   case uintValue:
973   case realValue:
974   case booleanValue:
975   case stringValue:
976      return 0;
977#ifndef JSON_VALUE_USE_INTERNAL_MAP
978   case arrayValue:  // size of the array is highest index + 1
979      if ( !value_.map_->empty() )
980      {
981         ObjectValues::const_iterator itLast = value_.map_->end();
982         --itLast;
983         return (*itLast).first.index()+1;
984      }
985      return 0;
986   case objectValue:
987      return ArrayIndex( value_.map_->size() );
988#else
989   case arrayValue:
990      return Int( value_.array_->size() );
991   case objectValue:
992      return Int( value_.map_->size() );
993#endif
994   default:
995      JSON_ASSERT_UNREACHABLE;
996   }
997   return 0; // unreachable;
998}
999
1000
1001bool
1002Value::empty() const
1003{
1004   if ( isNull() || isArray() || isObject() )
1005      return size() == 0u;
1006   else
1007      return false;
1008}
1009
1010
1011bool
1012Value::operator!() const
1013{
1014   return isNull();
1015}
1016
1017
1018void
1019Value::clear()
1020{
1021   JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue  || type_ == objectValue );
1022
1023   switch ( type_ )
1024   {
1025#ifndef JSON_VALUE_USE_INTERNAL_MAP
1026   case arrayValue:
1027   case objectValue:
1028      value_.map_->clear();
1029      break;
1030#else
1031   case arrayValue:
1032      value_.array_->clear();
1033      break;
1034   case objectValue:
1035      value_.map_->clear();
1036      break;
1037#endif
1038   default:
1039      break;
1040   }
1041}
1042
1043void
1044Value::resize( ArrayIndex newSize )
1045{
1046   JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue );
1047   if ( type_ == nullValue )
1048      *this = Value( arrayValue );
1049#ifndef JSON_VALUE_USE_INTERNAL_MAP
1050   ArrayIndex oldSize = size();
1051   if ( newSize == 0 )
1052      clear();
1053   else if ( newSize > oldSize )
1054      (*this)[ newSize - 1 ];
1055   else
1056   {
1057      for ( ArrayIndex index = newSize; index < oldSize; ++index )
1058      {
1059         value_.map_->erase( index );
1060      }
1061      assert( size() == newSize );
1062   }
1063#else
1064   value_.array_->resize( newSize );
1065#endif
1066}
1067
1068
1069Value &
1070Value::operator[]( ArrayIndex index )
1071{
1072   JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue );
1073   if ( type_ == nullValue )
1074      *this = Value( arrayValue );
1075#ifndef JSON_VALUE_USE_INTERNAL_MAP
1076   CZString key( index );
1077   ObjectValues::iterator it = value_.map_->lower_bound( key );
1078   if ( it != value_.map_->end()  &&  (*it).first == key )
1079      return (*it).second;
1080
1081   ObjectValues::value_type defaultValue( key, null );
1082   it = value_.map_->insert( it, defaultValue );
1083   return (*it).second;
1084#else
1085   return value_.array_->resolveReference( index );
1086#endif
1087}
1088
1089
1090Value &
1091Value::operator[]( int index )
1092{
1093   JSON_ASSERT( index >= 0 );
1094   return (*this)[ ArrayIndex(index) ];
1095}
1096
1097
1098const Value &
1099Value::operator[]( ArrayIndex index ) const
1100{
1101   JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue );
1102   if ( type_ == nullValue )
1103      return null;
1104#ifndef JSON_VALUE_USE_INTERNAL_MAP
1105   CZString key( index );
1106   ObjectValues::const_iterator it = value_.map_->find( key );
1107   if ( it == value_.map_->end() )
1108      return null;
1109   return (*it).second;
1110#else
1111   Value *value = value_.array_->find( index );
1112   return value ? *value : null;
1113#endif
1114}
1115
1116
1117const Value &
1118Value::operator[]( int index ) const
1119{
1120   JSON_ASSERT( index >= 0 );
1121   return (*this)[ ArrayIndex(index) ];
1122}
1123
1124
1125Value &
1126Value::operator[]( const char *key )
1127{
1128   return resolveReference( key, false );
1129}
1130
1131
1132Value &
1133Value::resolveReference( const char *key,
1134                         bool isStatic )
1135{
1136   JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
1137   if ( type_ == nullValue )
1138      *this = Value( objectValue );
1139#ifndef JSON_VALUE_USE_INTERNAL_MAP
1140   CZString actualKey( key, isStatic ? CZString::noDuplication
1141                                     : CZString::duplicateOnCopy );
1142   ObjectValues::iterator it = value_.map_->lower_bound( actualKey );
1143   if ( it != value_.map_->end()  &&  (*it).first == actualKey )
1144      return (*it).second;
1145
1146   ObjectValues::value_type defaultValue( actualKey, null );
1147   it = value_.map_->insert( it, defaultValue );
1148   Value &value = (*it).second;
1149   return value;
1150#else
1151   return value_.map_->resolveReference( key, isStatic );
1152#endif
1153}
1154
1155
1156Value
1157Value::get( ArrayIndex index,
1158            const Value &defaultValue ) const
1159{
1160   const Value *value = &((*this)[index]);
1161   return value == &null ? defaultValue : *value;
1162}
1163
1164
1165bool
1166Value::isValidIndex( ArrayIndex index ) const
1167{
1168   return index < size();
1169}
1170
1171
1172
1173const Value &
1174Value::operator[]( const char *key ) const
1175{
1176   JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
1177   if ( type_ == nullValue )
1178      return null;
1179#ifndef JSON_VALUE_USE_INTERNAL_MAP
1180   CZString actualKey( key, CZString::noDuplication );
1181   ObjectValues::const_iterator it = value_.map_->find( actualKey );
1182   if ( it == value_.map_->end() )
1183      return null;
1184   return (*it).second;
1185#else
1186   const Value *value = value_.map_->find( key );
1187   return value ? *value : null;
1188#endif
1189}
1190
1191
1192Value &
1193Value::operator[]( const std::string &key )
1194{
1195   return (*this)[ key.c_str() ];
1196}
1197
1198
1199const Value &
1200Value::operator[]( const std::string &key ) const
1201{
1202   return (*this)[ key.c_str() ];
1203}
1204
1205Value &
1206Value::operator[]( const StaticString &key )
1207{
1208   return resolveReference( key, true );
1209}
1210
1211
1212# ifdef JSON_USE_CPPTL
1213Value &
1214Value::operator[]( const CppTL::ConstString &key )
1215{
1216   return (*this)[ key.c_str() ];
1217}
1218
1219
1220const Value &
1221Value::operator[]( const CppTL::ConstString &key ) const
1222{
1223   return (*this)[ key.c_str() ];
1224}
1225# endif
1226
1227
1228Value &
1229Value::append( const Value &value )
1230{
1231   return (*this)[size()] = value;
1232}
1233
1234
1235Value
1236Value::get( const char *key,
1237            const Value &defaultValue ) const
1238{
1239   const Value *value = &((*this)[key]);
1240   return value == &null ? defaultValue : *value;
1241}
1242
1243
1244Value
1245Value::get( const std::string &key,
1246            const Value &defaultValue ) const
1247{
1248   return get( key.c_str(), defaultValue );
1249}
1250
1251Value
1252Value::removeMember( const char* key )
1253{
1254   JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
1255   if ( type_ == nullValue )
1256      return null;
1257#ifndef JSON_VALUE_USE_INTERNAL_MAP
1258   CZString actualKey( key, CZString::noDuplication );
1259   ObjectValues::iterator it = value_.map_->find( actualKey );
1260   if ( it == value_.map_->end() )
1261      return null;
1262   Value old(it->second);
1263   value_.map_->erase(it);
1264   return old;
1265#else
1266   Value *value = value_.map_->find( key );
1267   if (value){
1268      Value old(*value);
1269      value_.map_.remove( key );
1270      return old;
1271   } else {
1272      return null;
1273   }
1274#endif
1275}
1276
1277Value
1278Value::removeMember( const std::string &key )
1279{
1280   return removeMember( key.c_str() );
1281}
1282
1283# ifdef JSON_USE_CPPTL
1284Value
1285Value::get( const CppTL::ConstString &key,
1286            const Value &defaultValue ) const
1287{
1288   return get( key.c_str(), defaultValue );
1289}
1290# endif
1291
1292bool
1293Value::isMember( const char *key ) const
1294{
1295   const Value *value = &((*this)[key]);
1296   return value != &null;
1297}
1298
1299
1300bool
1301Value::isMember( const std::string &key ) const
1302{
1303   return isMember( key.c_str() );
1304}
1305
1306
1307# ifdef JSON_USE_CPPTL
1308bool
1309Value::isMember( const CppTL::ConstString &key ) const
1310{
1311   return isMember( key.c_str() );
1312}
1313#endif
1314
1315Value::Members
1316Value::getMemberNames() const
1317{
1318   JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
1319   if ( type_ == nullValue )
1320       return Value::Members();
1321   Members members;
1322   members.reserve( value_.map_->size() );
1323#ifndef JSON_VALUE_USE_INTERNAL_MAP
1324   ObjectValues::const_iterator it = value_.map_->begin();
1325   ObjectValues::const_iterator itEnd = value_.map_->end();
1326   for ( ; it != itEnd; ++it )
1327      members.push_back( std::string( (*it).first.c_str() ) );
1328#else
1329   ValueInternalMap::IteratorState it;
1330   ValueInternalMap::IteratorState itEnd;
1331   value_.map_->makeBeginIterator( it );
1332   value_.map_->makeEndIterator( itEnd );
1333   for ( ; !ValueInternalMap::equals( it, itEnd ); ValueInternalMap::increment(it) )
1334      members.push_back( std::string( ValueInternalMap::key( it ) ) );
1335#endif
1336   return members;
1337}
1338//
1339//# ifdef JSON_USE_CPPTL
1340//EnumMemberNames
1341//Value::enumMemberNames() const
1342//{
1343//   if ( type_ == objectValue )
1344//   {
1345//      return CppTL::Enum::any(  CppTL::Enum::transform(
1346//         CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
1347//         MemberNamesTransform() ) );
1348//   }
1349//   return EnumMemberNames();
1350//}
1351//
1352//
1353//EnumValues
1354//Value::enumValues() const
1355//{
1356//   if ( type_ == objectValue  ||  type_ == arrayValue )
1357//      return CppTL::Enum::anyValues( *(value_.map_),
1358//                                     CppTL::Type<const Value &>() );
1359//   return EnumValues();
1360//}
1361//
1362//# endif
1363
1364
1365bool
1366Value::isNull() const
1367{
1368   return type_ == nullValue;
1369}
1370
1371
1372bool
1373Value::isBool() const
1374{
1375   return type_ == booleanValue;
1376}
1377
1378
1379bool
1380Value::isInt() const
1381{
1382   return type_ == intValue;
1383}
1384
1385
1386bool
1387Value::isUInt() const
1388{
1389   return type_ == uintValue;
1390}
1391
1392
1393bool
1394Value::isIntegral() const
1395{
1396   return type_ == intValue 
1397          ||  type_ == uintValue 
1398          ||  type_ == booleanValue;
1399}
1400
1401
1402bool
1403Value::isDouble() const
1404{
1405   return type_ == realValue;
1406}
1407
1408
1409bool
1410Value::isNumeric() const
1411{
1412   return isIntegral() || isDouble();
1413}
1414
1415
1416bool
1417Value::isString() const
1418{
1419   return type_ == stringValue;
1420}
1421
1422
1423bool
1424Value::isArray() const
1425{
1426   return type_ == nullValue  ||  type_ == arrayValue;
1427}
1428
1429
1430bool
1431Value::isObject() const
1432{
1433   return type_ == nullValue  ||  type_ == objectValue;
1434}
1435
1436
1437void
1438Value::setComment( const char *comment,
1439                   CommentPlacement placement )
1440{
1441   if ( !comments_ )
1442      comments_ = new CommentInfo[numberOfCommentPlacement];
1443   comments_[placement].setComment( comment );
1444}
1445
1446
1447void
1448Value::setComment( const std::string &comment,
1449                   CommentPlacement placement )
1450{
1451   setComment( comment.c_str(), placement );
1452}
1453
1454
1455bool
1456Value::hasComment( CommentPlacement placement ) const
1457{
1458   return comments_ != 0  &&  comments_[placement].comment_ != 0;
1459}
1460
1461std::string
1462Value::getComment( CommentPlacement placement ) const
1463{
1464   if ( hasComment(placement) )
1465      return comments_[placement].comment_;
1466   return "";
1467}
1468
1469
1470std::string
1471Value::toStyledString() const
1472{
1473   StyledWriter writer;
1474   return writer.write( *this );
1475}
1476
1477
1478Value::const_iterator
1479Value::begin() const
1480{
1481   switch ( type_ )
1482   {
1483#ifdef JSON_VALUE_USE_INTERNAL_MAP
1484   case arrayValue:
1485      if ( value_.array_ )
1486      {
1487         ValueInternalArray::IteratorState it;
1488         value_.array_->makeBeginIterator( it );
1489         return const_iterator( it );
1490      }
1491      break;
1492   case objectValue:
1493      if ( value_.map_ )
1494      {
1495         ValueInternalMap::IteratorState it;
1496         value_.map_->makeBeginIterator( it );
1497         return const_iterator( it );
1498      }
1499      break;
1500#else
1501   case arrayValue:
1502   case objectValue:
1503      if ( value_.map_ )
1504         return const_iterator( value_.map_->begin() );
1505      break;
1506#endif
1507   default:
1508      break;
1509   }
1510   return const_iterator();
1511}
1512
1513Value::const_iterator
1514Value::end() const
1515{
1516   switch ( type_ )
1517   {
1518#ifdef JSON_VALUE_USE_INTERNAL_MAP
1519   case arrayValue:
1520      if ( value_.array_ )
1521      {
1522         ValueInternalArray::IteratorState it;
1523         value_.array_->makeEndIterator( it );
1524         return const_iterator( it );
1525      }
1526      break;
1527   case objectValue:
1528      if ( value_.map_ )
1529      {
1530         ValueInternalMap::IteratorState it;
1531         value_.map_->makeEndIterator( it );
1532         return const_iterator( it );
1533      }
1534      break;
1535#else
1536   case arrayValue:
1537   case objectValue:
1538      if ( value_.map_ )
1539         return const_iterator( value_.map_->end() );
1540      break;
1541#endif
1542   default:
1543      break;
1544   }
1545   return const_iterator();
1546}
1547
1548
1549Value::iterator
1550Value::begin()
1551{
1552   switch ( type_ )
1553   {
1554#ifdef JSON_VALUE_USE_INTERNAL_MAP
1555   case arrayValue:
1556      if ( value_.array_ )
1557      {
1558         ValueInternalArray::IteratorState it;
1559         value_.array_->makeBeginIterator( it );
1560         return iterator( it );
1561      }
1562      break;
1563   case objectValue:
1564      if ( value_.map_ )
1565      {
1566         ValueInternalMap::IteratorState it;
1567         value_.map_->makeBeginIterator( it );
1568         return iterator( it );
1569      }
1570      break;
1571#else
1572   case arrayValue:
1573   case objectValue:
1574      if ( value_.map_ )
1575         return iterator( value_.map_->begin() );
1576      break;
1577#endif
1578   default:
1579      break;
1580   }
1581   return iterator();
1582}
1583
1584Value::iterator
1585Value::end()
1586{
1587   switch ( type_ )
1588   {
1589#ifdef JSON_VALUE_USE_INTERNAL_MAP
1590   case arrayValue:
1591      if ( value_.array_ )
1592      {
1593         ValueInternalArray::IteratorState it;
1594         value_.array_->makeEndIterator( it );
1595         return iterator( it );
1596      }
1597      break;
1598   case objectValue:
1599      if ( value_.map_ )
1600      {
1601         ValueInternalMap::IteratorState it;
1602         value_.map_->makeEndIterator( it );
1603         return iterator( it );
1604      }
1605      break;
1606#else
1607   case arrayValue:
1608   case objectValue:
1609      if ( value_.map_ )
1610         return iterator( value_.map_->end() );
1611      break;
1612#endif
1613   default:
1614      break;
1615   }
1616   return iterator();
1617}
1618
1619
1620// class PathArgument
1621// //////////////////////////////////////////////////////////////////
1622
1623PathArgument::PathArgument()
1624   : kind_( kindNone )
1625{
1626}
1627
1628
1629PathArgument::PathArgument( ArrayIndex index )
1630   : index_( index )
1631   , kind_( kindIndex )
1632{
1633}
1634
1635
1636PathArgument::PathArgument( const char *key )
1637   : key_( key )
1638   , kind_( kindKey )
1639{
1640}
1641
1642
1643PathArgument::PathArgument( const std::string &key )
1644   : key_( key.c_str() )
1645   , kind_( kindKey )
1646{
1647}
1648
1649// class Path
1650// //////////////////////////////////////////////////////////////////
1651
1652Path::Path( const std::string &path,
1653            const PathArgument &a1,
1654            const PathArgument &a2,
1655            const PathArgument &a3,
1656            const PathArgument &a4,
1657            const PathArgument &a5 )
1658{
1659   InArgs in;
1660   in.push_back( &a1 );
1661   in.push_back( &a2 );
1662   in.push_back( &a3 );
1663   in.push_back( &a4 );
1664   in.push_back( &a5 );
1665   makePath( path, in );
1666}
1667
1668
1669void
1670Path::makePath( const std::string &path,
1671                const InArgs &in )
1672{
1673   const char *current = path.c_str();
1674   const char *end = current + path.length();
1675   InArgs::const_iterator itInArg = in.begin();
1676   while ( current != end )
1677   {
1678      if ( *current == '[' )
1679      {
1680         ++current;
1681         if ( *current == '%' )
1682            addPathInArg( path, in, itInArg, PathArgument::kindIndex );
1683         else
1684         {
1685            ArrayIndex index = 0;
1686            for ( ; current != end && *current >= '0'  &&  *current <= '9'; ++current )
1687               index = index * 10 + ArrayIndex(*current - '0');
1688            args_.push_back( index );
1689         }
1690         if ( current == end  ||  *current++ != ']' )
1691            invalidPath( path, int(current - path.c_str()) );
1692      }
1693      else if ( *current == '%' )
1694      {
1695         addPathInArg( path, in, itInArg, PathArgument::kindKey );
1696         ++current;
1697      }
1698      else if ( *current == '.' )
1699      {
1700         ++current;
1701      }
1702      else
1703      {
1704         const char *beginName = current;
1705         while ( current != end  &&  !strchr( "[.", *current ) )
1706            ++current;
1707         args_.push_back( std::string( beginName, current ) );
1708      }
1709   }
1710}
1711
1712
1713void
1714Path::addPathInArg( const std::string &path,
1715                    const InArgs &in,
1716                    InArgs::const_iterator &itInArg,
1717                    PathArgument::Kind kind )
1718{
1719   if ( itInArg == in.end() )
1720   {
1721      // Error: missing argument %d
1722   }
1723   else if ( (*itInArg)->kind_ != kind )
1724   {
1725      // Error: bad argument type
1726   }
1727   else
1728   {
1729      args_.push_back( **itInArg );
1730   }
1731}
1732
1733
1734void
1735Path::invalidPath( const std::string &path,
1736                   int location )
1737{
1738   // Error: invalid path.
1739}
1740
1741
1742const Value &
1743Path::resolve( const Value &root ) const
1744{
1745   const Value *node = &root;
1746   for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
1747   {
1748      const PathArgument &arg = *it;
1749      if ( arg.kind_ == PathArgument::kindIndex )
1750      {
1751         if ( !node->isArray()  ||  node->isValidIndex( arg.index_ ) )
1752         {
1753            // Error: unable to resolve path (array value expected at position...
1754         }
1755         node = &((*node)[arg.index_]);
1756      }
1757      else if ( arg.kind_ == PathArgument::kindKey )
1758      {
1759         if ( !node->isObject() )
1760         {
1761            // Error: unable to resolve path (object value expected at position...)
1762         }
1763         node = &((*node)[arg.key_]);
1764         if ( node == &Value::null )
1765         {
1766            // Error: unable to resolve path (object has no member named '' at position...)
1767         }
1768      }
1769   }
1770   return *node;
1771}
1772
1773
1774Value
1775Path::resolve( const Value &root,
1776               const Value &defaultValue ) const
1777{
1778   const Value *node = &root;
1779   for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
1780   {
1781      const PathArgument &arg = *it;
1782      if ( arg.kind_ == PathArgument::kindIndex )
1783      {
1784         if ( !node->isArray()  ||  node->isValidIndex( arg.index_ ) )
1785            return defaultValue;
1786         node = &((*node)[arg.index_]);
1787      }
1788      else if ( arg.kind_ == PathArgument::kindKey )
1789      {
1790         if ( !node->isObject() )
1791            return defaultValue;
1792         node = &((*node)[arg.key_]);
1793         if ( node == &Value::null )
1794            return defaultValue;
1795      }
1796   }
1797   return *node;
1798}
1799
1800
1801Value &
1802Path::make( Value &root ) const
1803{
1804   Value *node = &root;
1805   for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
1806   {
1807      const PathArgument &arg = *it;
1808      if ( arg.kind_ == PathArgument::kindIndex )
1809      {
1810         if ( !node->isArray() )
1811         {
1812            // Error: node is not an array at position ...
1813         }
1814         node = &((*node)[arg.index_]);
1815      }
1816      else if ( arg.kind_ == PathArgument::kindKey )
1817      {
1818         if ( !node->isObject() )
1819         {
1820            // Error: node is not an object at position...
1821         }
1822         node = &((*node)[arg.key_]);
1823      }
1824   }
1825   return *node;
1826}
1827
1828
1829} // namespace Json
Property changes on: trunk/src/lib/web/json/json_value.cpp
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/lib/web/json/reader.h
r0r24796
1// Copyright 2007-2010 Baptiste Lepilleur
2// Distributed under MIT license, or public domain if desired and
3// recognized in your jurisdiction.
4// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
5
6#ifndef CPPTL_JSON_READER_H_INCLUDED
7# define CPPTL_JSON_READER_H_INCLUDED
8
9#if !defined(JSON_IS_AMALGAMATION)
10# include "features.h"
11# include "value.h"
12#endif // if !defined(JSON_IS_AMALGAMATION)
13# include <deque>
14# include <stack>
15# include <string>
16# include <iostream>
17
18namespace Json {
19
20   /** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a Value.
21    *
22    */
23   class JSON_API Reader
24   {
25   public:
26      typedef char Char;
27      typedef const Char *Location;
28
29      /** \brief Constructs a Reader allowing all features
30       * for parsing.
31       */
32      Reader();
33
34      /** \brief Constructs a Reader allowing the specified feature set
35       * for parsing.
36       */
37      Reader( const Features &features );
38
39      /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
40       * \param document UTF-8 encoded string containing the document to read.
41       * \param root [out] Contains the root value of the document if it was
42       *             successfully parsed.
43       * \param collectComments \c true to collect comment and allow writing them back during
44       *                        serialization, \c false to discard comments.
45       *                        This parameter is ignored if Features::allowComments_
46       *                        is \c false.
47       * \return \c true if the document was successfully parsed, \c false if an error occurred.
48       */
49      bool parse( const std::string &document,
50                  Value &root,
51                  bool collectComments = true );
52
53      /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
54       * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the document to read.
55       * \param endDoc Pointer on the end of the UTF-8 encoded string of the document to read.
56       \               Must be >= beginDoc.
57       * \param root [out] Contains the root value of the document if it was
58       *             successfully parsed.
59       * \param collectComments \c true to collect comment and allow writing them back during
60       *                        serialization, \c false to discard comments.
61       *                        This parameter is ignored if Features::allowComments_
62       *                        is \c false.
63       * \return \c true if the document was successfully parsed, \c false if an error occurred.
64       */
65      bool parse( const char *beginDoc, const char *endDoc,
66                  Value &root,
67                  bool collectComments = true );
68
69      /// \brief Parse from input stream.
70      /// \see Json::operator>>(std::istream&, Json::Value&).
71      bool parse( std::istream &is,
72                  Value &root,
73                  bool collectComments = true );
74
75      /** \brief Returns a user friendly string that list errors in the parsed document.
76       * \return Formatted error message with the list of errors with their location in
77       *         the parsed document. An empty string is returned if no error occurred
78       *         during parsing.
79       * \deprecated Use getFormattedErrorMessages() instead (typo fix).
80       */
81      JSONCPP_DEPRECATED("Use getFormattedErrorMessages instead")
82      std::string getFormatedErrorMessages() const;
83
84      /** \brief Returns a user friendly string that list errors in the parsed document.
85       * \return Formatted error message with the list of errors with their location in
86       *         the parsed document. An empty string is returned if no error occurred
87       *         during parsing.
88       */
89      std::string getFormattedErrorMessages() const;
90
91   private:
92      enum TokenType
93      {
94         tokenEndOfStream = 0,
95         tokenObjectBegin,
96         tokenObjectEnd,
97         tokenArrayBegin,
98         tokenArrayEnd,
99         tokenString,
100         tokenNumber,
101         tokenTrue,
102         tokenFalse,
103         tokenNull,
104         tokenArraySeparator,
105         tokenMemberSeparator,
106         tokenComment,
107         tokenError
108      };
109
110      class Token
111      {
112      public:
113         TokenType type_;
114         Location start_;
115         Location end_;
116      };
117
118      class ErrorInfo
119      {
120      public:
121         Token token_;
122         std::string message_;
123         Location extra_;
124      };
125
126      typedef std::deque<ErrorInfo> Errors;
127
128      bool expectToken( TokenType type, Token &token, const char *message );
129      bool readToken( Token &token );
130      void skipSpaces();
131      bool match( Location pattern,
132                  int patternLength );
133      bool readComment();
134      bool readCStyleComment();
135      bool readCppStyleComment();
136      bool readString();
137      void readNumber();
138      bool readValue();
139      bool readObject( Token &token );
140      bool readArray( Token &token );
141      bool decodeNumber( Token &token );
142      bool decodeString( Token &token );
143      bool decodeString( Token &token, std::string &decoded );
144      bool decodeDouble( Token &token );
145      bool decodeUnicodeCodePoint( Token &token,
146                                   Location &current,
147                                   Location end,
148                                   unsigned int &unicode );
149      bool decodeUnicodeEscapeSequence( Token &token,
150                                        Location &current,
151                                        Location end,
152                                        unsigned int &unicode );
153      bool addError( const std::string &message,
154                     Token &token,
155                     Location extra = 0 );
156      bool recoverFromError( TokenType skipUntilToken );
157      bool addErrorAndRecover( const std::string &message,
158                               Token &token,
159                               TokenType skipUntilToken );
160      void skipUntilSpace();
161      Value &currentValue();
162      Char getNextChar();
163      void getLocationLineAndColumn( Location location,
164                                     int &line,
165                                     int &column ) const;
166      std::string getLocationLineAndColumn( Location location ) const;
167      void addComment( Location begin,
168                       Location end,
169                       CommentPlacement placement );
170      void skipCommentTokens( Token &token );
171   
172      typedef std::stack<Value *> Nodes;
173      Nodes nodes_;
174      Errors errors_;
175      std::string document_;
176      Location begin_;
177      Location end_;
178      Location current_;
179      Location lastValueEnd_;
180      Value *lastValue_;
181      std::string commentsBefore_;
182      Features features_;
183      bool collectComments_;
184   };
185
186   /** \brief Read from 'sin' into 'root'.
187
188    Always keep comments from the input JSON.
189
190    This can be used to read a file into a particular sub-object.
191    For example:
192    \code
193    Json::Value root;
194    cin >> root["dir"]["file"];
195    cout << root;
196    \endcode
197    Result:
198    \verbatim
199    {
200    "dir": {
201        "file": {
202        // The input stream JSON would be nested here.
203        }
204    }
205    }
206    \endverbatim
207    \throw std::exception on parse error.
208    \see Json::operator<<()
209   */
210   std::istream& operator>>( std::istream&, Value& );
211
212} // namespace Json
213
214#endif // CPPTL_JSON_READER_H_INCLUDED
Property changes on: trunk/src/lib/web/json/reader.h
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/lib/web/json/config.h
r0r24796
1// Copyright 2007-2010 Baptiste Lepilleur
2// Distributed under MIT license, or public domain if desired and
3// recognized in your jurisdiction.
4// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
5
6#ifndef JSON_CONFIG_H_INCLUDED
7# define JSON_CONFIG_H_INCLUDED
8
9/// If defined, indicates that json library is embedded in CppTL library.
10//# define JSON_IN_CPPTL 1
11
12/// If defined, indicates that json may leverage CppTL library
13//#  define JSON_USE_CPPTL 1
14/// If defined, indicates that cpptl vector based map should be used instead of std::map
15/// as Value container.
16//#  define JSON_USE_CPPTL_SMALLMAP 1
17/// If defined, indicates that Json specific container should be used
18/// (hash table & simple deque container with customizable allocator).
19/// THIS FEATURE IS STILL EXPERIMENTAL! There is know bugs: See #3177332
20//#  define JSON_VALUE_USE_INTERNAL_MAP 1
21/// Force usage of standard new/malloc based allocator instead of memory pool based allocator.
22/// The memory pools allocator used optimization (initializing Value and ValueInternalLink
23/// as if it was a POD) that may cause some validation tool to report errors.
24/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined.
25//#  define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1
26
27/// If defined, indicates that Json use exception to report invalid type manipulation
28/// instead of C assert macro.
29# define JSON_USE_EXCEPTION 1
30
31/// If defined, indicates that the source file is amalgated
32/// to prevent private header inclusion.
33/// Remarks: it is automatically defined in the generated amalgated header.
34// #define JSON_IS_AMALGAMATION
35
36
37# ifdef JSON_IN_CPPTL
38#  include <cpptl/config.h>
39#  ifndef JSON_USE_CPPTL
40#   define JSON_USE_CPPTL 1
41#  endif
42# endif
43
44# ifdef JSON_IN_CPPTL
45#  define JSON_API CPPTL_API
46# elif defined(JSON_DLL_BUILD)
47#  define JSON_API __declspec(dllexport)
48# elif defined(JSON_DLL)
49#  define JSON_API __declspec(dllimport)
50# else
51#  define JSON_API
52# endif
53
54// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for integer
55// Storages, and 64 bits integer support is disabled.
56// #define JSON_NO_INT64 1
57
58#if defined(_MSC_VER)  &&  _MSC_VER <= 1200 // MSVC 6
59// Microsoft Visual Studio 6 only support conversion from __int64 to double
60// (no conversion from unsigned __int64).
61#define JSON_USE_INT64_DOUBLE_CONVERSION 1
62#endif // if defined(_MSC_VER)  &&  _MSC_VER < 1200 // MSVC 6
63
64#if defined(_MSC_VER)  &&  _MSC_VER >= 1500 // MSVC 2008
65/// Indicates that the following function is deprecated.
66# define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
67#endif
68
69#if !defined(JSONCPP_DEPRECATED)
70# define JSONCPP_DEPRECATED(message)
71#endif // if !defined(JSONCPP_DEPRECATED)
72
73namespace Json {
74   typedef int Int;
75   typedef unsigned int UInt;
76# if defined(JSON_NO_INT64)
77   typedef int LargestInt;
78   typedef unsigned int LargestUInt;
79#  undef JSON_HAS_INT64
80# else // if defined(JSON_NO_INT64)
81   // For Microsoft Visual use specific types as long long is not supported
82#  if defined(_MSC_VER) // Microsoft Visual Studio
83   typedef __int64 Int64;
84   typedef unsigned __int64 UInt64;
85#  else // if defined(_MSC_VER) // Other platforms, use long long
86   typedef long long int Int64;
87   typedef unsigned long long int UInt64;
88#  endif // if defined(_MSC_VER)
89   typedef Int64 LargestInt;
90   typedef UInt64 LargestUInt;
91#  define JSON_HAS_INT64
92# endif // if defined(JSON_NO_INT64)
93} // end namespace Json
94
95
96#endif // JSON_CONFIG_H_INCLUDED
Property changes on: trunk/src/lib/web/json/config.h
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/lib/web/json/json_tool.h
r0r24796
1// Copyright 2007-2010 Baptiste Lepilleur
2// Distributed under MIT license, or public domain if desired and
3// recognized in your jurisdiction.
4// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
5
6#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
7# define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
8
9/* This header provides common string manipulation support, such as UTF-8,
10 * portable conversion from/to string...
11 *
12 * It is an internal header that must not be exposed.
13 */
14
15namespace Json {
16
17/// Converts a unicode code-point to UTF-8.
18static inline std::string
19codePointToUTF8(unsigned int cp)
20{
21   std::string result;
22   
23   // based on description from http://en.wikipedia.org/wiki/UTF-8
24
25   if (cp <= 0x7f)
26   {
27      result.resize(1);
28      result[0] = static_cast<char>(cp);
29   }
30   else if (cp <= 0x7FF)
31   {
32      result.resize(2);
33      result[1] = static_cast<char>(0x80 | (0x3f & cp));
34      result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
35   }
36   else if (cp <= 0xFFFF)
37   {
38      result.resize(3);
39      result[2] = static_cast<char>(0x80 | (0x3f & cp));
40      result[1] = 0x80 | static_cast<char>((0x3f & (cp >> 6)));
41      result[0] = 0xE0 | static_cast<char>((0xf & (cp >> 12)));
42   }
43   else if (cp <= 0x10FFFF)
44   {
45      result.resize(4);
46      result[3] = static_cast<char>(0x80 | (0x3f & cp));
47      result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
48      result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
49      result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
50   }
51
52   return result;
53}
54
55
56/// Returns true if ch is a control character (in range [0,32[).
57static inline bool
58isControlCharacter(char ch)
59{
60   return ch > 0 && ch <= 0x1F;
61}
62
63
64enum {
65   /// Constant that specify the size of the buffer that must be passed to uintToString.
66   uintToStringBufferSize = 3*sizeof(LargestUInt)+1
67};
68
69// Defines a char buffer for use with uintToString().
70typedef char UIntToStringBuffer[uintToStringBufferSize];
71
72
73/** Converts an unsigned integer to string.
74 * @param value Unsigned interger to convert to string
75 * @param current Input/Output string buffer.
76 *        Must have at least uintToStringBufferSize chars free.
77 */
78static inline void
79uintToString( LargestUInt value,
80              char *&current )
81{
82   *--current = 0;
83   do
84   {
85      *--current = char(value % 10) + '0';
86      value /= 10;
87   }
88   while ( value != 0 );
89}
90
91} // namespace Json {
92
93#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED
Property changes on: trunk/src/lib/web/json/json_tool.h
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/mame.c
r24795r24796
8585#include "validity.h"
8686#include "debug/debugcon.h"
8787#include "web/mongoose.h"
88#include "web/json/json.h"
8889#include <time.h>
8990
9091
r24795r24796
131132   return (&machine == global_machine);
132133}
133134
135// This function will be called by mongoose on every new request.
136static int begin_request_handler(struct mg_connection *conn) {
137   const struct mg_request_info *request_info = mg_get_request_info(conn);
138   if (!strcmp(request_info->uri, "/hello")) {
139      Json::Value data;
140      data["key1"] = "data1";
141      data["key2"] = "data2";
142      data["key3"] = "data3";
143      data["key4"] = "data4";
144     
145      Json::FastWriter writer;
146      const char *json = writer.write(data).c_str();
147     // Send HTTP reply to the client
148      mg_printf(conn,
149            "HTTP/1.1 200 OK\r\n"
150            "Content-Type: text/plain\r\n"
151            "Content-Length: %d\r\n"        // Always set Content-Length
152            "\r\n"
153            "%s",
154            (int)strlen(json), json);
134155
156      // Returning non-zero tells mongoose that our function has replied to
157      // the client, and mongoose should not send client any more data.
158      return 1;
159   }
160   return 0;
161}
135162/*-------------------------------------------------
136163    mame_execute - run the core emulation
137164-------------------------------------------------*/
r24795r24796
157184
158185   // Prepare callbacks structure.
159186   memset(&callbacks, 0, sizeof(callbacks));
187   callbacks.begin_request = begin_request_handler;
160188
161189   // Start the web server.
162190   if (options.http())

Previous 199869 Revisions Next


© 1997-2024 The MAME Team