ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/modules/rpc/json/value.C
Revision: 1.1
Committed: Thu Jul 19 08:24:56 2007 UTC (19 years, 4 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Log Message:
initial import. the most important changes since Atheme are:
- fixed many memory leaks
- fixed many bugs
- converted to C++ and use more STL containers
- added a (not very enhanced yet) perl module
- greatly improved XML-RPC speed
- added a JSON-RPC module with code from json-cpp
- added a valgrind memcheck module to operserv
- added a more object oriented base64 implementation
- added a specialised unit test framework
- improved stability
- use gettimeofday() if available
- reworked adding/removing commands
- MemoServ IGNORE DEL can now remove indices

File Contents

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