diff --git a/json11.cpp b/json11.cpp index d2bb65e..dd13298 100644 --- a/json11.cpp +++ b/json11.cpp @@ -206,19 +206,38 @@ public: JsonNull() : Value(nullptr) {} }; +/* * * * * * * * * * * * * * * * * * * * + * Static globals - static-init-safe + */ +struct Statics { + const std::shared_ptr null = make_shared(); + const std::shared_ptr t = make_shared(true); + const std::shared_ptr f = make_shared(false); + const string empty_string; + const vector empty_vector; + const map empty_map; +}; + +const Statics & statics() { + static const Statics s {}; + return s; +} + +const Json & static_null() { + // This has to be separate, not in Statics, because Json() accesses statics().null. + static const Json json_null; + return json_null; +} + /* * * * * * * * * * * * * * * * * * * * * Constructors */ -static const std::shared_ptr obj_null(make_shared()); -static const std::shared_ptr obj_true(make_shared(true)); -static const std::shared_ptr obj_false(make_shared(false)); - -Json::Json() noexcept : m_ptr(obj_null) {} -Json::Json(std::nullptr_t) noexcept : m_ptr(obj_null) {} +Json::Json() noexcept : m_ptr(statics().null) {} +Json::Json(std::nullptr_t) noexcept : m_ptr(statics().null) {} Json::Json(double value) : m_ptr(make_shared(value)) {} Json::Json(int value) : m_ptr(make_shared(value)) {} -Json::Json(bool value) : m_ptr(value ? obj_true : obj_false) {} +Json::Json(bool value) : m_ptr(value ? statics().t : statics().f) {} Json::Json(const string &value) : m_ptr(make_shared(value)) {} Json::Json(string &&value) : m_ptr(make_shared(move(value))) {} Json::Json(const char * value) : m_ptr(make_shared(value)) {} @@ -231,11 +250,6 @@ Json::Json(Json::object &&values) : m_ptr(make_shared(move(valu * Accessors */ -static const string empty_string; -static const vector empty_vector; -static const map empty_map; -static const Json json_null; - Json::Type Json::type() const { return m_ptr->type(); } double Json::number_value() const { return m_ptr->number_value(); } int Json::int_value() const { return m_ptr->int_value(); } @@ -249,18 +263,18 @@ const Json & Json::operator[] (const string &key) const { return (*m_ptr)[key]; double JsonValue::number_value() const { return 0; } int JsonValue::int_value() const { return 0; } bool JsonValue::bool_value() const { return false; } -const string & JsonValue::string_value() const { return empty_string; } -const vector & JsonValue::array_items() const { return empty_vector; } -const map & JsonValue::object_items() const { return empty_map; } -const Json & JsonValue::operator[] (size_t) const { return json_null; } -const Json & JsonValue::operator[] (const string &) const { return json_null; } +const string & JsonValue::string_value() const { return statics().empty_string; } +const vector & JsonValue::array_items() const { return statics().empty_vector; } +const map & JsonValue::object_items() const { return statics().empty_map; } +const Json & JsonValue::operator[] (size_t) const { return static_null(); } +const Json & JsonValue::operator[] (const string &) const { return static_null(); } const Json & JsonObject::operator[] (const string &key) const { auto iter = m_value.find(key); - return (iter == m_value.end()) ? json_null : iter->second; + return (iter == m_value.end()) ? static_null() : iter->second; } const Json & JsonArray::operator[] (size_t i) const { - if (i >= m_value.size()) return json_null; + if (i >= m_value.size()) return static_null(); else return m_value[i]; }