diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/dictionary.cpp | 11 | ||||
| -rw-r--r-- | src/float.cpp | 37 | ||||
| -rw-r--r-- | src/float.h | 11 | ||||
| -rw-r--r-- | src/gatsstream.cpp | 85 | ||||
| -rw-r--r-- | src/gatsstream.h | 31 | ||||
| -rw-r--r-- | src/object.cpp | 4 | ||||
| -rw-r--r-- | src/unit/basic.unit | 19 | ||||
| -rw-r--r-- | src/unit/io.unit | 127 |
8 files changed, 316 insertions, 9 deletions
diff --git a/src/dictionary.cpp b/src/dictionary.cpp index 2223c8b..1a9549f 100644 --- a/src/dictionary.cpp +++ b/src/dictionary.cpp | |||
| @@ -77,9 +77,9 @@ void Gats::Dictionary::insert( const Bu::FString &sKey, bool b ) | |||
| 77 | 77 | ||
| 78 | void Gats::Dictionary::insert( const Bu::FString &sKey, double d ) | 78 | void Gats::Dictionary::insert( const Bu::FString &sKey, double d ) |
| 79 | { | 79 | { |
| 80 | // Bu::Hash<Gats::String, Gats::Object *>::insert( | 80 | Bu::Hash<Gats::String, Gats::Object *>::insert( |
| 81 | // sKey, new Gats::Float( d ) | 81 | sKey, new Gats::Float( d ) |
| 82 | // ); | 82 | ); |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | void Gats::Dictionary::insert( const Bu::FString &sKey, const char *s ) | 85 | void Gats::Dictionary::insert( const Bu::FString &sKey, const char *s ) |
| @@ -117,14 +117,13 @@ int64_t Gats::Dictionary::getInt( const Bu::FString &sKey ) | |||
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | double Gats::Dictionary::getFloat( const Bu::FString &sKey ) | 119 | double Gats::Dictionary::getFloat( const Bu::FString &sKey ) |
| 120 | {/* | 120 | { |
| 121 | Gats::Boolean *pOb = dynamic_cast<Gats::Boolean *>( get( sKey ) ); | 121 | Gats::Boolean *pOb = dynamic_cast<Gats::Boolean *>( get( sKey ) ); |
| 122 | if( pOb ) | 122 | if( pOb ) |
| 123 | throw Bu::ExceptionBase("Cannot cast item '%s' to bool.", | 123 | throw Bu::ExceptionBase("Cannot cast item '%s' to bool.", |
| 124 | sKey.getStr() ); | 124 | sKey.getStr() ); |
| 125 | 125 | ||
| 126 | return pOb->getValue();*/ | 126 | return pOb->getValue(); |
| 127 | return 0.0; | ||
| 128 | } | 127 | } |
| 129 | 128 | ||
| 130 | Bu::FString Gats::Dictionary::getStr( const Bu::FString &sKey ) | 129 | Bu::FString Gats::Dictionary::getStr( const Bu::FString &sKey ) |
diff --git a/src/float.cpp b/src/float.cpp index e69de29..e257b37 100644 --- a/src/float.cpp +++ b/src/float.cpp | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | #include "gats/float.h" | ||
| 2 | #include "gats/integer.h" | ||
| 3 | |||
| 4 | Gats::Float::Float() : | ||
| 5 | fVal( 0.0 ) | ||
| 6 | { | ||
| 7 | } | ||
| 8 | |||
| 9 | Gats::Float::Float( double f ) : | ||
| 10 | fVal( f ) | ||
| 11 | { | ||
| 12 | } | ||
| 13 | |||
| 14 | Gats::Float::~Float() | ||
| 15 | { | ||
| 16 | } | ||
| 17 | |||
| 18 | void Gats::Float::write( Bu::Stream &rOut ) const | ||
| 19 | { | ||
| 20 | char buf[50]; | ||
| 21 | |||
| 22 | int iSize = snprintf( buf, 50, "%la", fVal ); | ||
| 23 | |||
| 24 | rOut.write("f", 1 ); | ||
| 25 | Gats::Integer::writePackedInt( rOut, iSize ); | ||
| 26 | rOut.write( buf, iSize ); | ||
| 27 | } | ||
| 28 | |||
| 29 | void Gats::Float::read( Bu::Stream &rIn, char cType ) | ||
| 30 | { | ||
| 31 | int iSize; | ||
| 32 | Gats::Integer::readPackedInt( rIn, iSize ); | ||
| 33 | char buf[50]; | ||
| 34 | rIn.read( buf, iSize ); | ||
| 35 | sscanf( buf, "%la", &fVal ); | ||
| 36 | } | ||
| 37 | |||
diff --git a/src/float.h b/src/float.h index cf20010..1b3a06a 100644 --- a/src/float.h +++ b/src/float.h | |||
| @@ -1,16 +1,25 @@ | |||
| 1 | #ifndef GATS_FLOAT_H | 1 | #ifndef GATS_FLOAT_H |
| 2 | #define GATS_FLOAT_H | 2 | #define GATS_FLOAT_H |
| 3 | 3 | ||
| 4 | #include "gats/object.h" | ||
| 5 | |||
| 4 | namespace Gats | 6 | namespace Gats |
| 5 | { | 7 | { |
| 6 | class Float | 8 | class Float : public Gats::Object |
| 7 | { | 9 | { |
| 8 | public: | 10 | public: |
| 9 | Float(); | 11 | Float(); |
| 10 | Float( double f ); | 12 | Float( double f ); |
| 11 | virtual ~Float(); | 13 | virtual ~Float(); |
| 12 | 14 | ||
| 15 | virtual Type getType() const { return typeFloat; } | ||
| 16 | double getValue() const { return fVal; } | ||
| 17 | |||
| 18 | virtual void write( Bu::Stream &rOut ) const; | ||
| 19 | virtual void read( Bu::Stream &rIn, char cType ); | ||
| 20 | |||
| 13 | private: | 21 | private: |
| 22 | double fVal; | ||
| 14 | }; | 23 | }; |
| 15 | } | 24 | } |
| 16 | 25 | ||
diff --git a/src/gatsstream.cpp b/src/gatsstream.cpp index 4b9cadf..38adfbb 100644 --- a/src/gatsstream.cpp +++ b/src/gatsstream.cpp | |||
| @@ -1,7 +1,9 @@ | |||
| 1 | #include "gats/gatsstream.h" | 1 | #include "gats/gatsstream.h" |
| 2 | #include "gats/object.h" | 2 | #include "gats/object.h" |
| 3 | 3 | ||
| 4 | #include <bu/sio.h> | 4 | #include <arpa/inet.h> |
| 5 | |||
| 6 | // #include <bu/sio.h> | ||
| 5 | #include <bu/nullstream.h> | 7 | #include <bu/nullstream.h> |
| 6 | using namespace Bu; | 8 | using namespace Bu; |
| 7 | 9 | ||
| @@ -16,7 +18,59 @@ Gats::GatsStream::~GatsStream() | |||
| 16 | 18 | ||
| 17 | Gats::Object *Gats::GatsStream::readObject() | 19 | Gats::Object *Gats::GatsStream::readObject() |
| 18 | { | 20 | { |
| 21 | char buf[1500]; | ||
| 22 | |||
| 23 | // sio << "Gats::GatsStream::readObject(): Scanning for object header." << sio.nl; | ||
| 24 | do | ||
| 25 | { | ||
| 26 | if( qbRead.getSize() < 5 ) | ||
| 27 | { | ||
| 28 | // sio << "Gats::GatsStream::readObject(): reading header data, need 5b, have " << qbRead.getSize() << "b." << sio.nl; | ||
| 29 | int iRead = rStream.read( buf, 5-qbRead.getSize() ); | ||
| 30 | qbRead.write( buf, iRead ); | ||
| 31 | |||
| 32 | if( qbRead.getSize() < 5 ) | ||
| 33 | return NULL; | ||
| 34 | } | ||
| 35 | } while( !skipReadNulls() ); | ||
| 36 | |||
| 37 | uint8_t uVer; | ||
| 38 | qbRead.peek( &uVer, 1 ); | ||
| 39 | // sio << "Gats::GatsStream::readObject(): Packet version: " << (int)uVer << sio.nl; | ||
| 40 | |||
| 41 | int32_t iSize; | ||
| 42 | qbRead.peek( &iSize, 4, 1 ); | ||
| 43 | iSize = ntohl( iSize ); | ||
| 44 | // sio << "Gats::GatsStream::readObject(): Header read, looking for " << iSize << "b, we have " << qbRead.getSize() << "b." << sio.nl; | ||
| 45 | while( qbRead.getSize() < iSize ) | ||
| 46 | { | ||
| 47 | int32_t iRead = iSize - qbRead.getSize(); | ||
| 48 | if( iRead > 1500 ) | ||
| 49 | iRead = 1500; | ||
| 50 | // sio << "Gats::GatsStream::readObject(): Attempting to read " << iRead << "b." << sio.nl; | ||
| 51 | int32_t iReal = rStream.read( buf, iRead ); | ||
| 52 | // sio << "Gats::GatsStream::readObject(): Read " << iReal << "b." << sio.nl; | ||
| 53 | qbRead.write( buf, iReal ); | ||
| 54 | if( iReal < iRead ) | ||
| 55 | { | ||
| 56 | // sio << "Gats::GatsStream::readObject(): Insufficient data read in block, bailing on read." << sio.nl; | ||
| 57 | return NULL; | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | if( qbRead.getSize() < iSize ) | ||
| 62 | { | ||
| 63 | // sio << "Gats::GatsStream::readObject(): Somehow, we still don't have enough data, bailing." << sio.nl; | ||
| 64 | return NULL; | ||
| 65 | } | ||
| 66 | |||
| 67 | // sio << "Gats::GatsStream::readObject(): We have " << qbRead.getSize() << "b of " << iSize << "b, time to read the object." << sio.nl; | ||
| 19 | 68 | ||
| 69 | qbRead.seek( 5 ); | ||
| 70 | Gats::Object *pObj = Gats::Object::read( qbRead ); | ||
| 71 | |||
| 72 | // sio << "Gats::GatsStream::readObject(): Read completed, there are " << qbRead.getSize() << "b left in the buffer." << sio.nl; | ||
| 73 | return pObj; | ||
| 20 | } | 74 | } |
| 21 | 75 | ||
| 22 | void Gats::GatsStream::writeObject( Gats::Object *pObject ) | 76 | void Gats::GatsStream::writeObject( Gats::Object *pObject ) |
| @@ -24,6 +78,33 @@ void Gats::GatsStream::writeObject( Gats::Object *pObject ) | |||
| 24 | Bu::NullStream ns; | 78 | Bu::NullStream ns; |
| 25 | pObject->write( ns ); | 79 | pObject->write( ns ); |
| 26 | 80 | ||
| 27 | sio << "Object consumed " << ns.tell() << "b." << sio.nl; | 81 | uint8_t uBuf = 1; |
| 82 | int32_t iSize = htonl( ns.tell()+5 ); | ||
| 83 | rStream.write( &uBuf, 1 ); | ||
| 84 | rStream.write( &iSize, 4 ); | ||
| 85 | pObject->write( rStream ); | ||
| 86 | |||
| 87 | // sio << "Object consumed " << ns.tell() << "b." << sio.nl; | ||
| 88 | } | ||
| 89 | |||
| 90 | bool Gats::GatsStream::skipReadNulls() | ||
| 91 | { | ||
| 92 | char buf; | ||
| 93 | |||
| 94 | // sio << "Gats::GatsStream::skipReadNulls(): Scanning for nulls, " << qbRead.getSize() << "b." << sio.nl; | ||
| 95 | bool bHaveSeeked = false; | ||
| 96 | for(;;) | ||
| 97 | { | ||
| 98 | if( qbRead.peek( &buf, 1 ) == 0 ) | ||
| 99 | return false; | ||
| 100 | if( buf != 0 ) | ||
| 101 | return !bHaveSeeked; //true; | ||
| 102 | else | ||
| 103 | { | ||
| 104 | // sio << "Gats::GatsStream::skipReadNulls(): Null byte read, not header yet..." << sio.nl; | ||
| 105 | qbRead.seek( 1 ); | ||
| 106 | bHaveSeeked = true; | ||
| 107 | } | ||
| 108 | } | ||
| 28 | } | 109 | } |
| 29 | 110 | ||
diff --git a/src/gatsstream.h b/src/gatsstream.h index d668c28..b5efb87 100644 --- a/src/gatsstream.h +++ b/src/gatsstream.h | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | #define GATS_STREAM_H | 2 | #define GATS_STREAM_H |
| 3 | 3 | ||
| 4 | #include <bu/stream.h> | 4 | #include <bu/stream.h> |
| 5 | #include <bu/queuebuf.h> | ||
| 5 | 6 | ||
| 6 | namespace Gats | 7 | namespace Gats |
| 7 | { | 8 | { |
| @@ -13,11 +14,41 @@ namespace Gats | |||
| 13 | GatsStream( Bu::Stream &rStream ); | 14 | GatsStream( Bu::Stream &rStream ); |
| 14 | virtual ~GatsStream(); | 15 | virtual ~GatsStream(); |
| 15 | 16 | ||
| 17 | /** | ||
| 18 | * Read an object packet from the assosiated stream. This will make | ||
| 19 | * every effort to only read exactly enough data to describe one packet, | ||
| 20 | * in case you want to do other things with your stream. It will | ||
| 21 | * automatically skip NULL byte spacing between packets, which makes | ||
| 22 | * a convinient padding method for encrypted data streams. Since | ||
| 23 | * sizing information is available in the packet header exact amounts | ||
| 24 | * of data can be read, however this function doesn't assume that it | ||
| 25 | * can read the entire object in one operation. If it fails to read | ||
| 26 | * a complete packet in one call, it will keep the data it's read so | ||
| 27 | * far buffered and return NULL, ready for another attempt. You can | ||
| 28 | * use the function hasReadBuffer() to deterimne if readObject() | ||
| 29 | * has read part of an object packet or not. If readObject returns | ||
| 30 | * non-null then hasReadBuffer should return false on it's next call. | ||
| 31 | */ | ||
| 16 | Gats::Object *readObject(); | 32 | Gats::Object *readObject(); |
| 33 | |||
| 34 | /** | ||
| 35 | * Write an object | ||
| 36 | */ | ||
| 17 | void writeObject( Gats::Object *pObject ); | 37 | void writeObject( Gats::Object *pObject ); |
| 18 | 38 | ||
| 39 | /** | ||
| 40 | * Tells you if there is data still in the read buffer, i.e. that a | ||
| 41 | * packet is part way through being read. If readObject has returned | ||
| 42 | * non-null in the most recent call, this should always be false. | ||
| 43 | */ | ||
| 44 | bool hasReadBuffer() { return qbRead.getSize() > 0; } | ||
| 45 | |||
| 46 | private: | ||
| 47 | bool skipReadNulls(); | ||
| 48 | |||
| 19 | private: | 49 | private: |
| 20 | Bu::Stream &rStream; | 50 | Bu::Stream &rStream; |
| 51 | Bu::QueueBuf qbRead; | ||
| 21 | }; | 52 | }; |
| 22 | }; | 53 | }; |
| 23 | 54 | ||
diff --git a/src/object.cpp b/src/object.cpp index 4c1f3ca..9176b49 100644 --- a/src/object.cpp +++ b/src/object.cpp | |||
| @@ -45,6 +45,10 @@ Gats::Object *Gats::Object::read( Bu::Stream &rIn ) | |||
| 45 | pObj = new Gats::Dictionary(); | 45 | pObj = new Gats::Dictionary(); |
| 46 | break; | 46 | break; |
| 47 | 47 | ||
| 48 | case 'f': | ||
| 49 | pObj = new Gats::Float(); | ||
| 50 | break; | ||
| 51 | |||
| 48 | case 'e': | 52 | case 'e': |
| 49 | return NULL; | 53 | return NULL; |
| 50 | 54 | ||
diff --git a/src/unit/basic.unit b/src/unit/basic.unit index 744d679..d0309ee 100644 --- a/src/unit/basic.unit +++ b/src/unit/basic.unit | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include "bu/sio.h" | 18 | #include "bu/sio.h" |
| 19 | 19 | ||
| 20 | #include <stdlib.h> | 20 | #include <stdlib.h> |
| 21 | #include <math.h> | ||
| 21 | 22 | ||
| 22 | using namespace Bu; | 23 | using namespace Bu; |
| 23 | 24 | ||
| @@ -120,6 +121,24 @@ suite Basic | |||
| 120 | } | 121 | } |
| 121 | } | 122 | } |
| 122 | 123 | ||
| 124 | test floats | ||
| 125 | { | ||
| 126 | Bu::MemBuf mb; | ||
| 127 | |||
| 128 | Gats::Float( M_PI ).write( mb ); | ||
| 129 | |||
| 130 | mb.setPos( 0 ); | ||
| 131 | |||
| 132 | Gats::Object *pObj = Gats::Object::read( mb ); | ||
| 133 | unitTest( pObj != NULL ); | ||
| 134 | unitTest( pObj->getType() == Gats::typeFloat ); | ||
| 135 | Gats::Float *pFlt = dynamic_cast<Gats::Float *>(pObj); | ||
| 136 | sio << "old = " << M_PI << ", new = " << pFlt->getValue() << sio.nl; | ||
| 137 | unitTest( pFlt->getValue() == M_PI ); | ||
| 138 | |||
| 139 | delete pObj; | ||
| 140 | } | ||
| 141 | |||
| 123 | test dictionary | 142 | test dictionary |
| 124 | { | 143 | { |
| 125 | MemBuf mb; | 144 | MemBuf mb; |
diff --git a/src/unit/io.unit b/src/unit/io.unit new file mode 100644 index 0000000..3e9c82c --- /dev/null +++ b/src/unit/io.unit | |||
| @@ -0,0 +1,127 @@ | |||
| 1 | // vim: syntax=cpp | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2007-2010 Xagasoft, All rights reserved. | ||
| 4 | * | ||
| 5 | * This file is part of the libbu++ library and is released under the | ||
| 6 | * terms of the license contained in the file LICENSE. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include "gats/dictionary.h" | ||
| 10 | #include "gats/integer.h" | ||
| 11 | #include "gats/float.h" | ||
| 12 | #include "gats/list.h" | ||
| 13 | #include "gats/boolean.h" | ||
| 14 | #include "gats/string.h" | ||
| 15 | #include "gats/gatsstream.h" | ||
| 16 | |||
| 17 | #include "bu/membuf.h" | ||
| 18 | #include "bu/list.h" | ||
| 19 | #include "bu/sio.h" | ||
| 20 | |||
| 21 | #include <stdlib.h> | ||
| 22 | |||
| 23 | using namespace Bu; | ||
| 24 | |||
| 25 | suite Basic | ||
| 26 | { | ||
| 27 | test basic | ||
| 28 | { | ||
| 29 | Bu::FString sTmpFileName("temp-XXXXXXXXX"); | ||
| 30 | Bu::File fIo = tempFile( sTmpFileName ); | ||
| 31 | |||
| 32 | { | ||
| 33 | Gats::Dictionary dTest; | ||
| 34 | dTest.insert("age", 27 ); | ||
| 35 | dTest.insert("firstName", "Mike"); | ||
| 36 | dTest.insert("lastName", "Buland"); | ||
| 37 | dTest.insert("awake", true ); | ||
| 38 | |||
| 39 | Gats::GatsStream sGats( fIo ); | ||
| 40 | sGats.writeObject( &dTest ); | ||
| 41 | } | ||
| 42 | |||
| 43 | fIo.setPos( 0 ); | ||
| 44 | |||
| 45 | { | ||
| 46 | Gats::GatsStream sGats( fIo ); | ||
| 47 | Gats::Object *pObj = sGats.readObject(); | ||
| 48 | unitTest( pObj != NULL ); | ||
| 49 | unitTest( pObj->getType() == Gats::typeDictionary ); | ||
| 50 | Gats::Dictionary *pDic = dynamic_cast<Gats::Dictionary *>(pObj); | ||
| 51 | unitTest( pDic->getSize() == 4 ); | ||
| 52 | unitTest( pDic->getInt("age") == 27 ); | ||
| 53 | unitTest( pDic->getStr("firstName") == "Mike" ); | ||
| 54 | unitTest( pDic->getStr("lastName") == "Buland" ); | ||
| 55 | unitTest( pDic->getBool("awake") == true ); | ||
| 56 | |||
| 57 | delete pDic; | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | test spacers | ||
| 62 | { | ||
| 63 | Bu::FString sTmpFileName("temp-XXXXXXXXX"); | ||
| 64 | Bu::File fIo = tempFile( sTmpFileName ); | ||
| 65 | |||
| 66 | { | ||
| 67 | Gats::GatsStream sGats( fIo ); | ||
| 68 | Gats::Integer i( -157 ); | ||
| 69 | sGats.writeObject( &i ); | ||
| 70 | fIo.write( "\x00\x00\x00", 3 ); | ||
| 71 | Gats::String s("negative one hundred and fifty seven"); | ||
| 72 | sGats.writeObject( &s ); | ||
| 73 | } | ||
| 74 | |||
| 75 | fIo.setPos( 0 ); | ||
| 76 | |||
| 77 | { | ||
| 78 | Gats::GatsStream sGats( fIo ); | ||
| 79 | Gats::Object *pObj1 = sGats.readObject(); | ||
| 80 | unitTest( pObj1 != NULL ); | ||
| 81 | unitTest( pObj1->getType() == Gats::typeInteger ); | ||
| 82 | unitTest( dynamic_cast<Gats::Integer *>(pObj1)->getValue() == -157 ); | ||
| 83 | |||
| 84 | Gats::Object *pObj2 = sGats.readObject(); | ||
| 85 | unitTest( pObj2 != NULL ); | ||
| 86 | unitTest( pObj2->getType() == Gats::typeString ); | ||
| 87 | unitTest( *dynamic_cast<Gats::String *>(pObj2) == | ||
| 88 | "negative one hundred and fifty seven" ); | ||
| 89 | |||
| 90 | delete pObj1; | ||
| 91 | delete pObj2; | ||
| 92 | } | ||
| 93 | } | ||
| 94 | test biggerSpacers | ||
| 95 | { | ||
| 96 | Bu::FString sTmpFileName("temp-XXXXXXXXX"); | ||
| 97 | Bu::File fIo = tempFile( sTmpFileName ); | ||
| 98 | |||
| 99 | { | ||
| 100 | Gats::GatsStream sGats( fIo ); | ||
| 101 | Gats::Integer i( -157 ); | ||
| 102 | sGats.writeObject( &i ); | ||
| 103 | fIo.write( "\x00\x00\x00\x00\x00\x00\x00\x00\x00", 9 ); | ||
| 104 | Gats::String s("negative one hundred and fifty seven"); | ||
| 105 | sGats.writeObject( &s ); | ||
| 106 | } | ||
| 107 | |||
| 108 | fIo.setPos( 0 ); | ||
| 109 | |||
| 110 | { | ||
| 111 | Gats::GatsStream sGats( fIo ); | ||
| 112 | Gats::Object *pObj1 = sGats.readObject(); | ||
| 113 | unitTest( pObj1 != NULL ); | ||
| 114 | unitTest( pObj1->getType() == Gats::typeInteger ); | ||
| 115 | unitTest( dynamic_cast<Gats::Integer *>(pObj1)->getValue() == -157 ); | ||
| 116 | |||
| 117 | Gats::Object *pObj2 = sGats.readObject(); | ||
| 118 | unitTest( pObj2 != NULL ); | ||
| 119 | unitTest( pObj2->getType() == Gats::typeString ); | ||
| 120 | unitTest( *dynamic_cast<Gats::String *>(pObj2) == | ||
| 121 | "negative one hundred and fifty seven" ); | ||
| 122 | |||
| 123 | delete pObj1; | ||
| 124 | delete pObj2; | ||
| 125 | } | ||
| 126 | } | ||
| 127 | } | ||
