Skip to content

Instantly share code, notes, and snippets.

@dolinenkov
Created September 21, 2018 05:57
Show Gist options
  • Select an option

  • Save dolinenkov/b8635bee1400812392ced169694d8b2f to your computer and use it in GitHub Desktop.

Select an option

Save dolinenkov/b8635bee1400812392ced169694d8b2f to your computer and use it in GitHub Desktop.
lightweight wrapper for jansson
#pragma once
#include <type_traits>
#include <string>
#include <jansson.h>
namespace jsw
{
namespace detail
{
template<class T>
struct IsMutableString: std::false_type {};
template<>
struct IsMutableString<std::string>: std::true_type {};
template<class T>
struct IsSequentialContainer: std::false_type {};
template<class T>
struct IsAssociativeContainer: std::false_type {};
}
//
//
//
class NamedConstIterator
{
public:
friend class NamedIterator;
NamedConstIterator(
json_t * _Parent,
void * _Iter
):
m_Parent(_Parent),
m_Iter(_Iter)
{
_Invalidate();
}
NamedConstIterator & operator++()
{
_Increase();
_Invalidate();
return *this;
}
const std::pair<const char *, Node> & operator*() const
{
return m_Pair;
}
bool operator!=(
const NamedConstIterator & _Another
) const
{
return m_Parent != _Another.m_Parent || m_Iter != _Another.m_Iter;
}
protected:
void _Increase()
{
m_Iter = json_object_iter_next(m_Parent, m_Iter);
}
void _Invalidate()
{
m_Pair = { json_object_iter_key(m_Iter), Node { json_object_iter_value(m_Iter) } };
}
protected:
json_t * const m_Parent;
void * m_Iter;
std::pair<const char *, Node> m_Pair;
};
class NamedIterator:
public NamedConstIterator
{
public:
using NamedConstIterator::NamedConstIterator;
std::pair<const char *, Node> & operator*()
{
return m_Pair;
}
bool operator!=(
const NamedConstIterator & _Another
) const
{
return m_Parent != _Another.m_Parent || m_Iter != _Another.m_Iter;
}
};
class NamedConstView
{
public:
explicit NamedConstView(
json_t * _Node
):
m_Node(_Node)
{
}
NamedConstIterator begin() const
{
return { m_Node, json_object_iter(m_Node) };
}
NamedConstIterator end() const
{
return { m_Node, nullptr };
}
const Node Find(const char * _Key) const
{
return Node(json_object_iter_value(json_object_iter_at(m_Node, _Key)));
}
protected:
json_t * m_Node;
};
class NamedView:
public NamedConstView
{
public:
using NamedConstView::NamedConstView;
NamedIterator begin()
{
return { m_Node, json_object_iter(m_Node) };
}
NamedIterator end()
{
return { m_Node, nullptr };
}
Node Find(const char * _Key)
{
return Node(json_object_iter_value(json_object_iter_at(m_Node, _Key)));
}
};
//
//
//
class IndexedConstIterator
{
public:
friend class IndexedIterator;
IndexedConstIterator(
json_t * _Parent,
size_t _Index
):
m_Parent(_Parent),
m_Index(_Index)
{
_Invalidate();
}
IndexedConstIterator & operator++()
{
_Increase();
_Invalidate();
return *this;
}
const std::pair<const size_t, Node> & operator*() const
{
return m_Pair;
}
bool operator!=(
const IndexedConstIterator & _Another
)
{
return m_Parent != _Another.m_Parent || m_Index != _Another.m_Index;
}
protected:
void _Increase()
{
if (m_Index < json_array_size(m_Parent))
++m_Index;
}
void _Invalidate()
{
m_Pair = { m_Index, Node { json_array_get(m_Parent, m_Index)} };
}
protected:
json_t * const m_Parent;
size_t m_Index;
std::pair<const size_t, Node> m_Pair;
};
class IndexedIterator:
public IndexedConstIterator
{
public:
using IndexedConstIterator::IndexedConstIterator;
std::pair<const size_t, Node> & operator*()
{
return m_Pair;
}
bool operator!=(
const IndexedIterator & _Another
) const
{
return m_Parent != _Another.m_Parent || m_Index != _Another.m_Index;
}
};
class IndexedConstView
{
public:
IndexedConstView(
json_t * _Node
):
m_Node(_Node)
{
}
IndexedConstIterator begin() const
{
return { m_Node, 0 };
}
IndexedConstIterator end() const
{
return { m_Node, json_array_size(m_Node) };
}
const Node Find(
size_t _Index
) const
{
return Node(json_array_get(m_Node, _Index));
}
protected:
json_t * m_Node;
};
class IndexedView:
public IndexedConstView
{
public:
using IndexedConstView::IndexedConstView;
IndexedIterator begin()
{
return { m_Node, 0 };
}
IndexedIterator end()
{
return { m_Node, json_array_size(m_Node) };
}
Node Find(
size_t _Index
)
{
return Node(json_array_get(m_Node, _Index));
}
};
class Node
{
public:
template<class T>
using _Null = typename std::enable_if<std::is_pointer<T>::value, T>;
template<class T>
using _Int = typename std::enable_if<std::is_integral<T>::value, T>;
template<class T>
using _Float = typename std::enable_if<std::is_floating_point<T>::value, T>;
template<class T>
using _MutableString = typename std::enable_if<detail::IsMutableString<T>::value, T>;
template<class T>
using _Sequential = typename std::enable_if<detail::IsSequentialContainer<T>::value, T>;
template<class T>
using _Associative = typename std::enable_if<detail::IsAssociativeContainer<T>::value, T>;
~Node();
Node();
Node(const Node & _Value);
Node(Node && _Value);
explicit Node(json_t * _JsonNode);
//
//
//
NamedConstView GetNamedView() const
{
return NamedConstView { m_JsonNode };
}
NamedView GetNamedView()
{
return NamedView { m_JsonNode };
}
//
//
//
IndexedConstView GetIndexedView() const
{
return IndexedConstView { m_JsonNode };
}
IndexedView GetIndexedView()
{
return IndexedView { m_JsonNode };
}
//
//
//
template<class UnknownType>
void Read(
UnknownType & _Value,
const UnknownType & _DefaultValue = {}
)
{
static_assert(false, "accessing json element as an unknown type!");
}
template<class T>
void Read(
_Null<T> & _Value,
const _Null<T> & _DefaultValue = {}
)
{
if (json_is_null(m_JsonNode))
_Value = nullptr;
else
_Value = _DefaultValue;
}
template<class T>
void Read(
_Int<T> & _Value,
const _Int<T> & _DefaultValue = {}
)
{
if (json_is_real(m_JsonNode))
_Value = static_cast<T>(json_real_value(m_JsonNode));
else
_Value = _DefaultValue;
}
template<class T>
void Read(
_Float<T> & _Value,
const _Float<T> & _DefaultValue = {}
)
{
if (json_is_number(m_JsonNode))
_Value = static_cast<T>(json_integer_value(m_JsonNode));
else
_Value = _DefaultValue;
}
template<class T>
void Read(
_MutableString<T> & _Value,
const _MutableString<T> & _DefaultValue = {}
)
{
if (json_is_string(m_JsonNode))
_Value = static_cast<T>(json_string_value(m_JsonNode));
else
_Value = _DefaultValue;
}
template<class T>
void Read(
_Sequential<T> & _Value,
const _Sequential<T> & _DefaultValue = {}
)
{
}
template<class T>
void Read(
_Associative<T> & _Value,
const _Associative<T> & _DefaultValue = {}
)
{
}
template<class T>
void Read(
const char * _Key,
T & _Value,
const T & _DefaultValue = {}
)
{
GetNamedView().Find(_Key).Read(_Value, _DefaultValue);
}
template<class T>
void Read(
size_t _Key,
T & _Value,
const T & _DefaultValue = {}
)
{
GetIndexedView().Find(_Key).Read(_Value, _DefaultValue);
}
//
//
// set
private:
json_t * m_JsonNode;
};
class Document
{
public:
void Load();
Node & Root();
private:
Node m_RootNode;
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment