ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/ermyth/modules/rpc/json/value.C
Revision: 1.2
Committed: Tue Aug 28 17:08:12 2007 UTC (19 years, 1 month ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.1: +35 -223 lines
Log Message:
- changed name
- updated the example config to the new system
- added more documentation
- enhanced documentation generators
- added a link to the pdf to the website
- added an RSS feed generator
- transitioned hooks to c++ callbacks
- did various merges with upstream along the way
- added const where appropriate
- removed the old block allocator
- fixed most memory leaks
- transitioned some dictionaries to std::map
- transitioned some lists to std::vector
- made some free functions members where appropriate
- renamed string to dynstr and added a static string ststr
- use NOW instead of time (NULL) if possible
- completely reworked database backends, crypto handlers and protocol handlers
  to use an object factory
- removed the old module system. ermyth does not do any dynamic loading anymore
- fixed most of the build system
- reworked how protocol commands work

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