Mercurial > code
changeset 244:777bc3cb665a
Add Json, a jansson wrapper
author | David Demelier <markand@malikania.fr> |
---|---|
date | Sat, 13 Sep 2014 19:42:15 +0200 |
parents | 73e5381d7baf |
children | 3c12f0e8bbb9 |
files | C++/Json.cpp C++/Json.h |
diffstat | 2 files changed, 701 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/C++/Json.cpp Sat Sep 13 19:42:15 2014 +0200 @@ -0,0 +1,275 @@ +/* + * Json.cpp -- jansson C++11 wrapper + * + * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "Json.h" + +Json Json::fromString(const std::string &data, int flags) +{ + return from(json_loads, data.c_str(), flags); +} + +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) +{ +} + +Json::Json(bool value) + : m_handle(json_boolean(value), json_decref) +{ +} + +Json::Json(int value) + : m_handle(json_integer(value), json_decref) +{ +} + +Json::Json(double value) + : m_handle(json_real(value), json_decref) +{ +} + +Json::Json(const 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)) +{ +} + +Json::Json(std::initializer_list<Json> list) + : m_handle(json_array(), json_decref) +{ + 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()); + } +} + +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 +{ + return json_is_object(m_handle.get()) != 0; +} + +bool Json::isArray() const +{ + return json_is_array(m_handle.get()) != 0; +} + +bool Json::isString() const +{ + return json_is_string(m_handle.get()) != 0; +} + +bool Json::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 +{ + return json_is_true(m_handle.get()) != 0; +} + +bool Json::isNull() const +{ + return json_is_null(m_handle.get()) != 0; +} + +bool Json::isNumber() const +{ + return json_is_number(m_handle.get()) != 0; +} + +bool Json::isInteger() const +{ + return json_is_integer(m_handle.get()) != 0; +} + +bool Json::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 +{ + auto value = json_string_value(m_handle.get()); + + return (value == nullptr) ? "" : value; +} + +int Json::toInteger() const noexcept +{ + return json_integer_value(m_handle.get()); +} + +double Json::toReal() const noexcept +{ + return json_real_value(m_handle.get()); +} + +std::string Json::dump(int flags) +{ + auto v = json_dumps(m_handle.get(), flags); + + if (v == nullptr) + throw std::runtime_error("failed to dump"); + + return std::string(v); +} + +void Json::dump(const std::string &path, int flags) +{ + if (json_dump_file(m_handle.get(), path.c_str(), flags) < 0) + throw std::runtime_error("failed to dump"); +} + +Json &Json::operator[](int index) +{ + if (!isArray()) + throw std::invalid_argument("not an array"); + + if (index >= m_list.size()) + throw std::out_of_range("invalid index"); + + return m_list[index]; +} + +const Json &Json::operator[](int index) const +{ + if (!isArray()) + throw std::invalid_argument("not an array"); + + if (index >= m_list.size()) + throw std::out_of_range("invalid index"); + + return m_list[index]; +} + +Json &Json::operator[](const std::string &name) +{ + if (!isObject()) + throw std::invalid_argument("not an object"); + + if (m_map.count(name) == 0) + throw std::out_of_range("invalid key"); + + return m_map[name]; +} + +const Json &Json::operator[](const std::string &name) const +{ + if (!isObject()) + throw std::invalid_argument("not an object"); + + if (m_map.count(name) == 0) + throw std::out_of_range("invalid key"); + + return m_map.at(name); +} + +bool operator==(const Json &j1, const Json &j2) +{ + return json_equal(j1.m_handle.get(), j2.m_handle.get()) != 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/C++/Json.h Sat Sep 13 19:42:15 2014 +0200 @@ -0,0 +1,426 @@ +/* + * Json.h -- jansson C++11 wrapper + * + * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _JSON_H_ +#define _JSON_H_ + +#include <initializer_list> +#include <memory> +#include <stdexcept> +#include <string> +#include <utility> +#include <vector> +#include <unordered_map> + +#include <jansson.h> + +/** + * @file Json.h + * @brief A jansson C++ modern wrapper + */ + +/** + * @class Json + * @brief Json value + * + * This class contains one or more json values. + */ +class Json final { +public: + using Handle = std::unique_ptr<json_t, void (*)(json_t *)>; + using Array = std::vector<Json>; + using Map = std::unordered_map<std::string, Json>; + + /** + * @class Error + * @brief Json error + */ + class Error : public std::exception { + private: + friend class Json; + + std::string m_text; + std::string m_source; + int m_line; + int m_column; + unsigned m_position; + + Error(const json_error_t error) + : m_text(error.text) + , m_source(error.source) + , m_line(error.line) + , m_column(error.column) + , m_position(error.position) + { + } + + public: + const char *what() const noexcept override + { + return m_text.c_str(); + } + }; + +private: + Handle m_handle; + Array m_list; + Map m_map; + + Json(Handle &&handle) + : m_handle(std::move(handle)) + { + } + + template <typename Func, typename... Args> + static Json from(Func func, Args&&... args) + { + json_error_t error; + json_t *value = func(std::forward<Args>(args)..., &error); + + if (!value) + throw Error(error); + + return Json(Handle(value, json_decref)); + } + +public: + /** + * Load data from a string. + * + * @param data the data + * @param flags the optional flags + * @return the json value + * @throw Error on failures + */ + static Json fromString(const std::string &data, int flags = 0); + + /** + * Load data from a file. + * + * @param path the path + * @param flags the optional flags + * @return the json value + * @throw Error on failures + */ + static Json fromFile(const std::string &path, int flags = 0); + + /** + * Create a json value of type JSON_OBJECT. + */ + explicit Json(); + + /** + * Create a JSON_NULL object. + * + * @param n the null value (nullptr) + */ + explicit Json(std::nullptr_t n); + + /** + * Create a boolean object. + * + * @param value the boolean value + */ + explicit Json(bool value); + + /** + * Create a JSON_INTEGER object. + * + * @param value the value + */ + explicit Json(int value); + + /** + * Create a JSON_REAL object. + * + * @param value the value + */ + explicit Json(double value); + + /** + * Create a JSON_STRING object. + * + * @param value the value + */ + explicit Json(const std::string &value); + + /** + * Create a JSON_ARRAY object. + * + * @param list the list of children + */ + explicit Json(std::initializer_list<Json> list); + + /** + * Create a JSON_STRING object. + * + * @param str the string + */ + template <size_t N> + explicit Json(const char str[N]) + : m_handle(json_string(str), json_decref) + { + } + + /** + * Copy the object, this does a deep copy. + * + * @param json the other value + */ + Json(const Json &json); + + /** + * Copy the object, this does a deep copy. + * + * @param json the other value + * @return *this + */ + Json &operator=(const Json &json); + + /** + * Move the object. + * + * @param json the other value + */ + Json(Json &&); + + /** + * Move the object. + * + * @param json the other value + * @return *this + */ + Json &operator=(Json &&); + + /** + * Get the type of value. + * + * @return the type + */ + int typeOf() const; + + /** + * Tells if the json value is an JSON_OBJECT. + * + * @return true or false + */ + bool isObject() const; + + /** + * Tells if the json value is an JSON_ARRAY. + * + * @return true or false + */ + bool isArray() const; + + /** + * Tells if the json value is an JSON_STRING. + * + * @return true or false + */ + bool isString() const; + + /** + * Tells if the json value is an JSON_REAL. + * + * @return true or false + */ + bool isReal() const; + + /** + * Tells if the json value is an JSON_TRUE. + * + * @return true or false + */ + bool isTrue() const; + + /** + * Tells if the json value is an JSON_FALSE. + * + * @return true or false + */ + bool isFalse() const; + + /** + * Tells if the json value is an JSON_NULL. + * + * @return true or false + */ + bool isNull() const; + + /** + * Tells if the json value is an JSON_INTEGER or JSON_REAL. + * + * @return true or false + */ + bool isNumber() const; + + /** + * Tells if the json value is an JSON_INTEGER. + * + * @return true or false + */ + bool isInteger() const; + + /** + * Tells if the json value is an JSON_TRUE or JSON_FALSE. + * + * @return true or false + */ + bool isBoolean() const; + + /** + * Get the number of values in the array + * + * @return the number or 0 + */ + unsigned size() const noexcept; + + /** + * Insert a copy of the value at the end. + * + * @param value the value to insert + */ + void append(const Json &value); + + /** + * Move the value at the end. + * + * @param value the value to insert + */ + void append(Json &&value); + + /** + * Insert a copy of the value at the specified index. + * + * @param value the value to insert + * @param index the position + */ + void insert(const Json &value, int index); + + /** + * Move the value at the specified index. + * + * @param value the value to insert + * @param index the position + */ + void insert(Json &&value, int index); + + /** + * Set a copy of value to the key 'name'. + * + * @param value the value + * @param name the key name. + */ + void set(const Json &value, const std::string &name); + + /** + * Move value to the key 'name'. + * + * @param value the value + * @param name the key name. + */ + void set(Json &&value, const std::string &name); + + /** + * Get the string value. + * + * @return the string + */ + std::string toString() const; + + /** + * Get the integer value. + * + * @return the value or 0 + */ + int toInteger() const noexcept; + + /** + * Get the real value. + * + * @return the value or 0 + */ + double toReal() const noexcept; + + /** + * Dump the value as a string. + * + * @param flags the optional flags + * @return the string + */ + std::string dump(int flags = 0); + + /** + * Dump the value to a path. + * + * @param path the path + * @param flags the optional flags + */ + void dump(const std::string &path, int flags = 0); + + /** + * Get the value at the specified index. + * + * @param index the position + * @return the reference to the value + * @throw std::invalid_argument on error + * @throw std::out_of_range on bad arguments + */ + Json &operator[](int index); + + /** + * Get the value at the specified index. + * + * @param index the position + * @return the reference to the value + * @throw std::invalid_argument on error + * @throw std::out_of_range on bad arguments + */ + const Json &operator[](int index) const; + + /** + * Get the value at the specified key. + * + * @param name the key + * @return the reference to the value + * @throw std::invalid_argument on error + * @throw std::out_of_range on bad arguments + */ + Json &operator[](const std::string &name); + + /** + * Get the value at the specified key. + * + * @param name the key + * @return the reference to the value + * @throw std::invalid_argument on error + * @throw std::out_of_range on bad arguments + */ + const Json &operator[](const std::string &name) const; + + /** + * Compare the values. + * + * @param j1 the first value + * @param j2 the second value + */ + friend bool operator==(const Json &j1, const Json &j2); +}; + +#endif // !_JSON_H_