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
* 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 {
friend class ValueIteratorBase;
@ -352,19 +358,25 @@ Json::Value obj_value(Json::objectValue); // {}
Value& append(const Value& value);
/// 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);
/// Access an object value by name, returns null if there is no member with
/// that name.
const Value& operator[](const char* key) const;
/// 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);
/// Access an object value by name, returns null if there is no member with
/// that name.
/// \param key may contain embedded nulls.
const Value& operator[](const std::string& key) const;
/** \brief Access an object value by name, create a null member if it does not
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.
* Example of use:
* \code
@ -384,11 +396,19 @@ Json::Value obj_value(Json::objectValue); // {}
/// Return the member named key if it exist, defaultValue otherwise.
Value get(const char* key, const Value& defaultValue) const;
/// 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;
#ifdef JSON_USE_CPPTL
/// Return the member named key if it exist, defaultValue otherwise.
Value get(const CppTL::ConstString& key, const Value& defaultValue) const;
#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.
///
/// Do nothing if it did not exist.
@ -398,14 +418,21 @@ Json::Value obj_value(Json::objectValue); // {}
/// \deprecated
Value removeMember(const char* key);
/// Same as removeMember(const char*)
/// \param key may contain embedded nulls.
/// \deprecated
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.
Update 'removed' iff removed.
\param key may contain embedded nulls.
\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.
O(n) expensive operations.
@ -417,7 +444,10 @@ Json::Value obj_value(Json::objectValue); // {}
/// Return true if the object has a member named key.
bool isMember(const char* key) const;
/// Return true if the object has a member named key.
/// \param key may contain embedded nulls.
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
/// Return true if the object has a member named key.
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(); }
const Value& Value::operator[](const char* key) const {
Value const* Value::find(char const* key, char const* end) const
{
JSON_ASSERT_MESSAGE(
type_ == nullValue || type_ == objectValue,
"in Json::Value::operator[](char const*)const: requires objectValue");
if (type_ == nullValue)
return null;
CZString actualKey(key, strlen(key), CZString::noDuplication);
"in Json::Value::find(key, end, found): requires objectValue or nullValue");
if (type_ == nullValue) return NULL;
CZString actualKey(key, end-key, CZString::noDuplication);
ObjectValues::const_iterator it = value_.map_->find(actualKey);
if (it == value_.map_->end())
return null;
return (*it).second;
if (it == value_.map_->end()) return NULL;
return &(*it).second;
}
Value& Value::operator[](const std::string& key) {
const Value& Value::operator[](const char* key) const
{
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()];
}
const Value& Value::operator[](const std::string& key) const {
return (*this)[key.c_str()];
Value const& Value::operator[](std::string const& key) const
{
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);
}
@ -896,29 +903,37 @@ Value& Value::operator[](const StaticString& key) {
Value& Value::operator[](const CppTL::ConstString& key) {
return (*this)[key.c_str()];
}
const Value& Value::operator[](const CppTL::ConstString& key) const {
return (*this)[key.c_str()];
Value const& Value::operator[](CppTL::ConstString const& key) const
{
Value const* found = find(key.c_str(), key.end_c_str());
if (!found) return null;
return *found;
}
#endif
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]);
return value == &null ? defaultValue : *value;
}
Value Value::get(const std::string& key, const Value& defaultValue) const {
Value Value::get(char const* key, Value const& 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);
}
bool Value::removeMember(const char* key, Value* removed) {
bool Value::removeMember(const char* key, const char* end, Value* removed)
{
if (type_ != objectValue) {
return false;
}
CZString actualKey(key, strlen(key), CZString::noDuplication);
CZString actualKey(key, end-key, CZString::noDuplication);
ObjectValues::iterator it = value_.map_->find(actualKey);
if (it == value_.map_->end())
return false;
@ -926,19 +941,27 @@ bool Value::removeMember(const char* key, Value* removed) {
value_.map_->erase(it);
return true;
}
Value Value::removeMember(const char* key) {
bool Value::removeMember(const char* key, Value* removed)
{
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,
"in Json::Value::removeMember(): requires objectValue");
if (type_ == nullValue)
return null;
Value removed; // null
removeMember(key, &removed);
removeMember(key, key + strlen(key), &removed);
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());
}
@ -972,13 +995,18 @@ Value Value::get(const CppTL::ConstString& key,
}
#endif
bool Value::isMember(const char* key) const {
const Value* value = &((*this)[key]);
return value != &null;
bool Value::isMember(char const* key, char const* end) const
{
Value const* value = find(key, end);
return NULL != value;
}
bool Value::isMember(const std::string& key) const {
return isMember(key.c_str());
bool Value::isMember(const char* key) const
{
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