ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/ermyth/modules/rpc/json/value.C
Revision: 1.3
Committed: Thu Aug 30 19:56:24 2007 UTC (19 years, 1 month ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.2: +45 -5 lines
Log Message:
- put faultcodes into their own namespace
- removed old files
- limited header garbage in atheme.h
- macros to inline bools for connection_t::is_*
- put some connection_t functions into the connection_t class

File Contents

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