ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/ermyth/modules/rpc/json/value.C
Revision: 1.5
Committed: Sat Sep 22 14:27:30 2007 UTC (19 years ago) by pippijn
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.4: +3 -10 lines
Log Message:
split up ermyth into ermyth-modules, libermyth (currently just ermyth-util) and ermyth-core

File Contents

# User Rev Content
1 pippijn 1.2 /*
2     * Copyright © 2007 Pippijn van Steenhoven / The Ermyth Team
3 pippijn 1.4 * Rights to this code are as documented in doc/pod/license.pod.
4 pippijn 1.2 *
5     * JSON-RPC for Ermyth
6     *
7 pippijn 1.5 * $Id: value.C,v 1.4 2007-09-05 11:23:15 pippijn Exp $
8 pippijn 1.2 */
9    
10 pippijn 1.1 //>>>>>>>>>>> value.C <<<<<<<<<<<//
11     #include <json/value.h>
12     #include <json/writer.h>
13    
14     #include <iostream>
15     #include <utility>
16     #include <stdexcept>
17    
18     #include <cstddef> // size_t
19    
20 pippijn 1.3 #include "atheme.h"
21 pippijn 1.5 #include <util/memory.h>
22     #include <util/containers.h>
23 pippijn 1.2
24 pippijn 1.1 namespace json
25     {
26 pippijn 1.3 namespace impl
27     {
28     template<typename inttype = int, typename floattype = float, inttype maxUlps = 200>
29     struct equals
30     {
31     bool operator () (floattype A, floattype B)
32     {
33     inttype aInt = *(inttype*)&A;
34     inttype bInt = *(inttype*)&B;
35    
36     // Make aInt lexicographically ordered as a twos-complement int
37     if (aInt < 0)
38     aInt = 0x80000000 - aInt;
39    
40     // Make bInt lexicographically ordered as a twos-complement int
41     if (bInt < 0)
42     bInt = 0x80000000 - bInt;
43    
44     inttype intDiff = abs(aInt - bInt);
45     if (intDiff <= maxUlps)
46     return true;
47    
48     return false;
49     }
50     };
51     }
52    
53 pippijn 1.2 void unreachable_internal (char const * const file,
54     int const line,
55     char const * const function)
56     __attribute__ ((__noreturn__));
57 pippijn 1.1 void
58 pippijn 1.2 unreachable_internal (char const * const file, int const line, char const * const function)
59 pippijn 1.1 {
60     char buf[1024];
61     snprintf (buf, 1024, "%s (%d) [%s] critical: Unreachable line reached.",
62     file, line, function);
63    
64     throw std::runtime_error (buf);
65     }
66    
67 pippijn 1.2 void throw_unless_internal (char const * const file,
68     int const line,
69     char const * const function,
70     char const * const condition)
71     __attribute__ ((__noreturn__));
72 pippijn 1.1 void
73 pippijn 1.2 throw_unless_internal (char const * const file, int const line, char const * const function, char const * const condition)
74 pippijn 1.1 {
75     char buf[1024];
76     snprintf (buf, 1024, "%s (%d) [%s] critical: Assertion `%s' failed.",
77     file, line, function, condition);
78    
79     throw std::runtime_error (buf);
80     }
81    
82 pippijn 1.2 void throw_msg_unless_internal (char const * const file,
83     int const line,
84     char const * const function,
85     char const * const message)
86     __attribute__ ((__noreturn__));
87 pippijn 1.1 void
88 pippijn 1.2 throw_msg_unless_internal (char const * const file, int const line, char const * const function, char const * const message)
89 pippijn 1.1 {
90     char buf[1024];
91     snprintf (buf, 1024, "%s (%d) [%s] critical: %s.",
92     file, line, function, message);
93    
94     throw std::runtime_error (buf);
95     }
96 pippijn 1.3
97     #define throw_unreachable unreachable_internal (__FILE__, __LINE__, __PRETTY_FUNCTION__)
98     #define throw_unless(condition) if (!expect_false (condition)) throw_unless_internal (__FILE__, __LINE__, __PRETTY_FUNCTION__, #condition)
99     #define throw_msg_unless(condition, message) if (!expect_false (condition)) throw_msg_unless_internal (__FILE__, __LINE__, __PRETTY_FUNCTION__, message)
100 pippijn 1.1
101     const Value Value::null;
102     const int Value::minInt = int (~ (unsigned (-1)/2));
103     const int Value::maxInt = int (unsigned (-1)/2);
104     const unsigned Value::maxUInt = unsigned (-1);
105    
106     ValueAllocator::~ValueAllocator ()
107     {
108     }
109    
110     class DefaultValueAllocator : public ValueAllocator
111     {
112     public:
113     virtual ~DefaultValueAllocator ()
114     {
115     }
116    
117     virtual char *makeMemberName (char const *memberName)
118     {
119     return duplicateStringValue (memberName);
120     }
121    
122     virtual void releaseMemberName (char *memberName)
123     {
124     releaseStringValue (memberName);
125     }
126    
127     virtual char *duplicateStringValue (char const *value, unsigned length = unknown)
128     {
129     //@todo invesgate this old optimization
130     #if 0
131     if (!value || value[0] == 0)
132     return 0;
133     #endif
134    
135     if (length == unknown)
136     length = (unsigned)strlen (value);
137 pippijn 1.3 char *newString = salloc<char> (length + 1);
138 pippijn 1.1 memcpy (newString, value, length);
139     newString[length] = 0;
140     return newString;
141     }
142    
143     virtual void releaseStringValue (char *value)
144     {
145     if (value)
146 pippijn 1.2 sfree (value);
147 pippijn 1.1 }
148     };
149    
150     static ValueAllocator *&valueAllocator ()
151     {
152     static DefaultValueAllocator defaultAllocator;
153     static ValueAllocator *valueAllocator = &defaultAllocator;
154     return valueAllocator;
155     }
156    
157     static struct DummyValueAllocatorInitializer {
158     DummyValueAllocatorInitializer ()
159     {
160     valueAllocator (); // ensure valueAllocator () statics are initialized before main ().
161     }
162     } dummyValueAllocatorInitializer;
163    
164    
165    
166     // class Value::CommentInfo
167     Value::CommentInfo::CommentInfo ()
168     : comment_ (0)
169     {
170     }
171    
172     Value::CommentInfo::~CommentInfo ()
173     {
174     if (comment_)
175     valueAllocator()->releaseStringValue (comment_);
176     }
177    
178    
179     void
180     Value::CommentInfo::setComment (char const *text)
181     {
182     if (comment_)
183     valueAllocator()->releaseStringValue (comment_);
184     throw_unless (text);
185     throw_msg_unless (text[0]=='\0' || text[0]=='/', "Comments must start with /");
186     // It seems that /**/ style comments are acceptable as well.
187     comment_ = valueAllocator()->duplicateStringValue (text);
188     }
189    
190    
191     // class Value::CZString
192    
193     // Notes: index_ indicates if the string was allocated when
194     // a string is stored.
195    
196 pippijn 1.2 Value::CZString::CZString (int idx)
197 pippijn 1.1 : cstr_ (0)
198 pippijn 1.2 , index_ (idx)
199 pippijn 1.1 {
200     }
201    
202     Value::CZString::CZString (char const *cstr, DuplicationPolicy allocate)
203     : cstr_ (allocate == duplicate ? valueAllocator()->makeMemberName (cstr)
204     : cstr)
205     , index_ (allocate)
206     {
207     }
208    
209     Value::CZString::CZString (const CZString &other)
210     : cstr_ (other.index_ != noDuplication && other.cstr_ != 0
211     ? valueAllocator()->makeMemberName (other.cstr_)
212     : other.cstr_)
213     , index_ (other.cstr_ ? (other.index_ == noDuplication ? noDuplication : duplicate)
214     : other.index_)
215     {
216     }
217    
218     Value::CZString::~CZString ()
219     {
220     if (cstr_ && index_ == duplicate)
221     valueAllocator()->releaseMemberName (const_cast<char *> (cstr_));
222     }
223    
224     void
225     Value::CZString::swap (CZString &other)
226     {
227     std::swap (cstr_, other.cstr_);
228     std::swap (index_, other.index_);
229     }
230    
231     Value::CZString &
232     Value::CZString::operator = (const CZString &other)
233     {
234     CZString temp (other);
235     swap (temp);
236     return *this;
237     }
238    
239     bool
240     Value::CZString::operator < (const CZString &other) const
241     {
242     if (cstr_)
243     return strcmp (cstr_, other.cstr_) < 0;
244     return index_ < other.index_;
245     }
246    
247     bool
248     Value::CZString::operator == (const CZString &other) const
249     {
250     if (cstr_)
251     return strcmp (cstr_, other.cstr_) == 0;
252     return index_ == other.index_;
253     }
254    
255    
256     int
257     Value::CZString::index () const
258     {
259     return index_;
260     }
261    
262    
263     char const *
264     Value::CZString::c_str () const
265     {
266     return cstr_;
267     }
268    
269     bool
270     Value::CZString::isStaticString () const
271     {
272     return index_ == noDuplication;
273     }
274    
275    
276     // class Value::Value
277    
278     /*! \internal Default constructor initialization must be equivalent to:
279     * memset (this, 0, sizeof (Value))
280     * This optimization is used in ValueInternalMap fast allocator.
281     */
282 pippijn 1.2 Value::Value (ValueType t)
283     : type_ (t)
284 pippijn 1.1 , allocated_ (0)
285     , comments_ (0)
286     {
287 pippijn 1.2 switch (t)
288 pippijn 1.1 {
289     case nullValue:
290     break;
291     case intValue:
292     case uintValue:
293     value_.int_ = 0;
294     break;
295     case realValue:
296     value_.real_ = 0.0;
297     break;
298     case stringValue:
299     value_.string_ = 0;
300     break;
301     case arrayValue:
302     case objectValue:
303     value_.map_ = new ObjectValues ();
304     break;
305     case booleanValue:
306     value_.bool_ = false;
307     break;
308     default:
309     throw_unreachable;
310     }
311     }
312    
313    
314     Value::Value (int value)
315     : type_ (intValue)
316     , comments_ (0)
317     {
318     value_.int_ = value;
319     }
320    
321    
322     Value::Value (unsigned value)
323     : type_ (uintValue)
324     , comments_ (0)
325     {
326     value_.uint_ = value;
327     }
328    
329     Value::Value (double value)
330     : type_ (realValue)
331     , comments_ (0)
332     {
333     value_.real_ = value;
334     }
335    
336     Value::Value (char const *value)
337     : type_ (stringValue)
338     , allocated_ (true)
339     , comments_ (0)
340     {
341     value_.string_ = valueAllocator()->duplicateStringValue (value);
342     }
343    
344     Value::Value (const std::string &value)
345     : type_ (stringValue)
346     , allocated_ (true)
347     , comments_ (0)
348     {
349     value_.string_ = valueAllocator()->duplicateStringValue (value.c_str (), (unsigned)value.length ());
350     }
351    
352     Value::Value (const StaticString &value)
353     : type_ (stringValue)
354     , allocated_ (false)
355     , comments_ (0)
356     {
357     value_.string_ = const_cast<char *> (value.c_str ());
358     }
359    
360    
361     Value::Value (bool value)
362     : type_ (booleanValue)
363     , comments_ (0)
364     {
365     value_.bool_ = value;
366     }
367    
368    
369     Value::Value (const Value &other)
370     : type_ (other.type_)
371     , comments_ (0)
372     {
373     switch (type_)
374     {
375     case nullValue:
376     case intValue:
377     case uintValue:
378     case realValue:
379     case booleanValue:
380     value_ = other.value_;
381     break;
382     case stringValue:
383     if (other.value_.string_)
384     {
385     value_.string_ = valueAllocator()->duplicateStringValue (other.value_.string_);
386     allocated_ = true;
387     }
388     else
389     value_.string_ = 0;
390     break;
391     case arrayValue:
392     case objectValue:
393     value_.map_ = new ObjectValues (*other.value_.map_);
394     break;
395     default:
396     throw_unreachable;
397     }
398     if (other.comments_)
399     {
400     comments_ = new CommentInfo[numberOfCommentPlacement];
401     for (int comment = 0; comment < numberOfCommentPlacement; ++comment)
402     {
403     const CommentInfo &otherComment = other.comments_[comment];
404     if (otherComment.comment_)
405     comments_[comment].setComment (otherComment.comment_);
406     }
407     }
408     }
409    
410    
411     Value::~Value ()
412     {
413     switch (type_)
414     {
415     case nullValue:
416     case intValue:
417     case uintValue:
418     case realValue:
419     case booleanValue:
420     break;
421     case stringValue:
422     if (allocated_)
423     valueAllocator()->releaseStringValue (value_.string_);
424     break;
425     case arrayValue:
426     case objectValue:
427     delete value_.map_;
428     break;
429     default:
430     throw_unreachable;
431     }
432    
433     if (comments_)
434     delete[] comments_;
435     }
436    
437     Value &
438     Value::operator = (const Value &other)
439     {
440     Value temp (other);
441     swap (temp);
442     return *this;
443     }
444    
445     void
446     Value::swap (Value &other)
447     {
448     ValueType temp = type_;
449     type_ = other.type_;
450     other.type_ = temp;
451     std::swap (value_, other.value_);
452     int temp2 = allocated_;
453     allocated_ = other.allocated_;
454     other.allocated_ = temp2;
455     }
456    
457     ValueType
458     Value::type () const
459     {
460     return type_;
461     }
462    
463     bool
464     Value::operator < (const Value &other) const
465     {
466     int typeDelta = type_ - other.type_;
467     if (typeDelta)
468     return typeDelta < 0 ? true : false;
469     switch (type_)
470     {
471     case nullValue:
472     return false;
473     case intValue:
474     return value_.int_ < other.value_.int_;
475     case uintValue:
476     return value_.uint_ < other.value_.uint_;
477     case realValue:
478     return value_.real_ < other.value_.real_;
479     case booleanValue:
480     return value_.bool_ < other.value_.bool_;
481     case stringValue:
482     return (value_.string_ == 0 && other.value_.string_)
483     || (other.value_.string_
484     && value_.string_
485     && strcmp (value_.string_, other.value_.string_) < 0);
486     case arrayValue:
487     case objectValue:
488     {
489     int delta = int (value_.map_->size () - other.value_.map_->size ());
490     if (delta)
491     return delta < 0;
492     return (*value_.map_) < (*other.value_.map_);
493     }
494     default:
495     throw_unreachable;
496     }
497     return 0; // unreachable
498     }
499    
500     bool
501     Value::operator <= (const Value &other) const
502     {
503     return !(other > *this);
504     }
505    
506     bool
507     Value::operator >= (const Value &other) const
508     {
509     return !(*this < other);
510     }
511    
512     bool
513     Value::operator > (const Value &other) const
514     {
515     return other < *this;
516     }
517    
518     bool
519     Value::operator == (const Value &other) const
520     {
521     if (type_ != other.type_)
522     return false;
523    
524     switch (type_)
525     {
526     case nullValue:
527     return true;
528     case intValue:
529     return value_.int_ == other.value_.int_;
530     case uintValue:
531     return value_.uint_ == other.value_.uint_;
532     case realValue:
533 pippijn 1.3 return impl::equals<> () (value_.real_, other.value_.real_);
534 pippijn 1.1 case booleanValue:
535     return value_.bool_ == other.value_.bool_;
536     case stringValue:
537     return (value_.string_ == other.value_.string_)
538     || (other.value_.string_
539     && value_.string_
540     && strcmp (value_.string_, other.value_.string_) == 0);
541     case arrayValue:
542     case objectValue:
543     return value_.map_->size () == other.value_.map_->size ()
544     && (*value_.map_) == (*other.value_.map_);
545     default:
546     throw_unreachable;
547     }
548     return 0; // unreachable
549     }
550    
551     bool
552     Value::operator != (const Value &other) const
553     {
554     return !(*this == other);
555     }
556    
557     Value::operator char const * () const
558     {
559     throw_unless (type_ == stringValue);
560     return value_.string_;
561     }
562    
563    
564     Value::operator std::string () const
565     {
566     switch (type_)
567     {
568     case nullValue:
569     return "";
570     case stringValue:
571     return value_.string_ ? value_.string_ : "";
572     case booleanValue:
573     return value_.bool_ ? "true" : "false";
574     case intValue:
575     case uintValue:
576     case realValue:
577     case arrayValue:
578     case objectValue:
579     throw_msg_unless (false, "Type is not convertible to string");
580     default:
581     throw_unreachable;
582     }
583     return ""; // unreachable
584     }
585    
586     Value::operator int () const
587     {
588     switch (type_)
589     {
590     case nullValue:
591     return 0;
592     case intValue:
593     return value_.int_;
594     case uintValue:
595     throw_msg_unless (value_.uint_ < (unsigned)maxInt, "integer out of signed integer range");
596     return value_.uint_;
597     case realValue:
598     throw_msg_unless (value_.real_ >= minInt && value_.real_ <= maxInt, "Real out of signed integer range");
599     return int (value_.real_);
600     case booleanValue:
601     return value_.bool_ ? 1 : 0;
602     case stringValue:
603     case arrayValue:
604     case objectValue:
605     throw_msg_unless (false, "Type is not convertible to int");
606     default:
607     throw_unreachable;
608     }
609     return 0; // unreachable;
610     }
611    
612     Value::operator unsigned () const
613     {
614     switch (type_)
615     {
616     case nullValue:
617     return 0;
618     case intValue:
619     throw_msg_unless (value_.int_ >= 0, "Negative integer can not be converted to unsigned integer");
620     return value_.int_;
621     case uintValue:
622     return value_.uint_;
623     case realValue:
624     throw_msg_unless (value_.real_ >= 0 && value_.real_ <= maxUInt, "Real out of unsigned integer range");
625     return unsigned (value_.real_);
626     case booleanValue:
627     return value_.bool_ ? 1 : 0;
628     case stringValue:
629     case arrayValue:
630     case objectValue:
631     throw_msg_unless (false, "Type is not convertible to uint");
632     default:
633     throw_unreachable;
634     }
635     return 0; // unreachable;
636     }
637    
638     Value::operator double () const
639     {
640     switch (type_)
641     {
642     case nullValue:
643     return 0.0;
644     case intValue:
645     return value_.int_;
646     case uintValue:
647     return value_.uint_;
648     case realValue:
649     return value_.real_;
650     case booleanValue:
651     return value_.bool_ ? 1.0 : 0.0;
652     case stringValue:
653     case arrayValue:
654     case objectValue:
655     throw_msg_unless (false, "Type is not convertible to double");
656     default:
657     throw_unreachable;
658     }
659     return 0; // unreachable;
660     }
661    
662     Value::operator bool () const
663     {
664     switch (type_)
665     {
666     case nullValue:
667     return false;
668     case intValue:
669     case uintValue:
670     return value_.int_ != 0;
671     case realValue:
672 pippijn 1.3 return impl::equals<> () (value_.real_, 0.0);
673 pippijn 1.1 case booleanValue:
674     return value_.bool_;
675     case stringValue:
676     return value_.string_ && value_.string_[0] != 0;
677     case arrayValue:
678     case objectValue:
679     return value_.map_->size () != 0;
680     default:
681     throw_unreachable;
682     }
683     return false; // unreachable;
684     }
685    
686    
687     bool
688     Value::isConvertibleTo (ValueType other) const
689     {
690     switch (type_)
691     {
692     case nullValue:
693     return true;
694     case intValue:
695     return (other == nullValue && value_.int_ == 0)
696     || other == intValue
697     || (other == uintValue && value_.int_ >= 0)
698     || other == realValue
699     || other == stringValue
700     || other == booleanValue;
701     case uintValue:
702     return (other == nullValue && value_.uint_ == 0)
703     || (other == intValue && value_.uint_ <= (unsigned)maxInt)
704     || other == uintValue
705     || other == realValue
706     || other == stringValue
707     || other == booleanValue;
708     case realValue:
709 pippijn 1.3 return (other == nullValue && impl::equals<> () (value_.real_, 0.0))
710 pippijn 1.1 || (other == intValue && value_.real_ >= minInt && value_.real_ <= maxInt)
711     || (other == uintValue && value_.real_ >= 0 && value_.real_ <= maxUInt)
712     || other == realValue
713     || other == stringValue
714     || other == booleanValue;
715     case booleanValue:
716     return (other == nullValue && value_.bool_ == false)
717     || other == intValue
718     || other == uintValue
719     || other == realValue
720     || other == stringValue
721     || other == booleanValue;
722     case stringValue:
723     return other == stringValue
724     || (other == nullValue && (!value_.string_ || value_.string_[0] == 0));
725     case arrayValue:
726     return other == arrayValue
727     || (other == nullValue && value_.map_->size () == 0);
728     case objectValue:
729     return other == objectValue
730     || (other == nullValue && value_.map_->size () == 0);
731     default:
732     throw_unreachable;
733     }
734     return false; // unreachable;
735     }
736    
737    
738     /// Number of values in array or object
739     unsigned
740     Value::size () const
741     {
742     switch (type_)
743     {
744     case nullValue:
745     case intValue:
746     case uintValue:
747     case realValue:
748     case booleanValue:
749     case stringValue:
750     return 0;
751     case arrayValue: // size of the array is highest index + 1
752     if (!value_.map_->empty ())
753     {
754     ObjectValues::const_iterator itLast = value_.map_->end ();
755     --itLast;
756     return itLast->first.index ()+1;
757     }
758     return 0;
759     case objectValue:
760     return int (value_.map_->size ());
761     default:
762     throw_unreachable;
763     }
764     return 0; // unreachable;
765     }
766    
767    
768     bool
769     Value::empty () const
770     {
771     if (isNull () || isArray () || isObject ())
772     return size () == 0u;
773     else
774     return false;
775     }
776    
777    
778     bool
779     Value::operator ! () const
780     {
781     return isNull ();
782     }
783    
784    
785     void
786     Value::clear ()
787     {
788     throw_unless (type_ == nullValue || type_ == arrayValue || type_ == objectValue);
789    
790     switch (type_)
791     {
792     case arrayValue:
793     case objectValue:
794     value_.map_->clear ();
795     break;
796     default:
797     break;
798     }
799     }
800    
801     void
802     Value::resize (unsigned newSize)
803     {
804     throw_unless (type_ == nullValue || type_ == arrayValue);
805     if (type_ == nullValue)
806     *this = Value (arrayValue);
807     unsigned oldSize = size ();
808     if (newSize == 0)
809     clear ();
810     else if (newSize > oldSize)
811     (*this)[ newSize - 1 ];
812     else
813     {
814     for (unsigned index = newSize; index < oldSize; ++index)
815     value_.map_->erase (index);
816     throw_unless (size () == newSize);
817     }
818     }
819    
820    
821     Value &
822     Value::operator [] (int index)
823     {
824     return operator [] (static_cast<unsigned> (index));
825     }
826    
827    
828     Value &
829     Value::operator [] (unsigned index)
830     {
831     throw_unless (type_ == nullValue || type_ == arrayValue);
832     if (type_ == nullValue)
833     *this = Value (arrayValue);
834     CZString key (index);
835     ObjectValues::iterator it = value_.map_->lower_bound (key);
836     if (it != value_.map_->end () && it->first == key)
837     return it->second;
838    
839     ObjectValues::value_type defaultValue (key, null);
840     it = value_.map_->insert (it, defaultValue);
841     return it->second;
842     }
843    
844    
845     const Value &
846     Value::operator [] (int index) const
847     {
848     return operator [] (static_cast<unsigned> (index));
849     }
850    
851    
852     const Value &
853     Value::operator [] (unsigned index) const
854     {
855     throw_unless (type_ == nullValue || type_ == arrayValue);
856     if (type_ == nullValue)
857     return null;
858     CZString key (index);
859     ObjectValues::const_iterator it = value_.map_->find (key);
860     if (it == value_.map_->end ())
861     return null;
862     return it->second;
863     }
864    
865    
866     Value &
867     Value::operator [] (char const *key)
868     {
869     return resolveReference (key, false);
870     }
871    
872    
873     Value &
874     Value::resolveReference (char const *key, bool isStatic)
875     {
876     throw_unless (type_ == nullValue || type_ == objectValue);
877     if (type_ == nullValue)
878     *this = Value (objectValue);
879     CZString actualKey (key, isStatic ? CZString::noDuplication
880     : CZString::duplicateOnCopy);
881     ObjectValues::iterator it = value_.map_->lower_bound (actualKey);
882     if (it != value_.map_->end () && it->first == actualKey)
883     return it->second;
884    
885     ObjectValues::value_type defaultValue (actualKey, null);
886     it = value_.map_->insert (it, defaultValue);
887     Value &value = it->second;
888     return value;
889     }
890    
891    
892     Value
893     Value::get (int index, const Value &defaultValue) const
894     {
895     return get (static_cast<unsigned> (index), defaultValue);
896     }
897    
898    
899     Value
900     Value::get (unsigned index, const Value &defaultValue) const
901     {
902     const Value *value = &((*this)[index]);
903     return value == &null ? defaultValue : *value;
904     }
905    
906    
907     bool
908     Value::isValidIndex (int index) const
909     {
910     return isValidIndex (static_cast<unsigned> (index));
911     }
912    
913    
914     bool
915     Value::isValidIndex (unsigned index) const
916     {
917     return index < size ();
918     }
919    
920    
921    
922     const Value &
923     Value::operator [] (char const *key) const
924     {
925     throw_unless (type_ == nullValue || type_ == objectValue);
926     if (type_ == nullValue)
927     return null;
928     CZString actualKey (key, CZString::noDuplication);
929     ObjectValues::const_iterator it = value_.map_->find (actualKey);
930     if (it == value_.map_->end ())
931     return null;
932     return it->second;
933     }
934    
935    
936     Value &
937     Value::operator [] (const std::string &key)
938     {
939     return (*this)[ key.c_str () ];
940     }
941    
942    
943     const Value &
944     Value::operator [] (const std::string &key) const
945     {
946     return (*this)[ key.c_str () ];
947     }
948    
949     Value &
950     Value::operator [] (const StaticString &key)
951     {
952     return resolveReference (key, true);
953     }
954    
955    
956     Value &
957     Value::append (const Value &value)
958     {
959     return (*this)[size ()] = value;
960     }
961    
962    
963     Value
964     Value::get (char const *key, const Value &defaultValue) const
965     {
966     const Value *value = &((*this)[key]);
967     return value == &null ? defaultValue : *value;
968     }
969    
970    
971     Value
972     Value::get (const std::string &key, const Value &defaultValue) const
973     {
974     return get (key.c_str (), defaultValue);
975     }
976    
977     Value
978     Value::removeMember (char const *key)
979     {
980     throw_unless (type_ == nullValue || type_ == objectValue);
981     if (type_ == nullValue)
982     return null;
983     CZString actualKey (key, CZString::noDuplication);
984     ObjectValues::iterator it = value_.map_->find (actualKey);
985     if (it == value_.map_->end ())
986     return null;
987     Value old (it->second);
988     value_.map_->erase (it);
989     return old;
990     }
991    
992     Value
993     Value::removeMember (const std::string &key)
994     {
995     return removeMember (key.c_str ());
996     }
997    
998     bool
999     Value::isMember (char const *key) const
1000     {
1001     const Value *value = &((*this)[key]);
1002     return value != &null;
1003     }
1004    
1005    
1006     bool
1007     Value::isMember (const std::string &key) const
1008     {
1009     return isMember (key.c_str ());
1010     }
1011    
1012    
1013     Value::Members
1014     Value::getMemberNames () const
1015     {
1016     throw_unless (type_ == nullValue || type_ == objectValue);
1017     if (type_ == nullValue)
1018     return Value::Members ();
1019     Members members;
1020     members.reserve (value_.map_->size ());
1021     ObjectValues::const_iterator it;
1022     ObjectValues::const_iterator itEnd = value_.map_->end ();
1023     for (it = value_.map_->begin (); it != itEnd; ++it)
1024     members.push_back (std::string (it->first.c_str()));
1025     return members;
1026     }
1027    
1028     bool
1029     Value::isNull () const
1030     {
1031     return type_ == nullValue;
1032     }
1033    
1034    
1035     bool
1036     Value::isBool () const
1037     {
1038     return type_ == booleanValue;
1039     }
1040    
1041    
1042     bool
1043     Value::isInt () const
1044     {
1045     return type_ == intValue;
1046     }
1047    
1048    
1049     bool
1050     Value::isUInt () const
1051     {
1052     return type_ == uintValue;
1053     }
1054    
1055    
1056     bool
1057     Value::isIntegral () const
1058     {
1059     return type_ == intValue
1060     || type_ == uintValue
1061     || type_ == booleanValue;
1062     }
1063    
1064    
1065     bool
1066     Value::isDouble () const
1067     {
1068     return type_ == realValue;
1069     }
1070    
1071    
1072     bool
1073     Value::isNumeric () const
1074     {
1075     return isIntegral () || isDouble ();
1076     }
1077    
1078    
1079     bool
1080     Value::isString () const
1081     {
1082     return type_ == stringValue;
1083     }
1084    
1085    
1086     bool
1087     Value::isArray () const
1088     {
1089     return type_ == nullValue || type_ == arrayValue;
1090     }
1091    
1092    
1093     bool
1094     Value::isObject () const
1095     {
1096     return type_ == nullValue || type_ == objectValue;
1097     }
1098    
1099    
1100     void
1101     Value::setComment (char const *comment,
1102     CommentPlacement placement)
1103     {
1104     if (!comments_)
1105     comments_ = new CommentInfo[numberOfCommentPlacement];
1106     comments_[placement].setComment (comment);
1107     }
1108    
1109    
1110     void
1111     Value::setComment (const std::string &comment,
1112     CommentPlacement placement)
1113     {
1114     setComment (comment.c_str (), placement);
1115     }
1116    
1117    
1118     bool
1119     Value::hasComment (CommentPlacement placement) const
1120     {
1121     return comments_ != 0 && comments_[placement].comment_ != 0;
1122     }
1123    
1124     std::string
1125     Value::getComment (CommentPlacement placement) const
1126     {
1127     if (hasComment (placement))
1128     return comments_[placement].comment_;
1129     return "";
1130     }
1131    
1132    
1133     std::string
1134     Value::toStyledString () const
1135     {
1136     StyledWriter writer;
1137     return writer.write (*this);
1138     }
1139    
1140    
1141     Value::const_iterator
1142     Value::begin () const
1143     {
1144     switch (type_)
1145     {
1146     case arrayValue:
1147     case objectValue:
1148     if (value_.map_)
1149     return const_iterator (value_.map_->begin ());
1150     break;
1151     default:
1152     break;
1153     }
1154     return const_iterator ();
1155     }
1156    
1157     Value::const_iterator
1158     Value::end () const
1159     {
1160     switch (type_)
1161     {
1162     case arrayValue:
1163     case objectValue:
1164     if (value_.map_)
1165     return const_iterator (value_.map_->end ());
1166     break;
1167     default:
1168     break;
1169     }
1170     return const_iterator ();
1171     }
1172    
1173    
1174     Value::iterator
1175     Value::begin ()
1176     {
1177     switch (type_)
1178     {
1179     case arrayValue:
1180     case objectValue:
1181     if (value_.map_)
1182     return iterator (value_.map_->begin ());
1183     break;
1184     default:
1185     break;
1186     }
1187     return iterator ();
1188     }
1189    
1190     Value::iterator
1191     Value::end ()
1192     {
1193     switch (type_)
1194     {
1195     case arrayValue:
1196     case objectValue:
1197     if (value_.map_)
1198     return iterator (value_.map_->end ());
1199     break;
1200     default:
1201     break;
1202     }
1203     return iterator ();
1204     }
1205     } // namespace json