Created
September 21, 2018 05:57
-
-
Save dolinenkov/b8635bee1400812392ced169694d8b2f to your computer and use it in GitHub Desktop.
lightweight wrapper for jansson
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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