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