From efcbdb7a0347b4399cbabacf3cbea432eeafb17b Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Tue, 17 May 2011 01:24:51 +0000 Subject: Gats::Object now has a strToGats function, it's pretty slick, it takes a string and produces a fully formed gats tree. Also, gatscon now can interact with a server directly. --- src/gatscon/clientthread.cpp | 38 +++++++++ src/gatscon/clientthread.h | 37 +++++++++ src/gatscon/clientwidget.cpp | 67 +++++++++++++-- src/gatscon/clientwidget.h | 13 ++- src/gatscon/clientwidget.ui | 33 +++++++- src/gatscon/gatstotree.cpp | 75 +++++++++++++++++ src/gatscon/gatstotree.h | 19 +++++ src/object.cpp | 192 +++++++++++++++++++++++++++++++++++++++++++ src/object.h | 8 ++ 9 files changed, 465 insertions(+), 17 deletions(-) create mode 100644 src/gatscon/clientthread.cpp create mode 100644 src/gatscon/clientthread.h (limited to 'src') diff --git a/src/gatscon/clientthread.cpp b/src/gatscon/clientthread.cpp new file mode 100644 index 0000000..b1dc4d0 --- /dev/null +++ b/src/gatscon/clientthread.cpp @@ -0,0 +1,38 @@ +#include "clientthread.h" + +#include + +ClientThread::ClientThread( QObject *pParent, const QByteArray &baHost, + int iPort ) : + QThread( pParent ), + baHost( baHost ), + iPort( iPort ), + gsCli( ssCli ) +{ +} + +ClientThread::~ClientThread() +{ +} + +void ClientThread::send( Gats::Object *pObj ) +{ + gsCli.writeObject( pObj ); +} + +void ClientThread::run() +{ + ssCli.setStream( + new Bu::TcpSocket( baHost.constData(), iPort ) + ); + + while( !ssCli.isEos() ) + { + Gats::Object *pObj = gsCli.readObject(); + if( pObj == NULL ) + break; + + emit recv( pObj ); + } +} + diff --git a/src/gatscon/clientthread.h b/src/gatscon/clientthread.h new file mode 100644 index 0000000..3182d37 --- /dev/null +++ b/src/gatscon/clientthread.h @@ -0,0 +1,37 @@ +#ifndef CLIENT_THREAD_H +#define CLIENT_THREAD_H + +#include +#include + +#include +#include + +namespace Gats +{ + class Object; +}; + +class ClientThread : public QThread +{ + Q_OBJECT; +public: + ClientThread( QObject *pParent, const QByteArray &baHost, int iPort ); + virtual ~ClientThread(); + + void send( Gats::Object *pObj ); + +signals: + void recv( Gats::Object *pObj ); + +protected: + virtual void run(); + +private: + QByteArray baHost; + int iPort; + Bu::StreamStack ssCli; + Gats::GatsStream gsCli; +}; + +#endif diff --git a/src/gatscon/clientwidget.cpp b/src/gatscon/clientwidget.cpp index 4872d9d..6039035 100644 --- a/src/gatscon/clientwidget.cpp +++ b/src/gatscon/clientwidget.cpp @@ -1,24 +1,73 @@ #include "clientwidget.h" #include "connectdlg.h" +#include "clientthread.h" + +#include "gatstotree.h" + +#include + +#include +#include + +using namespace Bu; ClientWidget::ClientWidget( QWidget *pParent ) : - QWidget( pParent ), - gsCli( ssCli ) + QWidget( pParent ) { setupUi( this ); - ConnectDlg dlg( this ); - dlg.exec(); + { + ConnectDlg dlg( this ); + dlg.exec(); - ssCli.setStream( - new Bu::TcpSocket( dlg.getHost().constData(), dlg.getPort() ) - ); + sio << "Connect: " << dlg.getHostname().constData() << ":" + << dlg.getPort() << sio.nl; - Gats::Object *pObj = gsCli.readObject(); - gatsToTree( twHistory, pObj ); + pCli = new ClientThread( this, dlg.getHostname(), dlg.getPort() ); + } + pCli->start(); + connect( pCli, SIGNAL(recv( Gats::Object *)), + this, SLOT(recv(Gats::Object *)), Qt::QueuedConnection ); } ClientWidget::~ClientWidget() { } +void ClientWidget::send() +{ + try + { + Gats::Object *pObj = Gats::Object::strToGats( + leGats->text().toAscii().constData() + ); + sio << "Send: " << *pObj << sio.nl; + QTreeWidgetItem *pIt = new QTreeWidgetItem( + twHistory->invisibleRootItem() + ); + pIt->setText( 0, "send" ); + gatsToTree( pIt, pObj ); + pCli->send( pObj ); + delete pObj; + + leGats->setText(""); + leGats->setFocus(); + } + catch( Bu::ExceptionBase &e ) + { + QMessageBox::critical( this, "GatsCon - Error", e.what() ); + } +} + +void ClientWidget::recv( Gats::Object *pObj ) +{ + sio << "Recv: " << *pObj << sio.nl; + + QTreeWidgetItem *pIt = new QTreeWidgetItem( + twHistory->invisibleRootItem() + ); + pIt->setText( 0, "recv" ); + gatsToTree( pIt, pObj ); + delete pObj; +} + diff --git a/src/gatscon/clientwidget.h b/src/gatscon/clientwidget.h index 3a96f07..21fb1b7 100644 --- a/src/gatscon/clientwidget.h +++ b/src/gatscon/clientwidget.h @@ -3,8 +3,10 @@ #include "ui_clientwidget.h" -#include -#include +namespace Gats +{ + class Object; +}; class ClientWidget : public QWidget, protected Ui::ClientWidget { @@ -13,9 +15,12 @@ public: ClientWidget( QWidget *pParent=NULL ); virtual ~ClientWidget(); +public slots: + void send(); + void recv( Gats::Object *pObj ); + private: - Bu::StreamStack ssCli; - Gats::GatsStream gsCli; + class ClientThread *pCli; }; #endif diff --git a/src/gatscon/clientwidget.ui b/src/gatscon/clientwidget.ui index 9761401..a0cb997 100644 --- a/src/gatscon/clientwidget.ui +++ b/src/gatscon/clientwidget.ui @@ -6,8 +6,8 @@ 0 0 - 364 - 289 + 363 + 291 @@ -21,6 +21,11 @@ Name + + + Type + + Value @@ -38,7 +43,7 @@ - + @@ -58,5 +63,25 @@ - + + + pushButton + clicked() + ClientWidget + send() + + + 332 + 276 + + + 322 + 367 + + + + + + send() + diff --git a/src/gatscon/gatstotree.cpp b/src/gatscon/gatstotree.cpp index af94fa5..d01e4b8 100644 --- a/src/gatscon/gatstotree.cpp +++ b/src/gatscon/gatstotree.cpp @@ -1,8 +1,83 @@ +#include "gatstotree.h" + #include #include void gatsToTree( QTreeWidgetItem *p, Gats::Object *pObj ) { + switch( pObj->getType() ) + { + case Gats::typeInteger: + gatsToTree( p, dynamic_cast( pObj ) ); + break; + + case Gats::typeString: + gatsToTree( p, dynamic_cast( pObj ) ); + break; + + case Gats::typeFloat: + gatsToTree( p, dynamic_cast( pObj ) ); + break; + + case Gats::typeBoolean: + gatsToTree( p, dynamic_cast( pObj ) ); + break; + + case Gats::typeList: + gatsToTree( p, dynamic_cast( pObj ) ); + break; + + case Gats::typeDictionary: + gatsToTree( p, dynamic_cast( pObj ) ); + break; + } +} + +void gatsToTree( QTreeWidgetItem *p, Gats::Integer *pObj ) +{ + p->setText( 1, "int"); + p->setText( 2, QString("%1").arg( pObj->getValue() ) ); +} + +void gatsToTree( QTreeWidgetItem *p, Gats::String *pObj ) +{ + p->setText( 1, "str"); + p->setText( 2, QString("%1").arg( pObj->getStr() ) ); +} + +void gatsToTree( QTreeWidgetItem *p, Gats::Float *pObj ) +{ + p->setText( 1, "float"); + p->setText( 2, QString("%1").arg( pObj->getValue() ) ); +} + +void gatsToTree( QTreeWidgetItem *p, Gats::Boolean *pObj ) +{ + p->setText( 1, "bool"); + p->setText( 2, pObj->getValue()?"true":"false" ); +} + +void gatsToTree( QTreeWidgetItem *p, Gats::List *pObj ) +{ + p->setText( 1, "list"); + int j = 0; + for( Gats::List::iterator i = pObj->begin(); i; i++ ) + { + QTreeWidgetItem *pIt = new QTreeWidgetItem( p ); + pIt->setText( 0, QString("%1").arg( j++ ) ); + gatsToTree( pIt, *i ); + } +} + +void gatsToTree( QTreeWidgetItem *p, Gats::Dictionary *pObj ) +{ + p->setText( 1, "dict"); + for( Gats::Dictionary::iterator i = pObj->begin(); i; i++ ) + { + QTreeWidgetItem *pIt = new QTreeWidgetItem( p ); + pIt->setText( 0, QString( i.getKey().getStr() ) ); + gatsToTree( pIt, *i ); + } } diff --git a/src/gatscon/gatstotree.h b/src/gatscon/gatstotree.h index cab9eee..26fb76c 100644 --- a/src/gatscon/gatstotree.h +++ b/src/gatscon/gatstotree.h @@ -3,6 +3,25 @@ class QTreeWidgetItem; +namespace Gats +{ + class Integer; + class String; + class Float; + class Boolean; + class List; + class Dictionary; + class Object; +}; + +#include + void gatsToTree( QTreeWidgetItem *p, Gats::Object *pObj ); +void gatsToTree( QTreeWidgetItem *p, Gats::Integer *pObj ); +void gatsToTree( QTreeWidgetItem *p, Gats::String *pObj ); +void gatsToTree( QTreeWidgetItem *p, Gats::Float *pObj ); +void gatsToTree( QTreeWidgetItem *p, Gats::Boolean *pObj ); +void gatsToTree( QTreeWidgetItem *p, Gats::List *pObj ); +void gatsToTree( QTreeWidgetItem *p, Gats::Dictionary *pObj ); #endif diff --git a/src/object.cpp b/src/object.cpp index af81017..da77ff8 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -7,9 +7,14 @@ #include "gats/list.h" #include "gats/dictionary.h" +#include + #include #include +#include +using namespace Bu; + Gats::Object::Object() { } @@ -63,6 +68,193 @@ Gats::Object *Gats::Object::read( Bu::Stream &rIn ) 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(;;) + { + 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 != '\"' ) + 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 ); + } + } + } + } + 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() ) diff --git a/src/object.h b/src/object.h index 1c114b3..91c48ad 100644 --- a/src/object.h +++ b/src/object.h @@ -1,6 +1,8 @@ #ifndef GATS_OBJECT_H #define GATS_OBJECT_H +#include + namespace Bu { class Stream; @@ -34,6 +36,12 @@ namespace Gats virtual void read( Bu::Stream &rIn, char cType )=0; static Object *read( Bu::Stream &rIn ); + static Object *strToGats( const Bu::String &sStr ); + + private: + static Object *strToGats( Bu::String::const_iterator &i ); + static Bu::String token( Bu::String::const_iterator &i ); + static void skipWs( Bu::String::const_iterator &i ); }; const char *typeToStr( Type t ); -- cgit v1.2.3