- default:
- throw_unreachable;
- }
- return 0; // unreachable
- }
-
- bool
- Value::operator <= (const Value &other) const
- {
- return !(other > *this);
- }
-
- bool
- Value::operator >= (const Value &other) const
- {
- return !(*this < other);
- }
-
- bool
- Value::operator > (const Value &other) const
- {
- return other < *this;
- }
-
- bool
- Value::operator == (const Value &other) const
- {
- if (type_ != other.type_)
- return false;
-
- switch (type_)
- {
- case nullValue:
- return true;
- case intValue:
- return value_.int_ == other.value_.int_;
- case uintValue:
- return value_.uint_ == other.value_.uint_;
- case realValue:
- return value_.real_ == other.value_.real_;
- case booleanValue:
- return value_.bool_ == other.value_.bool_;
- case stringValue:
- return (value_.string_ == other.value_.string_)
- || (other.value_.string_
- && value_.string_
- && strcmp (value_.string_, other.value_.string_) == 0);
- case arrayValue:
- case objectValue:
- return value_.map_->size () == other.value_.map_->size ()
- && (*value_.map_) == (*other.value_.map_);
- default:
- throw_unreachable;
- }
- return 0; // unreachable
- }
-
- bool
- Value::operator != (const Value &other) const
- {
- return !(*this == other);
- }
-
- Value::operator char const * () const
- {
- throw_unless (type_ == stringValue);
- return value_.string_;
- }
-
-
- Value::operator std::string () const
- {
- switch (type_)
- {
- case nullValue:
- return "";
- case stringValue:
- return value_.string_ ? value_.string_ : "";
- case booleanValue:
- return value_.bool_ ? "true" : "false";
- case intValue:
- case uintValue:
- case realValue:
- case arrayValue:
- case objectValue:
- throw_msg_unless (false, "Type is not convertible to string");
- default:
- throw_unreachable;
- }
- return ""; // unreachable
- }
-
- Value::operator int () const
- {
- switch (type_)
- {
- case nullValue:
- return 0;
- case intValue:
- return value_.int_;
- case uintValue:
- throw_msg_unless (value_.uint_ < (unsigned)maxInt, "integer out of signed integer range");
- return value_.uint_;
- case realValue:
- throw_msg_unless (value_.real_ >= minInt && value_.real_ <= maxInt, "Real out of signed integer range");
- return int (value_.real_);
- case booleanValue:
- return value_.bool_ ? 1 : 0;
- case stringValue:
- case arrayValue:
- case objectValue:
- throw_msg_unless (false, "Type is not convertible to int");
- default:
- throw_unreachable;
- }
- return 0; // unreachable;
- }
-
- Value::operator unsigned () const
- {
- switch (type_)
- {
- case nullValue:
- return 0;
- case intValue:
- throw_msg_unless (value_.int_ >= 0, "Negative integer can not be converted to unsigned integer");
- return value_.int_;
- case uintValue:
- return value_.uint_;
- case realValue:
- throw_msg_unless (value_.real_ >= 0 && value_.real_ <= maxUInt, "Real out of unsigned integer range");
- return unsigned (value_.real_);
- case booleanValue:
- return value_.bool_ ? 1 : 0;
- case stringValue:
- case arrayValue:
- case objectValue:
- throw_msg_unless (false, "Type is not convertible to uint");
- default:
- throw_unreachable;
- }
- return 0; // unreachable;
- }
-
- Value::operator double () const
- {
- switch (type_)
- {
- case nullValue:
- return 0.0;
- case intValue:
- return value_.int_;
- case uintValue:
- return value_.uint_;
- case realValue:
- return value_.real_;
- case booleanValue:
- return value_.bool_ ? 1.0 : 0.0;
- case stringValue:
- case arrayValue:
- case objectValue:
- throw_msg_unless (false, "Type is not convertible to double");
- default:
- throw_unreachable;
- }
- return 0; // unreachable;
- }
-
- Value::operator bool () const
- {
- switch (type_)
- {
- case nullValue:
- return false;
- case intValue:
- case uintValue:
- return value_.int_ != 0;
- case realValue:
- return value_.real_ != 0.0;
- case booleanValue:
- return value_.bool_;
- case stringValue:
- return value_.string_ && value_.string_[0] != 0;
- case arrayValue:
- case objectValue:
- return value_.map_->size () != 0;
- default:
- throw_unreachable;
- }
- return false; // unreachable;
- }
-
-
- bool
- Value::isConvertibleTo (ValueType other) const
- {
- switch (type_)
- {
- case nullValue:
- return true;
- case intValue:
- return (other == nullValue && value_.int_ == 0)
- || other == intValue
- || (other == uintValue && value_.int_ >= 0)
- || other == realValue
- || other == stringValue
- || other == booleanValue;
- case uintValue:
- return (other == nullValue && value_.uint_ == 0)
- || (other == intValue && value_.uint_ <= (unsigned)maxInt)
- || other == uintValue
- || other == realValue
- || other == stringValue
- || other == booleanValue;
- case realValue:
- return (other == nullValue && value_.real_ == 0.0)
- || (other == intValue && value_.real_ >= minInt && value_.real_ <= maxInt)
- || (other == uintValue && value_.real_ >= 0 && value_.real_ <= maxUInt)
- || other == realValue
- || other == stringValue
- || other == booleanValue;
- case booleanValue:
- return (other == nullValue && value_.bool_ == false)
- || other == intValue
- || other == uintValue
- || other == realValue
- || other == stringValue
- || other == booleanValue;
- case stringValue:
- return other == stringValue
- || (other == nullValue && (!value_.string_ || value_.string_[0] == 0));
- case arrayValue:
- return other == arrayValue
- || (other == nullValue && value_.map_->size () == 0);
- case objectValue:
- return other == objectValue
- || (other == nullValue && value_.map_->size () == 0);
- default:
- throw_unreachable;
- }
- return false; // unreachable;
- }
-
-
- /// Number of values in array or object
- unsigned
- Value::size () const
- {
- switch (type_)
- {
- case nullValue:
- case intValue:
- case uintValue:
- case realValue:
- case booleanValue:
- case stringValue:
- return 0;
- case arrayValue: // size of the array is highest index + 1
- if (!value_.map_->empty ())
- {
- ObjectValues::const_iterator itLast = value_.map_->end ();
- --itLast;
- return itLast->first.index ()+1;
- }
- return 0;
- case objectValue:
- return int (value_.map_->size ());
- default:
- throw_unreachable;
- }
- return 0; // unreachable;
- }
-
-
- bool
- Value::empty () const
- {
- if (isNull () || isArray () || isObject ())
- return size () == 0u;
- else
- return false;
- }
-
-
- bool
- Value::operator ! () const
- {
- return isNull ();
- }
-
-
- void
- Value::clear ()
- {
- throw_unless (type_ == nullValue || type_ == arrayValue || type_ == objectValue);
-
- switch (type_)
- {
- case arrayValue:
- case objectValue:
- value_.map_->clear ();
- break;
- default:
- break;
- }
- }
-
- void
- Value::resize (unsigned newSize)
- {
- throw_unless (type_ == nullValue || type_ == arrayValue);
- if (type_ == nullValue)
- *this = Value (arrayValue);
- unsigned oldSize = size ();
- if (newSize == 0)
- clear ();
- else if (newSize > oldSize)
- (*this)[ newSize - 1 ];
- else
- {
- for (unsigned index = newSize; index < oldSize; ++index)
- value_.map_->erase (index);
- throw_unless (size () == newSize);
- }
- }
-
-
- Value &
- Value::operator [] (int index)
- {
- return operator [] (static_cast<unsigned> (index));
- }
-
-
- Value &
- Value::operator [] (unsigned index)
- {
- throw_unless (type_ == nullValue || type_ == arrayValue);
- if (type_ == nullValue)
- *this = Value (arrayValue);
- CZString key (index);
- ObjectValues::iterator it = value_.map_->lower_bound (key);
- if (it != value_.map_->end () && it->first == key)
- return it->second;
-
- ObjectValues::value_type defaultValue (key, null);
- it = value_.map_->insert (it, defaultValue);
- return it->second;
- }
-
-
- const Value &
- Value::operator [] (int index) const
- {
- return operator [] (static_cast<unsigned> (index));
- }
-
-
- const Value &
- Value::operator [] (unsigned index) const
- {
- throw_unless (type_ == nullValue || type_ == arrayValue);
- if (type_ == nullValue)
- return null;
- CZString key (index);
- ObjectValues::const_iterator it = value_.map_->find (key);
- if (it == value_.map_->end ())
- return null;
- return it->second;
- }
-
-
- Value &
- Value::operator [] (char const *key)
- {
- return resolveReference (key, false);
- }
-
-
- Value &
- Value::resolveReference (char const *key, bool isStatic)
- {
- throw_unless (type_ == nullValue || type_ == objectValue);
- if (type_ == nullValue)
- *this = Value (objectValue);
- CZString actualKey (key, isStatic ? CZString::noDuplication
- : CZString::duplicateOnCopy);
- ObjectValues::iterator it = value_.map_->lower_bound (actualKey);
- if (it != value_.map_->end () && it->first == actualKey)
- return it->second;
-
- ObjectValues::value_type defaultValue (actualKey, null);
- it = value_.map_->insert (it, defaultValue);
- Value &value = it->second;
- return value;
- }
-
-
- Value
- Value::get (int index, const Value &defaultValue) const
- {
- return get (static_cast<unsigned> (index), defaultValue);
- }
-
-
- Value
- Value::get (unsigned index, const Value &defaultValue) const
- {
- const Value *value = &((*this)[index]);
- return value == &null ? defaultValue : *value;
- }
-
-
- bool
- Value::isValidIndex (int index) const
- {
- return isValidIndex (static_cast<unsigned> (index));
- }
-
-
- bool
- Value::isValidIndex (unsigned index) const
- {
- return index < size ();
- }
-
-
-
- const Value &
- Value::operator [] (char const *key) const
- {
- throw_unless (type_ == nullValue || type_ == objectValue);
- if (type_ == nullValue)
- return null;
- CZString actualKey (key, CZString::noDuplication);
- ObjectValues::const_iterator it = value_.map_->find (actualKey);
- if (it == value_.map_->end ())
- return null;
- return it->second;
- }
-
-
- Value &
- Value::operator [] (const std::string &key)
- {
- return (*this)[ key.c_str () ];
- }