support UTF-8 for const methods

This commit is contained in:
Christopher Dunn 2015-03-02 18:05:26 -06:00
parent 2b9abc3ebf
commit 25342bac13
2 changed files with 94 additions and 36 deletions

View File

@ -112,6 +112,12 @@ private:
* *
* It is possible to iterate over the list of a #objectValue values using * It is possible to iterate over the list of a #objectValue values using
* the getMemberNames() method. * the getMemberNames() method.
*
* \note Value string-length fit in size_t, but keys must fit in unsigned.
* (The reason is an implementation detail.) The readers will raise an
* exception if a bound is exceeded to avoid security holes in your app,
* but the Value API does *not* check bounds. That is the responsibility
* of the caller.
*/ */
class JSON_API Value { class JSON_API Value {
friend class ValueIteratorBase; friend class ValueIteratorBase;
@ -352,19 +358,25 @@ Json::Value obj_value(Json::objectValue); // {}
Value& append(const Value& value); Value& append(const Value& value);
/// Access an object value by name, create a null member if it does not exist. /// Access an object value by name, create a null member if it does not exist.
/// \note Because of our implementation, keys are limited to 2^30 -1 chars.
/// Exceeding that will cause an exception.
Value& operator[](const char* key); Value& operator[](const char* key);
/// Access an object value by name, returns null if there is no member with /// Access an object value by name, returns null if there is no member with
/// that name. /// that name.
const Value& operator[](const char* key) const; const Value& operator[](const char* key) const;
/// Access an object value by name, create a null member if it does not exist. /// Access an object value by name, create a null member if it does not exist.
/// \param key may contain embedded nulls.
Value& operator[](const std::string& key); Value& operator[](const std::string& key);
/// Access an object value by name, returns null if there is no member with /// Access an object value by name, returns null if there is no member with
/// that name. /// that name.
/// \param key may contain embedded nulls.
const Value& operator[](const std::string& key) const; const Value& operator[](const std::string& key) const;
/** \brief Access an object value by name, create a null member if it does not /** \brief Access an object value by name, create a null member if it does not
exist. exist.
* If the object as no entry for that name, then the member name used to store * \param key may contain embedded nulls.
*
* If the object has no entry for that name, then the member name used to store
* the new entry is not duplicated. * the new entry is not duplicated.
* Example of use: * Example of use:
* \code * \code
@ -384,11 +396,19 @@ Json::Value obj_value(Json::objectValue); // {}
/// Return the member named key if it exist, defaultValue otherwise. /// Return the member named key if it exist, defaultValue otherwise.
Value get(const char* key, const Value& defaultValue) const; Value get(const char* key, const Value& defaultValue) const;
/// Return the member named key if it exist, defaultValue otherwise. /// Return the member named key if it exist, defaultValue otherwise.
/// \param key may contain embedded nulls.
Value get(const char* key, const char* end, const Value& defaultValue) const;
/// Return the member named key if it exist, defaultValue otherwise.
/// \param key may contain embedded nulls.
Value get(const std::string& key, const Value& defaultValue) const; Value get(const std::string& key, const Value& defaultValue) const;
#ifdef JSON_USE_CPPTL #ifdef JSON_USE_CPPTL
/// Return the member named key if it exist, defaultValue otherwise. /// Return the member named key if it exist, defaultValue otherwise.
Value get(const CppTL::ConstString& key, const Value& defaultValue) const; Value get(const CppTL::ConstString& key, const Value& defaultValue) const;
#endif #endif
/// Most general and efficient version of isMember()const, get()const,
/// and operator[]const
/// \note As stated elsewhere, behavior is undefined if (end-key) >= 2^30
Value const* find(char const* key, char const* end) const;
/// \brief Remove and return the named member. /// \brief Remove and return the named member.
/// ///
/// Do nothing if it did not exist. /// Do nothing if it did not exist.
@ -398,14 +418,21 @@ Json::Value obj_value(Json::objectValue); // {}
/// \deprecated /// \deprecated
Value removeMember(const char* key); Value removeMember(const char* key);
/// Same as removeMember(const char*) /// Same as removeMember(const char*)
/// \param key may contain embedded nulls.
/// \deprecated /// \deprecated
Value removeMember(const std::string& key); Value removeMember(const std::string& key);
/// Same as removeMember(const char* key, const char* end, Value* removed),
/// but 'key' is null-terminated.
bool removeMember(const char* key, Value* removed);
/** \brief Remove the named map member. /** \brief Remove the named map member.
Update 'removed' iff removed. Update 'removed' iff removed.
\param key may contain embedded nulls.
\return true iff removed (no exceptions) \return true iff removed (no exceptions)
*/ */
bool removeMember(const char* key, Value* removed); bool removeMember(std::string const& key, Value* removed);
/// Same as removeMember(std::string const& key, Value* removed)
bool removeMember(const char* key, const char* end, Value* removed);
/** \brief Remove the indexed array element. /** \brief Remove the indexed array element.
O(n) expensive operations. O(n) expensive operations.
@ -417,7 +444,10 @@ Json::Value obj_value(Json::objectValue); // {}
/// Return true if the object has a member named key. /// Return true if the object has a member named key.
bool isMember(const char* key) const; bool isMember(const char* key) const;
/// Return true if the object has a member named key. /// Return true if the object has a member named key.
/// \param key may contain embedded nulls.
bool isMember(const std::string& key) const; bool isMember(const std::string& key) const;
/// Same as isMember(std::string const& key)const
bool isMember(const char* key, const char* end) const;
#ifdef JSON_USE_CPPTL #ifdef JSON_USE_CPPTL
/// Return true if the object has a member named key. /// Return true if the object has a member named key.
bool isMember(const CppTL::ConstString& key) const; bool isMember(const CppTL::ConstString& key) const;

View File

@ -867,28 +867,35 @@ Value Value::get(ArrayIndex index, const Value& defaultValue) const {
bool Value::isValidIndex(ArrayIndex index) const { return index < size(); } bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
const Value& Value::operator[](const char* key) const { Value const* Value::find(char const* key, char const* end) const
{
JSON_ASSERT_MESSAGE( JSON_ASSERT_MESSAGE(
type_ == nullValue || type_ == objectValue, type_ == nullValue || type_ == objectValue,
"in Json::Value::operator[](char const*)const: requires objectValue"); "in Json::Value::find(key, end, found): requires objectValue or nullValue");
if (type_ == nullValue) if (type_ == nullValue) return NULL;
return null; CZString actualKey(key, end-key, CZString::noDuplication);
CZString actualKey(key, strlen(key), CZString::noDuplication);
ObjectValues::const_iterator it = value_.map_->find(actualKey); ObjectValues::const_iterator it = value_.map_->find(actualKey);
if (it == value_.map_->end()) if (it == value_.map_->end()) return NULL;
return null; return &(*it).second;
return (*it).second;
} }
const Value& Value::operator[](const char* key) const
Value& Value::operator[](const std::string& key) { {
Value const* found = find(key, key + strlen(key));
if (!found) return null;
return *found;
}
Value& Value::operator[](const std::string& key)
{
return (*this)[key.c_str()]; return (*this)[key.c_str()];
} }
Value const& Value::operator[](std::string const& key) const
const Value& Value::operator[](const std::string& key) const { {
return (*this)[key.c_str()]; Value const* found = find(key.data(), key.data() + key.length());
if (!found) return null;
return *found;
} }
Value& Value::operator[](const StaticString& key)
Value& Value::operator[](const StaticString& key) { {
return resolveReference(key, true); return resolveReference(key, true);
} }
@ -896,29 +903,37 @@ Value& Value::operator[](const StaticString& key) {
Value& Value::operator[](const CppTL::ConstString& key) { Value& Value::operator[](const CppTL::ConstString& key) {
return (*this)[key.c_str()]; return (*this)[key.c_str()];
} }
Value const& Value::operator[](CppTL::ConstString const& key) const
const Value& Value::operator[](const CppTL::ConstString& key) const { {
return (*this)[key.c_str()]; Value const* found = find(key.c_str(), key.end_c_str());
if (!found) return null;
return *found;
} }
#endif #endif
Value& Value::append(const Value& value) { return (*this)[size()] = value; } Value& Value::append(const Value& value) { return (*this)[size()] = value; }
Value Value::get(const char* key, const Value& defaultValue) const { Value Value::get(char const* key, char const* end, Value const& defaultValue) const
{
const Value* value = &((*this)[key]); const Value* value = &((*this)[key]);
return value == &null ? defaultValue : *value; return value == &null ? defaultValue : *value;
} }
Value Value::get(char const* key, Value const& defaultValue) const
Value Value::get(const std::string& key, const Value& defaultValue) const { {
return get(key, key + strlen(key), defaultValue);
}
Value Value::get(std::string const& key, Value const& defaultValue) const
{
return get(key.c_str(), defaultValue); return get(key.c_str(), defaultValue);
} }
bool Value::removeMember(const char* key, Value* removed) { bool Value::removeMember(const char* key, const char* end, Value* removed)
{
if (type_ != objectValue) { if (type_ != objectValue) {
return false; return false;
} }
CZString actualKey(key, strlen(key), CZString::noDuplication); CZString actualKey(key, end-key, CZString::noDuplication);
ObjectValues::iterator it = value_.map_->find(actualKey); ObjectValues::iterator it = value_.map_->find(actualKey);
if (it == value_.map_->end()) if (it == value_.map_->end())
return false; return false;
@ -926,19 +941,27 @@ bool Value::removeMember(const char* key, Value* removed) {
value_.map_->erase(it); value_.map_->erase(it);
return true; return true;
} }
bool Value::removeMember(const char* key, Value* removed)
Value Value::removeMember(const char* key) { {
return removeMember(key, key + strlen(key), removed);
}
bool Value::removeMember(std::string const& key, Value* removed)
{
return removeMember(key.data(), key.data() + key.length(), removed);
}
Value Value::removeMember(const char* key)
{
JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue, JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
"in Json::Value::removeMember(): requires objectValue"); "in Json::Value::removeMember(): requires objectValue");
if (type_ == nullValue) if (type_ == nullValue)
return null; return null;
Value removed; // null Value removed; // null
removeMember(key, &removed); removeMember(key, key + strlen(key), &removed);
return removed; // still null if removeMember() did nothing return removed; // still null if removeMember() did nothing
} }
Value Value::removeMember(const std::string& key)
Value Value::removeMember(const std::string& key) { {
return removeMember(key.c_str()); return removeMember(key.c_str());
} }
@ -972,13 +995,18 @@ Value Value::get(const CppTL::ConstString& key,
} }
#endif #endif
bool Value::isMember(const char* key) const { bool Value::isMember(char const* key, char const* end) const
const Value* value = &((*this)[key]); {
return value != &null; Value const* value = find(key, end);
return NULL != value;
} }
bool Value::isMember(const char* key) const
bool Value::isMember(const std::string& key) const { {
return isMember(key.c_str()); return isMember(key, key + strlen(key));
}
bool Value::isMember(const std::string& key) const
{
return isMember(key.data(), key.data() + key.length());
} }
#ifdef JSON_USE_CPPTL #ifdef JSON_USE_CPPTL