view C++/Json.h @ 297:836903141476

Socket: provide experimental SSL support
author David Demelier <markand@malikania.fr>
date Sat, 15 Nov 2014 12:41:52 +0100
parents 777bc3cb665a
children ed3cc10761e4
line wrap: on
line source

/*
 * 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_