2 Commits

Author SHA1 Message Date
2273bdd966 Mutable v4 2022-03-20 16:58:17 +03:00
52a3af664f Fix compilation under clang 2022-01-15 23:38:58 +03:00
2 changed files with 80 additions and 19 deletions

View File

@@ -41,10 +41,6 @@ using std::move;
* Serialization
*/
static void dump(std::nullptr_t, string &out) {
out += "null";
}
static void dump(double value, string &out) {
if (std::isfinite(value)) {
char buf[32];
@@ -55,10 +51,6 @@ static void dump(double value, string &out) {
}
}
static void dump(int value, string &out) {
out += std::to_string(value);
}
static void dump(int64_ value, string &out) {
out += std::to_string(value);
}
@@ -146,6 +138,7 @@ void Json::dump(string &out) const {
template <Json::Type tag, typename T>
class Value : public JsonValue {
protected:
friend class JsonIndex;
// Constructors
explicit Value(const T &value) : m_value(value) {}
@@ -164,12 +157,12 @@ protected:
return m_value < static_cast<const Value<tag, T> *>(other)->m_value;
}
const T m_value;
T m_value;
void dump(string &out) const override { json11::dump(m_value, out); }
};
class JsonDouble final : public Value<Json::NUMBER, double> {
string as_string() const { return std::to_string(m_value); }
string as_string() const override { return std::to_string(m_value); }
bool bool_value() const override { return m_value != 0; }
double number_value() const override { return static_cast<double>(m_value); }
int64_ int64_value() const override { return static_cast<int64_>(m_value); }
@@ -181,7 +174,7 @@ public:
};
class JsonInt64 final : public Value<Json::NUMBER, int64_> {
string as_string() const { return std::to_string(m_value); }
string as_string() const override { return std::to_string(m_value); }
bool bool_value() const override { return m_value != 0; }
double number_value() const override { return static_cast<double>(m_value); }
int64_ int64_value() const override { return static_cast<int64_>(m_value); }
@@ -193,7 +186,7 @@ public:
};
class JsonUInt64 final : public Value<Json::NUMBER, uint64_> {
string as_string() const { return std::to_string(m_value); }
string as_string() const override { return std::to_string(m_value); }
bool bool_value() const override { return m_value != 0; }
double number_value() const override { return static_cast<double>(m_value); }
int64_ int64_value() const override { return static_cast<int64_>(m_value); }
@@ -211,7 +204,7 @@ public:
};
class JsonString final : public Value<Json::STRING, string> {
string as_string() const { return m_value; }
string as_string() const override { return m_value; }
const string &string_value() const override { return m_value; }
bool bool_value() const override { return m_value != "" && m_value != "0"; }
double number_value() const override
@@ -259,9 +252,23 @@ public:
explicit JsonObject(Json::object &&value) : Value(move(value)) {}
};
class JsonNull final : public Value<Json::NUL, std::nullptr_t> {
class JsonNull final : public JsonValue {
public:
JsonNull() : Value(nullptr) {}
JsonNull() {}
// Get type tag
Json::Type type() const override {
return Json::NUL;
}
// Comparisons - only within type
bool equals(const JsonValue * other) const override {
return true;
}
bool less(const JsonValue * other) const override {
return false;
}
void dump(string &out) const override {
out += "null";
}
};
/* * * * * * * * * * * * * * * * * * * *
@@ -321,7 +328,7 @@ const string & Json::string_value() const { return m_ptr->string_v
const vector<Json> & Json::array_items() const { return m_ptr->array_items(); }
const map<string, Json> & Json::object_items() const { return m_ptr->object_items(); }
const Json & Json::operator[] (size_t i) const { return (*m_ptr)[i]; }
const Json & Json::operator[] (const string &key) const { return (*m_ptr)[key]; }
JsonIndex Json::operator[] (const string &key) { return (JsonIndex){ .m_object = *this, .m_key = key }; }
double JsonValue::number_value() const { return 0; }
int64_ JsonValue::int64_value() const { return 0; }
@@ -836,8 +843,13 @@ bool Json::has_shape(const shape & types, string & err) const {
return false;
}
const auto & obj = object_items();
for (auto & item : types) {
if ((*this)[item.first].type() != item.second) {
auto it = obj.find(item.first);
if (it == obj.end()) {
return false;
}
if (it->second.type() != item.second) {
err = "bad type for " + item.first + " in " + dump();
return false;
}
@@ -846,4 +858,22 @@ bool Json::has_shape(const shape & types, string & err) const {
return true;
}
/* * * * * * * * * * * * * * * * * * * *
* Indexed wrapper to prevent autovivification
*/
const Json & JsonIndex::self() const {
if (m_object.is_object()) {
return ((JsonObject*)m_object.m_ptr.get())->m_value[m_key];
}
return static_null();
}
Json JsonIndex::operator =(Json value) {
if (m_object.is_object()) {
return ((JsonObject*)m_object.m_ptr.get())->m_value[m_key] = value;
}
return value;
}
} // namespace json11

View File

@@ -77,6 +77,8 @@ enum JsonParse {
class JsonValue;
class JsonIndex;
#if __cplusplus < 201103L
#error This project can only be compiled with a compiler that supports C++11
#else
@@ -165,7 +167,7 @@ public:
// Return a reference to arr[i] if this is an array, Json() otherwise.
const Json & operator[](size_t i) const;
// Return a reference to obj[key] if this is an object, Json() otherwise.
const Json & operator[](const std::string &key) const;
JsonIndex operator[](const std::string &key);
// Serialize.
void dump(std::string &out) const;
@@ -220,9 +222,38 @@ public:
bool has_shape(const shape & types, std::string & err) const;
private:
friend class JsonIndex;
std::shared_ptr<JsonValue> m_ptr;
};
class JsonIndex {
public:
Json m_object;
const std::string & m_key;
Json operator =(Json value);
operator const Json &() { return m_object[m_key]; }
const Json & self() const;
bool is_null() const { return self().is_null(); }
bool is_number() const { return self().is_number(); }
bool is_bool() const { return self().is_bool(); }
bool is_string() const { return self().is_string(); }
bool is_array() const { return self().is_array(); }
bool is_object() const { return self().is_object(); }
double number_value() const { return self().number_value(); }
int64_ int64_value() const { return self().int64_value(); }
uint64_ uint64_value() const { return self().uint64_value(); }
std::string as_string() const { return self().as_string(); }
bool bool_value() const { return self().bool_value(); }
const std::string &string_value() const { return self().string_value(); }
const Json::array &array_items() const { return self().array_items(); }
const Json::object &object_items() const { return self().object_items(); }
std::string dump() const { return self().dump(); }
};
// Internal class hierarchy - JsonValue objects are not exposed to users of this API.
class JsonValue {
protected: