Mercurial > code
diff C++/Json.cpp @ 311:ed3cc10761e4
Json:
* Split Json class into several classes
* Add unit tests
* Json is considered usable
author | David Demelier <markand@malikania.fr> |
---|---|
date | Fri, 13 Feb 2015 13:42:21 +0100 |
parents | 777bc3cb665a |
children | ea1a73a7d468 |
line wrap: on
line diff
--- a/C++/Json.cpp Wed Feb 11 19:52:13 2015 +0100 +++ b/C++/Json.cpp Fri Feb 13 13:42:21 2015 +0100 @@ -18,258 +18,245 @@ #include "Json.h" -Json Json::fromString(const std::string &data, int flags) -{ - return from(json_loads, data.c_str(), flags); -} +/* -------------------------------------------------------- + * JsonValue implementation + * -------------------------------------------------------- */ -Json Json::fromFile(const std::string &path, int flags) -{ - return from(json_load_file, path.c_str(), flags); -} - -Json::Json() - : m_handle(json_object(), json_decref) +JsonValue::JsonValue(const JsonValue &value) + : m_handle(json_deep_copy(value.m_handle.get()), json_decref) { } -Json::Json(bool value) +JsonValue &JsonValue::operator=(const JsonValue &value) +{ + m_handle = Handle(json_deep_copy(value.m_handle.get()), json_decref); +} + +JsonValue::JsonValue(json_t *json) + : m_handle(json, json_decref) +{ +} + +JsonValue::JsonValue() + : m_handle(json_null(), json_decref) +{ +} + +JsonValue::JsonValue(bool value) : m_handle(json_boolean(value), json_decref) { } -Json::Json(int value) +JsonValue::JsonValue(int value) : m_handle(json_integer(value), json_decref) { } -Json::Json(double value) +JsonValue::JsonValue(double value) : m_handle(json_real(value), json_decref) { } -Json::Json(const std::string &value) +JsonValue::JsonValue(std::string value) : m_handle(json_string(value.c_str()), json_decref) { } -Json::Json(const Json &json) - : m_handle(json_deep_copy(json.m_handle.get()), json_decref) - , m_list(json.m_list) - , m_map(json.m_map) -{ -} - -Json::Json(Json &&value) - : m_handle(value.m_handle.release(), json_decref) - , m_list(std::move(value.m_list)) - , m_map(std::move(value.m_map)) +JsonValue::JsonValue(const char *value) + : m_handle(json_string(value), json_decref) { } -Json::Json(std::initializer_list<Json> list) - : m_handle(json_array(), json_decref) +JsonType JsonValue::typeOf() const { - m_list.reserve(list.size()); - - for (const auto &v : list) { - m_list.push_back(v); - json_array_append(m_handle.get(), m_list.back().m_handle.get()); - } + return static_cast<JsonType>(json_typeof(m_handle.get())); } -Json &Json::operator=(const Json &json) -{ - m_handle = Handle(json.m_handle.get(), json_decref); - m_list = json.m_list; - m_map = json.m_map; - - return *this; -} - -Json &Json::operator=(Json &&value) -{ - m_handle = Handle(value.m_handle.release(), json_decref); - m_list = std::move(value.m_list); - m_map = std::move(value.m_map); - - return *this; -} - -int Json::typeOf() const -{ - return json_typeof(m_handle.get()); -} - -bool Json::isObject() const +bool JsonValue::isObject() const { return json_is_object(m_handle.get()) != 0; } -bool Json::isArray() const +bool JsonValue::isArray() const { return json_is_array(m_handle.get()) != 0; } -bool Json::isString() const +bool JsonValue::isString() const { return json_is_string(m_handle.get()) != 0; } -bool Json::isReal() const +bool JsonValue::isReal() const { return json_is_real(m_handle.get()) != 0; } -bool Json::isTrue() const -{ - return json_is_true(m_handle.get()) != 0; -} - -bool Json::isFalse() const +bool JsonValue::isTrue() const { return json_is_true(m_handle.get()) != 0; } -bool Json::isNull() const +bool JsonValue::isFalse() const +{ + return json_is_false(m_handle.get()) != 0; +} + +bool JsonValue::isNull() const { return json_is_null(m_handle.get()) != 0; } -bool Json::isNumber() const +bool JsonValue::isNumber() const { return json_is_number(m_handle.get()) != 0; } -bool Json::isInteger() const +bool JsonValue::isInteger() const { return json_is_integer(m_handle.get()) != 0; } -bool Json::isBoolean() const +bool JsonValue::isBoolean() const { return json_is_boolean(m_handle.get()) != 0; } -unsigned Json::size() const noexcept -{ - return m_list.size(); -} - -void Json::append(const Json &value) -{ - m_list.push_back(value); - json_array_append(m_handle.get(), m_list.back().m_handle.get()); -} - -void Json::append(Json &&value) -{ - m_list.push_back(std::move(value)); - json_array_append(m_handle.get(), m_list.back().m_handle.get()); -} - -void Json::insert(const Json &value, int index) -{ - m_list.insert(m_list.begin() + index, value); - json_array_insert(m_handle.get(), index, m_list[index].m_handle.get()); -} - -void Json::insert(Json &&value, int index) -{ - m_list.insert(m_list.begin() + index, std::move(value)); - json_array_insert(m_handle.get(), index, m_list[index].m_handle.get()); -} - -void Json::set(const Json &value, const std::string &name) -{ - m_map[name] = value; - json_object_set(m_handle.get(), name.c_str(), m_map[name].m_handle.get()); -} - -void Json::set(Json &&value, const std::string &name) -{ - m_map[name] = std::move(value); - json_object_set(m_handle.get(), name.c_str(), m_map[name].m_handle.get()); -} - -std::string Json::toString() const +std::string JsonValue::toString() const { auto value = json_string_value(m_handle.get()); return (value == nullptr) ? "" : value; } -int Json::toInteger() const noexcept +int JsonValue::toInteger() const noexcept { return json_integer_value(m_handle.get()); } -double Json::toReal() const noexcept +double JsonValue::toReal() const noexcept { return json_real_value(m_handle.get()); } -std::string Json::dump(int flags) +JsonObject JsonValue::toObject() const { - auto v = json_dumps(m_handle.get(), flags); + json_incref(m_handle.get()); + + return JsonObject(m_handle.get()); +} + +JsonArray JsonValue::toArray() const +{ + json_incref(m_handle.get()); - if (v == nullptr) - throw std::runtime_error("failed to dump"); + return JsonArray(m_handle.get()); +} + +/* -------------------------------------------------------- + * JsonArray + * -------------------------------------------------------- */ - return std::string(v); +JsonArray::JsonArray() + : JsonValue(json_array()) +{ +} + +unsigned JsonArray::size() const noexcept +{ + return json_array_size(m_handle.get()); } -void Json::dump(const std::string &path, int flags) +void JsonArray::push(const JsonValue &value) { - if (json_dump_file(m_handle.get(), path.c_str(), flags) < 0) - throw std::runtime_error("failed to dump"); + json_array_insert(m_handle.get(), 0, value.m_handle.get()); +} + +void JsonArray::append(const JsonValue &value) +{ + json_array_append(m_handle.get(), value.m_handle.get()); } -Json &Json::operator[](int index) +void JsonArray::insert(const JsonValue &value, int index) { - if (!isArray()) - throw std::invalid_argument("not an array"); + json_array_insert(m_handle.get(), index, value.m_handle.get()); +} - if (index >= m_list.size()) - throw std::out_of_range("invalid index"); +JsonValue JsonArray::operator[](int index) const +{ + if (typeOf() != JsonType::Array) + throw JsonError("not an array"); + + auto value = json_array_get(m_handle.get(), index); - return m_list[index]; + if (value == nullptr) + throw JsonError("index out of bounds"); + + json_incref(value); + + return JsonValue(value); } -const Json &Json::operator[](int index) const +/* -------------------------------------------------------- + * JsonObject + * -------------------------------------------------------- */ + +JsonObject::JsonObject() + : JsonValue(json_object()) { - if (!isArray()) - throw std::invalid_argument("not an array"); +} + +JsonValue JsonObject::operator[](const std::string &name) const +{ + if (typeOf() != JsonType::Object) + throw JsonError("not an object"); - if (index >= m_list.size()) - throw std::out_of_range("invalid index"); + auto value = json_object_get(m_handle.get(), name.c_str()); + + if (value == nullptr) + throw JsonError("key " + name + +" not found"); + + json_incref(value); - return m_list[index]; + return JsonValue(value); +} + +void JsonObject::set(const std::string &key, const JsonValue &value) +{ + json_object_set(m_handle.get(), key.c_str(), value.m_handle.get()); } -Json &Json::operator[](const std::string &name) -{ - if (!isObject()) - throw std::invalid_argument("not an object"); +/* -------------------------------------------------------- + * JsonReaderFile + * -------------------------------------------------------- */ - if (m_map.count(name) == 0) - throw std::out_of_range("invalid key"); - - return m_map[name]; +JsonReaderFile::JsonReaderFile(std::string path) + : m_path(std::move(path)) +{ } -const Json &Json::operator[](const std::string &name) const +JsonValue JsonReaderFile::read() { - if (!isObject()) - throw std::invalid_argument("not an object"); + json_error_t error; + json_t *handle = json_load_file(m_path.c_str(), 0, &error); - if (m_map.count(name) == 0) - throw std::out_of_range("invalid key"); + if (handle == nullptr) + throw JsonError{error}; - return m_map.at(name); + return JsonValue(handle); } -bool operator==(const Json &j1, const Json &j2) +/* -------------------------------------------------------- + * JsonWriterFile + * -------------------------------------------------------- */ + +JsonWriterFile::JsonWriterFile(std::string path) + : m_path(std::move(path)) { - return json_equal(j1.m_handle.get(), j2.m_handle.get()) != 0; } + +void JsonWriterFile::write(const JsonValue &value) +{ + if (json_dump_file(value, m_path.c_str(), 0) < 0) + throw JsonError("Failed to write file: " + m_path); +}