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

File Contents

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