Mercurial > code
diff C++/modules/Json/Json.cpp @ 405:f81478065901
Json:
- Complete rewrite,
- Convert jansson tree to own C++ tree,
- Conversion from Value to Object/Array makes copies
author | David Demelier <markand@malikania.fr> |
---|---|
date | Mon, 05 Oct 2015 17:04:40 +0200 |
parents | 9ab878fb9fa2 |
children | d485d36a8de1 |
line wrap: on
line diff
--- a/C++/modules/Json/Json.cpp Mon Oct 05 14:39:57 2015 +0200 +++ b/C++/modules/Json/Json.cpp Mon Oct 05 17:04:40 2015 +0200 @@ -1,5 +1,5 @@ /* - * Json.cpp -- jansson C++11 wrapper + * Json.cpp -- C++14 JSON manipulation using jansson parser * * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr> * @@ -16,147 +16,147 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <stdexcept> +#include "Json.h" -#include "Json.h" +#include <jansson.h> namespace json { -/* -------------------------------------------------------- - * Object - * -------------------------------------------------------- */ +namespace { + +void readObject(Value &parent, json_t *object); +void readArray(Value &parent, json_t *array); + +Value readValue(json_t *v) +{ + if (json_is_null(v)) { + return Value{nullptr}; + } + if (json_is_string(v)) { + return Value{json_string_value(v)}; + } + if (json_is_number(v)) { + return Value{json_number_value(v)}; + } + if (json_is_boolean(v)) { + return Value{json_boolean_value(v)}; + } + if (json_is_object(v)) { + Object object; + + readObject(object, v); + + return object; + } + if (json_is_array(v)) { + Array array; + + readArray(array, v); + + return array; + } + + return Value{}; +} + +void readObject(Value &parent, json_t *object) +{ + const char *key; + json_t *value; + + json_object_foreach(object, key, value) { + static_cast<Object &>(parent).insert(key, readValue(value)); + } +} + +void readArray(Value &parent, json_t *array) +{ + size_t index; + json_t *value; + + json_array_foreach(array, index, value) { + static_cast<Array &>(parent).append(readValue(value)); + } +} + +template <typename Func, typename... Args> +Value convert(Func fn, Args&&... args) +{ + json_error_t error; + json_t *json = fn(std::forward<Args>(args)..., &error); + + if (json == nullptr) { + throw Error{error.text, error.source, error.line, error.column, error.position}; + } + + Value value; + + if (json_is_object(json)) { + value = Object{}; + readObject(value, json); + } else { + value = Array{}; + readArray(value, json); + } + + json_decref(json); + + return value; +} + +} // !namespace + +bool Value::toBool() const noexcept +{ + if (m_type != Type::Boolean) + return false; + + return m_boolean; +} + +double Value::toNumber() const noexcept +{ + if (m_type != Type::Number) + return 0; + + return m_number; +} + +std::string Value::toString() const noexcept +{ + if (m_type != Type::String) { + return ""; + } + + return m_string; +} Object Value::toObject() const noexcept { - json_incref(m_handle.get()); + if (m_type != Type::Object) { + return Object{}; + } - return Object(m_handle.get()); + return Object(*this); } Array Value::toArray() const noexcept { - json_incref(m_handle.get()); - - return Array(m_handle.get()); -} - -/* -------------------------------------------------------- - * Array - * -------------------------------------------------------- */ - -Value Array::at(int index) const -{ - auto value = json_array_get(m_handle.get(), index); - - if (value == nullptr) - throw Error("index out of bounds"); - - json_incref(value); - - return Value{value}; -} - -Value Array::operator[](int index) const noexcept -{ - auto value = json_array_get(m_handle.get(), index); - - if (value == nullptr) - return Value(); - - json_incref(value); + if (m_type != Type::Array) { + return Array{}; + } - return Value(value); -} - -Array::Ref Array::operator[](int index) noexcept -{ - auto value = json_array_get(m_handle.get(), index); - - if (value == nullptr) - value = json_null(); - else - json_incref(value); - - return Ref(value, *this, index); -} - -/* -------------------------------------------------------- - * Object - * -------------------------------------------------------- */ - -Object::Ref Object::operator[](const std::string &name) -{ - if (typeOf() != Type::Object) - return Ref(Value(), *this, name); - - auto value = json_object_get(m_handle.get(), name.c_str()); - - json_incref(value); - - return Ref(value, *this, name); + return Array(*this); } -Value Object::operator[](const std::string &name) const +Document::Document(Buffer buffer) { - if (typeOf() != Type::Object) - return Value(); - - auto value = json_object_get(m_handle.get(), name.c_str()); - - if (value == nullptr) - return Value(); - - json_incref(value); - - return Value(value); -} - -/* -------------------------------------------------------- - * Document - * -------------------------------------------------------- */ - -Value Document::read(std::string content, int flags) const -{ - json_error_t error; - json_t *json = json_loads(content.c_str(), flags, &error); - - if (json == nullptr) - throw Error(error); - - return Value(json); + m_value = convert(json_loads, buffer.text.c_str(), 0); } -Value Document::read(std::ifstream &stream, int flags) const +Document::Document(File file) { - if (!stream.is_open()) - throw Error("File not opened"); - - stream.seekg(0, stream.end); - auto length = stream.tellg(); - stream.seekg(0, stream.beg); - - std::string buffer; - buffer.resize(length, ' '); - - stream.read(&buffer[0], length); - stream.close(); - - return read(std::move(buffer), flags); -} - -Document::Document(std::ifstream &stream, int flags) -{ - m_value = read(stream, flags); -} - -Document::Document(std::ifstream &&stream, int flags) -{ - m_value = read(stream, flags); -} - -Document::Document(std::string content, int flags) -{ - m_value = read(std::move(content), flags); + m_value = convert(json_load_file, file.path.c_str(), 0); } } // !json \ No newline at end of file