ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/cf.schmorp.de/dclient/src/backend/json/json_value.cpp
Revision: 1.2
Committed: Mon Oct 18 06:53:59 2010 UTC (15 years, 11 months ago) by sf-pippijn
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +2 -2 lines
Log Message:
gcc 4.5; moved some code; background colour support

File Contents

# User Rev Content
1 sf-pippijn 1.1 #include "adt/make/cast.h"
2    
3     #include "json_batchallocator.h"
4     #include <cassert>
5     #include <cstddef> /* size_t */
6     #include <cstring>
7     #include <iostream>
8     #include <json/value.h>
9     #include <json/writer.h>
10     #include <stdexcept>
11     #include <utility>
12    
13     #define JSON_ASSERT_UNREACHABLE assert (false)
14     #define JSON_ASSERT(condition) assert (condition); /* @todo <= change this into an exception throw */
15     #define JSON_ASSERT_MESSAGE(condition, message) if (!(condition)) throw std::runtime_error (message);
16    
17     namespace Json
18     {
19    
20     const Value Value::null;
21     const Int Value::minInt = Int (~(UInt (-1) / 2));
22     const Int Value::maxInt = Int (UInt (-1) / 2);
23     const UInt Value::maxUInt = UInt (-1);
24    
25     ValueAllocator::~ValueAllocator ()
26     {
27     }
28    
29     class DefaultValueAllocator
30     : public ValueAllocator
31     {
32     public:
33     virtual
34     ~DefaultValueAllocator ()
35     {
36     }
37    
38     virtual char *
39     makeMemberName (const char *memberName)
40     {
41     return duplicateStringValue (memberName);
42     }
43    
44     virtual void
45     releaseMemberName (char *memberName)
46     {
47     releaseStringValue (memberName);
48     }
49    
50     virtual char *
51     duplicateStringValue (const char *value, unsigned int length = unknown)
52     {
53     /*
54     * @todo invesgate this old optimization
55     * if ( !value || value[0] == 0 )
56     * return 0;
57     */
58    
59     if (length == unknown)
60     length = (unsigned int)strlen (value);
61     char *newString = static_cast<char *> (malloc (length + 1));
62     memcpy (newString, value, length);
63     newString[length] = 0;
64     return newString;
65     }
66    
67     virtual void
68     releaseStringValue (char *value)
69     {
70     if (value)
71     free (value);
72     }
73     };
74    
75     static ValueAllocator * &
76     valueAllocator ()
77     {
78     static DefaultValueAllocator defaultAllocator;
79     static ValueAllocator *valueAllocator = &defaultAllocator;
80    
81     return valueAllocator;
82     }
83    
84     static struct DummyValueAllocatorInitializer
85     {
86     DummyValueAllocatorInitializer ()
87     {
88     valueAllocator (); /* ensure valueAllocator() statics are initialized before main(). */
89     }
90     } dummyValueAllocatorInitializer;
91    
92    
93    
94     /*
95     * //////////////////////////////////////////////////////////////////
96     * //////////////////////////////////////////////////////////////////
97     * //////////////////////////////////////////////////////////////////
98     * class ValueIteratorBase
99     * //////////////////////////////////////////////////////////////////
100     * //////////////////////////////////////////////////////////////////
101     * //////////////////////////////////////////////////////////////////
102     */
103    
104     ValueIteratorBase::ValueIteratorBase ()
105     : current_ ()
106     , isNull_ (true)
107     {
108     }
109    
110     ValueIteratorBase::ValueIteratorBase (const Value::ObjectValues::iterator &current)
111     : current_ (current)
112     , isNull_ (false)
113     {
114     }
115    
116     Value &
117     ValueIteratorBase::deref () const
118     {
119     return current_->second;
120     }
121    
122     void
123     ValueIteratorBase::increment ()
124     {
125     ++current_;
126     }
127    
128     void
129     ValueIteratorBase::decrement ()
130     {
131     --current_;
132     }
133    
134     ValueIteratorBase::difference_type
135     ValueIteratorBase::computeDistance (const SelfType &other) const
136     {
137     /*
138     * Iterator for null value are initialized using the default
139     * constructor, which initialize current_ to the default
140     * std::map::iterator. As begin() and end() are two instance
141     * of the default std::map::iterator, they can not be compared.
142     * To allow this, we handle this comparison specifically.
143     */
144     if (isNull_ && other.isNull_)
145     return 0;
146    
147    
148     /*
149     * Usage of std::distance is not portable (does not compile with Sun Studio 12 RogueWave STL,
150     * which is the one used by default).
151     * Using a portable hand-made version for non random iterator instead:
152     * return difference_type( std::distance( current_, other.current_ ) );
153     */
154     difference_type myDistance = 0;
155     for (Value::ObjectValues::iterator it = current_; it != other.current_; ++it)
156     ++myDistance;
157     return myDistance;
158     }
159    
160     bool
161     ValueIteratorBase::isEqual (const SelfType &other) const
162     {
163     if (isNull_)
164     return other.isNull_;
165     return current_ == other.current_;
166     }
167    
168     void
169     ValueIteratorBase::copy (const SelfType &other)
170     {
171     current_ = other.current_;
172     }
173    
174     Value
175     ValueIteratorBase::key () const
176     {
177     const Value::CZString czstring = (*current_).first;
178    
179     if (czstring.c_str ())
180     {
181     if (czstring.isStaticString ())
182     return Value (StaticString (czstring.c_str ()));
183     return Value (czstring.c_str ());
184     }
185     return Value (czstring.index ());
186     }
187    
188     UInt
189     ValueIteratorBase::index () const
190     {
191     const Value::CZString czstring = (*current_).first;
192    
193     if (!czstring.c_str ())
194     return czstring.index ();
195     return Value::UInt (-1);
196     }
197    
198     const char *
199     ValueIteratorBase::memberName () const
200     {
201     const char *name = (*current_).first.c_str ();
202    
203     return name ? name : "";
204     }
205    
206     /*
207     * //////////////////////////////////////////////////////////////////
208     * //////////////////////////////////////////////////////////////////
209     * //////////////////////////////////////////////////////////////////
210     * class ValueConstIterator
211     * //////////////////////////////////////////////////////////////////
212     * //////////////////////////////////////////////////////////////////
213     * //////////////////////////////////////////////////////////////////
214     */
215    
216     ValueConstIterator::ValueConstIterator ()
217     {
218     }
219    
220     ValueConstIterator::ValueConstIterator (const Value::ObjectValues::iterator &current)
221     : ValueIteratorBase (current)
222     {
223     }
224    
225     ValueConstIterator &
226     ValueConstIterator::operator = (const ValueIteratorBase &other)
227     {
228     copy (other);
229     return *this;
230     }
231    
232     /*
233     * //////////////////////////////////////////////////////////////////
234     * //////////////////////////////////////////////////////////////////
235     * //////////////////////////////////////////////////////////////////
236     * class ValueIterator
237     * //////////////////////////////////////////////////////////////////
238     * //////////////////////////////////////////////////////////////////
239     * //////////////////////////////////////////////////////////////////
240     */
241    
242     ValueIterator::ValueIterator ()
243     {
244     }
245    
246     ValueIterator::ValueIterator (const Value::ObjectValues::iterator &current)
247     : ValueIteratorBase (current)
248     {
249     }
250    
251     ValueIterator::ValueIterator (const ValueConstIterator &other)
252     : ValueIteratorBase (other)
253     {
254     }
255    
256     ValueIterator::ValueIterator (const ValueIterator &other)
257     : ValueIteratorBase (other)
258     {
259     }
260    
261     ValueIterator &
262     ValueIterator::operator = (const SelfType &other)
263     {
264     copy (other);
265     return *this;
266     }
267    
268    
269     /*
270     * //////////////////////////////////////////////////////////////////
271     * //////////////////////////////////////////////////////////////////
272     * //////////////////////////////////////////////////////////////////
273     * class Value::CommentInfo
274     * //////////////////////////////////////////////////////////////////
275     * //////////////////////////////////////////////////////////////////
276     * //////////////////////////////////////////////////////////////////
277     */
278    
279    
280     Value::CommentInfo::CommentInfo ()
281     : comment_ (0)
282     {
283     }
284    
285     Value::CommentInfo::~CommentInfo ()
286     {
287     if (comment_)
288     valueAllocator ()->releaseStringValue (comment_);
289     }
290    
291     void
292     Value::CommentInfo::setComment (const char *text)
293     {
294     if (comment_)
295     valueAllocator ()->releaseStringValue (comment_);
296     JSON_ASSERT (text);
297     JSON_ASSERT_MESSAGE (text[0] == '\0' || text[0] == '/', "Comments must start with /");
298     /* It seems that / ** / style comments are acceptable as well. */
299     comment_ = valueAllocator ()->duplicateStringValue (text);
300     }
301    
302     /*
303     * //////////////////////////////////////////////////////////////////
304     * //////////////////////////////////////////////////////////////////
305     * //////////////////////////////////////////////////////////////////
306     * class Value::CZString
307     * //////////////////////////////////////////////////////////////////
308     * //////////////////////////////////////////////////////////////////
309     * //////////////////////////////////////////////////////////////////
310     */
311    
312     /*
313     * Notes: index_ indicates if the string was allocated when
314     * a string is stored.
315     */
316    
317     Value::CZString::CZString (int index)
318     : cstr_ (0)
319     , index_ (index)
320     {
321     }
322    
323     Value::CZString::CZString (const char *cstr, DuplicationPolicy allocate)
324     : cstr_ (allocate == duplicate ? valueAllocator ()->makeMemberName (cstr)
325     : cstr)
326     , index_ (allocate)
327     {
328     }
329    
330     Value::CZString::CZString (const CZString &other)
331     : cstr_ (other.index_ != noDuplication && other.cstr_ != 0
332     ? valueAllocator ()->makeMemberName (other.cstr_)
333     : other.cstr_)
334     , index_ (other.cstr_ ? (other.index_ == noDuplication ? noDuplication
335     : duplicate)
336     : other.index_)
337     {
338     }
339    
340     Value::CZString::~CZString ()
341     {
342     if (cstr_ && index_ == duplicate)
343     valueAllocator ()->releaseMemberName (const_cast<char *> (cstr_));
344     }
345    
346     void
347     Value::CZString::swap (CZString &other)
348     {
349     std::swap (cstr_, other.cstr_);
350     std::swap (index_, other.index_);
351     }
352    
353     Value::CZString &
354     Value::CZString::operator = (const CZString &other)
355     {
356     CZString temp (other);
357    
358     swap (temp);
359     return *this;
360     }
361    
362     bool
363     Value::CZString::operator < (const CZString &other) const
364     {
365     if (cstr_)
366     return strcmp (cstr_, other.cstr_) < 0;
367     return index_ < other.index_;
368     }
369    
370     bool
371     Value::CZString::operator == (const CZString &other) const
372     {
373     if (cstr_)
374     return strcmp (cstr_, other.cstr_) == 0;
375     return index_ == other.index_;
376     }
377    
378     int
379     Value::CZString::index () const
380     {
381     return index_;
382     }
383    
384     const char *
385     Value::CZString::c_str () const
386     {
387     return cstr_;
388     }
389    
390     bool
391     Value::CZString::isStaticString () const
392     {
393     return index_ == noDuplication;
394     }
395    
396     /*
397     * //////////////////////////////////////////////////////////////////
398     * //////////////////////////////////////////////////////////////////
399     * //////////////////////////////////////////////////////////////////
400     * class Value::Value
401     * //////////////////////////////////////////////////////////////////
402     * //////////////////////////////////////////////////////////////////
403     * //////////////////////////////////////////////////////////////////
404     */
405    
406     /*! \internal Default constructor initialization must be equivalent to:
407     * memset( this, 0, sizeof(Value) )
408     * This optimization is used in ValueInternalMap fast allocator.
409     */
410     Value::Value (ValueType type)
411     : comments_ (nullptr)
412     , type_ (type)
413     , allocated_ (0)
414     {
415     switch (type)
416     {
417     case nullValue :
418     break;
419     case intValue :
420     case uintValue :
421     value_.int_ = 0;
422     break;
423     case realValue :
424     value_.real_ = 0.0;
425     break;
426     case stringValue:
427     value_.string_ = 0;
428     break;
429     case arrayValue:
430     case objectValue:
431     value_.map_ = new ObjectValues ();
432     break;
433     case booleanValue:
434     value_.bool_ = false;
435     break;
436     default:
437     JSON_ASSERT_UNREACHABLE;
438     }
439     }
440    
441     Value::Value (Int value)
442     : comments_ (nullptr)
443     , type_ (intValue)
444     {
445     value_.int_ = value;
446     }
447    
448     Value::Value (UInt value)
449     : comments_ (nullptr)
450     , type_ (uintValue)
451     {
452     value_.uint_ = value;
453     }
454    
455     Value::Value (double value)
456     : comments_ (nullptr)
457     , type_ (realValue)
458     {
459     value_.real_ = value;
460     }
461    
462     Value::Value (const char *value)
463     : comments_ (nullptr)
464     , type_ (stringValue)
465     , allocated_ (true)
466     {
467     value_.string_ = valueAllocator ()->duplicateStringValue (value);
468     }
469    
470     Value::Value (const char *beginValue, const char *endValue)
471     : comments_ (nullptr)
472     , type_ (stringValue)
473     , allocated_ (true)
474     {
475     value_.string_ = valueAllocator ()->duplicateStringValue (beginValue,
476     UInt (endValue - beginValue));
477     }
478    
479     static Value
480     make_value (make::value const &v)
481     {
482     using make::value;
483     using make::value_cast;
484     switch (v.type_code ())
485     {
486     case value::VALUE:
487     if (is_integral (*v.type))
488     if (is_signed (*v.type))
489     return Value (value_cast<Int> (v));
490     else
491     return Value (value_cast<UInt> (v));
492     else if (is_floating_point (*v.type))
493     return Value (value_cast<double> (v));
494     return Value (v.str ());
495     case value::ARRAY:
496     return Value (v.array ());
497     case value::MAP:
498     return Value (v.map ());
499     default:
500     throw __func__;
501     }
502     }
503    
504     Value::Value (make::array const &value)
505     : comments_ (nullptr)
506     , type_ (nullValue)
507     , allocated_ (false)
508     {
509     UInt i = 0;
510 sf-pippijn 1.2 foreach (make::value const &v, value.data)
511 sf-pippijn 1.1 (*this)[i++] = make_value (v);
512     }
513    
514     Value::Value (make::map const &value)
515     : comments_ (nullptr)
516     , type_ (nullValue)
517     , allocated_ (false)
518     {
519 sf-pippijn 1.2 foreach (make::value_pair const &v, value.data)
520 sf-pippijn 1.1 (*this)[v.first.str ()] = make_value (v.second);
521     }
522    
523     Value::Value (const std::string &value)
524     : comments_ (nullptr)
525     , type_ (stringValue)
526     , allocated_ (true)
527     {
528     value_.string_ = valueAllocator ()->duplicateStringValue (value.c_str (),
529     (unsigned int)value.length ());
530     }
531    
532     Value::Value (const StaticString &value)
533     : comments_ (nullptr)
534     , type_ (stringValue)
535     , allocated_ (false)
536     {
537     value_.string_ = const_cast<char *> (value.c_str ());
538     }
539    
540     Value::Value (bool value)
541     : comments_ (nullptr)
542     , type_ (booleanValue)
543     {
544     value_.bool_ = value;
545     }
546    
547     Value::Value (const Value &other)
548     : comments_ (nullptr)
549     , type_ (other.type_)
550     {
551     switch (type_)
552     {
553     case nullValue:
554     case intValue:
555     case uintValue:
556     case realValue:
557     case booleanValue:
558     value_ = other.value_;
559     break;
560     case stringValue:
561     if (other.value_.string_)
562     {
563     value_.string_ = valueAllocator ()->duplicateStringValue (other.value_.string_);
564     allocated_ = true;
565     }
566     else
567     value_.string_ = 0;
568     break;
569     case arrayValue:
570     case objectValue:
571     value_.map_ = new ObjectValues (*other.value_.map_);
572     break;
573     default:
574     JSON_ASSERT_UNREACHABLE;
575     }
576     if (other.comments_)
577     {
578     comments_ = new CommentInfo[numberOfCommentPlacement];
579     for (int comment = 0; comment < numberOfCommentPlacement; ++comment)
580     {
581     const CommentInfo &otherComment = other.comments_[comment];
582     if (otherComment.comment_)
583     comments_[comment].setComment (otherComment.comment_);
584     }
585     }
586     }
587    
588     Value::~Value ()
589     {
590     switch (type_)
591     {
592     case nullValue:
593     case intValue:
594     case uintValue:
595     case realValue:
596     case booleanValue:
597     break;
598     case stringValue:
599     if (allocated_)
600     valueAllocator ()->releaseStringValue (value_.string_);
601     break;
602     case arrayValue:
603     case objectValue:
604     delete value_.map_;
605     break;
606     default:
607     JSON_ASSERT_UNREACHABLE;
608     }
609    
610     if (comments_)
611     delete[] comments_;
612     }
613    
614     Value &
615     Value::operator = (const Value &other)
616     {
617     Value temp (other);
618    
619     swap (temp);
620     return *this;
621     }
622    
623     void
624     Value::swap (Value &other)
625     {
626     ValueType temp = type_;
627    
628     type_ = other.type_;
629     other.type_ = temp;
630     std::swap (value_, other.value_);
631     int temp2 = allocated_;
632     allocated_ = other.allocated_;
633     other.allocated_ = temp2;
634     }
635    
636     ValueType
637     Value::type () const
638     {
639     return type_;
640     }
641    
642     int
643     Value::compare (const Value &other)
644     {
645     /*
646     * int typeDelta = other.type_ - type_;
647     * switch ( type_ )
648     * {
649     * case nullValue:
650     *
651     * return other.type_ == type_;
652     * case intValue:
653     * if ( other.type_.isNumeric()
654     * case uintValue:
655     * case realValue:
656     * case booleanValue:
657     * break;
658     * case stringValue,
659     * break;
660     * case arrayValue:
661     * delete value_.array_;
662     * break;
663     * case objectValue:
664     * delete value_.map_;
665     * default:
666     * JSON_ASSERT_UNREACHABLE;
667     * }
668     */
669     return 0; /* unreachable */
670     }
671    
672     bool
673     Value::operator < (const Value &other) const
674     {
675     int typeDelta = type_ - other.type_;
676    
677     if (typeDelta)
678     return typeDelta < 0 ? true : false;
679     switch (type_)
680     {
681     case nullValue:
682     return false;
683     case intValue:
684     return value_.int_ < other.value_.int_;
685     case uintValue:
686     return value_.uint_ < other.value_.uint_;
687     case realValue:
688     return value_.real_ < other.value_.real_;
689     case booleanValue:
690     return value_.bool_ < other.value_.bool_;
691     case stringValue:
692     return (value_.string_ == 0 && other.value_.string_)
693     || (other.value_.string_
694     && value_.string_
695     && strcmp (value_.string_, other.value_.string_) < 0);
696     case arrayValue:
697     case objectValue:
698     {
699     int delta = int(value_.map_->size () - other.value_.map_->size ());
700     if (delta)
701     return delta < 0;
702     return (*value_.map_) < (*other.value_.map_);
703     }
704     default:
705     JSON_ASSERT_UNREACHABLE;
706     }
707     return 0; /* unreachable */
708     }
709    
710     bool
711     Value::operator <= (const Value &other) const
712     {
713     return !(other > *this);
714     }
715    
716     bool
717     Value::operator >= (const Value &other) const
718     {
719     return !(*this < other);
720     }
721    
722     bool
723     Value::operator > (const Value &other) const
724     {
725     return other < *this;
726     }
727    
728     bool
729     Value::operator == (const Value &other) const
730     {
731     /*
732     * if ( type_ != other.type_ )
733     * GCC 2.95.3 says:
734     * attempt to take address of bit-field structure member `Json::Value::type_'
735     * Beats me, but a temp solves the problem.
736     */
737     int temp = other.type_;
738    
739     if (type_ != temp)
740     return false;
741     switch (type_)
742     {
743     case nullValue:
744     return true;
745     case intValue:
746     return value_.int_ == other.value_.int_;
747     case uintValue:
748     return value_.uint_ == other.value_.uint_;
749     case realValue:
750     return value_.real_ == other.value_.real_;
751     case booleanValue:
752     return value_.bool_ == other.value_.bool_;
753     case stringValue:
754     return (value_.string_ == other.value_.string_)
755     || (other.value_.string_
756     && value_.string_
757     && strcmp (value_.string_, other.value_.string_) == 0);
758     case arrayValue:
759     case objectValue:
760     return value_.map_->size () == other.value_.map_->size ()
761     && (*value_.map_) == (*other.value_.map_);
762     default:
763     JSON_ASSERT_UNREACHABLE;
764     }
765     return 0; /* unreachable */
766     }
767    
768     bool
769     Value::operator != (const Value &other) const
770     {
771     return !(*this == other);
772     }
773    
774     const char *
775     Value::asCString () const
776     {
777     JSON_ASSERT (type_ == stringValue);
778     return value_.string_;
779     }
780    
781     std::string
782     Value::asString () const
783     {
784     switch (type_)
785     {
786     case nullValue:
787     return "";
788     case stringValue:
789     return value_.string_ ? value_.string_ : "";
790     case booleanValue:
791     return value_.bool_ ? "true" : "false";
792     case intValue:
793     case uintValue:
794     case realValue:
795     case arrayValue:
796     case objectValue:
797     JSON_ASSERT_MESSAGE (false, "Type is not convertible to string");
798     default:
799     JSON_ASSERT_UNREACHABLE;
800     }
801     return ""; /* unreachable */
802     }
803    
804     Value::Int
805     Value::asInt () const
806     {
807     switch (type_)
808     {
809     case nullValue:
810     return 0;
811     case intValue:
812     return value_.int_;
813     case uintValue:
814     JSON_ASSERT_MESSAGE (value_.uint_ < (unsigned)maxInt, "integer out of signed integer range");
815     return value_.uint_;
816     case realValue:
817     JSON_ASSERT_MESSAGE (value_.real_ >= minInt && value_.real_ <= maxInt, "Real out of signed integer range");
818     return Int (value_.real_);
819     case booleanValue:
820     return value_.bool_ ? 1 : 0;
821     case stringValue:
822     case arrayValue:
823     case objectValue:
824     JSON_ASSERT_MESSAGE (false, "Type is not convertible to int");
825     default:
826     JSON_ASSERT_UNREACHABLE;
827     }
828     return 0; /* unreachable; */
829     }
830    
831     Value::UInt
832     Value::asUInt () const
833     {
834     switch (type_)
835     {
836     case nullValue:
837     return 0;
838     case intValue:
839     JSON_ASSERT_MESSAGE (value_.int_ >= 0, "Negative integer can not be converted to unsigned integer");
840     return value_.int_;
841     case uintValue:
842     return value_.uint_;
843     case realValue:
844     JSON_ASSERT_MESSAGE (value_.real_ >= 0 && value_.real_ <= maxUInt, "Real out of unsigned integer range");
845     return UInt (value_.real_);
846     case booleanValue:
847     return value_.bool_ ? 1 : 0;
848     case stringValue:
849     case arrayValue:
850     case objectValue:
851     JSON_ASSERT_MESSAGE (false, "Type is not convertible to uint");
852     default:
853     JSON_ASSERT_UNREACHABLE;
854     }
855     return 0; /* unreachable; */
856     }
857    
858     double
859     Value::asDouble () const
860     {
861     switch (type_)
862     {
863     case nullValue:
864     return 0.0;
865     case intValue:
866     return value_.int_;
867     case uintValue:
868     return value_.uint_;
869     case realValue:
870     return value_.real_;
871     case booleanValue:
872     return value_.bool_ ? 1.0 : 0.0;
873     case stringValue:
874     case arrayValue:
875     case objectValue:
876     JSON_ASSERT_MESSAGE (false, "Type is not convertible to double");
877     default:
878     JSON_ASSERT_UNREACHABLE;
879     }
880     return 0; /* unreachable; */
881     }
882    
883     bool
884     Value::asBool () const
885     {
886     switch (type_)
887     {
888     case nullValue:
889     return false;
890     case intValue:
891     case uintValue:
892     return value_.int_ != 0;
893     case realValue:
894     return value_.real_ != 0.0;
895     case booleanValue:
896     return value_.bool_;
897     case stringValue:
898     return value_.string_ && value_.string_[0] != 0;
899     case arrayValue:
900     case objectValue:
901     return value_.map_->size () != 0;
902     default:
903     JSON_ASSERT_UNREACHABLE;
904     }
905     return false; /* unreachable; */
906     }
907    
908     bool
909     Value::isConvertibleTo (ValueType other) const
910     {
911     switch (type_)
912     {
913     case nullValue:
914     return true;
915     case intValue:
916     return (other == nullValue && value_.int_ == 0)
917     || other == intValue
918     || (other == uintValue && value_.int_ >= 0)
919     || other == realValue
920     || other == stringValue
921     || other == booleanValue;
922     case uintValue:
923     return (other == nullValue && value_.uint_ == 0)
924     || (other == intValue && value_.uint_ <= (unsigned)maxInt)
925     || other == uintValue
926     || other == realValue
927     || other == stringValue
928     || other == booleanValue;
929     case realValue:
930     return (other == nullValue && value_.real_ == 0.0)
931     || (other == intValue && value_.real_ >= minInt && value_.real_ <= maxInt)
932     || (other == uintValue && value_.real_ >= 0 && value_.real_ <= maxUInt)
933     || other == realValue
934     || other == stringValue
935     || other == booleanValue;
936     case booleanValue:
937     return (other == nullValue && value_.bool_ == false)
938     || other == intValue
939     || other == uintValue
940     || other == realValue
941     || other == stringValue
942     || other == booleanValue;
943     case stringValue:
944     return other == stringValue
945     || (other == nullValue && (!value_.string_ || value_.string_[0] == 0));
946     case arrayValue:
947     return other == arrayValue
948     || (other == nullValue && value_.map_->size () == 0);
949     case objectValue:
950     return other == objectValue
951     || (other == nullValue && value_.map_->size () == 0);
952     default:
953     JSON_ASSERT_UNREACHABLE;
954     }
955     return false; /* unreachable; */
956     }
957    
958     /* / Number of values in array or object */
959     Value::UInt
960     Value::size () const
961     {
962     switch (type_)
963     {
964     case nullValue:
965     case intValue:
966     case uintValue:
967     case realValue:
968     case booleanValue:
969     case stringValue:
970     return 0;
971     case arrayValue: /* size of the array is highest index + 1 */
972     if (!value_.map_->empty ())
973     {
974     ObjectValues::const_iterator itLast = value_.map_->end ();
975     --itLast;
976     return (*itLast).first.index () + 1;
977     }
978     return 0;
979     case objectValue:
980     return Int (value_.map_->size ());
981     default:
982     JSON_ASSERT_UNREACHABLE;
983     }
984     return 0; /* unreachable; */
985     }
986    
987     bool
988     Value::empty () const
989     {
990     if (isNull () || isArray () || isObject ())
991     return size () == 0u;
992     else
993     return false;
994     }
995    
996     bool
997     Value::operator ! () const
998     {
999     return isNull ();
1000     }
1001    
1002     void
1003     Value::clear ()
1004     {
1005     JSON_ASSERT (type_ == nullValue || type_ == arrayValue || type_ == objectValue);
1006    
1007     switch (type_)
1008     {
1009     case arrayValue:
1010     case objectValue:
1011     value_.map_->clear ();
1012     break;
1013     default:
1014     break;
1015     }
1016     }
1017    
1018     void
1019     Value::resize (UInt newSize)
1020     {
1021     JSON_ASSERT (type_ == nullValue || type_ == arrayValue);
1022     if (type_ == nullValue)
1023     *this = Value (arrayValue);
1024     UInt oldSize = size ();
1025     if (newSize == 0)
1026     clear ();
1027     else if (newSize > oldSize)
1028     (*this)[newSize - 1];
1029     else
1030     {
1031     for (UInt index = newSize; index < oldSize; ++index)
1032     value_.map_->erase (index);
1033     assert (size () == newSize);
1034     }
1035     }
1036    
1037     Value &
1038     Value::operator [] (UInt index)
1039     {
1040     JSON_ASSERT (type_ == nullValue || type_ == arrayValue);
1041     if (type_ == nullValue)
1042     *this = Value (arrayValue);
1043     CZString key (index);
1044     ObjectValues::iterator it = value_.map_->lower_bound (key);
1045     if (it != value_.map_->end () && (*it).first == key)
1046     return (*it).second;
1047    
1048     ObjectValues::value_type defaultValue (key, null);
1049     it = value_.map_->insert (it, defaultValue);
1050     return (*it).second;
1051     }
1052    
1053     const Value &
1054     Value::operator [] (UInt index) const
1055     {
1056     JSON_ASSERT (type_ == nullValue || type_ == arrayValue);
1057     if (type_ == nullValue)
1058     return null;
1059     CZString key (index);
1060     ObjectValues::const_iterator it = value_.map_->find (key);
1061     if (it == value_.map_->end ())
1062     return null;
1063     return (*it).second;
1064     }
1065    
1066     Value &
1067     Value::operator [] (const char *key)
1068     {
1069     return resolveReference (key, false);
1070     }
1071    
1072     Value &
1073     Value::resolveReference (const char *key, bool isStatic)
1074     {
1075     JSON_ASSERT (type_ == nullValue || type_ == objectValue);
1076     if (type_ == nullValue)
1077     *this = Value (objectValue);
1078     CZString actualKey (key, isStatic ? CZString::noDuplication
1079     : CZString::duplicateOnCopy);
1080     ObjectValues::iterator it = value_.map_->lower_bound (actualKey);
1081     if (it != value_.map_->end () && (*it).first == actualKey)
1082     return (*it).second;
1083    
1084     ObjectValues::value_type defaultValue (actualKey, null);
1085     it = value_.map_->insert (it, defaultValue);
1086     Value &value = (*it).second;
1087     return value;
1088     }
1089    
1090     Value
1091     Value::get (UInt index, const Value &defaultValue) const
1092     {
1093     const Value *value = &((*this)[index]);
1094    
1095     return value == &null ? defaultValue : *value;
1096     }
1097    
1098     bool
1099     Value::isValidIndex (UInt index) const
1100     {
1101     return index < size ();
1102     }
1103    
1104     const Value &
1105     Value::operator [] (const char *key) const
1106     {
1107     JSON_ASSERT (type_ == nullValue || type_ == objectValue);
1108     if (type_ == nullValue)
1109     return null;
1110     CZString actualKey (key, CZString::noDuplication);
1111     ObjectValues::const_iterator it = value_.map_->find (actualKey);
1112     if (it == value_.map_->end ())
1113     return null;
1114     return it->second;
1115     }
1116    
1117     Value &
1118     Value::operator [] (const std::string &key)
1119     {
1120     return (*this)[key.c_str ()];
1121     }
1122    
1123     const Value &
1124     Value::operator [] (const std::string &key) const
1125     {
1126     return (*this)[key.c_str ()];
1127     }
1128    
1129     Value &
1130     Value::operator [] (const StaticString &key)
1131     {
1132     return resolveReference (key.c_str (), true);
1133     }
1134    
1135     Value &
1136     Value::append (const Value &value)
1137     {
1138     return (*this)[size ()] = value;
1139     }
1140    
1141     Value
1142     Value::get (const char *key, const Value &defaultValue) const
1143     {
1144     const Value *value = &((*this)[key]);
1145    
1146     return value == &null ? defaultValue : *value;
1147     }
1148    
1149     Value
1150     Value::get (const std::string &key, const Value &defaultValue) const
1151     {
1152     return get (key.c_str (), defaultValue);
1153     }
1154    
1155     Value
1156     Value::removeMember (const char *key)
1157     {
1158     JSON_ASSERT (type_ == nullValue || type_ == objectValue);
1159     if (type_ == nullValue)
1160     return null;
1161     CZString actualKey (key, CZString::noDuplication);
1162     ObjectValues::iterator it = value_.map_->find (actualKey);
1163     if (it == value_.map_->end ())
1164     return null;
1165     Value old (it->second);
1166     value_.map_->erase (it);
1167     return old;
1168     }
1169    
1170     Value
1171     Value::removeMember (const std::string &key)
1172     {
1173     return removeMember (key.c_str ());
1174     }
1175    
1176     bool
1177     Value::isMember (const char *key) const
1178     {
1179     const Value *value = &((*this)[key]);
1180    
1181     return value != &null;
1182     }
1183    
1184     bool
1185     Value::isMember (const std::string &key) const
1186     {
1187     return isMember (key.c_str ());
1188     }
1189    
1190     Value::Members
1191     Value::getMemberNames () const
1192     {
1193     JSON_ASSERT (type_ == nullValue || type_ == objectValue);
1194     if (type_ == nullValue)
1195     return Value::Members ();
1196     Members members;
1197     members.reserve (value_.map_->size ());
1198     ObjectValues::const_iterator it = value_.map_->begin ();
1199     ObjectValues::const_iterator itEnd = value_.map_->end ();
1200     for (; it != itEnd; ++it)
1201     members.push_back (std::string ((*it).first.c_str ()));
1202     return members;
1203     }
1204    
1205     bool
1206     Value::isNull () const
1207     {
1208     return type_ == nullValue;
1209     }
1210    
1211     bool
1212     Value::isBool () const
1213     {
1214     return type_ == booleanValue;
1215     }
1216    
1217     bool
1218     Value::isInt () const
1219     {
1220     return type_ == intValue;
1221     }
1222    
1223     bool
1224     Value::isUInt () const
1225     {
1226     return type_ == uintValue;
1227     }
1228    
1229     bool
1230     Value::isIntegral () const
1231     {
1232     return type_ == intValue
1233     || type_ == uintValue
1234     || type_ == booleanValue;
1235     }
1236    
1237     bool
1238     Value::isDouble () const
1239     {
1240     return type_ == realValue;
1241     }
1242    
1243     bool
1244     Value::isNumeric () const
1245     {
1246     return isIntegral () || isDouble ();
1247     }
1248    
1249     bool
1250     Value::isString () const
1251     {
1252     return type_ == stringValue;
1253     }
1254    
1255     bool
1256     Value::isArray () const
1257     {
1258     return type_ == nullValue || type_ == arrayValue;
1259     }
1260    
1261     bool
1262     Value::isObject () const
1263     {
1264     return type_ == nullValue || type_ == objectValue;
1265     }
1266    
1267     void
1268     Value::setComment (const char *comment, CommentPlacement placement)
1269     {
1270     if (!comments_)
1271     comments_ = new CommentInfo[numberOfCommentPlacement];
1272     comments_[placement].setComment (comment);
1273     }
1274    
1275     void
1276     Value::setComment (const std::string &comment, CommentPlacement placement)
1277     {
1278     setComment (comment.c_str (), placement);
1279     }
1280    
1281     bool
1282     Value::hasComment (CommentPlacement placement) const
1283     {
1284     return comments_ != 0 && comments_[placement].comment_ != 0;
1285     }
1286    
1287     std::string
1288     Value::getComment (CommentPlacement placement) const
1289     {
1290     if (hasComment (placement))
1291     return comments_[placement].comment_;
1292     return "";
1293     }
1294    
1295     std::string
1296     Value::toStyledString () const
1297     {
1298     StyledWriter writer;
1299    
1300     return writer.write (*this);
1301     }
1302    
1303     Value::const_iterator
1304     Value::begin () const
1305     {
1306     switch (type_)
1307     {
1308     case arrayValue:
1309     case objectValue:
1310     if (value_.map_)
1311     return const_iterator (value_.map_->begin ());
1312     break;
1313     default:
1314     break;
1315     }
1316     return const_iterator ();
1317     }
1318    
1319     Value::const_iterator
1320     Value::end () const
1321     {
1322     switch (type_)
1323     {
1324     case arrayValue:
1325     case objectValue:
1326     if (value_.map_)
1327     return const_iterator (value_.map_->end ());
1328     break;
1329     default:
1330     break;
1331     }
1332     return const_iterator ();
1333     }
1334    
1335     Value::iterator
1336     Value::begin ()
1337     {
1338     switch (type_)
1339     {
1340     case arrayValue:
1341     case objectValue:
1342     if (value_.map_)
1343     return iterator (value_.map_->begin ());
1344     break;
1345     default:
1346     break;
1347     }
1348     return iterator ();
1349     }
1350    
1351     Value::iterator
1352     Value::end ()
1353     {
1354     switch (type_)
1355     {
1356     case arrayValue:
1357     case objectValue:
1358     if (value_.map_)
1359     return iterator (value_.map_->end ());
1360     break;
1361     default:
1362     break;
1363     }
1364     return iterator ();
1365     }
1366    
1367     /*
1368     * class PathArgument
1369     * //////////////////////////////////////////////////////////////////
1370     */
1371    
1372     PathArgument::PathArgument ()
1373     : kind_ (kindNone)
1374     {
1375     }
1376    
1377     PathArgument::PathArgument (Value::UInt index)
1378     : index_ (index)
1379     , kind_ (kindIndex)
1380     {
1381     }
1382    
1383     PathArgument::PathArgument (const char *key)
1384     : key_ (key)
1385     , kind_ (kindKey)
1386     {
1387     }
1388    
1389     PathArgument::PathArgument (const std::string &key)
1390     : key_ (key.c_str ())
1391     , kind_ (kindKey)
1392     {
1393     }
1394    
1395     /*
1396     * class Path
1397     * //////////////////////////////////////////////////////////////////
1398     */
1399    
1400     Path::Path (const std::string &path, const PathArgument &a1, const PathArgument &a2, const PathArgument &a3, const PathArgument &a4, const PathArgument &a5)
1401     {
1402     InArgs in;
1403    
1404     in.push_back (&a1);
1405     in.push_back (&a2);
1406     in.push_back (&a3);
1407     in.push_back (&a4);
1408     in.push_back (&a5);
1409     makePath (path, in);
1410     }
1411    
1412     void
1413     Path::makePath (const std::string &path, const InArgs &in)
1414     {
1415     const char *current = path.c_str ();
1416     const char *end = current + path.length ();
1417     InArgs::const_iterator itInArg = in.begin ();
1418    
1419     while (current != end)
1420     {
1421     if (*current == '[')
1422     {
1423     ++current;
1424     if (*current == '%')
1425     addPathInArg (path, in, itInArg, PathArgument::kindIndex);
1426     else
1427     {
1428     Value::UInt index = 0;
1429     for (; current != end && *current >= '0' && *current <= '9'; ++current)
1430     index = index * 10 + Value::UInt (*current - '0');
1431     args_.push_back (index);
1432     }
1433     if (current == end || *current++ != ']')
1434     invalidPath (path, int(current - path.c_str ()));
1435     }
1436     else if (*current == '%')
1437     {
1438     addPathInArg (path, in, itInArg, PathArgument::kindKey);
1439     ++current;
1440     }
1441     else if (*current == '.')
1442     ++current;
1443     else
1444     {
1445     const char *beginName = current;
1446     while (current != end && !strchr ("[.", *current))
1447     ++current;
1448     args_.push_back (std::string (beginName, current));
1449     }
1450     }
1451     }
1452    
1453     void
1454     Path::addPathInArg (const std::string &path, const InArgs &in, InArgs::const_iterator &itInArg, PathArgument::Kind kind)
1455     {
1456     if (itInArg == in.end ())
1457     {
1458     /* Error: missing argument %d */
1459     }
1460     else if ((*itInArg)->kind_ != kind)
1461     {
1462     /* Error: bad argument type */
1463     }
1464     else
1465     args_.push_back (**itInArg);
1466     }
1467    
1468     void
1469     Path::invalidPath (const std::string &path, int location)
1470     {
1471     /* Error: invalid path. */
1472     }
1473    
1474     const Value &
1475     Path::resolve (const Value &root) const
1476     {
1477     const Value *node = &root;
1478    
1479     for (Args::const_iterator it = args_.begin (); it != args_.end (); ++it)
1480     {
1481     const PathArgument &arg = *it;
1482     if (arg.kind_ == PathArgument::kindIndex)
1483     {
1484     if (!node->isArray () || node->isValidIndex (arg.index_))
1485     {
1486     /* Error: unable to resolve path (array value expected at position... */
1487     }
1488     node = &((*node)[arg.index_]);
1489     }
1490     else if (arg.kind_ == PathArgument::kindKey)
1491     {
1492     if (!node->isObject ())
1493     {
1494     /* Error: unable to resolve path (object value expected at position...) */
1495     }
1496     node = &((*node)[arg.key_]);
1497     if (node == &Value::null)
1498     {
1499     /* Error: unable to resolve path (object has no member named '' at position...) */
1500     }
1501     }
1502     }
1503     return *node;
1504     }
1505    
1506     Value
1507     Path::resolve (const Value &root, const Value &defaultValue) const
1508     {
1509     const Value *node = &root;
1510    
1511     for (Args::const_iterator it = args_.begin (); it != args_.end (); ++it)
1512     {
1513     const PathArgument &arg = *it;
1514     if (arg.kind_ == PathArgument::kindIndex)
1515     {
1516     if (!node->isArray () || node->isValidIndex (arg.index_))
1517     return defaultValue;
1518     node = &((*node)[arg.index_]);
1519     }
1520     else if (arg.kind_ == PathArgument::kindKey)
1521     {
1522     if (!node->isObject ())
1523     return defaultValue;
1524     node = &((*node)[arg.key_]);
1525     if (node == &Value::null)
1526     return defaultValue;
1527     }
1528     }
1529     return *node;
1530     }
1531    
1532     Value &
1533     Path::make (Value &root) const
1534     {
1535     Value *node = &root;
1536    
1537     for (Args::const_iterator it = args_.begin (); it != args_.end (); ++it)
1538     {
1539     const PathArgument &arg = *it;
1540     if (arg.kind_ == PathArgument::kindIndex)
1541     {
1542     if (!node->isArray ())
1543     {
1544     /* Error: node is not an array at position ... */
1545     }
1546     node = &((*node)[arg.index_]);
1547     }
1548     else if (arg.kind_ == PathArgument::kindKey)
1549     {
1550     if (!node->isObject ())
1551     {
1552     /* Error: node is not an object at position... */
1553     }
1554     node = &((*node)[arg.key_]);
1555     }
1556     }
1557     return *node;
1558     }
1559    
1560     } /* namespace Json */