/* * Copyright (C) 2007-2012 Xagasoft, All rights reserved. * * This file is part of the libgats library and is released under the * terms of the license contained in the file LICENSE. */ #include "gats/object.h" #include "gats/integer.h" #include "gats/float.h" #include "gats/boolean.h" #include "gats/string.h" #include "gats/list.h" #include "gats/dictionary.h" #include "gats/null.h" #include #include #include #include using namespace Bu; Gats::Object::Object() { } Gats::Object::~Object() { } Gats::Object *Gats::Object::read( Bu::Stream &rIn ) { char buf; rIn.read( &buf, 1 ); Object *pObj = NULL; switch( buf ) { case 'i': pObj = new Gats::Integer(); break; case 's': pObj = new Gats::String(); break; case '0': case '1': pObj = new Gats::Boolean(); break; case 'l': pObj = new Gats::List(); break; case 'd': pObj = new Gats::Dictionary(); break; case 'f': // Normal floats case 'F': // Special float values pObj = new Gats::Float(); break; case 'n': pObj = new Gats::Null(); break; case 'e': return NULL; default: throw Bu::ExceptionBase("Invalid Gats type discovered: %c.", buf ); } pObj->read( rIn, buf ); return pObj; } void Gats::Object::skipWs( Bu::String::const_iterator &i ) { for(; *i == ' ' || *i == '\t' || *i == '\r' || *i == '\n'; i++ ) { } } Bu::String Gats::Object::token( Bu::String::const_iterator &i ) { Bu::String sRet; if( *i == '\"' ) { for( i++; i && *i != '\"' ; i++ ) { if( *i == '\\' ) i++; sRet += i; } i++; } else { for(; i && *i != ' ' && *i != '\t' && *i != '\r' && *i != '\n' && *i != ',' && *i != ']' && *i != '}' && *i != '[' && *i != '{'; i++ ) { sRet += i; } } return sRet; } Gats::Object *Gats::Object::strToGats( Bu::String::const_iterator &i ) { skipWs( i ); switch( *i ) { case '[': { Gats::List *pLst = new Gats::List(); i++; for(;;) { skipWs( i ); if( *i == ']' ) { i++; return pLst; } Gats::Object *pObj = strToGats( i ); if( !pObj ) break; pLst->append( pObj ); skipWs( i ); switch( *i ) { case ',': i++; break; case ']': i++; return pLst; default: throw Bu::ExceptionBase("Invalid character found."); } } } break; case '{': { Gats::Dictionary *pDict = new Gats::Dictionary(); i++; for(;;) { skipWs( i ); if( *i == '}' ) { i++; return pDict; } if( *i != '\"' ) throw Bu::ExceptionBase("Keys must be quoted strings."); Bu::String sKey = token( i ); skipWs( i ); if( *i != ':' ) throw Bu::ExceptionBase("Keys and values must be " "seperated with colons."); i++; Gats::Object *pObj = strToGats( i ); if( !pObj ) throw Bu::ExceptionBase("No value object found."); pDict->insert( sKey, pObj ); skipWs( i ); switch( *i ) { case ',': i++; break; case '}': i++; return pDict; default: throw Bu::ExceptionBase("Invalid character found."); } } } break; case '\"': return new Gats::String( token( i ) ); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '.': case '+': case '-': { Bu::String s = token( i ); int iSize = s.getSize(); if( s[iSize-1] == 'i' ) { return new Gats::Integer( strtoll( s.getStr(), NULL, 10 ) ); } else if( s[iSize-1] == 'f' ) { return new Gats::Float( strtod( s.getStr(), NULL ) ); } else { for( Bu::String::iterator i = s.begin(); i; i++ ) { if( *i == '.' ) return new Gats::Float( strtod( s.getStr(), NULL ) ); } return new Gats::Integer( strtoll( s.getStr(), NULL, 10 ) ); } } break; default: { Bu::String s = token( i ); int iSize = s.getSize(); // Test for explicit types first if( iSize > 2 ) { if( (s[0] >= '0' && s[0] <= '9') || s[0] == '+' || s[0] == '-' ) { } else { Bu::String st = s.toLower(); if( st == "true" ) { return new Gats::Boolean( true ); } else if( st == "false" ) { return new Gats::Boolean( false ); } else if( st == "null" ) { return new Gats::Null(); } } } } break; } return NULL; } Gats::Object *Gats::Object::strToGats( const Bu::String &sStr ) { Bu::String::const_iterator i = sStr.begin(); return strToGats( i ); } Bu::Formatter &operator<<( Bu::Formatter &f, const Gats::Object &obj ) { switch( obj.getType() ) { case Gats::typeDictionary: return f << dynamic_cast(obj); case Gats::typeList: return f << dynamic_cast(obj); case Gats::typeString: return f << dynamic_cast(obj); case Gats::typeInteger: return f << dynamic_cast(obj); case Gats::typeFloat: return f << dynamic_cast(obj); case Gats::typeBoolean: return f << dynamic_cast(obj); case Gats::typeNull: return f << dynamic_cast(obj); default: return f << "***ERROR: Bad Gats type***"; } } Bu::Formatter &operator<<( Bu::Formatter &f, const Gats::Type &t ) { switch( t ) { case Gats::typeDictionary: return f << "dictionary"; case Gats::typeList: return f << "list"; case Gats::typeString: return f << "string"; case Gats::typeInteger: return f << "integer"; case Gats::typeFloat: return f << "float"; case Gats::typeBoolean: return f << "boolean"; case Gats::typeNull: return f << "null"; } return f << "***unknown***"; } const char *Gats::typeToStr( Gats::Type t ) { switch( t ) { case Gats::typeDictionary: return "dictionary"; case Gats::typeList: return "list"; case Gats::typeString: return "string"; case Gats::typeInteger: return "integer"; case Gats::typeFloat: return "float"; case Gats::typeBoolean: return "boolean"; case Gats::typeNull: return "null"; } return "***unknown***"; }