ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/cf.schmorp.de/dclient/src/backend/json/json_value.cpp
Revision: 1.2
Committed: Mon Oct 18 06:53:59 2010 UTC (15 years, 11 months ago) by sf-pippijn
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +2 -2 lines
Log Message:
gcc 4.5; moved some code; background colour support

File Contents

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