/c++-libbu++/src/object.cpp
C++ | 380 lines | 325 code | 48 blank | 7 comment | 87 complexity | 076689f62f79b1fd9277742df4ad4ebc MD5 | raw file
Possible License(s): BSD-3-Clause
- /*
- * Copyright (C) 2007-2013 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 <stdlib.h>
- #include <bu/formatter.h>
- #include <bu/stream.h>
- #include <bu/sio.h>
- 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( Gats::Object::StrPos &i )
- {
- for(; *i == ' ' || *i == '\t' || *i == '\r' || *i == '\n' || *i == '/'; i++ )
- {
- if( *i == '/' )
- {
- i++;
- if( *i == '/' )
- for(i++; *i != '\n' && *i != '\r'; i++ ) { }
- else if( *i == '*' )
- {
- for(i++; i; i++ )
- {
- if( *i == '*' )
- {
- i++;
- if( *i == '/' )
- {
- i++;
- break;
- }
- }
- }
- }
- else
- return;
- }
- }
- }
- Bu::String Gats::Object::token( Gats::Object::StrPos &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 != '/'; i++ )
- {
- sRet += *i;
- }
- }
- return sRet;
- }
- Bu::String::FormatProxy Gats::Object::posError( Gats::Object::StrPos &i, const Bu::String &msg )
- {
- return msg.format( new Thrower(i) );
- }
- Gats::Object *Gats::Object::strToGats( Gats::Object::StrPos &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:
- posError(i, "Expected ',' or ']' but found '%1'.").
- arg( *i );
- }
- }
- }
- break;
- case '{':
- {
- Gats::Dictionary *pDict = new Gats::Dictionary();
- i++;
- for(;;)
- {
- skipWs( i );
- if( *i == '}' )
- {
- i++;
- return pDict;
- }
- if( *i != '\"' )
- posError(i, "Dictionary keys must be quoted strings.");
- Bu::String sKey = token( i );
- skipWs( i );
- if( *i != ':' )
- posError(i, "Dictionary keys and values must be "
- "seperated with colons.");
- StrPos ih( i );
- i++;
- skipWs( i );
- Gats::Object *pObj = strToGats( i );
- if( !pObj )
- posError(ih, "Dictionary key has no value.");
- pDict->insert( sKey, pObj );
- skipWs( i );
- switch( *i )
- {
- case ',':
- i++;
- break;
- case '}':
- i++;
- return pDict;
- default:
- posError(i, "Expected ',' or '}' but found '%1'.")
- .arg( *i );
- }
- }
- }
- 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 )
- {
- StrPos 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<const Gats::Dictionary &>(obj);
-
- case Gats::typeList:
- return f << dynamic_cast<const Gats::List &>(obj);
-
- case Gats::typeString:
- return f << dynamic_cast<const Gats::String &>(obj);
-
- case Gats::typeInteger:
- return f << dynamic_cast<const Gats::Integer &>(obj);
-
- case Gats::typeFloat:
- return f << dynamic_cast<const Gats::Float &>(obj);
-
- case Gats::typeBoolean:
- return f << dynamic_cast<const Gats::Boolean &>(obj);
- case Gats::typeNull:
- return f << dynamic_cast<const Gats::Null &>(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***";
- }