/********************************************** License: BSD Project Webpage: http://cajun-jsonapi.sourceforge.net/ Author: Terry Caton ***********************************************/ #include "visitor.h" #include "reader.h" #include #include #include /* TODO: * better documentation */ namespace json { inline Exception::Exception(const std::string& sMessage) : std::runtime_error(sMessage) {} ///////////////////////// // UnknownElement members class UnknownElement::Imp { public: virtual ~Imp() {} virtual Imp* Clone() const = 0; virtual bool Compare(const Imp& imp) const = 0; virtual void Accept(ConstVisitor& visitor) const = 0; virtual void Accept(Visitor& visitor) = 0; }; template class UnknownElement::Imp_T : public UnknownElement::Imp { public: Imp_T(const ElementTypeT& element) : m_Element(element) {} virtual Imp* Clone() const { return new Imp_T(*this); } virtual void Accept(ConstVisitor& visitor) const { visitor.Visit(m_Element); } virtual void Accept(Visitor& visitor) { visitor.Visit(m_Element); } virtual bool Compare(const Imp& imp) const { ConstCastVisitor_T castVisitor; imp.Accept(castVisitor); return castVisitor.m_pElement && m_Element == *castVisitor.m_pElement; } private: ElementTypeT m_Element; }; class UnknownElement::ConstCastVisitor : public ConstVisitor { virtual void Visit(const Array& array) {} virtual void Visit(const Object& object) {} virtual void Visit(const Number& number) {} virtual void Visit(const String& string) {} virtual void Visit(const Boolean& boolean) {} virtual void Visit(const Null& null) {} }; template class UnknownElement::ConstCastVisitor_T : public ConstCastVisitor { public: ConstCastVisitor_T() : m_pElement(0) {} virtual void Visit(const ElementTypeT& element) { m_pElement = &element; } // we don't know what this is, but it overrides one of the base's no-op functions const ElementTypeT* m_pElement; }; class UnknownElement::CastVisitor : public Visitor { virtual void Visit(Array& array) {} virtual void Visit(Object& object) {} virtual void Visit(Number& number) {} virtual void Visit(String& string) {} virtual void Visit(Boolean& boolean) {} virtual void Visit(Null& null) {} }; template class UnknownElement::CastVisitor_T : public CastVisitor { public: CastVisitor_T() : m_pElement(0) {} virtual void Visit(ElementTypeT& element) { m_pElement = &element; } // we don't know what this is, but it overrides one of the base's no-op functions ElementTypeT* m_pElement; }; inline UnknownElement::UnknownElement() : m_pImp( new Imp_T( Null()) ) {} inline UnknownElement::UnknownElement(const UnknownElement& unknown) : m_pImp( unknown.m_pImp->Clone()) {} inline UnknownElement::UnknownElement(const Object& object) : m_pImp( new Imp_T(object)) {} inline UnknownElement::UnknownElement(const Array& array) : m_pImp( new Imp_T(array)) {} inline UnknownElement::UnknownElement(const Number& number) : m_pImp( new Imp_T(number)) {} inline UnknownElement::UnknownElement(const Boolean& boolean) : m_pImp( new Imp_T(boolean)) {} inline UnknownElement::UnknownElement(const String& string) : m_pImp( new Imp_T(string)) {} inline UnknownElement::UnknownElement(const Null& null) : m_pImp( new Imp_T(null)) {} inline UnknownElement::~UnknownElement() { delete m_pImp; } inline UnknownElement::operator const Object& () const { return CastTo(); } inline UnknownElement::operator const Array& () const { return CastTo(); } inline UnknownElement::operator const Number& () const { return CastTo(); } inline UnknownElement::operator const Boolean& () const { return CastTo(); } inline UnknownElement::operator const String& () const { return CastTo(); } inline UnknownElement::operator const Null& () const { return CastTo(); } inline UnknownElement::operator Object& () { return ConvertTo(); } inline UnknownElement::operator Array& () { return ConvertTo(); } inline UnknownElement::operator Number& () { return ConvertTo(); } inline UnknownElement::operator Boolean& () { return ConvertTo(); } inline UnknownElement::operator String& () { return ConvertTo(); } inline UnknownElement::operator Null& () { return ConvertTo(); } inline UnknownElement& UnknownElement::operator = (const UnknownElement& unknown) { delete m_pImp; m_pImp = unknown.m_pImp->Clone(); return *this; } inline UnknownElement& UnknownElement::operator[] (const std::string& key) { // the people want an object. make us one if we aren't already Object& object = ConvertTo(); return object[key]; } inline const UnknownElement& UnknownElement::operator[] (const std::string& key) const { // throws if we aren't an object const Object& object = CastTo(); return object[key]; } inline UnknownElement& UnknownElement::operator[] (size_t index) { // the people want an array. make us one if we aren't already Array& array = ConvertTo(); return array[index]; } inline const UnknownElement& UnknownElement::operator[] (size_t index) const { // throws if we aren't an array const Array& array = CastTo(); return array[index]; } template const ElementTypeT& UnknownElement::CastTo() const { ConstCastVisitor_T castVisitor; m_pImp->Accept(castVisitor); if (castVisitor.m_pElement == 0) throw Exception("Bad cast"); return *castVisitor.m_pElement; } template ElementTypeT& UnknownElement::ConvertTo() { CastVisitor_T castVisitor; m_pImp->Accept(castVisitor); if (castVisitor.m_pElement == 0) { // we're not the right type. fix it & try again *this = ElementTypeT(); m_pImp->Accept(castVisitor); } return *castVisitor.m_pElement; } inline void UnknownElement::Accept(ConstVisitor& visitor) const { m_pImp->Accept(visitor); } inline void UnknownElement::Accept(Visitor& visitor) { m_pImp->Accept(visitor); } inline bool UnknownElement::operator == (const UnknownElement& element) const { return m_pImp->Compare(*element.m_pImp); } ////////////////// // Object members inline Object::Member::Member(const std::string& nameIn, const UnknownElement& elementIn) : name(nameIn), element(elementIn) {} inline bool Object::Member::operator == (const Member& member) const { return name == member.name && element == member.element; } class Object::Finder : public std::unary_function { public: Finder(const std::string& name) : m_name(name) {} bool operator () (const Object::Member& member) { return member.name == m_name; } private: std::string m_name; }; inline Object::iterator Object::Begin() { return m_Members.begin(); } inline Object::iterator Object::End() { return m_Members.end(); } inline Object::const_iterator Object::Begin() const { return m_Members.begin(); } inline Object::const_iterator Object::End() const { return m_Members.end(); } inline size_t Object::Size() const { return m_Members.size(); } inline bool Object::Empty() const { return m_Members.empty(); } inline Object::iterator Object::Find(const std::string& name) { return std::find_if(m_Members.begin(), m_Members.end(), Finder(name)); } inline Object::const_iterator Object::Find(const std::string& name) const { return std::find_if(m_Members.begin(), m_Members.end(), Finder(name)); } inline Object::iterator Object::Insert(const Member& member) { return Insert(member, End()); } inline Object::iterator Object::Insert(const Member& member, iterator itWhere) { iterator it = Find(member.name); if (it != m_Members.end()) throw Exception("Object member already exists: " + member.name); it = m_Members.insert(itWhere, member); return it; } inline Object::iterator Object::Erase(iterator itWhere) { return m_Members.erase(itWhere); } inline UnknownElement& Object::operator [](const std::string& name) { iterator it = Find(name); if (it == m_Members.end()) { Member member(name); it = Insert(member, End()); } return it->element; } inline const UnknownElement& Object::operator [](const std::string& name) const { const_iterator it = Find(name); if (it == End()) throw Exception("Object member not found: " + name); return it->element; } inline void Object::Clear() { m_Members.clear(); } inline bool Object::operator == (const Object& object) const { return m_Members == object.m_Members; } ///////////////// // Array members inline Array::iterator Array::Begin() { return m_Elements.begin(); } inline Array::iterator Array::End() { return m_Elements.end(); } inline Array::const_iterator Array::Begin() const { return m_Elements.begin(); } inline Array::const_iterator Array::End() const { return m_Elements.end(); } inline Array::iterator Array::Insert(const UnknownElement& element, iterator itWhere) { return m_Elements.insert(itWhere, element); } inline Array::iterator Array::Insert(const UnknownElement& element) { return Insert(element, End()); } inline Array::iterator Array::Erase(iterator itWhere) { return m_Elements.erase(itWhere); } inline void Array::Resize(size_t newSize) { m_Elements.resize(newSize); } inline size_t Array::Size() const { return m_Elements.size(); } inline bool Array::Empty() const { return m_Elements.empty(); } inline UnknownElement& Array::operator[] (size_t index) { size_t nMinSize = index + 1; // zero indexed if (m_Elements.size() < nMinSize) m_Elements.resize(nMinSize); return m_Elements[index]; } inline const UnknownElement& Array::operator[] (size_t index) const { if (index >= m_Elements.size()) throw Exception("Array out of bounds"); return m_Elements[index]; } inline void Array::Clear() { m_Elements.clear(); } inline bool Array::operator == (const Array& array) const { return m_Elements == array.m_Elements; } //////////////////////// // TrivialType_T members template TrivialType_T::TrivialType_T(const DataTypeT& t) : m_tValue(t) {} template TrivialType_T::operator DataTypeT&() { return Value(); } template TrivialType_T::operator const DataTypeT&() const { return Value(); } template DataTypeT& TrivialType_T::Value() { return m_tValue; } template const DataTypeT& TrivialType_T::Value() const { return m_tValue; } template bool TrivialType_T::operator == (const TrivialType_T& trivial) const { return m_tValue == trivial.m_tValue; } ////////////////// // Null members inline bool Null::operator == (const Null& trivial) const { return true; } } // End namespace