/********************************************** License: BSD Project Webpage: http://cajun-jsonapi.sourceforge.net/ Author: Terry Caton ***********************************************/ #include "libaegisub/cajun/elements.h" #include "libaegisub/cajun/visitor.h" #ifndef LAGI_PRE #include #include #endif namespace json { ///////////////////////// // UnknownElement members class CastVisitor : public ConstVisitor { virtual void Visit(const Array&) { } virtual void Visit(const Object&) { } virtual void Visit(const Number&) { } virtual void Visit(const String&) { } virtual void Visit(const Boolean&) { } virtual void Visit(const Null&) { } }; template class CastVisitor_T : public CastVisitor { public: const ElementTypeT *element; CastVisitor_T() : element(0) { } // we don't know what this is, but it overrides one of the base's no-op functions void Visit(const ElementTypeT& element) { this->element = &element; } }; 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 { CastVisitor_T castVisitor; imp.Accept(castVisitor); return castVisitor.element && m_Element == *castVisitor.element; } private: ElementTypeT m_Element; }; UnknownElement::UnknownElement() : m_pImp( new Imp_T( Null() ) ) {} UnknownElement::UnknownElement(const UnknownElement& unknown) : m_pImp( unknown.m_pImp->Clone()) {} UnknownElement::UnknownElement(const Object& object) : m_pImp( new Imp_T(object) ) {} UnknownElement::UnknownElement(const Array& array) : m_pImp( new Imp_T(array) ) {} UnknownElement::UnknownElement(double number) : m_pImp( new Imp_T(number) ) {} UnknownElement::UnknownElement(int number) : m_pImp( new Imp_T(number) ) {} UnknownElement::UnknownElement(long number) : m_pImp( new Imp_T(number) ) {} UnknownElement::UnknownElement(bool boolean) : m_pImp( new Imp_T(boolean) ) {} UnknownElement::UnknownElement(const char *string) : m_pImp( new Imp_T(string) ) {} UnknownElement::UnknownElement(const String& string) : m_pImp( new Imp_T(string) ) {} UnknownElement::UnknownElement(const Null& null) : m_pImp( new Imp_T(null) ) {} UnknownElement::~UnknownElement() { delete m_pImp; } UnknownElement::operator const Object& () const { return CastTo(); } UnknownElement::operator const Array& () const { return CastTo(); } UnknownElement::operator const Number& () const { return CastTo(); } UnknownElement::operator const Boolean& () const { return CastTo(); } UnknownElement::operator const String& () const { return CastTo(); } UnknownElement::operator const Null& () const { return CastTo(); } UnknownElement::operator Object& () { return ConvertTo(); } UnknownElement::operator Array& () { return ConvertTo(); } UnknownElement::operator Number& () { return ConvertTo(); } UnknownElement::operator Boolean& () { return ConvertTo(); } UnknownElement::operator String& () { return ConvertTo(); } UnknownElement::operator Null& () { return ConvertTo(); } UnknownElement& UnknownElement::operator = (const UnknownElement& unknown) { delete m_pImp; m_pImp = unknown.m_pImp->Clone(); return *this; } UnknownElement& UnknownElement::operator[] (const std::string& key) { // the people want an object. make us one if we aren't already return ConvertTo()[key]; } const UnknownElement& UnknownElement::operator[] (const std::string& key) const { // throws if we aren't an object Object const& obj = CastTo(); Object::const_iterator it = obj.find(key); if (it == obj.end()) throw Exception("Object member not found: " + key); return it->second; } UnknownElement& UnknownElement::operator[] (size_t index) { // the people want an array. make us one if we aren't already return ConvertTo()[index]; } const UnknownElement& UnknownElement::operator[] (size_t index) const { // throws if we aren't an array return CastTo()[index]; } template const ElementTypeT& UnknownElement::CastTo() const { CastVisitor_T castVisitor; m_pImp->Accept(castVisitor); if (!castVisitor.element) throw Exception("Bad cast"); return *castVisitor.element; } template ElementTypeT& UnknownElement::ConvertTo() { CastVisitor_T castVisitor; Accept(castVisitor); if (!castVisitor.element) { // we're not the right type. fix it & try again *this = ElementTypeT(); } return *this; } void UnknownElement::Accept(ConstVisitor& visitor) const { m_pImp->Accept(visitor); } void UnknownElement::Accept(Visitor& visitor) { m_pImp->Accept(visitor); } bool UnknownElement::operator == (const UnknownElement& element) const { return m_pImp->Compare(*element.m_pImp); } } // end namespace