mirror of
https://github.com/open-source-parsers/jsoncpp.git
synced 2024-12-28 03:50:53 +08:00
Use a Myers Singleton for null
Avoid some static initialization problems. From @marklakata See #488
This commit is contained in:
parent
e0f9aab0bf
commit
0f288aecdd
@ -190,6 +190,8 @@ public:
|
|||||||
|
|
||||||
static const Value& null; ///< We regret this reference to a global instance; prefer the simpler Value().
|
static const Value& null; ///< We regret this reference to a global instance; prefer the simpler Value().
|
||||||
static const Value& nullRef; ///< just a kludge for binary-compatibility; same as null
|
static const Value& nullRef; ///< just a kludge for binary-compatibility; same as null
|
||||||
|
static Value const& nullSingleton(); ///< Prefer this to null or nullRef.
|
||||||
|
|
||||||
/// Minimum signed integer value that can be stored in a Json::Value.
|
/// Minimum signed integer value that can be stored in a Json::Value.
|
||||||
static const LargestInt minLargestInt;
|
static const LargestInt minLargestInt;
|
||||||
/// Maximum signed integer value that can be stored in a Json::Value.
|
/// Maximum signed integer value that can be stored in a Json::Value.
|
||||||
|
@ -31,10 +31,22 @@ namespace Json {
|
|||||||
#else
|
#else
|
||||||
#define ALIGNAS(byte_alignment)
|
#define ALIGNAS(byte_alignment)
|
||||||
#endif
|
#endif
|
||||||
static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
|
//static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
|
||||||
const unsigned char& kNullRef = kNull[0];
|
//const unsigned char& kNullRef = kNull[0];
|
||||||
const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
|
//const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
|
||||||
const Value& Value::nullRef = null;
|
//const Value& Value::nullRef = null;
|
||||||
|
|
||||||
|
// static
|
||||||
|
Value const& Value::nullSingleton()
|
||||||
|
{
|
||||||
|
static Value const* nullStatic = new Value;
|
||||||
|
return *nullStatic;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for backwards compatibility, we'll leave these global references around, but DO NOT
|
||||||
|
// use them in JSONCPP library code any more!
|
||||||
|
Value const& Value::null = Value::nullSingleton();
|
||||||
|
Value const& Value::nullRef = Value::nullSingleton();
|
||||||
|
|
||||||
const Int Value::minInt = Int(~(UInt(-1) / 2));
|
const Int Value::minInt = Int(~(UInt(-1) / 2));
|
||||||
const Int Value::maxInt = Int(UInt(-1) / 2);
|
const Int Value::maxInt = Int(UInt(-1) / 2);
|
||||||
@ -972,7 +984,7 @@ Value& Value::operator[](ArrayIndex index) {
|
|||||||
if (it != value_.map_->end() && (*it).first == key)
|
if (it != value_.map_->end() && (*it).first == key)
|
||||||
return (*it).second;
|
return (*it).second;
|
||||||
|
|
||||||
ObjectValues::value_type defaultValue(key, nullRef);
|
ObjectValues::value_type defaultValue(key, nullSingleton());
|
||||||
it = value_.map_->insert(it, defaultValue);
|
it = value_.map_->insert(it, defaultValue);
|
||||||
return (*it).second;
|
return (*it).second;
|
||||||
}
|
}
|
||||||
@ -989,11 +1001,11 @@ const Value& Value::operator[](ArrayIndex index) const {
|
|||||||
type_ == nullValue || type_ == arrayValue,
|
type_ == nullValue || type_ == arrayValue,
|
||||||
"in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
|
"in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
|
||||||
if (type_ == nullValue)
|
if (type_ == nullValue)
|
||||||
return nullRef;
|
return nullSingleton();
|
||||||
CZString key(index);
|
CZString key(index);
|
||||||
ObjectValues::const_iterator it = value_.map_->find(key);
|
ObjectValues::const_iterator it = value_.map_->find(key);
|
||||||
if (it == value_.map_->end())
|
if (it == value_.map_->end())
|
||||||
return nullRef;
|
return nullSingleton();
|
||||||
return (*it).second;
|
return (*it).second;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1027,7 +1039,7 @@ Value& Value::resolveReference(const char* key) {
|
|||||||
if (it != value_.map_->end() && (*it).first == actualKey)
|
if (it != value_.map_->end() && (*it).first == actualKey)
|
||||||
return (*it).second;
|
return (*it).second;
|
||||||
|
|
||||||
ObjectValues::value_type defaultValue(actualKey, nullRef);
|
ObjectValues::value_type defaultValue(actualKey, nullSingleton());
|
||||||
it = value_.map_->insert(it, defaultValue);
|
it = value_.map_->insert(it, defaultValue);
|
||||||
Value& value = (*it).second;
|
Value& value = (*it).second;
|
||||||
return value;
|
return value;
|
||||||
@ -1047,7 +1059,7 @@ Value& Value::resolveReference(char const* key, char const* cend)
|
|||||||
if (it != value_.map_->end() && (*it).first == actualKey)
|
if (it != value_.map_->end() && (*it).first == actualKey)
|
||||||
return (*it).second;
|
return (*it).second;
|
||||||
|
|
||||||
ObjectValues::value_type defaultValue(actualKey, nullRef);
|
ObjectValues::value_type defaultValue(actualKey, nullSingleton());
|
||||||
it = value_.map_->insert(it, defaultValue);
|
it = value_.map_->insert(it, defaultValue);
|
||||||
Value& value = (*it).second;
|
Value& value = (*it).second;
|
||||||
return value;
|
return value;
|
||||||
@ -1055,7 +1067,7 @@ Value& Value::resolveReference(char const* key, char const* cend)
|
|||||||
|
|
||||||
Value Value::get(ArrayIndex index, const Value& defaultValue) const {
|
Value Value::get(ArrayIndex index, const Value& defaultValue) const {
|
||||||
const Value* value = &((*this)[index]);
|
const Value* value = &((*this)[index]);
|
||||||
return value == &nullRef ? defaultValue : *value;
|
return value == &nullSingleton() ? defaultValue : *value;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
|
bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
|
||||||
@ -1074,13 +1086,13 @@ Value const* Value::find(char const* key, char const* cend) const
|
|||||||
const Value& Value::operator[](const char* key) const
|
const Value& Value::operator[](const char* key) const
|
||||||
{
|
{
|
||||||
Value const* found = find(key, key + strlen(key));
|
Value const* found = find(key, key + strlen(key));
|
||||||
if (!found) return nullRef;
|
if (!found) return nullSingleton();
|
||||||
return *found;
|
return *found;
|
||||||
}
|
}
|
||||||
Value const& Value::operator[](JSONCPP_STRING const& key) const
|
Value const& Value::operator[](JSONCPP_STRING const& key) const
|
||||||
{
|
{
|
||||||
Value const* found = find(key.data(), key.data() + key.length());
|
Value const* found = find(key.data(), key.data() + key.length());
|
||||||
if (!found) return nullRef;
|
if (!found) return nullSingleton();
|
||||||
return *found;
|
return *found;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1103,7 +1115,7 @@ Value& Value::operator[](const CppTL::ConstString& key) {
|
|||||||
Value const& Value::operator[](CppTL::ConstString const& key) const
|
Value const& Value::operator[](CppTL::ConstString const& key) const
|
||||||
{
|
{
|
||||||
Value const* found = find(key.c_str(), key.end_c_str());
|
Value const* found = find(key.c_str(), key.end_c_str());
|
||||||
if (!found) return nullRef;
|
if (!found) return nullSingleton();
|
||||||
return *found;
|
return *found;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1151,7 +1163,7 @@ 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 nullRef;
|
return nullSingleton();
|
||||||
|
|
||||||
Value removed; // null
|
Value removed; // null
|
||||||
removeMember(key, key + strlen(key), &removed);
|
removeMember(key, key + strlen(key), &removed);
|
||||||
@ -1538,7 +1550,7 @@ const Value& Path::resolve(const Value& root) const {
|
|||||||
// Error: unable to resolve path (object value expected at position...)
|
// Error: unable to resolve path (object value expected at position...)
|
||||||
}
|
}
|
||||||
node = &((*node)[arg.key_]);
|
node = &((*node)[arg.key_]);
|
||||||
if (node == &Value::nullRef) {
|
if (node == &Value::nullSingleton()) {
|
||||||
// Error: unable to resolve path (object has no member named '' at
|
// Error: unable to resolve path (object has no member named '' at
|
||||||
// position...)
|
// position...)
|
||||||
}
|
}
|
||||||
@ -1559,7 +1571,7 @@ Value Path::resolve(const Value& root, const Value& defaultValue) const {
|
|||||||
if (!node->isObject())
|
if (!node->isObject())
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
node = &((*node)[arg.key_]);
|
node = &((*node)[arg.key_]);
|
||||||
if (node == &Value::nullRef)
|
if (node == &Value::nullSingleton())
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user