Skip to content

Use a Myers Singleton for null #490

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 27, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ ENDMACRO()
#SET( JSONCPP_VERSION_MAJOR X )
#SET( JSONCPP_VERSION_MINOR Y )
#SET( JSONCPP_VERSION_PATCH Z )
SET( JSONCPP_VERSION 1.7.2 )
SET( JSONCPP_VERSION 1.7.3 )
jsoncpp_parse_version( ${JSONCPP_VERSION} JSONCPP_VERSION )
#IF(NOT JSONCPP_VERSION_FOUND)
# MESSAGE(FATAL_ERROR "Failed to parse version string properly. Expect X.Y.Z")
Expand Down
2 changes: 2 additions & 0 deletions include/json/value.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ class JSON_API 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 Value const& nullSingleton(); ///< Prefer this to null or nullRef.

/// Minimum signed integer value that can be stored in a Json::Value.
static const LargestInt minLargestInt;
/// Maximum signed integer value that can be stored in a Json::Value.
Expand Down
4 changes: 2 additions & 2 deletions include/json/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
#ifndef JSON_VERSION_H_INCLUDED
# define JSON_VERSION_H_INCLUDED

# define JSONCPP_VERSION_STRING "1.7.2"
# define JSONCPP_VERSION_STRING "1.7.3"
# define JSONCPP_VERSION_MAJOR 1
# define JSONCPP_VERSION_MINOR 7
# define JSONCPP_VERSION_PATCH 2
# define JSONCPP_VERSION_PATCH 3
# define JSONCPP_VERSION_QUALIFIER
# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8))

Expand Down
44 changes: 28 additions & 16 deletions src/lib_json/json_value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,22 @@ namespace Json {
#else
#define ALIGNAS(byte_alignment)
#endif
static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
const unsigned char& kNullRef = kNull[0];
const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
const Value& Value::nullRef = null;
//static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
//const unsigned char& kNullRef = kNull[0];
//const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
//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::maxInt = Int(UInt(-1) / 2);
Expand Down Expand Up @@ -972,7 +984,7 @@ Value& Value::operator[](ArrayIndex index) {
if (it != value_.map_->end() && (*it).first == key)
return (*it).second;

ObjectValues::value_type defaultValue(key, nullRef);
ObjectValues::value_type defaultValue(key, nullSingleton());
it = value_.map_->insert(it, defaultValue);
return (*it).second;
}
Expand All @@ -989,11 +1001,11 @@ const Value& Value::operator[](ArrayIndex index) const {
type_ == nullValue || type_ == arrayValue,
"in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
if (type_ == nullValue)
return nullRef;
return nullSingleton();
CZString key(index);
ObjectValues::const_iterator it = value_.map_->find(key);
if (it == value_.map_->end())
return nullRef;
return nullSingleton();
return (*it).second;
}

Expand Down Expand Up @@ -1027,7 +1039,7 @@ Value& Value::resolveReference(const char* key) {
if (it != value_.map_->end() && (*it).first == actualKey)
return (*it).second;

ObjectValues::value_type defaultValue(actualKey, nullRef);
ObjectValues::value_type defaultValue(actualKey, nullSingleton());
it = value_.map_->insert(it, defaultValue);
Value& value = (*it).second;
return value;
Expand All @@ -1047,15 +1059,15 @@ Value& Value::resolveReference(char const* key, char const* cend)
if (it != value_.map_->end() && (*it).first == actualKey)
return (*it).second;

ObjectValues::value_type defaultValue(actualKey, nullRef);
ObjectValues::value_type defaultValue(actualKey, nullSingleton());
it = value_.map_->insert(it, defaultValue);
Value& value = (*it).second;
return value;
}

Value Value::get(ArrayIndex index, const Value& defaultValue) const {
const Value* value = &((*this)[index]);
return value == &nullRef ? defaultValue : *value;
return value == &nullSingleton() ? defaultValue : *value;
}

bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
Expand All @@ -1074,13 +1086,13 @@ Value const* Value::find(char const* key, char const* cend) const
const Value& Value::operator[](const char* key) const
{
Value const* found = find(key, key + strlen(key));
if (!found) return nullRef;
if (!found) return nullSingleton();
return *found;
}
Value const& Value::operator[](JSONCPP_STRING const& key) const
{
Value const* found = find(key.data(), key.data() + key.length());
if (!found) return nullRef;
if (!found) return nullSingleton();
return *found;
}

Expand All @@ -1103,7 +1115,7 @@ Value& Value::operator[](const CppTL::ConstString& key) {
Value const& Value::operator[](CppTL::ConstString const& key) const
{
Value const* found = find(key.c_str(), key.end_c_str());
if (!found) return nullRef;
if (!found) return nullSingleton();
return *found;
}
#endif
Expand Down Expand Up @@ -1151,7 +1163,7 @@ Value Value::removeMember(const char* key)
JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
"in Json::Value::removeMember(): requires objectValue");
if (type_ == nullValue)
return nullRef;
return nullSingleton();

Value removed; // null
removeMember(key, key + strlen(key), &removed);
Expand Down Expand Up @@ -1538,7 +1550,7 @@ const Value& Path::resolve(const Value& root) const {
// Error: unable to resolve path (object value expected at position...)
}
node = &((*node)[arg.key_]);
if (node == &Value::nullRef) {
if (node == &Value::nullSingleton()) {
// Error: unable to resolve path (object has no member named '' at
// position...)
}
Expand All @@ -1559,7 +1571,7 @@ Value Path::resolve(const Value& root, const Value& defaultValue) const {
if (!node->isObject())
return defaultValue;
node = &((*node)[arg.key_]);
if (node == &Value::nullRef)
if (node == &Value::nullSingleton())
return defaultValue;
}
}
Expand Down
2 changes: 1 addition & 1 deletion version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.7.2
1.7.3