/********************************************** License: BSD Project Webpage: http://cajun-jsonapi.sourceforge.net/ Author: Terry Caton ***********************************************/ #pragma once #include #include #include #include /* TODO: * better documentation (doxygen?) * Unicode support * parent element accessors */ namespace json { ///////////////////////////////////////////////// // forward declarations (more info further below) class Visitor; class ConstVisitor; template class TrivialType_T; typedef TrivialType_T Number; typedef TrivialType_T Boolean; typedef TrivialType_T String; class Object; class Array; class Null; ///////////////////////////////////////////////////////////////////////// // Exception - base class for all JSON-related runtime errors class Exception : public std::runtime_error { public: Exception(const std::string& sMessage); }; ///////////////////////////////////////////////////////////////////////// // UnknownElement - provides a typesafe surrogate for any of the JSON- // sanctioned element types. This class allows the Array and Object // class to effectively contain a heterogeneous set of child elements. // The cast operators provide convenient implicit downcasting, while // preserving dynamic type safety by throwing an exception during a // a bad cast. // The object & array element index operators (operators [std::string] // and [size_t]) provide convenient, quick access to child elements. // They are a logical extension of the cast operators. These child // element accesses can be chained together, allowing the following // (when document structure is well-known): // String str = objInvoices[1]["Customer"]["Company"]; class UnknownElement { public: UnknownElement(); UnknownElement(const UnknownElement& unknown); UnknownElement(const Object& object); UnknownElement(const Array& array); UnknownElement(const Number& number); UnknownElement(const Boolean& boolean); UnknownElement(const String& string); UnknownElement(const Null& null); ~UnknownElement(); UnknownElement& operator = (const UnknownElement& unknown); // implicit cast to actual element type. throws on failure operator const Object& () const; operator const Array& () const; operator const Number& () const; operator const Boolean& () const; operator const String& () const; operator const Null& () const; // implicit cast to actual element type. *converts* on failure, and always returns success operator Object& (); operator Array& (); operator Number& (); operator Boolean& (); operator String& (); operator Null& (); // provides quick access to children when real element type is object UnknownElement& operator[] (const std::string& key); const UnknownElement& operator[] (const std::string& key) const; // provides quick access to children when real element type is array UnknownElement& operator[] (size_t index); const UnknownElement& operator[] (size_t index) const; // implements visitor pattern void Accept(ConstVisitor& visitor) const; void Accept(Visitor& visitor); // tests equality. first checks type, then value if possible bool operator == (const UnknownElement& element) const; private: class Imp; template class Imp_T; class CastVisitor; class ConstCastVisitor; template class CastVisitor_T; template class ConstCastVisitor_T; template const ElementTypeT& CastTo() const; template ElementTypeT& ConvertTo(); Imp* m_pImp; }; ///////////////////////////////////////////////////////////////////////////////// // Array - mimics std::deque. The array contents are effectively // heterogeneous thanks to the ElementUnknown class. push_back has been replaced // by more generic insert functions. class Array { public: typedef std::deque Elements; typedef Elements::iterator iterator; typedef Elements::const_iterator const_iterator; iterator Begin(); iterator End(); const_iterator Begin() const; const_iterator End() const; iterator Insert(const UnknownElement& element, iterator itWhere); iterator Insert(const UnknownElement& element); iterator Erase(iterator itWhere); void Resize(size_t newSize); void Clear(); size_t Size() const; bool Empty() const; UnknownElement& operator[] (size_t index); const UnknownElement& operator[] (size_t index) const; bool operator == (const Array& array) const; private: Elements m_Elements; }; ///////////////////////////////////////////////////////////////////////////////// // Object - mimics std::map. The member value // contents are effectively heterogeneous thanks to the UnknownElement class class Object { public: struct Member { Member(const std::string& nameIn = std::string(), const UnknownElement& elementIn = UnknownElement()); bool operator == (const Member& member) const; std::string name; UnknownElement element; }; typedef std::list Members; // map faster, but does not preserve order typedef Members::iterator iterator; typedef Members::const_iterator const_iterator; bool operator == (const Object& object) const; iterator Begin(); iterator End(); const_iterator Begin() const; const_iterator End() const; size_t Size() const; bool Empty() const; iterator Find(const std::string& name); const_iterator Find(const std::string& name) const; iterator Insert(const Member& member); iterator Insert(const Member& member, iterator itWhere); iterator Erase(iterator itWhere); void Clear(); UnknownElement& operator [](const std::string& name); const UnknownElement& operator [](const std::string& name) const; private: class Finder; Members m_Members; }; ///////////////////////////////////////////////////////////////////////////////// // TrivialType_T - class template for encapsulates a simple data type, such as // a string, number, or boolean. Provides implicit const & noncost cast operators // for that type, allowing "DataTypeT type = trivialType;" template class TrivialType_T { public: TrivialType_T(const DataTypeT& t = DataTypeT()); operator DataTypeT&(); operator const DataTypeT&() const; DataTypeT& Value(); const DataTypeT& Value() const; bool operator == (const TrivialType_T& trivial) const; private: DataTypeT m_tValue; }; ///////////////////////////////////////////////////////////////////////////////// // Null - doesn't do much of anything but satisfy the JSON spec. It is the default // element type of UnknownElement class Null { public: bool operator == (const Null& trivial) const; }; } // End namespace #include "elements.inl"