From f4c20290509d7ed3a8fd5304577e7a4cc0b9d974 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Tue, 3 Apr 2007 03:49:53 +0000 Subject: Ok, no code is left in src, it's all in src/old. We'll gradually move code back into src as it's fixed and re-org'd. This includes tests, which, I may write a unit test system into libbu++ just to make my life easier. --- src/fstring.h | 651 ---------------------------------------------------------- 1 file changed, 651 deletions(-) delete mode 100644 src/fstring.h (limited to 'src/fstring.h') diff --git a/src/fstring.h b/src/fstring.h deleted file mode 100644 index c5397cc..0000000 --- a/src/fstring.h +++ /dev/null @@ -1,651 +0,0 @@ -#ifndef F_STRING_H -#define F_STRING_H - -#include -#include -#include "serializable.h" -#include "serializer.h" - -template< typename chr > -struct FStringChunk -{ - long nLength; - chr *pData; - FStringChunk *pNext; -}; - -/** - * Flexible String class. This class was designed with string passing and - * generation in mind. Like the standard string class you can specify what - * datatype to use for each character. Unlike the standard string class, - * collection of appended and prepended terms is done lazily, making long - * operations that involve many appends very inexpensive. In addition internal - * ref-counting means that if you pass strings around between functions there's - * almost no overhead in time or memory since a reference is created and no - * data is actually copied. This also means that you never need to put any - * FBasicString into a ref-counting container class. - */ -template< typename chr, typename chralloc=std::allocator, typename chunkalloc=std::allocator > > -class FBasicString : public Serializable -{ -#ifndef VALTEST -#define cpy( dest, src, size ) memcpy( dest, src, size*sizeof(chr) ) -#endif -private: - typedef struct FStringChunk Chunk; - typedef struct FBasicString MyType; - -public: - FBasicString() : - nLength( 0 ), - pnRefs( NULL ), - pFirst( NULL ), - pLast( NULL ) - { - } - - FBasicString( const chr *pData ) : - nLength( 0 ), - pnRefs( NULL ), - pFirst( NULL ), - pLast( NULL ) - { - append( pData ); - } - - FBasicString( const chr *pData, long nLength ) : - nLength( 0 ), - pnRefs( NULL ), - pFirst( NULL ), - pLast( NULL ) - { - append( pData, nLength ); - } - - FBasicString( const MyType &rSrc ) : - nLength( 0 ), - pnRefs( NULL ), - pFirst( NULL ), - pLast( NULL ) - { - // Here we have no choice but to copy, since the other guy is a const. - // In the case that the source were flat, we could get a reference, it - // would make some things faster, but not matter in many other cases. - - joinShare( rSrc ); - //copyFrom( rSrc ); - } - - FBasicString( const MyType &rSrc, long nLength ) : - nLength( 0 ), - pnRefs( NULL ), - pFirst( NULL ), - pLast( NULL ) - { - append( rSrc.pFirst->pData, nLength ); - } - - FBasicString( const MyType &rSrc, long nStart, long nLength ) : - nLength( 0 ), - pnRefs( NULL ), - pFirst( NULL ), - pLast( NULL ) - { - append( rSrc.pFirst->pData+nStart, nLength ); - } - - FBasicString( long nSize ) : - nLength( nSize ), - pnRefs( NULL ), - pFirst( NULL ), - pLast( NULL ) - { - pFirst = pLast = newChunk( nSize ); - } - - virtual ~FBasicString() - { - clear(); - } - - void append( const chr *pData ) - { - long nLen; - for( nLen = 0; pData[nLen] != (chr)0; nLen++ ); - - Chunk *pNew = newChunk( nLen ); - cpy( pNew->pData, pData, nLen ); - - appendChunk( pNew ); - } - - void append( const chr *pData, long nLen ) - { - Chunk *pNew = newChunk( nLen ); - - cpy( pNew->pData, pData, nLen ); - - appendChunk( pNew ); - } - - void prepend( const chr *pData ) - { - long nLen; - for( nLen = 0; pData[nLen] != (chr)0; nLen++ ); - - Chunk *pNew = newChunk( nLen ); - cpy( pNew->pData, pData, nLen ); - - prependChunk( pNew ); - } - - void prepend( const chr *pData, long nLen ) - { - Chunk *pNew = newChunk( nLen ); - - cpy( pNew->pData, pData, nLen ); - - prependChunk( pNew ); - } - - void clear() - { - realClear(); - } - - void resize( long nNewSize ) - { - if( nLength == nNewSize ) - return; - - flatten(); - - Chunk *pNew = newChunk( nNewSize ); - long nNewLen = (nNewSizepData, pFirst->pData, nNewLen ); - pNew->pData[nNewLen] = (chr)0; - aChr.deallocate( pFirst->pData, pFirst->nLength+1 ); - aChunk.deallocate( pFirst, 1 ); - pFirst = pLast = pNew; - nLength = nNewSize; - } - - long getSize() const - { - return nLength; - } - - chr *getStr() - { - if( pFirst == NULL ) - return NULL; - - flatten(); - return pFirst->pData; - } - - const chr *getStr() const - { - if( pFirst == NULL ) - return NULL; - - flatten(); - return pFirst->pData; - } - - chr *c_str() - { - if( pFirst == NULL ) - return NULL; - - flatten(); - return pFirst->pData; - } - - const chr *c_str() const - { - if( pFirst == NULL ) - return NULL; - - flatten(); - return pFirst->pData; - } - - MyType &operator +=( const chr *pData ) - { - append( pData ); - - return (*this); - } - - MyType &operator +=( const MyType &rSrc ) - { - rSrc.flatten(); - append( rSrc.pFirst->pData, rSrc.nLength ); - - return (*this); - } - - MyType &operator +=( const chr pData ) - { - chr tmp[2] = { pData, (chr)0 }; - append( tmp ); - - return (*this); - } - - MyType &operator =( const chr *pData ) - { - clear(); - append( pData ); - - return (*this); - } - - MyType &operator =( const MyType &rSrc ) - { - //if( rSrc.isFlat() ) - //{ - joinShare( rSrc ); - //} - //else - //{ - // copyFrom( rSrc ); - //} - // - - return (*this); - } - - bool operator ==( const chr *pData ) const - { - if( pFirst == NULL ) { - if( pData == NULL ) - return true; - return false; - } - - flatten(); - const chr *a = pData; - chr *b = pFirst->pData; - for( ; *a!=(chr)0; a++, b++ ) - { - if( *a != *b ) - return false; - } - - return true; - } - - bool operator ==( const MyType &pData ) const - { - if( pFirst == pData.pFirst ) - return true; - if( pFirst == NULL ) - return false; - - flatten(); - pData.flatten(); - const chr *a = pData.pFirst->pData; - chr *b = pFirst->pData; - for( ; *a!=(chr)0; a++, b++ ) - { - if( *a != *b ) - return false; - } - - return true; - } - - bool operator !=(const chr *pData ) const - { - return !(*this == pData); - } - - bool operator !=(const MyType &pData ) const - { - return !(*this == pData); - } - - chr &operator[]( long nIndex ) - { - flatten(); - - return pFirst->pData[nIndex]; - } - - const chr &operator[]( long nIndex ) const - { - flatten(); - - return pFirst->pData[nIndex]; - } - - bool isWS( long nIndex ) const - { - flatten(); - - return pFirst->pData[nIndex]==' ' || pFirst->pData[nIndex]=='\t' - || pFirst->pData[nIndex]=='\r' || pFirst->pData[nIndex]=='\n'; - } - - bool isAlpha( long nIndex ) const - { - flatten(); - - return (pFirst->pData[nIndex] >= 'a' && pFirst->pData[nIndex] <= 'z') - || (pFirst->pData[nIndex] >= 'A' && pFirst->pData[nIndex] <= 'Z'); - } - - void toLower() - { - flatten(); - unShare(); - - for( long j = 0; j < nLength; j++ ) - { - if( pFirst->pData[j] >= 'A' && pFirst->pData[j] <= 'Z' ) - pFirst->pData[j] -= 'A'-'a'; - } - } - - void toUpper() - { - flatten(); - unShare(); - - for( long j = 0; j < nLength; j++ ) - { - if( pFirst->pData[j] >= 'a' && pFirst->pData[j] <= 'z' ) - pFirst->pData[j] += 'A'-'a'; - } - } - - void serialize( class Serializer &ar ) - { - if( ar.isLoading() ) - { - clear(); - long nLen; - ar >> nLen; - - Chunk *pNew = newChunk( nLen ); - ar.read( pNew->pData, nLen*sizeof(chr) ); - appendChunk( pNew ); - } - else - { - flatten(); - - ar << nLength; - ar.write( pFirst->pData, nLength*sizeof(chr) ); - } - } - -private: - void flatten() const - { - if( isFlat() ) - return; - - if( pFirst == NULL ) - return; - - unShare(); - - Chunk *pNew = newChunk( nLength ); - chr *pos = pNew->pData; - Chunk *i = pFirst; - for(;;) - { - cpy( pos, i->pData, i->nLength ); - pos += i->nLength; - i = i->pNext; - if( i == NULL ) - break; - } - realClear(); - - pLast = pFirst = pNew; - nLength = pNew->nLength; - } - - void realClear() const - { - if( pFirst == NULL ) - return; - - if( isShared() ) - { - decRefs(); - } - else - { - Chunk *i = pFirst; - for(;;) - { - Chunk *n = i->pNext; - aChr.deallocate( i->pData, i->nLength+1 ); - aChunk.deallocate( i, 1 ); - if( n == NULL ) - break; - i = n; - } - pFirst = pLast = NULL; - nLength = 0; - } - } - - void copyFrom( const FBasicString &rSrc ) - { - if( rSrc.pFirst == NULL ) - return; - - decRefs(); - - Chunk *pNew = newChunk( rSrc.nLength ); - chr *pos = pNew->pData; - Chunk *i = rSrc.pFirst; - for(;;) - { - cpy( pos, i->pData, i->nLength ); - pos += i->nLength; - i = i->pNext; - if( i == NULL ) - break; - } - clear(); - - appendChunk( pNew ); - } - - bool isFlat() const - { - return (pFirst == pLast); - } - - bool isShared() const - { - return (pnRefs != NULL); - } - - Chunk *newChunk() const - { - Chunk *pNew = aChunk.allocate( 1 ); - pNew->pNext = NULL; - return pNew; - } - - Chunk *newChunk( long nLen ) const - { - Chunk *pNew = aChunk.allocate( 1 ); - pNew->pNext = NULL; - pNew->nLength = nLen; - pNew->pData = aChr.allocate( nLen+1 ); - pNew->pData[nLen] = (chr)0; - return pNew; - } - - void appendChunk( Chunk *pNewChunk ) - { - unShare(); - - if( pFirst == NULL ) - pLast = pFirst = pNewChunk; - else - { - pLast->pNext = pNewChunk; - pLast = pNewChunk; - } - - nLength += pNewChunk->nLength; - } - - void prependChunk( Chunk *pNewChunk ) - { - unShare(); - - if( pFirst == NULL ) - pLast = pFirst = pNewChunk; - else - { - pNewChunk->pNext = pFirst; - pFirst = pNewChunk; - } - - nLength += pNewChunk->nLength; - } - - void joinShare( MyType &rSrc ) - { - clear(); - - if( !rSrc.isFlat() ) - rSrc.flatten(); - - rSrc.initCount(); - pnRefs = rSrc.pnRefs; - (*pnRefs)++; - nLength = rSrc.nLength; - pFirst = rSrc.pFirst; - pLast = rSrc.pLast; - } - - void joinShare( const MyType &rSrc ) - { - clear(); - - rSrc.flatten(); - - if( !rSrc.isShared() ) - { - rSrc.pnRefs = new uint32_t; - (*rSrc.pnRefs) = 1; - } - pnRefs = rSrc.pnRefs; - (*pnRefs)++; - nLength = rSrc.nLength; - pFirst = rSrc.pFirst; - pLast = rSrc.pLast; - } - - /** - * This takes an object that was shared and makes a copy of the base data - * that was being shared so that this copy can be changed. This should be - * added before any call that will change this object; - */ - void unShare() const - { - if( isShared() == false ) - return; - - Chunk *pNew = newChunk( nLength ); - chr *pos = pNew->pData; - Chunk *i = pFirst; - for(;;) - { - cpy( pos, i->pData, i->nLength ); - pos += i->nLength; - i = i->pNext; - if( i == NULL ) - break; - } - decRefs(); - pLast = pFirst = pNew; - nLength = pNew->nLength; - } - - /** - * This decrements our ref count and pulls us out of the share. If the ref - * count hits zero because of this, it destroys the share. This is not - * safe to call on it's own, it's much better to call unShare. - */ - void decRefs() const - { - if( isShared() ) - { - (*pnRefs)--; - if( (*pnRefs) == 0 ) - destroyShare(); - else - { - pnRefs = NULL; - pFirst = NULL; - pLast = NULL; - nLength = 0; - } - } - } - - /** - * While the unShare function removes an instance from a share, this - * function destroys the data that was in the share, removing the share - * itself. This should only be called when the refcount for the share has - * or is about to reach zero. - */ - void destroyShare() const - { - delete pnRefs; - pnRefs = NULL; - realClear(); - } - -#ifdef VALTEST - void cpy( chr *dest, const chr *src, long count ) const - { - for( int j = 0; j < count; j++ ) - { - *dest = *src; - dest++; - src++; - } - } -#endif - - void initCount() const - { - if( !isShared() ) - { - pnRefs = new uint32_t; - (*pnRefs) = 1; - } - } - -private: - mutable long nLength; - mutable uint32_t *pnRefs; - mutable Chunk *pFirst; - mutable Chunk *pLast; - - mutable chralloc aChr; - mutable chunkalloc aChunk; -}; - -typedef FBasicString FString; - -#include "hash.h" -template<> uint32_t __calcHashCode( const FString &k ); -template<> bool __cmpHashKeys( const FString &a, const FString &b ); - - -#endif -- cgit v1.2.3 From da89e6d30e57bd6dbb10b4d36b093ce9bbf5c666 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Tue, 3 Apr 2007 04:50:36 +0000 Subject: The first batch seem to have made it alright. Unfortunately the Archive class isn't done yet, I'm going to make it rely on streams, so those will be next, then we can make it work all sortsa' well. --- src/archable.cpp | 10 + src/archable.h | 35 +++ src/archive.cpp | 337 +++++++++++++++++++++ src/archive.h | 93 ++++++ src/exceptionbase.cpp | 70 +++++ src/exceptionbase.h | 114 +++++++ src/exceptions.cpp | 10 + src/exceptions.h | 28 ++ src/fstring.cpp | 14 + src/fstring.h | 653 ++++++++++++++++++++++++++++++++++++++++ src/hash.cpp | 101 +++++++ src/hash.h | 745 ++++++++++++++++++++++++++++++++++++++++++++++ src/old/exceptionbase.cpp | 70 ----- src/old/exceptionbase.h | 105 ------- src/old/exceptions.cpp | 8 - src/old/exceptions.h | 25 -- src/old/fstring.cpp | 13 - src/old/fstring.h | 651 ---------------------------------------- src/old/hash.cpp | 113 ------- src/old/hash.h | 744 --------------------------------------------- src/old/hashable.cpp | 1 - src/old/hashable.h | 12 - src/old/serializable.cpp | 8 - src/old/serializable.h | 34 --- src/old/serializer.cpp | 338 --------------------- src/old/serializer.h | 80 ----- src/old/stream.cpp | 10 - src/old/stream.h | 27 -- src/stream.cpp | 10 + src/stream.h | 34 +++ src/tests/archive.cpp | 7 + tests/comments.xml | 12 - tests/guy.cpp | 22 -- tests/makeplugin.sh | 3 - 34 files changed, 2261 insertions(+), 2276 deletions(-) create mode 100644 src/archable.cpp create mode 100644 src/archable.h create mode 100644 src/archive.cpp create mode 100644 src/archive.h create mode 100644 src/exceptionbase.cpp create mode 100644 src/exceptionbase.h create mode 100644 src/exceptions.cpp create mode 100644 src/exceptions.h create mode 100644 src/fstring.cpp create mode 100644 src/fstring.h create mode 100644 src/hash.cpp create mode 100644 src/hash.h delete mode 100644 src/old/exceptionbase.cpp delete mode 100644 src/old/exceptionbase.h delete mode 100644 src/old/exceptions.cpp delete mode 100644 src/old/exceptions.h delete mode 100644 src/old/fstring.cpp delete mode 100644 src/old/fstring.h delete mode 100644 src/old/hash.cpp delete mode 100644 src/old/hash.h delete mode 100644 src/old/hashable.cpp delete mode 100644 src/old/hashable.h delete mode 100644 src/old/serializable.cpp delete mode 100644 src/old/serializable.h delete mode 100644 src/old/serializer.cpp delete mode 100644 src/old/serializer.h delete mode 100644 src/old/stream.cpp delete mode 100644 src/old/stream.h create mode 100644 src/stream.cpp create mode 100644 src/stream.h create mode 100644 src/tests/archive.cpp delete mode 100644 tests/comments.xml delete mode 100644 tests/guy.cpp delete mode 100755 tests/makeplugin.sh (limited to 'src/fstring.h') diff --git a/src/archable.cpp b/src/archable.cpp new file mode 100644 index 0000000..38fc31f --- /dev/null +++ b/src/archable.cpp @@ -0,0 +1,10 @@ +#include "archable.h" + +Bu::Archable::Archable() +{ +} + +Bu::Archable::~Archable() +{ +} + diff --git a/src/archable.h b/src/archable.h new file mode 100644 index 0000000..ed05a78 --- /dev/null +++ b/src/archable.h @@ -0,0 +1,35 @@ +#ifndef ARCHABLE_H +#define ARCHABLE_H + +namespace Bu +{ + /** + * The base class for any class you want to archive. Simply include this as + * a base class, implement the purely virtual archive function and you've + * got an easily archiveable class. + */ + class Archable + { + public: + /** + * Does nothing, here for completeness. + */ + Archable(); + + /** + * Here to ensure the deconstructor is virtual. + */ + virtual ~Archable(); + + /** + * This is the main workhorse of the archive system, just override and + * you've got a archiveable class. A reference to the Archive + * used is passed in as your only parameter, query it to discover if + * you are loading or saving. + * @param ar A reference to the Archive object to use. + */ + virtual void archive( class Archive &ar )=0; + }; +} + +#endif diff --git a/src/archive.cpp b/src/archive.cpp new file mode 100644 index 0000000..5f5145c --- /dev/null +++ b/src/archive.cpp @@ -0,0 +1,337 @@ +#include "archive.h" + +Bu::Archive::Archive(bool bLoading): + bLoading(bLoading) +{ +} +Bu::Archive::~Archive() +{ +} + +bool Bu::Archive::isLoading() +{ + return bLoading; +} +Bu::Archive &Bu::Archive::operator<<(bool p) +{ + write( &p, sizeof(p) ); + return *this; +} +Bu::Archive &Bu::Archive::operator<<(int8_t p) +{ + write( &p, sizeof(p) ); + return *this; +} +Bu::Archive &Bu::Archive::operator<<(int16_t p) +{ + write( &p, sizeof(p) ); + return *this; +} +Bu::Archive &Bu::Archive::operator<<(int32_t p) +{ + write( &p, sizeof(p) ); + return *this; +} +Bu::Archive &Bu::Archive::operator<<(int64_t p) +{ + write( &p, sizeof(p) ); + return *this; +} +Bu::Archive &Bu::Archive::operator<<(uint8_t p) +{ + write( &p, sizeof(p) ); + return *this; +} +Bu::Archive &Bu::Archive::operator<<(uint16_t p) +{ + write( &p, sizeof(p) ); + return *this; +} +Bu::Archive &Bu::Archive::operator<<(uint32_t p) +{ + write( &p, sizeof(p) ); + return *this; +} +Bu::Archive &Bu::Archive::operator<<(uint64_t p) +{ + write( &p, sizeof(p) ); + return *this; +} +Bu::Archive &Bu::Archive::operator<<(long p) +{ + write( &p, sizeof(p) ); + return *this; +} +Bu::Archive &Bu::Archive::operator<<(float p) +{ + write( &p, sizeof(p) ); + return *this; +} +Bu::Archive &Bu::Archive::operator<<(double p) +{ + write( &p, sizeof(p) ); + return *this; +} +Bu::Archive &Bu::Archive::operator<<(long double p) +{ + write( &p, sizeof(p) ); + return *this; +} + +Bu::Archive &Bu::Archive::operator>>(bool &p) +{ + read( &p, sizeof(p) ); + return *this; +} +Bu::Archive &Bu::Archive::operator>>(int8_t &p) +{ + read( &p, sizeof(p) ); + return *this; +} +Bu::Archive &Bu::Archive::operator>>(int16_t &p) +{ + read( &p, sizeof(p) ); + return *this; +} +Bu::Archive &Bu::Archive::operator>>(int32_t &p) +{ + read( &p, sizeof(p) ); + return *this; +} +Bu::Archive &Bu::Archive::operator>>(int64_t &p) +{ + read( &p, sizeof(p) ); + return *this; +} +Bu::Archive &Bu::Archive::operator>>(uint8_t &p) +{ + read( &p, sizeof(p) ); + return *this; +} +Bu::Archive &Bu::Archive::operator>>(uint16_t &p) +{ + read( &p, sizeof(p) ); + return *this; +} +Bu::Archive &Bu::Archive::operator>>(uint32_t &p) +{ + read( &p, sizeof(p) ); + return *this; +} +Bu::Archive &Bu::Archive::operator>>(uint64_t &p) +{ + read( &p, sizeof(p) ); + return *this; +} +Bu::Archive &Bu::Archive::operator>>(long &p) +{ + read( &p, sizeof(p) ); + return *this; +} +Bu::Archive &Bu::Archive::operator>>(float &p) +{ + read( &p, sizeof(p) ); + return *this; +} +Bu::Archive &Bu::Archive::operator>>(double &p) +{ + read( &p, sizeof(p) ); + return *this; +} +Bu::Archive &Bu::Archive::operator>>(long double &p) +{ + read( &p, sizeof(p) ); + return *this; +} + +Bu::Archive &Bu::Archive::operator&&(bool &p) +{ + if (bLoading) + { + return *this >> p; + } + else + { + return *this << p; + } +} + +Bu::Archive &Bu::Archive::operator&&(int8_t &p) +{ + if (bLoading) + { + return *this >> p; + } + else + { + return *this << p; + } +} + +Bu::Archive &Bu::Archive::operator&&(int16_t &p) +{ + if (bLoading) + { + return *this >> p; + } + else + { + return *this << p; + } +} + +Bu::Archive &Bu::Archive::operator&&(int32_t &p) +{ + if (bLoading) + { + return *this >> p; + } + else + { + return *this << p; + } +} + +Bu::Archive &Bu::Archive::operator&&(int64_t &p) +{ + if (bLoading) + { + return *this >> p; + } + else + { + return *this << p; + } +} + +Bu::Archive &Bu::Archive::operator&&(uint8_t &p) +{ + if (bLoading) + { + return *this >> p; + } + else + { + return *this << p; + } +} + +Bu::Archive &Bu::Archive::operator&&(uint16_t &p) +{ + if (bLoading) + { + return *this >> p; + } + else + { + return *this << p; + } +} + +Bu::Archive &Bu::Archive::operator&&(uint32_t &p) +{ + if (bLoading) + { + return *this >> p; + } + else + { + return *this << p; + } +} + +Bu::Archive &Bu::Archive::operator&&(uint64_t &p) +{ + if (bLoading) + { + return *this >> p; + } + else + { + return *this << p; + } +} + +Bu::Archive &Bu::Archive::operator&&(float &p) +{ + if (bLoading) + { + return *this >> p; + } + else + { + return *this << p; + } +} + +Bu::Archive &Bu::Archive::operator&&(double &p) +{ + if (bLoading) + { + return *this >> p; + } + else + { + return *this << p; + } +} + +Bu::Archive &Bu::Archive::operator&&(long double &p) +{ + if (bLoading) + { + return *this >> p; + } + else + { + return *this << p; + } +} + + +Bu::Archive &Bu::operator<<(Bu::Archive &s, Bu::Archable &p) +{ + p.archive( s ); + return s; +} + +Bu::Archive &Bu::operator>>(Bu::Archive &s, Bu::Archable &p) +{ + p.archive( s ); + return s; +} + +/* +Bu::Archive &Bu::operator&&(Bu::Archive &s, Bu::Archable &p) +{ + if (s.isLoading()) + { + return s >> p; + } + else + { + return s << p; + } +}*/ + +Bu::Archive &Bu::operator<<( Bu::Archive &ar, std::string &s ) +{ + ar << (uint32_t)s.length(); + ar.write( s.c_str(), s.length() ); + + return ar; +} + +Bu::Archive &Bu::operator>>( Bu::Archive &ar, std::string &s ) +{ + uint32_t l; + ar >> l; + char *tmp = new char[l+1]; + tmp[l] = '\0'; + ar.read( tmp, l ); + s = tmp; + delete[] tmp; + + return ar; +} + diff --git a/src/archive.h b/src/archive.h new file mode 100644 index 0000000..7de9220 --- /dev/null +++ b/src/archive.h @@ -0,0 +1,93 @@ +#ifndef ARCHIVE_H +#define ARCHIVE_H + +#include +#include +#include "archable.h" + +namespace Bu +{ + class Archive + { + private: + bool bLoading; + public: + bool isLoading(); + + enum + { + load = true, + save = false + }; + + Archive( bool bLoading ); + virtual ~Archive(); + virtual void close()=0; + + virtual void write(const void *, int32_t)=0; + virtual void read(void *, int32_t)=0; + + virtual Archive &operator<<(bool); + virtual Archive &operator<<(int8_t); + virtual Archive &operator<<(int16_t); + virtual Archive &operator<<(int32_t); + virtual Archive &operator<<(int64_t); + virtual Archive &operator<<(uint8_t); + virtual Archive &operator<<(uint16_t); + virtual Archive &operator<<(uint32_t); + virtual Archive &operator<<(uint64_t); + virtual Archive &operator<<(long); + virtual Archive &operator<<(float); + virtual Archive &operator<<(double); + virtual Archive &operator<<(long double); + + virtual Archive &operator>>(bool &); + virtual Archive &operator>>(int8_t &); + virtual Archive &operator>>(int16_t &); + virtual Archive &operator>>(int32_t &); + virtual Archive &operator>>(int64_t &); + virtual Archive &operator>>(uint8_t &); + virtual Archive &operator>>(uint16_t &); + virtual Archive &operator>>(uint32_t &); + virtual Archive &operator>>(uint64_t &); + virtual Archive &operator>>(long &); + virtual Archive &operator>>(float &); + virtual Archive &operator>>(double &); + virtual Archive &operator>>(long double &); + + virtual Archive &operator&&(bool &); + virtual Archive &operator&&(int8_t &); + virtual Archive &operator&&(int16_t &); + virtual Archive &operator&&(int32_t &); + virtual Archive &operator&&(int64_t &); + virtual Archive &operator&&(uint8_t &); + virtual Archive &operator&&(uint16_t &); + virtual Archive &operator&&(uint32_t &); + virtual Archive &operator&&(uint64_t &); + virtual Archive &operator&&(float &); + virtual Archive &operator&&(double &); + virtual Archive &operator&&(long double &); + }; + + Archive &operator<<(Archive &, class Bu::Archable &); + Archive &operator>>(Archive &, class Bu::Archable &); + //Archive &operator&&(Archive &s, class Bu::Archable &p); + + Archive &operator<<(Archive &, std::string &); + Archive &operator>>(Archive &, std::string &); + //Archive &operator&&(Archive &, std::string &); + + template Archive &operator&&( Archive &ar, T &dat ) + { + if( ar.isLoading() ) + { + return ar >> dat; + } + else + { + return ar << dat; + } + } +} + +#endif diff --git a/src/exceptionbase.cpp b/src/exceptionbase.cpp new file mode 100644 index 0000000..f6ec625 --- /dev/null +++ b/src/exceptionbase.cpp @@ -0,0 +1,70 @@ +#include "exceptionbase.h" +#include + +Bu::ExceptionBase::ExceptionBase( const char *lpFormat, ... ) throw() : + nErrorCode( 0 ), + sWhat( NULL ) +{ + va_list ap; + + va_start(ap, lpFormat); + setWhat( lpFormat, ap ); + va_end(ap); +} + +Bu::ExceptionBase::ExceptionBase( int nCode, const char *lpFormat, ... ) throw() : + nErrorCode( nCode ), + sWhat( NULL ) +{ + va_list ap; + + va_start(ap, lpFormat); + setWhat( lpFormat, ap ); + va_end(ap); +} + +Bu::ExceptionBase::ExceptionBase( int nCode ) throw() : + nErrorCode( nCode ), + sWhat( NULL ) +{ +} + +Bu::ExceptionBase::~ExceptionBase() throw() +{ + if( sWhat ) + { + delete[] sWhat; + sWhat = NULL; + } +} + +void Bu::ExceptionBase::setWhat( const char *lpFormat, va_list &vargs ) +{ + if( sWhat ) delete[] sWhat; + int nSize; + + nSize = vsnprintf( NULL, 0, lpFormat, vargs ); + sWhat = new char[nSize+1]; + vsnprintf( sWhat, nSize+1, lpFormat, vargs ); +} + +void Bu::ExceptionBase::setWhat( const char *lpText ) +{ + if( sWhat ) delete[] sWhat; + int nSize; + + nSize = strlen( lpText ); + sWhat = new char[nSize+1]; + strcpy( sWhat, lpText ); +} + +const char *Bu::ExceptionBase::what() const throw() +{ + return sWhat; +} + +int Bu::ExceptionBase::getErrorCode() +{ + return nErrorCode; +} + diff --git a/src/exceptionbase.h b/src/exceptionbase.h new file mode 100644 index 0000000..fd78089 --- /dev/null +++ b/src/exceptionbase.h @@ -0,0 +1,114 @@ +#ifndef EXCEPTION_BASE_H +#define EXCEPTION_BASE_H + +#include +#include +#include + +namespace Bu +{ + /** + * A generalized Exception base class. This is nice for making general and + * flexible child classes that can create new error code classes. + * + * In order to create your own exception class use these two lines. + * + * in your header: subExceptionDecl( NewClassName ); + * + * in your source: subExcpetienDef( NewClassName ); + */ + class ExceptionBase : public std::exception + { + public: + /** + * Construct an exception with an error code of zero, but with a + * description. The use of this is not reccomended most of the time, + * it's generally best to include an error code with the exception so + * your program can handle the exception in a better way. + * @param sFormat The format of the text. See printf for more info. + */ + ExceptionBase( const char *sFormat, ... ) throw(); + + /** + * + * @param nCode + * @param sFormat + */ + ExceptionBase( int nCode, const char *sFormat, ... ) throw(); + + /** + * + * @param nCode + * @return + */ + ExceptionBase( int nCode=0 ) throw(); + + /** + * + * @return + */ + virtual ~ExceptionBase() throw(); + + /** + * + * @return + */ + virtual const char *what() const throw(); + + /** + * + * @return + */ + int getErrorCode(); + + /** + * + * @param lpFormat + * @param vargs + */ + void setWhat( const char *lpFormat, va_list &vargs ); + + /** + * + * @param lpText + */ + void setWhat( const char *lpText ); + + private: + int nErrorCode; /**< The code for the error that occured. */ + char *sWhat; /**< The text string telling people what went wrong. */ + }; +} + +#define subExceptionDecl( name ) \ +class name : public ExceptionBase \ +{ \ + public: \ + name( const char *sFormat, ... ) throw (); \ + name( int nCode, const char *sFormat, ... ) throw(); \ + name( int nCode=0 ) throw (); \ +}; + +#define subExceptionDef( name ) \ +name::name( const char *lpFormat, ... ) throw() : \ + ExceptionBase( 0 ) \ +{ \ + va_list ap; \ + va_start( ap, lpFormat ); \ + setWhat( lpFormat, ap ); \ + va_end( ap ); \ +} \ +name::name( int nCode, const char *lpFormat, ... ) throw() : \ + ExceptionBase( nCode ) \ +{ \ + va_list ap; \ + va_start( ap, lpFormat ); \ + setWhat( lpFormat, ap ); \ + va_end( ap ); \ +} \ +name::name( int nCode ) throw() : \ + ExceptionBase( nCode ) \ +{ \ +} + +#endif diff --git a/src/exceptions.cpp b/src/exceptions.cpp new file mode 100644 index 0000000..37f09a4 --- /dev/null +++ b/src/exceptions.cpp @@ -0,0 +1,10 @@ +#include "exceptions.h" +#include + +namespace Bu +{ + subExceptionDef( XmlException ) + subExceptionDef( FileException ) + subExceptionDef( ConnectionException ) + subExceptionDef( PluginException ) +} diff --git a/src/exceptions.h b/src/exceptions.h new file mode 100644 index 0000000..b28d292 --- /dev/null +++ b/src/exceptions.h @@ -0,0 +1,28 @@ +#ifndef EXCEPTIONS_H +#define EXCEPTIONS_H + +#include "exceptionbase.h" +#include + +namespace Bu +{ + subExceptionDecl( XmlException ) + subExceptionDecl( FileException ) + subExceptionDecl( ConnectionException ) + subExceptionDecl( PluginException ) + + enum eFileException + { + excodeEOF + }; + + enum eConnectionException + { + excodeReadError, + excodeBadReadError, + excodeConnectionClosed, + excodeSocketTimeout + }; +} + +#endif diff --git a/src/fstring.cpp b/src/fstring.cpp new file mode 100644 index 0000000..56d2173 --- /dev/null +++ b/src/fstring.cpp @@ -0,0 +1,14 @@ +#include "fstring.h" +#include "hash.h" + +template<> uint32_t Bu::__calcHashCode( const Bu::FString &k ) +{ + return __calcHashCode( k.c_str() ); +} + +template<> bool Bu::__cmpHashKeys( + const Bu::FString &a, const Bu::FString &b ) +{ + return a == b; +} + diff --git a/src/fstring.h b/src/fstring.h new file mode 100644 index 0000000..717068f --- /dev/null +++ b/src/fstring.h @@ -0,0 +1,653 @@ +#ifndef F_STRING_H +#define F_STRING_H + +#include +#include +#include "archable.h" +#include "archive.h" +#include "hash.h" + +namespace Bu +{ + template< typename chr > + struct FStringChunk + { + long nLength; + chr *pData; + FStringChunk *pNext; + }; + + /** + * Flexible String class. This class was designed with string passing and + * generation in mind. Like the standard string class you can specify what + * datatype to use for each character. Unlike the standard string class, + * collection of appended and prepended terms is done lazily, making long + * operations that involve many appends very inexpensive. In addition internal + * ref-counting means that if you pass strings around between functions there's + * almost no overhead in time or memory since a reference is created and no + * data is actually copied. This also means that you never need to put any + * FBasicString into a ref-counting container class. + */ + template< typename chr, typename chralloc=std::allocator, typename chunkalloc=std::allocator > > + class FBasicString : public Archable + { +#ifndef VALTEST +#define cpy( dest, src, size ) memcpy( dest, src, size*sizeof(chr) ) +#endif + private: + typedef struct FStringChunk Chunk; + typedef struct FBasicString MyType; + + public: + FBasicString() : + nLength( 0 ), + pnRefs( NULL ), + pFirst( NULL ), + pLast( NULL ) + { + } + + FBasicString( const chr *pData ) : + nLength( 0 ), + pnRefs( NULL ), + pFirst( NULL ), + pLast( NULL ) + { + append( pData ); + } + + FBasicString( const chr *pData, long nLength ) : + nLength( 0 ), + pnRefs( NULL ), + pFirst( NULL ), + pLast( NULL ) + { + append( pData, nLength ); + } + + FBasicString( const MyType &rSrc ) : + nLength( 0 ), + pnRefs( NULL ), + pFirst( NULL ), + pLast( NULL ) + { + // Here we have no choice but to copy, since the other guy is a const. + // In the case that the source were flat, we could get a reference, it + // would make some things faster, but not matter in many other cases. + + joinShare( rSrc ); + //copyFrom( rSrc ); + } + + FBasicString( const MyType &rSrc, long nLength ) : + nLength( 0 ), + pnRefs( NULL ), + pFirst( NULL ), + pLast( NULL ) + { + append( rSrc.pFirst->pData, nLength ); + } + + FBasicString( const MyType &rSrc, long nStart, long nLength ) : + nLength( 0 ), + pnRefs( NULL ), + pFirst( NULL ), + pLast( NULL ) + { + append( rSrc.pFirst->pData+nStart, nLength ); + } + + FBasicString( long nSize ) : + nLength( nSize ), + pnRefs( NULL ), + pFirst( NULL ), + pLast( NULL ) + { + pFirst = pLast = newChunk( nSize ); + } + + virtual ~FBasicString() + { + clear(); + } + + void append( const chr *pData ) + { + long nLen; + for( nLen = 0; pData[nLen] != (chr)0; nLen++ ); + + Chunk *pNew = newChunk( nLen ); + cpy( pNew->pData, pData, nLen ); + + appendChunk( pNew ); + } + + void append( const chr *pData, long nLen ) + { + Chunk *pNew = newChunk( nLen ); + + cpy( pNew->pData, pData, nLen ); + + appendChunk( pNew ); + } + + void prepend( const chr *pData ) + { + long nLen; + for( nLen = 0; pData[nLen] != (chr)0; nLen++ ); + + Chunk *pNew = newChunk( nLen ); + cpy( pNew->pData, pData, nLen ); + + prependChunk( pNew ); + } + + void prepend( const chr *pData, long nLen ) + { + Chunk *pNew = newChunk( nLen ); + + cpy( pNew->pData, pData, nLen ); + + prependChunk( pNew ); + } + + void clear() + { + realClear(); + } + + void resize( long nNewSize ) + { + if( nLength == nNewSize ) + return; + + flatten(); + + Chunk *pNew = newChunk( nNewSize ); + long nNewLen = (nNewSizepData, pFirst->pData, nNewLen ); + pNew->pData[nNewLen] = (chr)0; + aChr.deallocate( pFirst->pData, pFirst->nLength+1 ); + aChunk.deallocate( pFirst, 1 ); + pFirst = pLast = pNew; + nLength = nNewSize; + } + + long getSize() const + { + return nLength; + } + + chr *getStr() + { + if( pFirst == NULL ) + return NULL; + + flatten(); + return pFirst->pData; + } + + const chr *getStr() const + { + if( pFirst == NULL ) + return NULL; + + flatten(); + return pFirst->pData; + } + + chr *c_str() + { + if( pFirst == NULL ) + return NULL; + + flatten(); + return pFirst->pData; + } + + const chr *c_str() const + { + if( pFirst == NULL ) + return NULL; + + flatten(); + return pFirst->pData; + } + + MyType &operator +=( const chr *pData ) + { + append( pData ); + + return (*this); + } + + MyType &operator +=( const MyType &rSrc ) + { + rSrc.flatten(); + append( rSrc.pFirst->pData, rSrc.nLength ); + + return (*this); + } + + MyType &operator +=( const chr pData ) + { + chr tmp[2] = { pData, (chr)0 }; + append( tmp ); + + return (*this); + } + + MyType &operator =( const chr *pData ) + { + clear(); + append( pData ); + + return (*this); + } + + MyType &operator =( const MyType &rSrc ) + { + //if( rSrc.isFlat() ) + //{ + joinShare( rSrc ); + //} + //else + //{ + // copyFrom( rSrc ); + //} + // + + return (*this); + } + + bool operator ==( const chr *pData ) const + { + if( pFirst == NULL ) { + if( pData == NULL ) + return true; + return false; + } + + flatten(); + const chr *a = pData; + chr *b = pFirst->pData; + for( ; *a!=(chr)0; a++, b++ ) + { + if( *a != *b ) + return false; + } + + return true; + } + + bool operator ==( const MyType &pData ) const + { + if( pFirst == pData.pFirst ) + return true; + if( pFirst == NULL ) + return false; + + flatten(); + pData.flatten(); + const chr *a = pData.pFirst->pData; + chr *b = pFirst->pData; + for( ; *a!=(chr)0; a++, b++ ) + { + if( *a != *b ) + return false; + } + + return true; + } + + bool operator !=(const chr *pData ) const + { + return !(*this == pData); + } + + bool operator !=(const MyType &pData ) const + { + return !(*this == pData); + } + + chr &operator[]( long nIndex ) + { + flatten(); + + return pFirst->pData[nIndex]; + } + + const chr &operator[]( long nIndex ) const + { + flatten(); + + return pFirst->pData[nIndex]; + } + + bool isWS( long nIndex ) const + { + flatten(); + + return pFirst->pData[nIndex]==' ' || pFirst->pData[nIndex]=='\t' + || pFirst->pData[nIndex]=='\r' || pFirst->pData[nIndex]=='\n'; + } + + bool isAlpha( long nIndex ) const + { + flatten(); + + return (pFirst->pData[nIndex] >= 'a' && pFirst->pData[nIndex] <= 'z') + || (pFirst->pData[nIndex] >= 'A' && pFirst->pData[nIndex] <= 'Z'); + } + + void toLower() + { + flatten(); + unShare(); + + for( long j = 0; j < nLength; j++ ) + { + if( pFirst->pData[j] >= 'A' && pFirst->pData[j] <= 'Z' ) + pFirst->pData[j] -= 'A'-'a'; + } + } + + void toUpper() + { + flatten(); + unShare(); + + for( long j = 0; j < nLength; j++ ) + { + if( pFirst->pData[j] >= 'a' && pFirst->pData[j] <= 'z' ) + pFirst->pData[j] += 'A'-'a'; + } + } + + void archive( class Archive &ar ) + { + if( ar.isLoading() ) + { + clear(); + long nLen; + ar >> nLen; + + Chunk *pNew = newChunk( nLen ); + ar.read( pNew->pData, nLen*sizeof(chr) ); + appendChunk( pNew ); + } + else + { + flatten(); + + ar << nLength; + ar.write( pFirst->pData, nLength*sizeof(chr) ); + } + } + + private: + void flatten() const + { + if( isFlat() ) + return; + + if( pFirst == NULL ) + return; + + unShare(); + + Chunk *pNew = newChunk( nLength ); + chr *pos = pNew->pData; + Chunk *i = pFirst; + for(;;) + { + cpy( pos, i->pData, i->nLength ); + pos += i->nLength; + i = i->pNext; + if( i == NULL ) + break; + } + realClear(); + + pLast = pFirst = pNew; + nLength = pNew->nLength; + } + + void realClear() const + { + if( pFirst == NULL ) + return; + + if( isShared() ) + { + decRefs(); + } + else + { + Chunk *i = pFirst; + for(;;) + { + Chunk *n = i->pNext; + aChr.deallocate( i->pData, i->nLength+1 ); + aChunk.deallocate( i, 1 ); + if( n == NULL ) + break; + i = n; + } + pFirst = pLast = NULL; + nLength = 0; + } + } + + void copyFrom( const FBasicString &rSrc ) + { + if( rSrc.pFirst == NULL ) + return; + + decRefs(); + + Chunk *pNew = newChunk( rSrc.nLength ); + chr *pos = pNew->pData; + Chunk *i = rSrc.pFirst; + for(;;) + { + cpy( pos, i->pData, i->nLength ); + pos += i->nLength; + i = i->pNext; + if( i == NULL ) + break; + } + clear(); + + appendChunk( pNew ); + } + + bool isFlat() const + { + return (pFirst == pLast); + } + + bool isShared() const + { + return (pnRefs != NULL); + } + + Chunk *newChunk() const + { + Chunk *pNew = aChunk.allocate( 1 ); + pNew->pNext = NULL; + return pNew; + } + + Chunk *newChunk( long nLen ) const + { + Chunk *pNew = aChunk.allocate( 1 ); + pNew->pNext = NULL; + pNew->nLength = nLen; + pNew->pData = aChr.allocate( nLen+1 ); + pNew->pData[nLen] = (chr)0; + return pNew; + } + + void appendChunk( Chunk *pNewChunk ) + { + unShare(); + + if( pFirst == NULL ) + pLast = pFirst = pNewChunk; + else + { + pLast->pNext = pNewChunk; + pLast = pNewChunk; + } + + nLength += pNewChunk->nLength; + } + + void prependChunk( Chunk *pNewChunk ) + { + unShare(); + + if( pFirst == NULL ) + pLast = pFirst = pNewChunk; + else + { + pNewChunk->pNext = pFirst; + pFirst = pNewChunk; + } + + nLength += pNewChunk->nLength; + } + + void joinShare( MyType &rSrc ) + { + clear(); + + if( !rSrc.isFlat() ) + rSrc.flatten(); + + rSrc.initCount(); + pnRefs = rSrc.pnRefs; + (*pnRefs)++; + nLength = rSrc.nLength; + pFirst = rSrc.pFirst; + pLast = rSrc.pLast; + } + + void joinShare( const MyType &rSrc ) + { + clear(); + + rSrc.flatten(); + + if( !rSrc.isShared() ) + { + rSrc.pnRefs = new uint32_t; + (*rSrc.pnRefs) = 1; + } + pnRefs = rSrc.pnRefs; + (*pnRefs)++; + nLength = rSrc.nLength; + pFirst = rSrc.pFirst; + pLast = rSrc.pLast; + } + + /** + * This takes an object that was shared and makes a copy of the base data + * that was being shared so that this copy can be changed. This should be + * added before any call that will change this object; + */ + void unShare() const + { + if( isShared() == false ) + return; + + Chunk *pNew = newChunk( nLength ); + chr *pos = pNew->pData; + Chunk *i = pFirst; + for(;;) + { + cpy( pos, i->pData, i->nLength ); + pos += i->nLength; + i = i->pNext; + if( i == NULL ) + break; + } + decRefs(); + pLast = pFirst = pNew; + nLength = pNew->nLength; + } + + /** + * This decrements our ref count and pulls us out of the share. If the ref + * count hits zero because of this, it destroys the share. This is not + * safe to call on it's own, it's much better to call unShare. + */ + void decRefs() const + { + if( isShared() ) + { + (*pnRefs)--; + if( (*pnRefs) == 0 ) + destroyShare(); + else + { + pnRefs = NULL; + pFirst = NULL; + pLast = NULL; + nLength = 0; + } + } + } + + /** + * While the unShare function removes an instance from a share, this + * function destroys the data that was in the share, removing the share + * itself. This should only be called when the refcount for the share has + * or is about to reach zero. + */ + void destroyShare() const + { + delete pnRefs; + pnRefs = NULL; + realClear(); + } + +#ifdef VALTEST + void cpy( chr *dest, const chr *src, long count ) const + { + for( int j = 0; j < count; j++ ) + { + *dest = *src; + dest++; + src++; + } + } +#endif + + void initCount() const + { + if( !isShared() ) + { + pnRefs = new uint32_t; + (*pnRefs) = 1; + } + } + + private: + mutable long nLength; + mutable uint32_t *pnRefs; + mutable Chunk *pFirst; + mutable Chunk *pLast; + + mutable chralloc aChr; + mutable chunkalloc aChunk; + }; + + typedef FBasicString FString; + + template<> uint32_t __calcHashCode( const FString &k ); + template<> bool __cmpHashKeys( const FString &a, const FString &b ); +} + +#endif diff --git a/src/hash.cpp b/src/hash.cpp new file mode 100644 index 0000000..a207c29 --- /dev/null +++ b/src/hash.cpp @@ -0,0 +1,101 @@ +#include "hash.h" + +namespace Bu { subExceptionDef( HashException ) } + +template<> uint32_t Bu::__calcHashCode( const int &k ) +{ + return k; +} + +template<> bool Bu::__cmpHashKeys( const int &a, const int &b ) +{ + return a == b; +} + +template<> uint32_t Bu::__calcHashCode( const unsigned int &k ) +{ + return k; +} + +template<> bool Bu::__cmpHashKeys( const unsigned int &a, const unsigned int &b ) +{ + return a == b; +} + +template<> +uint32_t Bu::__calcHashCode( const char * const &k ) +{ + if (k == NULL) + { + return 0; + } + + unsigned long int nPos = 0; + for( const char *s = k; *s; s++ ) + { + nPos = *s + (nPos << 6) + (nPos << 16) - nPos; + } + + return nPos; +} + +template<> bool Bu::__cmpHashKeys( const char * const &a, const char * const &b ) +{ + if( a == b ) + return true; + + for(int j=0; a[j] == b[j]; j++ ) + if( a[j] == '\0' ) + return true; + + return false; +} + +template<> +uint32_t Bu::__calcHashCode( char * const &k ) +{ + if (k == NULL) + { + return 0; + } + + unsigned long int nPos = 0; + for( const char *s = k; *s; s++ ) + { + nPos = *s + (nPos << 6) + (nPos << 16) - nPos; + } + + return nPos; +} + +template<> bool Bu::__cmpHashKeys( char * const &a, char * const &b ) +{ + if( a == b ) + return true; + + for(int j=0; a[j] == b[j]; j++ ) + if( a[j] == '\0' ) + return true; + + return false; +} + +template<> uint32_t Bu::__calcHashCode( const std::string &k ) +{ + std::string::size_type j, sz = k.size(); + const char *s = k.c_str(); + + unsigned long int nPos = 0; + for( j = 0; j < sz; j++, s++ ) + { + nPos = *s + (nPos << 6) + (nPos << 16) - nPos; + } + + return nPos; +} + +template<> bool Bu::__cmpHashKeys( const std::string &a, const std::string &b ) +{ + return a == b; +} + diff --git a/src/hash.h b/src/hash.h new file mode 100644 index 0000000..9e498f1 --- /dev/null +++ b/src/hash.h @@ -0,0 +1,745 @@ +#ifndef HASH_H +#define HASH_H + +#include +#include +#include +#include +#include +#include +#include "exceptionbase.h" +#include "archable.h" +#include "archive.h" + +#define bitsToBytes( n ) (n/32+(n%32>0 ? 1 : 0)) + +namespace Bu +{ + subExceptionDecl( HashException ) + + enum eHashException + { + excodeNotFilled + }; + + template + uint32_t __calcHashCode( const T &k ); + + template + bool __cmpHashKeys( const T &a, const T &b ); + + struct __calcNextTSize_fast + { + uint32_t operator()( uint32_t nCapacity, uint32_t nFill, uint32_t nDeleted ) const + { + if( nDeleted >= nCapacity/2 ) + return nCapacity; + return nCapacity*2+1; + } + }; + + template, typename valuealloc = std::allocator, typename challoc = std::allocator > + class Hash; + + template< typename key, typename _value, typename sizecalc = __calcNextTSize_fast, typename keyalloc = std::allocator, typename valuealloc = std::allocator<_value>, typename challoc = std::allocator > + struct HashProxy + { + friend class Hash; + private: + HashProxy( Hash &h, key *k, uint32_t nPos, uint32_t hash ) : + hsh( h ), + pKey( k ), + nPos( nPos ), + hash( hash ), + bFilled( false ) + { + } + + HashProxy( Hash &h, uint32_t nPos, _value *pValue ) : + hsh( h ), + nPos( nPos ), + pValue( pValue ), + bFilled( true ) + { + } + + Hash &hsh; + key *pKey; + uint32_t nPos; + _value *pValue; + uint32_t hash; + bool bFilled; + + public: + operator _value &() + { + if( bFilled == false ) + throw HashException( + excodeNotFilled, + "No data assosiated with that key." + ); + return *pValue; + } + + _value &value() + { + if( bFilled == false ) + throw HashException( + excodeNotFilled, + "No data assosiated with that key." + ); + return *pValue; + } + + bool isFilled() + { + return bFilled; + } + + void erase() + { + if( bFilled ) + { + hsh._erase( nPos ); + hsh.onDelete(); + } + } + + _value operator=( _value nval ) + { + if( bFilled ) + { + hsh.va.destroy( pValue ); + hsh.va.construct( pValue, nval ); + hsh.onUpdate(); + } + else + { + hsh.fill( nPos, *pKey, nval, hash ); + hsh.onInsert(); + } + + return nval; + } + + _value *operator->() + { + if( bFilled == false ) + throw HashException( + excodeNotFilled, + "No data assosiated with that key." + ); + return pValue; + } + }; + + template + class Hash + { + friend struct HashProxy; + public: + Hash() : + nCapacity( 11 ), + nFilled( 0 ), + nDeleted( 0 ), + bFilled( NULL ), + bDeleted( NULL ), + aKeys( NULL ), + aValues( NULL ), + aHashCodes( NULL ) + { + nKeysSize = bitsToBytes( nCapacity ); + bFilled = ca.allocate( nKeysSize ); + bDeleted = ca.allocate( nKeysSize ); + clearBits(); + + aHashCodes = ca.allocate( nCapacity ); + aKeys = ka.allocate( nCapacity ); + aValues = va.allocate( nCapacity ); + } + + Hash( const Hash &src ) : + nCapacity( src.nCapacity ), + nFilled( 0 ), + nDeleted( 0 ), + bFilled( NULL ), + bDeleted( NULL ), + aKeys( NULL ), + aValues( NULL ), + aHashCodes( NULL ) + { + nKeysSize = bitsToBytes( nCapacity ); + bFilled = ca.allocate( nKeysSize ); + bDeleted = ca.allocate( nKeysSize ); + clearBits(); + + aHashCodes = ca.allocate( nCapacity ); + aKeys = ka.allocate( nCapacity ); + aValues = va.allocate( nCapacity ); + + for( uint32_t j = 0; j < src.nCapacity; j++ ) + { + if( src.isFilled( j ) ) + { + insert( src.aKeys[j], src.aValues[j] ); + } + } + } + + Hash &operator=( const Hash &src ) + { + for( uint32_t j = 0; j < nCapacity; j++ ) + { + if( isFilled( j ) ) + if( !isDeleted( j ) ) + { + va.destroy( &aValues[j] ); + ka.destroy( &aKeys[j] ); + } + } + va.deallocate( aValues, nCapacity ); + ka.deallocate( aKeys, nCapacity ); + ca.deallocate( bFilled, nKeysSize ); + ca.deallocate( bDeleted, nKeysSize ); + ca.deallocate( aHashCodes, nCapacity ); + + nFilled = 0; + nDeleted = 0; + nCapacity = src.nCapacity; + nKeysSize = bitsToBytes( nCapacity ); + bFilled = ca.allocate( nKeysSize ); + bDeleted = ca.allocate( nKeysSize ); + clearBits(); + + aHashCodes = ca.allocate( nCapacity ); + aKeys = ka.allocate( nCapacity ); + aValues = va.allocate( nCapacity ); + + for( uint32_t j = 0; j < src.nCapacity; j++ ) + { + if( src.isFilled( j ) ) + { + insert( src.aKeys[j], src.aValues[j] ); + } + } + + return *this; + } + + virtual ~Hash() + { + for( uint32_t j = 0; j < nCapacity; j++ ) + { + if( isFilled( j ) ) + if( !isDeleted( j ) ) + { + va.destroy( &aValues[j] ); + ka.destroy( &aKeys[j] ); + } + } + va.deallocate( aValues, nCapacity ); + ka.deallocate( aKeys, nCapacity ); + ca.deallocate( bFilled, nKeysSize ); + ca.deallocate( bDeleted, nKeysSize ); + ca.deallocate( aHashCodes, nCapacity ); + } + + uint32_t getCapacity() + { + return nCapacity; + } + + uint32_t getFill() + { + return nFilled; + } + + uint32_t size() + { + return nFilled-nDeleted; + } + + uint32_t getDeleted() + { + return nDeleted; + } + + virtual HashProxy operator[]( key k ) + { + uint32_t hash = __calcHashCode( k ); + bool bFill; + uint32_t nPos = probe( hash, k, bFill ); + + if( bFill ) + { + return HashProxy( *this, nPos, &aValues[nPos] ); + } + else + { + return HashProxy( *this, &k, nPos, hash ); + } + } + + virtual void insert( key k, value v ) + { + uint32_t hash = __calcHashCode( k ); + bool bFill; + uint32_t nPos = probe( hash, k, bFill ); + + if( bFill ) + { + va.destroy( &aValues[nPos] ); + va.construct( &aValues[nPos], v ); + onUpdate(); + } + else + { + fill( nPos, k, v, hash ); + onInsert(); + } + } + + virtual void erase( key k ) + { + uint32_t hash = __calcHashCode( k ); + bool bFill; + uint32_t nPos = probe( hash, k, bFill ); + + if( bFill ) + { + _erase( nPos ); + onDelete(); + } + } + + struct iterator; + virtual void erase( struct iterator &i ) + { + if( this != &i.hsh ) + throw HashException("This iterator didn't come from this Hash."); + if( isFilled( i.nPos ) && !isDeleted( i.nPos ) ) + { + _erase( i.nPos ); + onDelete(); + } + } + + virtual void clear() + { + for( uint32_t j = 0; j < nCapacity; j++ ) + { + if( isFilled( j ) ) + if( !isDeleted( j ) ) + { + va.destroy( &aValues[j] ); + ka.destroy( &aKeys[j] ); + onDelete(); + } + } + + clearBits(); + } + + virtual value &get( key k ) + { + uint32_t hash = __calcHashCode( k ); + bool bFill; + uint32_t nPos = probe( hash, k, bFill ); + + if( bFill ) + { + return aValues[nPos]; + } + else + { + throw HashException( + excodeNotFilled, + "No data assosiated with that key." + ); + } + } + + virtual bool has( key k ) + { + bool bFill; + probe( __calcHashCode( k ), k, bFill, false ); + + return bFill; + } + + typedef struct iterator + { + friend class Hash; + private: + iterator( Hash &hsh ) : + hsh( hsh ), + nPos( 0 ), + bFinished( false ) + { + nPos = hsh.getFirstPos( bFinished ); + } + + iterator( Hash &hsh, bool bDone ) : + hsh( hsh ), + nPos( 0 ), + bFinished( bDone ) + { + } + + Hash &hsh; + uint32_t nPos; + bool bFinished; + + public: + iterator operator++( int ) + { + if( bFinished == false ) + nPos = hsh.getNextPos( nPos, bFinished ); + + return *this; + } + + iterator operator++() + { + if( bFinished == false ) + nPos = hsh.getNextPos( nPos, bFinished ); + + return *this; + } + + bool operator==( const iterator &oth ) + { + if( bFinished != oth.bFinished ) + return false; + if( bFinished == true ) + { + return true; + } + else + { + if( oth.nPos == nPos ) + return true; + return false; + } + } + + bool operator!=( const iterator &oth ) + { + return !(*this == oth ); + } + + iterator operator=( const iterator &oth ) + { + if( &hsh != &oth.hsh ) + throw HashException( + "Cannot mix iterators from different hash objects."); + nPos = oth.nPos; + bFinished = oth.bFinished; + } + + std::pair operator *() + { + return hsh.getAtPos( nPos ); + } + + key &getKey() + { + return hsh.getKeyAtPos( nPos ); + } + + value &getValue() + { + return hsh.getValueAtPos( nPos ); + } + }; + + iterator begin() + { + return iterator( *this ); + } + + iterator end() + { + return iterator( *this, true ); + } + + std::list getKeys() + { + std::list lKeys; + + for( uint32_t j = 0; j < nCapacity; j++ ) + { + if( isFilled( j ) ) + { + if( !isDeleted( j ) ) + { + lKeys.push_back( aKeys[j] ); + } + } + } + + return lKeys; + } + + protected: + virtual void onInsert() {} + virtual void onUpdate() {} + virtual void onDelete() {} + virtual void onReHash() {} + + virtual void clearBits() + { + for( uint32_t j = 0; j < nKeysSize; j++ ) + { + bFilled[j] = bDeleted[j] = 0; + } + } + + virtual void fill( uint32_t loc, key &k, value &v, uint32_t hash ) + { + bFilled[loc/32] |= (1<<(loc%32)); + va.construct( &aValues[loc], v ); + ka.construct( &aKeys[loc], k ); + aHashCodes[loc] = hash; + nFilled++; + //printf("Filled: %d, Deleted: %d, Capacity: %d\n", + // nFilled, nDeleted, nCapacity ); + } + + virtual void _erase( uint32_t loc ) + { + bDeleted[loc/32] |= (1<<(loc%32)); + va.destroy( &aValues[loc] ); + ka.destroy( &aKeys[loc] ); + nDeleted++; + //printf("Filled: %d, Deleted: %d, Capacity: %d\n", + // nFilled, nDeleted, nCapacity ); + } + + virtual std::pair getAtPos( uint32_t nPos ) + { + return std::pair(aKeys[nPos],aValues[nPos]); + } + + virtual key &getKeyAtPos( uint32_t nPos ) + { + return aKeys[nPos]; + } + + virtual value &getValueAtPos( uint32_t nPos ) + { + return aValues[nPos]; + } + + virtual uint32_t getFirstPos( bool &bFinished ) + { + for( uint32_t j = 0; j < nCapacity; j++ ) + { + if( isFilled( j ) ) + if( !isDeleted( j ) ) + return j; + } + + bFinished = true; + return 0; + } + + virtual uint32_t getNextPos( uint32_t nPos, bool &bFinished ) + { + for( uint32_t j = nPos+1; j < nCapacity; j++ ) + { + if( isFilled( j ) ) + if( !isDeleted( j ) ) + return j; + } + + bFinished = true; + return 0; + } + + uint32_t probe( uint32_t hash, key k, bool &bFill, bool rehash=true ) + { + uint32_t nCur = hash%nCapacity; + + // First we scan to see if the key is already there, abort if we + // run out of probing room, or we find a non-filled entry + for( int8_t j = 0; + isFilled( nCur ) && j < 32; + nCur = (nCur + (1< uint32_t __calcHashCode( const int &k ); + template<> bool __cmpHashKeys( const int &a, const int &b ); + + template<> uint32_t __calcHashCode( const unsigned int &k ); + template<> bool __cmpHashKeys( const unsigned int &a, const unsigned int &b ); + + template<> uint32_t __calcHashCode( const char * const &k ); + template<> bool __cmpHashKeys( const char * const &a, const char * const &b ); + + template<> uint32_t __calcHashCode( char * const &k ); + template<> bool __cmpHashKeys( char * const &a, char * const &b ); + + template<> uint32_t __calcHashCode( const std::string &k ); + template<> bool __cmpHashKeys( const std::string &a, const std::string &b ); + + template + Archive &operator<<( Archive &ar, Hash &h ) + { + ar << h.size(); + for( typename Hash::iterator i = h.begin(); i != h.end(); i++ ) + { + std::pair p = *i; + ar << p.first << p.second; + } + + return ar; + } + + template + Archive &operator>>( Archive &ar, Hash &h ) + { + h.clear(); + uint32_t nSize; + ar >> nSize; + + for( uint32_t j = 0; j < nSize; j++ ) + { + key k; value v; + ar >> k >> v; + h.insert( k, v ); + } + + return ar; + } + + /* + template + Serializer &operator&&( Serializer &ar, Hash &h ) + { + if( ar.isLoading() ) + { + return ar >> h; + } + else + { + return ar << h; + } + }*/ +} + +#endif diff --git a/src/old/exceptionbase.cpp b/src/old/exceptionbase.cpp deleted file mode 100644 index f3d22da..0000000 --- a/src/old/exceptionbase.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include "exceptionbase.h" -#include - -ExceptionBase::ExceptionBase( const char *lpFormat, ... ) throw() : - nErrorCode( 0 ), - sWhat( NULL ) -{ - va_list ap; - - va_start(ap, lpFormat); - setWhat( lpFormat, ap ); - va_end(ap); -} - -ExceptionBase::ExceptionBase( int nCode, const char *lpFormat, ... ) throw() : - nErrorCode( nCode ), - sWhat( NULL ) -{ - va_list ap; - - va_start(ap, lpFormat); - setWhat( lpFormat, ap ); - va_end(ap); -} - -ExceptionBase::ExceptionBase( int nCode ) throw() : - nErrorCode( nCode ), - sWhat( NULL ) -{ -} - -ExceptionBase::~ExceptionBase() throw() -{ - if( sWhat ) - { - delete[] sWhat; - sWhat = NULL; - } -} - -void ExceptionBase::setWhat( const char *lpFormat, va_list &vargs ) -{ - if( sWhat ) delete[] sWhat; - int nSize; - - nSize = vsnprintf( NULL, 0, lpFormat, vargs ); - sWhat = new char[nSize+1]; - vsnprintf( sWhat, nSize+1, lpFormat, vargs ); -} - -void ExceptionBase::setWhat( const char *lpText ) -{ - if( sWhat ) delete[] sWhat; - int nSize; - - nSize = strlen( lpText ); - sWhat = new char[nSize+1]; - strcpy( sWhat, lpText ); -} - -const char *ExceptionBase::what() const throw() -{ - return sWhat; -} - -int ExceptionBase::getErrorCode() -{ - return nErrorCode; -} - diff --git a/src/old/exceptionbase.h b/src/old/exceptionbase.h deleted file mode 100644 index 6f1eca7..0000000 --- a/src/old/exceptionbase.h +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef EXCEPTION_BASE_H -#define EXCEPTION_BASE_H - -#include -#include -#include - -/** - * A generalized Exception base class. This is nice for making general and - * flexible child classes that can create new error code classes. - */ -class ExceptionBase : public std::exception -{ -public: - /** - * Construct an exception with an error code of zero, but with a - * description. The use of this is not reccomended most of the time, it's - * generally best to include an error code with the exception so your - * program can handle the exception in a better way. - * @param sFormat The format of the text. See printf for more info. - */ - ExceptionBase( const char *sFormat, ... ) throw(); - - /** - * - * @param nCode - * @param sFormat - */ - ExceptionBase( int nCode, const char *sFormat, ... ) throw(); - - /** - * - * @param nCode - * @return - */ - ExceptionBase( int nCode=0 ) throw(); - - /** - * - * @return - */ - virtual ~ExceptionBase() throw(); - - /** - * - * @return - */ - virtual const char *what() const throw(); - - /** - * - * @return - */ - int getErrorCode(); - - /** - * - * @param lpFormat - * @param vargs - */ - void setWhat( const char *lpFormat, va_list &vargs ); - - /** - * - * @param lpText - */ - void setWhat( const char *lpText ); - -private: - int nErrorCode; /**< The code for the error that occured. */ - char *sWhat; /**< The text string telling people what went wrong. */ -}; - -#define subExceptionDecl( name ) \ -class name : public ExceptionBase \ -{ \ - public: \ - name( const char *sFormat, ... ) throw (); \ - name( int nCode, const char *sFormat, ... ) throw(); \ - name( int nCode=0 ) throw (); \ -}; - -#define subExceptionDef( name ) \ -name::name( const char *lpFormat, ... ) throw() : \ - ExceptionBase( 0 ) \ -{ \ - va_list ap; \ - va_start( ap, lpFormat ); \ - setWhat( lpFormat, ap ); \ - va_end( ap ); \ -} \ -name::name( int nCode, const char *lpFormat, ... ) throw() : \ - ExceptionBase( nCode ) \ -{ \ - va_list ap; \ - va_start( ap, lpFormat ); \ - setWhat( lpFormat, ap ); \ - va_end( ap ); \ -} \ -name::name( int nCode ) throw() : \ - ExceptionBase( nCode ) \ -{ \ -} - -#endif diff --git a/src/old/exceptions.cpp b/src/old/exceptions.cpp deleted file mode 100644 index ce79a5e..0000000 --- a/src/old/exceptions.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include "exceptions.h" -#include - -subExceptionDef( XmlException ) -subExceptionDef( FileException ) -subExceptionDef( ConnectionException ) -subExceptionDef( PluginException ) - diff --git a/src/old/exceptions.h b/src/old/exceptions.h deleted file mode 100644 index 0ab2b15..0000000 --- a/src/old/exceptions.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef EXCEPTIONS_H -#define EXCEPTIONS_H - -#include "exceptionbase.h" -#include - -subExceptionDecl( XmlException ) -subExceptionDecl( FileException ) -subExceptionDecl( ConnectionException ) -subExceptionDecl( PluginException ) - -enum eFileException -{ - excodeEOF -}; - -enum eConnectionException -{ - excodeReadError, - excodeBadReadError, - excodeConnectionClosed, - excodeSocketTimeout -}; - -#endif diff --git a/src/old/fstring.cpp b/src/old/fstring.cpp deleted file mode 100644 index 82d024d..0000000 --- a/src/old/fstring.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "fstring.h" -#include "hash.h" - -template<> uint32_t __calcHashCode( const FString &k ) -{ - return __calcHashCode( k.c_str() ); -} - -template<> bool __cmpHashKeys( const FString &a, const FString &b ) -{ - return a == b; -} - diff --git a/src/old/fstring.h b/src/old/fstring.h deleted file mode 100644 index c5397cc..0000000 --- a/src/old/fstring.h +++ /dev/null @@ -1,651 +0,0 @@ -#ifndef F_STRING_H -#define F_STRING_H - -#include -#include -#include "serializable.h" -#include "serializer.h" - -template< typename chr > -struct FStringChunk -{ - long nLength; - chr *pData; - FStringChunk *pNext; -}; - -/** - * Flexible String class. This class was designed with string passing and - * generation in mind. Like the standard string class you can specify what - * datatype to use for each character. Unlike the standard string class, - * collection of appended and prepended terms is done lazily, making long - * operations that involve many appends very inexpensive. In addition internal - * ref-counting means that if you pass strings around between functions there's - * almost no overhead in time or memory since a reference is created and no - * data is actually copied. This also means that you never need to put any - * FBasicString into a ref-counting container class. - */ -template< typename chr, typename chralloc=std::allocator, typename chunkalloc=std::allocator > > -class FBasicString : public Serializable -{ -#ifndef VALTEST -#define cpy( dest, src, size ) memcpy( dest, src, size*sizeof(chr) ) -#endif -private: - typedef struct FStringChunk Chunk; - typedef struct FBasicString MyType; - -public: - FBasicString() : - nLength( 0 ), - pnRefs( NULL ), - pFirst( NULL ), - pLast( NULL ) - { - } - - FBasicString( const chr *pData ) : - nLength( 0 ), - pnRefs( NULL ), - pFirst( NULL ), - pLast( NULL ) - { - append( pData ); - } - - FBasicString( const chr *pData, long nLength ) : - nLength( 0 ), - pnRefs( NULL ), - pFirst( NULL ), - pLast( NULL ) - { - append( pData, nLength ); - } - - FBasicString( const MyType &rSrc ) : - nLength( 0 ), - pnRefs( NULL ), - pFirst( NULL ), - pLast( NULL ) - { - // Here we have no choice but to copy, since the other guy is a const. - // In the case that the source were flat, we could get a reference, it - // would make some things faster, but not matter in many other cases. - - joinShare( rSrc ); - //copyFrom( rSrc ); - } - - FBasicString( const MyType &rSrc, long nLength ) : - nLength( 0 ), - pnRefs( NULL ), - pFirst( NULL ), - pLast( NULL ) - { - append( rSrc.pFirst->pData, nLength ); - } - - FBasicString( const MyType &rSrc, long nStart, long nLength ) : - nLength( 0 ), - pnRefs( NULL ), - pFirst( NULL ), - pLast( NULL ) - { - append( rSrc.pFirst->pData+nStart, nLength ); - } - - FBasicString( long nSize ) : - nLength( nSize ), - pnRefs( NULL ), - pFirst( NULL ), - pLast( NULL ) - { - pFirst = pLast = newChunk( nSize ); - } - - virtual ~FBasicString() - { - clear(); - } - - void append( const chr *pData ) - { - long nLen; - for( nLen = 0; pData[nLen] != (chr)0; nLen++ ); - - Chunk *pNew = newChunk( nLen ); - cpy( pNew->pData, pData, nLen ); - - appendChunk( pNew ); - } - - void append( const chr *pData, long nLen ) - { - Chunk *pNew = newChunk( nLen ); - - cpy( pNew->pData, pData, nLen ); - - appendChunk( pNew ); - } - - void prepend( const chr *pData ) - { - long nLen; - for( nLen = 0; pData[nLen] != (chr)0; nLen++ ); - - Chunk *pNew = newChunk( nLen ); - cpy( pNew->pData, pData, nLen ); - - prependChunk( pNew ); - } - - void prepend( const chr *pData, long nLen ) - { - Chunk *pNew = newChunk( nLen ); - - cpy( pNew->pData, pData, nLen ); - - prependChunk( pNew ); - } - - void clear() - { - realClear(); - } - - void resize( long nNewSize ) - { - if( nLength == nNewSize ) - return; - - flatten(); - - Chunk *pNew = newChunk( nNewSize ); - long nNewLen = (nNewSizepData, pFirst->pData, nNewLen ); - pNew->pData[nNewLen] = (chr)0; - aChr.deallocate( pFirst->pData, pFirst->nLength+1 ); - aChunk.deallocate( pFirst, 1 ); - pFirst = pLast = pNew; - nLength = nNewSize; - } - - long getSize() const - { - return nLength; - } - - chr *getStr() - { - if( pFirst == NULL ) - return NULL; - - flatten(); - return pFirst->pData; - } - - const chr *getStr() const - { - if( pFirst == NULL ) - return NULL; - - flatten(); - return pFirst->pData; - } - - chr *c_str() - { - if( pFirst == NULL ) - return NULL; - - flatten(); - return pFirst->pData; - } - - const chr *c_str() const - { - if( pFirst == NULL ) - return NULL; - - flatten(); - return pFirst->pData; - } - - MyType &operator +=( const chr *pData ) - { - append( pData ); - - return (*this); - } - - MyType &operator +=( const MyType &rSrc ) - { - rSrc.flatten(); - append( rSrc.pFirst->pData, rSrc.nLength ); - - return (*this); - } - - MyType &operator +=( const chr pData ) - { - chr tmp[2] = { pData, (chr)0 }; - append( tmp ); - - return (*this); - } - - MyType &operator =( const chr *pData ) - { - clear(); - append( pData ); - - return (*this); - } - - MyType &operator =( const MyType &rSrc ) - { - //if( rSrc.isFlat() ) - //{ - joinShare( rSrc ); - //} - //else - //{ - // copyFrom( rSrc ); - //} - // - - return (*this); - } - - bool operator ==( const chr *pData ) const - { - if( pFirst == NULL ) { - if( pData == NULL ) - return true; - return false; - } - - flatten(); - const chr *a = pData; - chr *b = pFirst->pData; - for( ; *a!=(chr)0; a++, b++ ) - { - if( *a != *b ) - return false; - } - - return true; - } - - bool operator ==( const MyType &pData ) const - { - if( pFirst == pData.pFirst ) - return true; - if( pFirst == NULL ) - return false; - - flatten(); - pData.flatten(); - const chr *a = pData.pFirst->pData; - chr *b = pFirst->pData; - for( ; *a!=(chr)0; a++, b++ ) - { - if( *a != *b ) - return false; - } - - return true; - } - - bool operator !=(const chr *pData ) const - { - return !(*this == pData); - } - - bool operator !=(const MyType &pData ) const - { - return !(*this == pData); - } - - chr &operator[]( long nIndex ) - { - flatten(); - - return pFirst->pData[nIndex]; - } - - const chr &operator[]( long nIndex ) const - { - flatten(); - - return pFirst->pData[nIndex]; - } - - bool isWS( long nIndex ) const - { - flatten(); - - return pFirst->pData[nIndex]==' ' || pFirst->pData[nIndex]=='\t' - || pFirst->pData[nIndex]=='\r' || pFirst->pData[nIndex]=='\n'; - } - - bool isAlpha( long nIndex ) const - { - flatten(); - - return (pFirst->pData[nIndex] >= 'a' && pFirst->pData[nIndex] <= 'z') - || (pFirst->pData[nIndex] >= 'A' && pFirst->pData[nIndex] <= 'Z'); - } - - void toLower() - { - flatten(); - unShare(); - - for( long j = 0; j < nLength; j++ ) - { - if( pFirst->pData[j] >= 'A' && pFirst->pData[j] <= 'Z' ) - pFirst->pData[j] -= 'A'-'a'; - } - } - - void toUpper() - { - flatten(); - unShare(); - - for( long j = 0; j < nLength; j++ ) - { - if( pFirst->pData[j] >= 'a' && pFirst->pData[j] <= 'z' ) - pFirst->pData[j] += 'A'-'a'; - } - } - - void serialize( class Serializer &ar ) - { - if( ar.isLoading() ) - { - clear(); - long nLen; - ar >> nLen; - - Chunk *pNew = newChunk( nLen ); - ar.read( pNew->pData, nLen*sizeof(chr) ); - appendChunk( pNew ); - } - else - { - flatten(); - - ar << nLength; - ar.write( pFirst->pData, nLength*sizeof(chr) ); - } - } - -private: - void flatten() const - { - if( isFlat() ) - return; - - if( pFirst == NULL ) - return; - - unShare(); - - Chunk *pNew = newChunk( nLength ); - chr *pos = pNew->pData; - Chunk *i = pFirst; - for(;;) - { - cpy( pos, i->pData, i->nLength ); - pos += i->nLength; - i = i->pNext; - if( i == NULL ) - break; - } - realClear(); - - pLast = pFirst = pNew; - nLength = pNew->nLength; - } - - void realClear() const - { - if( pFirst == NULL ) - return; - - if( isShared() ) - { - decRefs(); - } - else - { - Chunk *i = pFirst; - for(;;) - { - Chunk *n = i->pNext; - aChr.deallocate( i->pData, i->nLength+1 ); - aChunk.deallocate( i, 1 ); - if( n == NULL ) - break; - i = n; - } - pFirst = pLast = NULL; - nLength = 0; - } - } - - void copyFrom( const FBasicString &rSrc ) - { - if( rSrc.pFirst == NULL ) - return; - - decRefs(); - - Chunk *pNew = newChunk( rSrc.nLength ); - chr *pos = pNew->pData; - Chunk *i = rSrc.pFirst; - for(;;) - { - cpy( pos, i->pData, i->nLength ); - pos += i->nLength; - i = i->pNext; - if( i == NULL ) - break; - } - clear(); - - appendChunk( pNew ); - } - - bool isFlat() const - { - return (pFirst == pLast); - } - - bool isShared() const - { - return (pnRefs != NULL); - } - - Chunk *newChunk() const - { - Chunk *pNew = aChunk.allocate( 1 ); - pNew->pNext = NULL; - return pNew; - } - - Chunk *newChunk( long nLen ) const - { - Chunk *pNew = aChunk.allocate( 1 ); - pNew->pNext = NULL; - pNew->nLength = nLen; - pNew->pData = aChr.allocate( nLen+1 ); - pNew->pData[nLen] = (chr)0; - return pNew; - } - - void appendChunk( Chunk *pNewChunk ) - { - unShare(); - - if( pFirst == NULL ) - pLast = pFirst = pNewChunk; - else - { - pLast->pNext = pNewChunk; - pLast = pNewChunk; - } - - nLength += pNewChunk->nLength; - } - - void prependChunk( Chunk *pNewChunk ) - { - unShare(); - - if( pFirst == NULL ) - pLast = pFirst = pNewChunk; - else - { - pNewChunk->pNext = pFirst; - pFirst = pNewChunk; - } - - nLength += pNewChunk->nLength; - } - - void joinShare( MyType &rSrc ) - { - clear(); - - if( !rSrc.isFlat() ) - rSrc.flatten(); - - rSrc.initCount(); - pnRefs = rSrc.pnRefs; - (*pnRefs)++; - nLength = rSrc.nLength; - pFirst = rSrc.pFirst; - pLast = rSrc.pLast; - } - - void joinShare( const MyType &rSrc ) - { - clear(); - - rSrc.flatten(); - - if( !rSrc.isShared() ) - { - rSrc.pnRefs = new uint32_t; - (*rSrc.pnRefs) = 1; - } - pnRefs = rSrc.pnRefs; - (*pnRefs)++; - nLength = rSrc.nLength; - pFirst = rSrc.pFirst; - pLast = rSrc.pLast; - } - - /** - * This takes an object that was shared and makes a copy of the base data - * that was being shared so that this copy can be changed. This should be - * added before any call that will change this object; - */ - void unShare() const - { - if( isShared() == false ) - return; - - Chunk *pNew = newChunk( nLength ); - chr *pos = pNew->pData; - Chunk *i = pFirst; - for(;;) - { - cpy( pos, i->pData, i->nLength ); - pos += i->nLength; - i = i->pNext; - if( i == NULL ) - break; - } - decRefs(); - pLast = pFirst = pNew; - nLength = pNew->nLength; - } - - /** - * This decrements our ref count and pulls us out of the share. If the ref - * count hits zero because of this, it destroys the share. This is not - * safe to call on it's own, it's much better to call unShare. - */ - void decRefs() const - { - if( isShared() ) - { - (*pnRefs)--; - if( (*pnRefs) == 0 ) - destroyShare(); - else - { - pnRefs = NULL; - pFirst = NULL; - pLast = NULL; - nLength = 0; - } - } - } - - /** - * While the unShare function removes an instance from a share, this - * function destroys the data that was in the share, removing the share - * itself. This should only be called when the refcount for the share has - * or is about to reach zero. - */ - void destroyShare() const - { - delete pnRefs; - pnRefs = NULL; - realClear(); - } - -#ifdef VALTEST - void cpy( chr *dest, const chr *src, long count ) const - { - for( int j = 0; j < count; j++ ) - { - *dest = *src; - dest++; - src++; - } - } -#endif - - void initCount() const - { - if( !isShared() ) - { - pnRefs = new uint32_t; - (*pnRefs) = 1; - } - } - -private: - mutable long nLength; - mutable uint32_t *pnRefs; - mutable Chunk *pFirst; - mutable Chunk *pLast; - - mutable chralloc aChr; - mutable chunkalloc aChunk; -}; - -typedef FBasicString FString; - -#include "hash.h" -template<> uint32_t __calcHashCode( const FString &k ); -template<> bool __cmpHashKeys( const FString &a, const FString &b ); - - -#endif diff --git a/src/old/hash.cpp b/src/old/hash.cpp deleted file mode 100644 index c52e6b1..0000000 --- a/src/old/hash.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include "hash.h" - -subExceptionDef( HashException ) - -template<> uint32_t __calcHashCode( const int &k ) -{ - return k; -} - -template<> bool __cmpHashKeys( const int &a, const int &b ) -{ - return a == b; -} - -template<> uint32_t __calcHashCode( const unsigned int &k ) -{ - return k; -} - -template<> bool __cmpHashKeys( const unsigned int &a, const unsigned int &b ) -{ - return a == b; -} - -template<> -uint32_t __calcHashCode( const char * const &k ) -{ - if (k == NULL) - { - return 0; - } - - unsigned long int nPos = 0; - for( const char *s = k; *s; s++ ) - { - nPos = *s + (nPos << 6) + (nPos << 16) - nPos; - } - - return nPos; -} - -template<> bool __cmpHashKeys( const char * const &a, const char * const &b ) -{ - if( a == b ) - return true; - - for(int j=0; a[j] == b[j]; j++ ) - if( a[j] == '\0' ) - return true; - - return false; -} - -template<> -uint32_t __calcHashCode( char * const &k ) -{ - if (k == NULL) - { - return 0; - } - - unsigned long int nPos = 0; - for( const char *s = k; *s; s++ ) - { - nPos = *s + (nPos << 6) + (nPos << 16) - nPos; - } - - return nPos; -} - -template<> bool __cmpHashKeys( char * const &a, char * const &b ) -{ - if( a == b ) - return true; - - for(int j=0; a[j] == b[j]; j++ ) - if( a[j] == '\0' ) - return true; - - return false; -} - -template<> uint32_t __calcHashCode( const std::string &k ) -{ - std::string::size_type j, sz = k.size(); - const char *s = k.c_str(); - - unsigned long int nPos = 0; - for( j = 0; j < sz; j++, s++ ) - { - nPos = *s + (nPos << 6) + (nPos << 16) - nPos; - } - - return nPos; -} - -template<> bool __cmpHashKeys( const std::string &a, const std::string &b ) -{ - return a == b; -} - -template<> uint32_t __calcHashCode( const Hashable &k ) -{ - return 0; - //return k.getHashCode(); -} - -template<> bool __cmpHashKeys( const Hashable &a, const Hashable &b ) -{ - return false; - //return a.compareForHash( b ); -} - diff --git a/src/old/hash.h b/src/old/hash.h deleted file mode 100644 index e819379..0000000 --- a/src/old/hash.h +++ /dev/null @@ -1,744 +0,0 @@ -#ifndef HASH_H -#define HASH_H - -#include -#include -#include -#include -#include -#include "exceptionbase.h" -#include "hashable.h" -#include "serializable.h" -#include "serializer.h" - -#define bitsToBytes( n ) (n/32+(n%32>0 ? 1 : 0)) - -subExceptionDecl( HashException ) - -enum eHashException -{ - excodeNotFilled -}; - -template -uint32_t __calcHashCode( const T &k ); - -template -bool __cmpHashKeys( const T &a, const T &b ); - -struct __calcNextTSize_fast -{ - uint32_t operator()( uint32_t nCapacity, uint32_t nFill, uint32_t nDeleted ) const - { - if( nDeleted >= nCapacity/2 ) - return nCapacity; - return nCapacity*2+1; - } -}; - -template, typename valuealloc = std::allocator, typename challoc = std::allocator > -class Hash; - -template< typename key, typename _value, typename sizecalc = __calcNextTSize_fast, typename keyalloc = std::allocator, typename valuealloc = std::allocator<_value>, typename challoc = std::allocator > -struct HashProxy -{ - friend class Hash; -private: - HashProxy( Hash &h, key *k, uint32_t nPos, uint32_t hash ) : - hsh( h ), - pKey( k ), - nPos( nPos ), - hash( hash ), - bFilled( false ) - { - } - - HashProxy( Hash &h, uint32_t nPos, _value *pValue ) : - hsh( h ), - nPos( nPos ), - pValue( pValue ), - bFilled( true ) - { - } - - Hash &hsh; - key *pKey; - uint32_t nPos; - _value *pValue; - uint32_t hash; - bool bFilled; - -public: - operator _value &() - { - if( bFilled == false ) - throw HashException( - excodeNotFilled, - "No data assosiated with that key." - ); - return *pValue; - } - - _value &value() - { - if( bFilled == false ) - throw HashException( - excodeNotFilled, - "No data assosiated with that key." - ); - return *pValue; - } - - bool isFilled() - { - return bFilled; - } - - void erase() - { - if( bFilled ) - { - hsh._erase( nPos ); - hsh.onDelete(); - } - } - - _value operator=( _value nval ) - { - if( bFilled ) - { - hsh.va.destroy( pValue ); - hsh.va.construct( pValue, nval ); - hsh.onUpdate(); - } - else - { - hsh.fill( nPos, *pKey, nval, hash ); - hsh.onInsert(); - } - - return nval; - } - - _value *operator->() - { - if( bFilled == false ) - throw HashException( - excodeNotFilled, - "No data assosiated with that key." - ); - return pValue; - } -}; - -template -class Hash -{ - friend struct HashProxy; -public: - Hash() : - nCapacity( 11 ), - nFilled( 0 ), - nDeleted( 0 ), - bFilled( NULL ), - bDeleted( NULL ), - aKeys( NULL ), - aValues( NULL ), - aHashCodes( NULL ) - { - nKeysSize = bitsToBytes( nCapacity ); - bFilled = ca.allocate( nKeysSize ); - bDeleted = ca.allocate( nKeysSize ); - clearBits(); - - aHashCodes = ca.allocate( nCapacity ); - aKeys = ka.allocate( nCapacity ); - aValues = va.allocate( nCapacity ); - } - - Hash( const Hash &src ) : - nCapacity( src.nCapacity ), - nFilled( 0 ), - nDeleted( 0 ), - bFilled( NULL ), - bDeleted( NULL ), - aKeys( NULL ), - aValues( NULL ), - aHashCodes( NULL ) - { - nKeysSize = bitsToBytes( nCapacity ); - bFilled = ca.allocate( nKeysSize ); - bDeleted = ca.allocate( nKeysSize ); - clearBits(); - - aHashCodes = ca.allocate( nCapacity ); - aKeys = ka.allocate( nCapacity ); - aValues = va.allocate( nCapacity ); - - for( uint32_t j = 0; j < src.nCapacity; j++ ) - { - if( src.isFilled( j ) ) - { - insert( src.aKeys[j], src.aValues[j] ); - } - } - } - - Hash &operator=( const Hash &src ) - { - for( uint32_t j = 0; j < nCapacity; j++ ) - { - if( isFilled( j ) ) - if( !isDeleted( j ) ) - { - va.destroy( &aValues[j] ); - ka.destroy( &aKeys[j] ); - } - } - va.deallocate( aValues, nCapacity ); - ka.deallocate( aKeys, nCapacity ); - ca.deallocate( bFilled, nKeysSize ); - ca.deallocate( bDeleted, nKeysSize ); - ca.deallocate( aHashCodes, nCapacity ); - - nFilled = 0; - nDeleted = 0; - nCapacity = src.nCapacity; - nKeysSize = bitsToBytes( nCapacity ); - bFilled = ca.allocate( nKeysSize ); - bDeleted = ca.allocate( nKeysSize ); - clearBits(); - - aHashCodes = ca.allocate( nCapacity ); - aKeys = ka.allocate( nCapacity ); - aValues = va.allocate( nCapacity ); - - for( uint32_t j = 0; j < src.nCapacity; j++ ) - { - if( src.isFilled( j ) ) - { - insert( src.aKeys[j], src.aValues[j] ); - } - } - - return *this; - } - - virtual ~Hash() - { - for( uint32_t j = 0; j < nCapacity; j++ ) - { - if( isFilled( j ) ) - if( !isDeleted( j ) ) - { - va.destroy( &aValues[j] ); - ka.destroy( &aKeys[j] ); - } - } - va.deallocate( aValues, nCapacity ); - ka.deallocate( aKeys, nCapacity ); - ca.deallocate( bFilled, nKeysSize ); - ca.deallocate( bDeleted, nKeysSize ); - ca.deallocate( aHashCodes, nCapacity ); - } - - uint32_t getCapacity() - { - return nCapacity; - } - - uint32_t getFill() - { - return nFilled; - } - - uint32_t size() - { - return nFilled-nDeleted; - } - - uint32_t getDeleted() - { - return nDeleted; - } - - virtual HashProxy operator[]( key k ) - { - uint32_t hash = __calcHashCode( k ); - bool bFill; - uint32_t nPos = probe( hash, k, bFill ); - - if( bFill ) - { - return HashProxy( *this, nPos, &aValues[nPos] ); - } - else - { - return HashProxy( *this, &k, nPos, hash ); - } - } - - virtual void insert( key k, value v ) - { - uint32_t hash = __calcHashCode( k ); - bool bFill; - uint32_t nPos = probe( hash, k, bFill ); - - if( bFill ) - { - va.destroy( &aValues[nPos] ); - va.construct( &aValues[nPos], v ); - onUpdate(); - } - else - { - fill( nPos, k, v, hash ); - onInsert(); - } - } - - virtual void erase( key k ) - { - uint32_t hash = __calcHashCode( k ); - bool bFill; - uint32_t nPos = probe( hash, k, bFill ); - - if( bFill ) - { - _erase( nPos ); - onDelete(); - } - } - - struct iterator; - virtual void erase( struct iterator &i ) - { - if( this != &i.hsh ) - throw HashException("This iterator didn't come from this Hash."); - if( isFilled( i.nPos ) && !isDeleted( i.nPos ) ) - { - _erase( i.nPos ); - onDelete(); - } - } - - virtual void clear() - { - for( uint32_t j = 0; j < nCapacity; j++ ) - { - if( isFilled( j ) ) - if( !isDeleted( j ) ) - { - va.destroy( &aValues[j] ); - ka.destroy( &aKeys[j] ); - onDelete(); - } - } - - clearBits(); - } - - virtual value &get( key k ) - { - uint32_t hash = __calcHashCode( k ); - bool bFill; - uint32_t nPos = probe( hash, k, bFill ); - - if( bFill ) - { - return aValues[nPos]; - } - else - { - throw HashException( - excodeNotFilled, - "No data assosiated with that key." - ); - } - } - - virtual bool has( key k ) - { - bool bFill; - probe( __calcHashCode( k ), k, bFill, false ); - - return bFill; - } - - typedef struct iterator - { - friend class Hash; - private: - iterator( Hash &hsh ) : - hsh( hsh ), - nPos( 0 ), - bFinished( false ) - { - nPos = hsh.getFirstPos( bFinished ); - } - - iterator( Hash &hsh, bool bDone ) : - hsh( hsh ), - nPos( 0 ), - bFinished( bDone ) - { - } - - Hash &hsh; - uint32_t nPos; - bool bFinished; - - public: - iterator operator++( int ) - { - if( bFinished == false ) - nPos = hsh.getNextPos( nPos, bFinished ); - - return *this; - } - - iterator operator++() - { - if( bFinished == false ) - nPos = hsh.getNextPos( nPos, bFinished ); - - return *this; - } - - bool operator==( const iterator &oth ) - { - if( bFinished != oth.bFinished ) - return false; - if( bFinished == true ) - { - return true; - } - else - { - if( oth.nPos == nPos ) - return true; - return false; - } - } - - bool operator!=( const iterator &oth ) - { - return !(*this == oth ); - } - - iterator operator=( const iterator &oth ) - { - if( &hsh != &oth.hsh ) - throw HashException( - "Cannot mix iterators from different hash objects."); - nPos = oth.nPos; - bFinished = oth.bFinished; - } - - std::pair operator *() - { - return hsh.getAtPos( nPos ); - } - - key &getKey() - { - return hsh.getKeyAtPos( nPos ); - } - - value &getValue() - { - return hsh.getValueAtPos( nPos ); - } - }; - - iterator begin() - { - return iterator( *this ); - } - - iterator end() - { - return iterator( *this, true ); - } - - std::list getKeys() - { - std::list lKeys; - - for( uint32_t j = 0; j < nCapacity; j++ ) - { - if( isFilled( j ) ) - { - if( !isDeleted( j ) ) - { - lKeys.push_back( aKeys[j] ); - } - } - } - - return lKeys; - } - -protected: - virtual void onInsert() {} - virtual void onUpdate() {} - virtual void onDelete() {} - virtual void onReHash() {} - - virtual void clearBits() - { - for( uint32_t j = 0; j < nKeysSize; j++ ) - { - bFilled[j] = bDeleted[j] = 0; - } - } - - virtual void fill( uint32_t loc, key &k, value &v, uint32_t hash ) - { - bFilled[loc/32] |= (1<<(loc%32)); - va.construct( &aValues[loc], v ); - ka.construct( &aKeys[loc], k ); - aHashCodes[loc] = hash; - nFilled++; - //printf("Filled: %d, Deleted: %d, Capacity: %d\n", - // nFilled, nDeleted, nCapacity ); - } - - virtual void _erase( uint32_t loc ) - { - bDeleted[loc/32] |= (1<<(loc%32)); - va.destroy( &aValues[loc] ); - ka.destroy( &aKeys[loc] ); - nDeleted++; - //printf("Filled: %d, Deleted: %d, Capacity: %d\n", - // nFilled, nDeleted, nCapacity ); - } - - virtual std::pair getAtPos( uint32_t nPos ) - { - return std::pair(aKeys[nPos],aValues[nPos]); - } - - virtual key &getKeyAtPos( uint32_t nPos ) - { - return aKeys[nPos]; - } - - virtual value &getValueAtPos( uint32_t nPos ) - { - return aValues[nPos]; - } - - virtual uint32_t getFirstPos( bool &bFinished ) - { - for( uint32_t j = 0; j < nCapacity; j++ ) - { - if( isFilled( j ) ) - if( !isDeleted( j ) ) - return j; - } - - bFinished = true; - return 0; - } - - virtual uint32_t getNextPos( uint32_t nPos, bool &bFinished ) - { - for( uint32_t j = nPos+1; j < nCapacity; j++ ) - { - if( isFilled( j ) ) - if( !isDeleted( j ) ) - return j; - } - - bFinished = true; - return 0; - } - - uint32_t probe( uint32_t hash, key k, bool &bFill, bool rehash=true ) - { - uint32_t nCur = hash%nCapacity; - - // First we scan to see if the key is already there, abort if we - // run out of probing room, or we find a non-filled entry - for( int8_t j = 0; - isFilled( nCur ) && j < 32; - nCur = (nCur + (1< uint32_t __calcHashCode( const int &k ); -template<> bool __cmpHashKeys( const int &a, const int &b ); - -template<> uint32_t __calcHashCode( const unsigned int &k ); -template<> bool __cmpHashKeys( const unsigned int &a, const unsigned int &b ); - -template<> uint32_t __calcHashCode( const char * const &k ); -template<> bool __cmpHashKeys( const char * const &a, const char * const &b ); - -template<> uint32_t __calcHashCode( char * const &k ); -template<> bool __cmpHashKeys( char * const &a, char * const &b ); - -template<> uint32_t __calcHashCode( const std::string &k ); -template<> bool __cmpHashKeys( const std::string &a, const std::string &b ); - -template<> uint32_t __calcHashCode( const Hashable &k ); -template<> bool __cmpHashKeys( const Hashable &a, const Hashable &b ); - -template -Serializer &operator<<( Serializer &ar, Hash &h ) -{ - ar << h.size(); - for( typename Hash::iterator i = h.begin(); i != h.end(); i++ ) - { - std::pair p = *i; - ar << p.first << p.second; - } - - return ar; -} - -template -Serializer &operator>>( Serializer &ar, Hash &h ) -{ - h.clear(); - uint32_t nSize; - ar >> nSize; - - for( uint32_t j = 0; j < nSize; j++ ) - { - key k; value v; - ar >> k >> v; - h.insert( k, v ); - } - - return ar; -} - -template -Serializer &operator&&( Serializer &ar, Hash &h ) -{ - if( ar.isLoading() ) - { - return ar >> h; - } - else - { - return ar << h; - } -} - -#endif diff --git a/src/old/hashable.cpp b/src/old/hashable.cpp deleted file mode 100644 index 8565956..0000000 --- a/src/old/hashable.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "hashable.h" diff --git a/src/old/hashable.h b/src/old/hashable.h deleted file mode 100644 index 98643d5..0000000 --- a/src/old/hashable.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef HASHABLE_H -#define HASHABLE_H - -class Hashable -{ -public: - virtual ~Hashable() {}; - virtual unsigned long int getHashCode() = 0; - virtual bool compareForHash( Hashable &other ) = 0; -}; - -#endif diff --git a/src/old/serializable.cpp b/src/old/serializable.cpp deleted file mode 100644 index fd50943..0000000 --- a/src/old/serializable.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include "serializable.h" - -Serializable::Serializable() -{ -} -Serializable::~Serializable() -{ -} diff --git a/src/old/serializable.h b/src/old/serializable.h deleted file mode 100644 index 06def29..0000000 --- a/src/old/serializable.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef SERIALIZER_H -#define SERIALIZER_H - -//#include "serializer.h" - -/** - * The base class for any class you want to serialize. Simply include this as - * a base class, implement the purely virtual serialize function and you've got - * an easily serializable class. - */ -class Serializable -{ -public: - /** - * Does nothing, here for completeness. - */ - Serializable(); - - /** - * Here to ensure the deconstructor is virtual. - */ - virtual ~Serializable(); - - /** - * This is the main workhorse of the serialization system, just override and - * you've got a serializable class. A reference to the Serializer archive - * used is passed in as your only parameter, query it to discover if you are - * loading or saving. - * @param ar A reference to the Serializer object to use. - */ - virtual void serialize( class Serializer &ar )=0; -}; - -#endif diff --git a/src/old/serializer.cpp b/src/old/serializer.cpp deleted file mode 100644 index 636224e..0000000 --- a/src/old/serializer.cpp +++ /dev/null @@ -1,338 +0,0 @@ -#include "serializer.h" -#include "serializable.h" -#include - -Serializer::Serializer(bool bLoading): - bLoading(bLoading) -{ -} -Serializer::~Serializer() -{ -} - -bool Serializer::isLoading() -{ - return bLoading; -} -Serializer &Serializer::operator<<(bool p) -{ - write( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator<<(int8_t p) -{ - write( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator<<(int16_t p) -{ - write( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator<<(int32_t p) -{ - write( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator<<(int64_t p) -{ - write( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator<<(uint8_t p) -{ - write( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator<<(uint16_t p) -{ - write( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator<<(uint32_t p) -{ - write( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator<<(uint64_t p) -{ - write( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator<<(long p) -{ - write( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator<<(float p) -{ - write( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator<<(double p) -{ - write( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator<<(long double p) -{ - write( &p, sizeof(p) ); - return *this; -} - -Serializer &Serializer::operator>>(bool &p) -{ - read( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator>>(int8_t &p) -{ - read( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator>>(int16_t &p) -{ - read( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator>>(int32_t &p) -{ - read( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator>>(int64_t &p) -{ - read( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator>>(uint8_t &p) -{ - read( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator>>(uint16_t &p) -{ - read( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator>>(uint32_t &p) -{ - read( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator>>(uint64_t &p) -{ - read( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator>>(long &p) -{ - read( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator>>(float &p) -{ - read( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator>>(double &p) -{ - read( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator>>(long double &p) -{ - read( &p, sizeof(p) ); - return *this; -} - -Serializer &Serializer::operator&&(bool &p) -{ - if (bLoading) - { - return *this >> p; - } - else - { - return *this << p; - } -} - -Serializer &Serializer::operator&&(int8_t &p) -{ - if (bLoading) - { - return *this >> p; - } - else - { - return *this << p; - } -} - -Serializer &Serializer::operator&&(int16_t &p) -{ - if (bLoading) - { - return *this >> p; - } - else - { - return *this << p; - } -} - -Serializer &Serializer::operator&&(int32_t &p) -{ - if (bLoading) - { - return *this >> p; - } - else - { - return *this << p; - } -} - -Serializer &Serializer::operator&&(int64_t &p) -{ - if (bLoading) - { - return *this >> p; - } - else - { - return *this << p; - } -} - -Serializer &Serializer::operator&&(uint8_t &p) -{ - if (bLoading) - { - return *this >> p; - } - else - { - return *this << p; - } -} - -Serializer &Serializer::operator&&(uint16_t &p) -{ - if (bLoading) - { - return *this >> p; - } - else - { - return *this << p; - } -} - -Serializer &Serializer::operator&&(uint32_t &p) -{ - if (bLoading) - { - return *this >> p; - } - else - { - return *this << p; - } -} - -Serializer &Serializer::operator&&(uint64_t &p) -{ - if (bLoading) - { - return *this >> p; - } - else - { - return *this << p; - } -} - -Serializer &Serializer::operator&&(float &p) -{ - if (bLoading) - { - return *this >> p; - } - else - { - return *this << p; - } -} - -Serializer &Serializer::operator&&(double &p) -{ - if (bLoading) - { - return *this >> p; - } - else - { - return *this << p; - } -} - -Serializer &Serializer::operator&&(long double &p) -{ - if (bLoading) - { - return *this >> p; - } - else - { - return *this << p; - } -} - - -Serializer &operator<<(Serializer &s, Serializable &p) -{ - p.serialize( s ); - return s; -} - -Serializer &operator>>(Serializer &s, Serializable &p) -{ - p.serialize( s ); - return s; -} - -Serializer &operator&&(Serializer &s, Serializable &p) -{ - if (s.isLoading()) - { - return s >> p; - } - else - { - return s << p; - } -} - -Serializer &operator<<( Serializer &ar, std::string &s ) -{ - ar << (uint32_t)s.length(); - ar.write( s.c_str(), s.length() ); - - return ar; -} - -Serializer &operator>>( Serializer &ar, std::string &s ) -{ - uint32_t l; - ar >> l; - char *tmp = new char[l+1]; - tmp[l] = '\0'; - ar.read( tmp, l ); - s = tmp; - delete[] tmp; - - return ar; -} - diff --git a/src/old/serializer.h b/src/old/serializer.h deleted file mode 100644 index 3af489c..0000000 --- a/src/old/serializer.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef SERIALIZABLE_H -#define SERIALIZABLE_H - -#include -#include -#include -//#include "serializable.h" - -class Serializer -{ -private: - bool bLoading; -public: - bool isLoading(); - - enum - { - load = true, - save = false - }; - - Serializer(bool bLoading); - virtual ~Serializer(); - virtual void close()=0; - - virtual void write(const void *, int32_t)=0; - virtual void read(void *, int32_t)=0; - - virtual Serializer &operator<<(bool); - virtual Serializer &operator<<(int8_t); - virtual Serializer &operator<<(int16_t); - virtual Serializer &operator<<(int32_t); - virtual Serializer &operator<<(int64_t); - virtual Serializer &operator<<(uint8_t); - virtual Serializer &operator<<(uint16_t); - virtual Serializer &operator<<(uint32_t); - virtual Serializer &operator<<(uint64_t); - virtual Serializer &operator<<(long); - virtual Serializer &operator<<(float); - virtual Serializer &operator<<(double); - virtual Serializer &operator<<(long double); - - virtual Serializer &operator>>(bool &); - virtual Serializer &operator>>(int8_t &); - virtual Serializer &operator>>(int16_t &); - virtual Serializer &operator>>(int32_t &); - virtual Serializer &operator>>(int64_t &); - virtual Serializer &operator>>(uint8_t &); - virtual Serializer &operator>>(uint16_t &); - virtual Serializer &operator>>(uint32_t &); - virtual Serializer &operator>>(uint64_t &); - virtual Serializer &operator>>(long &); - virtual Serializer &operator>>(float &); - virtual Serializer &operator>>(double &); - virtual Serializer &operator>>(long double &); - - virtual Serializer &operator&&(bool &); - virtual Serializer &operator&&(int8_t &); - virtual Serializer &operator&&(int16_t &); - virtual Serializer &operator&&(int32_t &); - virtual Serializer &operator&&(int64_t &); - virtual Serializer &operator&&(uint8_t &); - virtual Serializer &operator&&(uint16_t &); - virtual Serializer &operator&&(uint32_t &); - virtual Serializer &operator&&(uint64_t &); - virtual Serializer &operator&&(float &); - virtual Serializer &operator&&(double &); - virtual Serializer &operator&&(long double &); - - //virtual Serializer &operator&(Serializable &); -}; - -Serializer &operator<<(Serializer &, class Serializable &); -Serializer &operator>>(Serializer &, class Serializable &); -Serializer &operator&&(Serializer &s, class Serializable &p); - -Serializer &operator<<(Serializer &, std::string &); -Serializer &operator>>(Serializer &, std::string &); - -#endif diff --git a/src/old/stream.cpp b/src/old/stream.cpp deleted file mode 100644 index 856a58d..0000000 --- a/src/old/stream.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "stream.h" - -Stream::Stream() -{ -} - -Stream::~Stream() -{ -} - diff --git a/src/old/stream.h b/src/old/stream.h deleted file mode 100644 index e086e28..0000000 --- a/src/old/stream.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef STREAM_H -#define STREAM_H - -#include -#include - -class Stream -{ -public: - Stream(); - virtual ~Stream(); - - virtual void close() = 0; - virtual size_t read( char *pBuf, size_t nBytes ) = 0; - virtual size_t write( const char *pBuf, size_t nBytes ) = 0; - - virtual long tell() = 0; - virtual void seek( long offset ) = 0; - virtual void setPos( long pos ) = 0; - virtual void setPosEnd( long pos ) = 0; - virtual bool isEOS() = 0; - -private: - -}; - -#endif diff --git a/src/stream.cpp b/src/stream.cpp new file mode 100644 index 0000000..267a7d1 --- /dev/null +++ b/src/stream.cpp @@ -0,0 +1,10 @@ +#include "stream.h" + +Bu::Stream::Stream() +{ +} + +Bu::Stream::~Stream() +{ +} + diff --git a/src/stream.h b/src/stream.h new file mode 100644 index 0000000..274f4fd --- /dev/null +++ b/src/stream.h @@ -0,0 +1,34 @@ +#ifndef STREAM_H +#define STREAM_H + +#include +#include + +namespace Bu +{ + class Stream + { + public: + Stream(); + virtual ~Stream(); + + virtual void close() = 0; + virtual size_t read( char *pBuf, size_t nBytes ) = 0; + virtual size_t write( const char *pBuf, size_t nBytes ) = 0; + + virtual long tell() = 0; + virtual void seek( long offset ) = 0; + virtual void setPos( long pos ) = 0; + virtual void setPosEnd( long pos ) = 0; + virtual bool isEOS() = 0; + + virtual bool canRead() = 0; + virtual bool canWrite() = 0; + virtual bool canSeek() = 0; + + private: + + }; +} + +#endif diff --git a/src/tests/archive.cpp b/src/tests/archive.cpp new file mode 100644 index 0000000..fb0d97c --- /dev/null +++ b/src/tests/archive.cpp @@ -0,0 +1,7 @@ +#include "archive.h" + +int main() +{ + //Archive +} + diff --git a/tests/comments.xml b/tests/comments.xml deleted file mode 100644 index df05b3b..0000000 --- a/tests/comments.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - Aaaugh! - - diff --git a/tests/guy.cpp b/tests/guy.cpp deleted file mode 100644 index 6510771..0000000 --- a/tests/guy.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "stdio.h" -#include "plugin.h" -#include "plugger.h" - -class Guy : public Plugin -{ -public: - Guy() - { - printf("I'm guy!\n"); - } - - virtual ~Guy() - { - printf("Guy is dead...\n"); - } - -private: -}; - -PluginInterface( Guy, Plugin, "Mike", 0, 1 ) - diff --git a/tests/makeplugin.sh b/tests/makeplugin.sh deleted file mode 100755 index 086fefd..0000000 --- a/tests/makeplugin.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -g++ -fPIC -shared -Wl,-soname,guy.so -o guy.so -I../src -I../src/test/plugin guy.cpp ../src/test/plugin/plugin.cpp -- cgit v1.2.3 From 5a0d7856dc265580cebaa833e0367d03ef21bbc3 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Tue, 10 Apr 2007 13:53:18 +0000 Subject: Woo, changed the name of Achable to Archival, I dig that, and added the ground- work for the SSocket, that should be cool. --- src/archable.cpp | 10 ---------- src/archable.h | 35 ----------------------------------- src/archival.cpp | 10 ++++++++++ src/archival.h | 38 ++++++++++++++++++++++++++++++++++++++ src/archive.cpp | 6 +++--- src/archive.h | 8 ++++---- src/fstring.h | 4 ++-- src/hash.h | 2 +- src/ssocket.cpp | 9 +++++++++ src/ssocket.h | 24 ++++++++++++++++++++++++ 10 files changed, 91 insertions(+), 55 deletions(-) delete mode 100644 src/archable.cpp delete mode 100644 src/archable.h create mode 100644 src/archival.cpp create mode 100644 src/archival.h create mode 100644 src/ssocket.cpp create mode 100644 src/ssocket.h (limited to 'src/fstring.h') diff --git a/src/archable.cpp b/src/archable.cpp deleted file mode 100644 index 38fc31f..0000000 --- a/src/archable.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "archable.h" - -Bu::Archable::Archable() -{ -} - -Bu::Archable::~Archable() -{ -} - diff --git a/src/archable.h b/src/archable.h deleted file mode 100644 index ed05a78..0000000 --- a/src/archable.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef ARCHABLE_H -#define ARCHABLE_H - -namespace Bu -{ - /** - * The base class for any class you want to archive. Simply include this as - * a base class, implement the purely virtual archive function and you've - * got an easily archiveable class. - */ - class Archable - { - public: - /** - * Does nothing, here for completeness. - */ - Archable(); - - /** - * Here to ensure the deconstructor is virtual. - */ - virtual ~Archable(); - - /** - * This is the main workhorse of the archive system, just override and - * you've got a archiveable class. A reference to the Archive - * used is passed in as your only parameter, query it to discover if - * you are loading or saving. - * @param ar A reference to the Archive object to use. - */ - virtual void archive( class Archive &ar )=0; - }; -} - -#endif diff --git a/src/archival.cpp b/src/archival.cpp new file mode 100644 index 0000000..79c28f1 --- /dev/null +++ b/src/archival.cpp @@ -0,0 +1,10 @@ +#include "archival.h" + +Bu::Archival::Archival() +{ +} + +Bu::Archival::~Archival() +{ +} + diff --git a/src/archival.h b/src/archival.h new file mode 100644 index 0000000..e2c803c --- /dev/null +++ b/src/archival.h @@ -0,0 +1,38 @@ +#ifndef ARCHIVAL_H +#define ARCHIVAL_H + +namespace Bu +{ + /** + * The base class for any class you want to archive. Simply include this as + * a base class, implement the purely virtual archive function and you've + * got an easily archiveable class. + * + * Archival: "of or pertaining to archives or valuable records; contained + * in or comprising such archives or records." + */ + class Archival + { + public: + /** + * Does nothing, here for completeness. + */ + Archival(); + + /** + * Here to ensure the deconstructor is virtual. + */ + virtual ~Archival(); + + /** + * This is the main workhorse of the archive system, just override and + * you've got a archiveable class. A reference to the Archive + * used is passed in as your only parameter, query it to discover if + * you are loading or saving. + * @param ar A reference to the Archive object to use. + */ + virtual void archive( class Archive &ar )=0; + }; +} + +#endif diff --git a/src/archive.cpp b/src/archive.cpp index be06c0e..edc8625 100644 --- a/src/archive.cpp +++ b/src/archive.cpp @@ -312,20 +312,20 @@ Bu::Archive &Bu::Archive::operator&&(long double &p) } -Bu::Archive &Bu::operator<<(Bu::Archive &s, Bu::Archable &p) +Bu::Archive &Bu::operator<<(Bu::Archive &s, Bu::Archival &p) { p.archive( s ); return s; } -Bu::Archive &Bu::operator>>(Bu::Archive &s, Bu::Archable &p) +Bu::Archive &Bu::operator>>(Bu::Archive &s, Bu::Archival &p) { p.archive( s ); return s; } /* -Bu::Archive &Bu::operator&&(Bu::Archive &s, Bu::Archable &p) +Bu::Archive &Bu::operator&&(Bu::Archive &s, Bu::Archival &p) { if (s.isLoading()) { diff --git a/src/archive.h b/src/archive.h index 26e430b..a8ce53e 100644 --- a/src/archive.h +++ b/src/archive.h @@ -3,7 +3,7 @@ #include #include -#include "archable.h" +#include "archival.h" #include "stream.h" namespace Bu @@ -73,9 +73,9 @@ namespace Bu Stream &rStream; }; - Archive &operator<<(Archive &, class Bu::Archable &); - Archive &operator>>(Archive &, class Bu::Archable &); - //Archive &operator&&(Archive &s, class Bu::Archable &p); + Archive &operator<<(Archive &, class Bu::Archival &); + Archive &operator>>(Archive &, class Bu::Archival &); + //Archive &operator&&(Archive &s, class Bu::Archival &p); Archive &operator<<(Archive &, std::string &); Archive &operator>>(Archive &, std::string &); diff --git a/src/fstring.h b/src/fstring.h index 717068f..0184301 100644 --- a/src/fstring.h +++ b/src/fstring.h @@ -3,7 +3,7 @@ #include #include -#include "archable.h" +#include "archival.h" #include "archive.h" #include "hash.h" @@ -29,7 +29,7 @@ namespace Bu * FBasicString into a ref-counting container class. */ template< typename chr, typename chralloc=std::allocator, typename chunkalloc=std::allocator > > - class FBasicString : public Archable + class FBasicString : public Archival { #ifndef VALTEST #define cpy( dest, src, size ) memcpy( dest, src, size*sizeof(chr) ) diff --git a/src/hash.h b/src/hash.h index 9e498f1..dc097df 100644 --- a/src/hash.h +++ b/src/hash.h @@ -8,7 +8,7 @@ #include #include #include "exceptionbase.h" -#include "archable.h" +#include "archival.h" #include "archive.h" #define bitsToBytes( n ) (n/32+(n%32>0 ? 1 : 0)) diff --git a/src/ssocket.cpp b/src/ssocket.cpp new file mode 100644 index 0000000..bdaac24 --- /dev/null +++ b/src/ssocket.cpp @@ -0,0 +1,9 @@ +#include "ssocket.h" + +SSocket::SSocket() +{ +} + +SSocket::~SSocket() +{ +} diff --git a/src/ssocket.h b/src/ssocket.h new file mode 100644 index 0000000..ce02091 --- /dev/null +++ b/src/ssocket.h @@ -0,0 +1,24 @@ +#ifndef S_SOCKET_H +#define S_SOCKET_H + +#include + +#include "stream.h" + +namespace Bu +{ + /** + * + */ + class SSocket : public Stream + { + public: + SSocket(); + virtual ~SSocket(); + + private: + + }; +} + +#endif -- cgit v1.2.3 From b6e100b94b12f3f92ec025dc2363eaf7c0ee6662 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Tue, 10 Apr 2007 16:02:07 +0000 Subject: Well, we've got the basis of a workable unit test harness thing. There should be a few more add-ons to it, but it works just fine, and eventually it should cover command line options and creating logs, and possibly even provide output functionality so that output from tests can be logged and kept track of well. --- build.conf | 16 +++++++++++++ src/fstring.h | 24 +++++++++++++++++++ src/ssocket.cpp | 4 ++-- src/unit/fstring.cpp | 28 ++++++++++++++++++++++ src/unit/sfile.cpp | 27 +++++++++++++++++++++ src/unitsuite.cpp | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/unitsuite.h | 60 ++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 224 insertions(+), 2 deletions(-) create mode 100644 src/unit/fstring.cpp create mode 100644 src/unit/sfile.cpp create mode 100644 src/unitsuite.cpp create mode 100644 src/unitsuite.h (limited to 'src/fstring.h') diff --git a/build.conf b/build.conf index 5c4dbb6..bc186f9 100644 --- a/build.conf +++ b/build.conf @@ -30,6 +30,22 @@ filesIn("src/tests") filter regexp("^src/tests/(.*)\\.cpp$", "tests/{re:1}"): set "LDFLAGS" += "-L. -lbu++", input "src/{target}.cpp" +directoriesIn("src/unit","unit/"): + rule "exe", + target file, + requires "libbu++.a", + set "CXXFLAGS" += "-Isrc", + set "LDFLAGS" += "-L. -lbu++", + input filesIn("{fulldir}") filter regexp("^.*\\.cpp$") + +filesIn("src/unit") filter regexp("^src/unit/(.*)\\.cpp$", "unit/{re:1}"): + rule "exe", + target file, + requires "libbu++.a", + set "CXXFLAGS" += "-Isrc", + set "LDFLAGS" += "-L. -lbu++", + input "src/{target}.cpp" + "tests/plugin": set "LDFLAGS" += "-ldl" rule "exe": diff --git a/src/fstring.h b/src/fstring.h index 0184301..751beb8 100644 --- a/src/fstring.h +++ b/src/fstring.h @@ -364,6 +364,30 @@ namespace Bu } } + long find( const char *sText ) + { + long nTLen = strlen( sText ); + flatten(); + for( long j = 0; j < pFirst->nLength-nTLen; j++ ) + { + if( !strncmp( sText, pFirst->pData+j, nTLen ) ) + return j; + } + return -1; + } + + long rfind( const char *sText ) + { + long nTLen = strlen( sText ); + flatten(); + for( long j = pFirst->nLength-nTLen-1; j >= 0; j-- ) + { + if( !strncmp( sText, pFirst->pData+j, nTLen ) ) + return j; + } + return -1; + } + void archive( class Archive &ar ) { if( ar.isLoading() ) diff --git a/src/ssocket.cpp b/src/ssocket.cpp index bdaac24..85a2da0 100644 --- a/src/ssocket.cpp +++ b/src/ssocket.cpp @@ -1,9 +1,9 @@ #include "ssocket.h" -SSocket::SSocket() +Bu::SSocket::SSocket() { } -SSocket::~SSocket() +Bu::SSocket::~SSocket() { } diff --git a/src/unit/fstring.cpp b/src/unit/fstring.cpp new file mode 100644 index 0000000..72755eb --- /dev/null +++ b/src/unit/fstring.cpp @@ -0,0 +1,28 @@ +#include "fstring.h" +#include "unitsuite.h" + +class Unit : public Bu::UnitSuite +{ +public: + Unit() + { + setName("FString"); + addTest( Unit::test1 ); + } + + virtual ~Unit() + { + } + + void test1() + { + unitTest( 1 == 1 ); + unitTest( 1 == 0 ); + } +}; + +int main( int argc, char *argv[] ) +{ + return Unit().run( argc, argv ); +} + diff --git a/src/unit/sfile.cpp b/src/unit/sfile.cpp new file mode 100644 index 0000000..7b19942 --- /dev/null +++ b/src/unit/sfile.cpp @@ -0,0 +1,27 @@ +#include "unitsuite.h" + +class Unit : public Bu::UnitSuite +{ +public: + Unit() + { + setName("SFile"); + addTest( Unit::test ); + } + + virtual ~Unit() { } + + // + // Tests go here + // + void test() + { + unitTest( 1 == 1 ); + } +}; + +int main( int argc, char *argv[] ) +{ + return Unit().run( argc, argv ); +} + diff --git a/src/unitsuite.cpp b/src/unitsuite.cpp new file mode 100644 index 0000000..2a28eb5 --- /dev/null +++ b/src/unitsuite.cpp @@ -0,0 +1,67 @@ +#include "unitsuite.h" + +Bu::UnitSuite::UnitSuite() +{ +} + +Bu::UnitSuite::~UnitSuite() +{ +} + +int Bu::UnitSuite::run( int argc, char *argv[] ) +{ + for( TestList::iterator i = lTests.begin(); i != lTests.end(); i++ ) + { + printf("%s: ", i->sName.getStr() ); + fflush( stdout ); + try + { + (this->*(i->fTest))(); + printf("passed.\n"); + } + catch( Failed &e ) + { + if( e.bFile ) + { + printf("unitTest(%s) failed. (%s:%d)\n", + e.str.getStr(), + e.sFile.getStr(), + e.nLine + ); + } + else + { + printf("unitTest(%s) failed.\n", + e.str.getStr() + ); + } + } + catch( ... ) + { + printf("failed with external exception.\n"); + } + } + + return 0; +} + +void Bu::UnitSuite::add( Test fTest, Bu::FString sName ) +{ + TestInfo ti; + ti.sName = sName; + long index = ti.sName.rfind("::"); + if( index != -1 ) + { + FString tmp = sSuiteName; + tmp += ti.sName.getStr()+index; + ti.sName = tmp; + } + ti.fTest = fTest; + lTests.push_back( ti ); +} + +void Bu::UnitSuite::setName( const FString &sName ) +{ + sSuiteName = sName; +} + diff --git a/src/unitsuite.h b/src/unitsuite.h new file mode 100644 index 0000000..3502a1b --- /dev/null +++ b/src/unitsuite.h @@ -0,0 +1,60 @@ +#ifndef UNIT_SUITE_H +#define UNIT_SUITE_H + +#include +#include +#include "fstring.h" + +namespace Bu +{ + /** + * + */ + class UnitSuite + { + public: + UnitSuite(); + virtual ~UnitSuite(); + + int run( int argc=0, char *argv[]=NULL ); + + typedef void (UnitSuite::*Test)(); + + class Failed + { + public: + Failed() : str(""), bFile( false ) { } + Failed( const FString &s ) : str( s ), bFile( false ) { } + Failed( const FString &s, const FString &sFile, int nLine ) : + str( s ), sFile( sFile ), nLine( nLine ), bFile( true ) { } + + FString str; + FString sFile; + int nLine; + bool bFile; + }; + + protected: + void add( Test fTest, Bu::FString sName ); + void setName( const FString &sName ); + + private: + typedef struct TestInfo + { + FString sName; + Test fTest; + } TestInfo; + + typedef std::list TestList; + TestList lTests; + FString sSuiteName; + }; +} + +#define addTest( fn ) add( static_cast(&fn), #fn ) +#define unitTest( tst ) if( !(tst) ) \ +{ \ + throw Bu::UnitSuite::Failed( #tst, __FILE__, __LINE__ ); \ +} + +#endif -- cgit v1.2.3 From 0f0be6146dc711f8d44db0348e8fe0d010a31ca7 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Mon, 7 May 2007 22:26:06 +0000 Subject: Added some more helpers to FString, now contemplating a cast operator to a const pointer version of the raw data. --- src/fstring.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/fstring.h') diff --git a/src/fstring.h b/src/fstring.h index 751beb8..877e5a7 100644 --- a/src/fstring.h +++ b/src/fstring.h @@ -245,6 +245,18 @@ namespace Bu return (*this); } + void set( const chr *pData ) + { + clear(); + append( pData ); + } + + void set( const chr *pData, long nSize ) + { + clear(); + append( pData, nSize ); + } + MyType &operator =( const MyType &rSrc ) { //if( rSrc.isFlat() ) -- cgit v1.2.3 From 033c41ed57348abb3a418166b1fb39bfad3312de Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Fri, 11 May 2007 07:51:40 +0000 Subject: Added a list template class, seems to work pretty well for now, I may have forgotten proper cleanup in the deconstructor, but besides that you can do almost everything you need. I'll make a slist/stack next, probably with the same basic code, just a different structure (not doubley-linked). The xml system from old-libbu++ is almost completely converted, I was going to re-write it, but this seemed easier at first, it may not have been, we'll see. It almost parses everything again, and almost outputs again, and it does use streams now. The FString is partway to doing minimum chunk allocations, so that adding single-characters will be really fast up to the minimum chunk size. I also figured out how to add this optimization without any extra variables taking up space, and it's optional in the template, which is cool. You can specify the size of the blocks (default 256 bytes), if it's 0 then they'll be like the old FString, 1 chunk per operation. The next FString update should be allowing efficient removal from the begining of the string by faking it, and simply moving a secondary base pointer ahead, and then optimizing appends after that fact to simply move the existing data around if you shouldn't have to re-allocate (alla FlexBuf). The final fun addition that I'm planning is a simple switch in the template (boolean) that will switch an FString into a thread-safe mode without changing the interface or anything that you can do with them at all. It may increasing memory usage, but they should still be better than std::strings, and totally thread-safe. The best part of that is that if it's done with a boolean template parameter and if statements that only test that parameter controlling flow, the code that you don't want (threadsafe/non-threadsafe) won't be included at all post-optimization. --- src/fstring.h | 14 +++-- src/list.cpp | 2 + src/list.h | 176 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/tests/list.cpp | 22 +++++++ src/tests/xml.cpp | 6 +- src/xmldocument.cpp | 20 +++--- src/xmldocument.h | 8 +-- src/xmlnode.cpp | 106 ++++++++++--------------------- src/xmlnode.h | 101 +++++++++++------------------- src/xmlreader.cpp | 170 +++++++++++++++++++++++++------------------------- src/xmlreader.h | 31 ++++----- src/xmlwriter.cpp | 62 +++++++++--------- src/xmlwriter.h | 16 ++--- 13 files changed, 428 insertions(+), 306 deletions(-) create mode 100644 src/list.cpp create mode 100644 src/list.h create mode 100644 src/tests/list.cpp (limited to 'src/fstring.h') diff --git a/src/fstring.h b/src/fstring.h index 877e5a7..f738f63 100644 --- a/src/fstring.h +++ b/src/fstring.h @@ -28,7 +28,7 @@ namespace Bu * data is actually copied. This also means that you never need to put any * FBasicString into a ref-counting container class. */ - template< typename chr, typename chralloc=std::allocator, typename chunkalloc=std::allocator > > + template< typename chr, int nMinSize=256, typename chralloc=std::allocator, typename chunkalloc=std::allocator > > class FBasicString : public Archival { #ifndef VALTEST @@ -36,7 +36,7 @@ namespace Bu #endif private: typedef struct FStringChunk Chunk; - typedef struct FBasicString MyType; + typedef struct FBasicString MyType; public: FBasicString() : @@ -131,6 +131,11 @@ namespace Bu appendChunk( pNew ); } + void append( const chr cData ) + { + append( &cData, 1 ); + } + void prepend( const chr *pData ) { long nLen; @@ -231,8 +236,7 @@ namespace Bu MyType &operator +=( const chr pData ) { - chr tmp[2] = { pData, (chr)0 }; - append( tmp ); + append( &pData, 1 ); return (*this); } @@ -475,7 +479,7 @@ namespace Bu } } - void copyFrom( const FBasicString &rSrc ) + void copyFrom( const FBasicString &rSrc ) { if( rSrc.pFirst == NULL ) return; diff --git a/src/list.cpp b/src/list.cpp new file mode 100644 index 0000000..abe92ad --- /dev/null +++ b/src/list.cpp @@ -0,0 +1,2 @@ +#include "bu/list.h" + diff --git a/src/list.h b/src/list.h new file mode 100644 index 0000000..ec63496 --- /dev/null +++ b/src/list.h @@ -0,0 +1,176 @@ +#ifndef LIST_H +#define LIST_H + +#include +#include "bu/exceptionbase.h" + +namespace Bu +{ + template + struct ListLink + { + value *pValue; + ListLink *pNext; + ListLink *pPrev; + }; + template, typename linkalloc=std::allocator > > + class List + { + private: + typedef struct ListLink Link; + typedef class List MyType; + + public: + List() : + pFirst( NULL ), + pLast( NULL ) + { + } + + void append( value v ) + { + Link *pNew = la.allocate( sizeof( Link ) ); + pNew->pValue = va.allocate( sizeof( value ) ); + va.construct( pNew->pValue, v ); + if( pFirst == NULL ) + { + // Empty list + pFirst = pLast = pNew; + pNew->pNext = pNew->pPrev = NULL; + } + else + { + pNew->pNext = NULL; + pNew->pPrev = pLast; + pLast->pNext = pNew; + pLast = pNew; + } + } + + void prepend( value v ) + { + Link *pNew = la.allocate( sizeof( Link ) ); + pNew->pValue = va.allocate( sizeof( value ) ); + va.construct( pNew->pValue, v ); + if( pFirst == NULL ) + { + // Empty list + pFirst = pLast = pNew; + pNew->pNext = pNew->pPrev = NULL; + } + else + { + pNew->pNext = pFirst; + pNew->pPrev = NULL; + pFirst->pPrev = pNew; + pFirst = pNew; + } + } + + typedef struct iterator + { + friend class List; + private: + Link *pLink; + iterator() : + pLink( NULL ) + { + } + + iterator( Link *pLink ) : + pLink( pLink ) + { + } + + public: + bool operator==( const iterator &oth ) + { + return ( pLink == oth.pLink ); + } + + bool operator==( const Link *pOth ) + { + return ( pLink == pOth ); + } + + bool operator!=( const iterator &oth ) + { + return ( pLink != oth.pLink ); + } + + bool operator!=( const Link *pOth ) + { + return ( pLink != pOth ); + } + + value &operator*() + { + return *(pLink->pValue); + } + + value *operator->() + { + return pLink->pValue(); + } + + iterator operator++() + { + if( pLink != NULL ) + pLink = pLink->pNext; + return *this; + } + + iterator operator--() + { + if( pLink != NULL ) + pLink = pLink->pPrev; + return *this; + } + + iterator operator++( int ) + { + if( pLink != NULL ) + pLink = pLink->pNext; + return *this; + } + + iterator operator--( int ) + { + if( pLink != NULL ) + pLink = pLink->pPrev; + return *this; + } + + iterator operator=( const iterator &oth ) + { + pLink = oth.pLink; + } + }; + + iterator begin() + { + return iterator( pFirst ); + } + + const Link *end() + { + return NULL; + } + + int getSize() + { + int j = 0; + for( Link *pCur = pFirst; pCur; pCur = pCur->pNext ) + j++; + return j; + } + + private: + Link *pFirst; + Link *pLast; + linkalloc la; + valuealloc va; + }; +} + +#endif diff --git a/src/tests/list.cpp b/src/tests/list.cpp new file mode 100644 index 0000000..34ab656 --- /dev/null +++ b/src/tests/list.cpp @@ -0,0 +1,22 @@ +#include "bu/list.h" + +int main() +{ + Bu::List l; + + l.append( 0 ); + + for( int j = 3; j <= 21; j += 3 ) + { + l.append( j ); + l.prepend( -j ); + } + + for( Bu::List::iterator i = l.begin(); i != l.end(); i++ ) + { + printf("%d ", *i ); + } + + printf("\n\n"); +} + diff --git a/src/tests/xml.cpp b/src/tests/xml.cpp index 9ef6a7e..9689a28 100644 --- a/src/tests/xml.cpp +++ b/src/tests/xml.cpp @@ -6,9 +6,9 @@ int main() { Bu::File f("test.xml", "r"); - Bu::XmlReader xr( f ); - - xr.read(); + XmlReader xr( f ); + + //xr.read(); return 0; } diff --git a/src/xmldocument.cpp b/src/xmldocument.cpp index d7867d5..95b9788 100644 --- a/src/xmldocument.cpp +++ b/src/xmldocument.cpp @@ -1,6 +1,6 @@ #include #include -#include "xmlwriter.h" +#include "xmldocument.h" XmlDocument::XmlDocument( XmlNode *pRoot ) { @@ -17,28 +17,23 @@ XmlDocument::~XmlDocument() } } -void XmlDocument::addNode( const char *sName, const char *sContent, bool bClose ) +void XmlDocument::addNode( const Bu::FString &sName ) { if( pRoot == NULL ) { // This is the first node, so ignore position and just insert it. - pCurrent = pRoot = new XmlNode( sName, NULL, sContent ); + pCurrent = pRoot = new XmlNode( sName ); } else { - pCurrent = pCurrent->addChild( sName, sContent ); - } - - if( bClose ) - { - closeNode(); + pCurrent = pCurrent->addChild( sName ); } } - +/* void XmlDocument::setName( const char *sName ) { pCurrent->setName( sName ); -} +}*/ bool XmlDocument::isCompleted() { @@ -143,7 +138,8 @@ void XmlDocument::setContent( const char *sContent ) { if( pCurrent ) { - pCurrent->setContent( sContent ); + printf("XmlDocument::setContent: not yet implemented.\n"); + //pCurrent->setContent( sContent ); } } diff --git a/src/xmldocument.h b/src/xmldocument.h index 6671c41..e0c36eb 100644 --- a/src/xmldocument.h +++ b/src/xmldocument.h @@ -39,13 +39,7 @@ public: * the node and setting the content and name. If this is set to true the * node is appended, but the context node doesn't change. */ - void addNode( const char *sName=NULL, const char *sContent=NULL, bool bClose=false ); - - /** - * Set the name of the current node context. - *@param sName The new name of the node. - */ - void setName( const char *sName ); + void addNode( const Bu::FString &sName ); /** * Close the current node context. This will move the current context to diff --git a/src/xmlnode.cpp b/src/xmlnode.cpp index b1ed9a9..96d5850 100644 --- a/src/xmlnode.cpp +++ b/src/xmlnode.cpp @@ -1,53 +1,15 @@ #include "xmlnode.h" -#include "hashfunctionstring.h" -XmlNode::XmlNode( const char *sName, XmlNode *pParent, const char *sContent ) : - hProperties( new HashFunctionString(), 53, false ), - hChildren( new HashFunctionString(), 53, true ) +XmlNode::XmlNode( const Bu::FString &sName, XmlNode *pParent ) : + sName( sName ), + pParent( pParent ) { - this->pParent = pParent; - if( sName != NULL ) - { - setName( sName ); - } - if( sContent != NULL ) - { - this->sPreContent = new std::string( sContent ); - } - else - { - this->sPreContent = NULL; - } - nCurContent = 0; } XmlNode::~XmlNode() { - for( int j = 0; j < lChildren.getSize(); j++ ) - { - delete (XmlNode *)lChildren[j]; - } - for( int j = 0; j < lPropNames.getSize(); j++ ) - { - delete (std::string *)lPropNames[j]; - } - for( int j = 0; j < lPropValues.getSize(); j++ ) - { - delete (std::string *)lPropValues[j]; - } - for( int j = 0; j < lPostContent.getSize(); j++ ) - { - if( lPostContent[j] != NULL ) - { - delete (std::string *)lPostContent[j]; - } - } - if( sPreContent ) - { - delete sPreContent; - } } - +/* void XmlNode::setName( const char *sName ) { if( pParent ) @@ -120,18 +82,18 @@ const char *XmlNode::getContent( int nIndex ) } return NULL; -} +}*/ -XmlNode *XmlNode::addChild( const char *sName, const char *sContent ) +XmlNode *XmlNode::addChild( const Bu::FString &sName ) { - return addChild( new XmlNode( sName, this, sContent ) ); + return addChild( new XmlNode( sName, this ) ); } XmlNode *XmlNode::addChild( XmlNode *pNode ) { - lChildren.append( pNode ); - lPostContent.append( NULL ); - nCurContent++; + Child c = { typeNode }; + c.pNode = pNode; + lChildren.append( c ); pNode->pParent = this; return pNode; @@ -142,21 +104,16 @@ XmlNode *XmlNode::getParent() return pParent; } -void XmlNode::addProperty( const char *sName, const char *sValue ) +void XmlNode::addProperty( const Bu::FString &sName, const Bu::FString &sValue ) { - std::string *pName = new std::string( sName ); - std::string *pValue = new std::string( sValue ); - - hProperties.insert( pName->c_str(), pValue->c_str() ); - lPropNames.append( pName ); - lPropValues.append( pValue ); + hProperties.insert( sName, sValue ); } int XmlNode::getNumProperties() { - return lPropNames.getSize(); + return hProperties.size(); } - +/* const char *XmlNode::getPropertyName( int nIndex ) { std::string *tmp = ((std::string *)lPropNames[nIndex]); @@ -172,15 +129,12 @@ const char *XmlNode::getProperty( int nIndex ) return NULL; return tmp->c_str(); } - -const char *XmlNode::getProperty( const char *sName ) +*/ +Bu::FString XmlNode::getProperty( const Bu::FString &sName ) { - const char *tmp = (const char *)hProperties[sName]; - if( tmp == NULL ) - return NULL; - return tmp; + return hProperties[sName]; } - +/* void XmlNode::deleteProperty( int nIndex ) { hProperties.del( ((std::string *)lPropNames[nIndex])->c_str() ); @@ -194,29 +148,33 @@ void XmlNode::deleteProperty( int nIndex ) bool XmlNode::hasChildren() { - return lChildren.getSize()>0; -} + return hChildren.getSize()>0; +}*/ int XmlNode::getNumChildren() { return lChildren.getSize(); } - +/* XmlNode *XmlNode::getChild( int nIndex ) { return (XmlNode *)lChildren[nIndex]; } - -XmlNode *XmlNode::getChild( const char *sName, int nSkip ) +*/ +XmlNode *XmlNode::getChild( const Bu::FString &sName, int nSkip ) { - return (XmlNode *)hChildren.get( sName, nSkip ); + if( !hChildren.has( sName ) ) + return NULL; + + Bu::List::iterator i = hChildren[sName]->begin(); + return *i; } -const char *XmlNode::getName() +Bu::FString XmlNode::getName() { - return sName.c_str(); + return sName; } - +/* void XmlNode::deleteNode( int nIndex, const char *sReplacementText ) { XmlNode *xRet = detatchNode( nIndex, sReplacementText ); @@ -442,4 +400,4 @@ void XmlNode::deleteNodeKeepChildren( int nIndex ) void XmlNode::replaceNodeWithChildren( int nIndex, XmlNode *pNewNode ) { } - +*/ diff --git a/src/xmlnode.h b/src/xmlnode.h index 7525306..c895cd8 100644 --- a/src/xmlnode.h +++ b/src/xmlnode.h @@ -2,8 +2,9 @@ #define XMLNODE #include -#include "linkedlist.h" -#include "hashtable.h" +#include "bu/list.h" +#include "bu/hash.h" +#include "bu/fstring.h" /** * Maintains all data pertient to an XML node, including sub-nodes and content. @@ -25,9 +26,8 @@ public: *@param sContent The initial content string. */ XmlNode( - const char *sName=NULL, - XmlNode *pParent = NULL, - const char *sContent=NULL + const Bu::FString &sName, + XmlNode *pParent=NULL ); /** @@ -39,7 +39,7 @@ public: * Change the name of the node. *@param sName The new name of the node. */ - void setName( const char *sName ); + //void setName( const char *sName ); /** * Construct a new node and add it as a child to this node, also return a @@ -48,7 +48,7 @@ public: *@param sContent The initial content of the new node. *@returns A pointer to the newly created child node. */ - XmlNode *addChild( const char *sName, const char *sContent=NULL ); + XmlNode *addChild( const Bu::FString &sName ); /** * Add an already created XmlNode as a child to this node. The new child @@ -65,7 +65,7 @@ public: * in use will overwrite that property. *@param sValue The textual value of the property. */ - void addProperty( const char *sName, const char *sValue ); + void addProperty( const Bu::FString &sName, const Bu::FString &sValue ); /** * Get a pointer to the parent node, if any. @@ -85,14 +85,6 @@ public: */ int getNumChildren(); - /** - * Get a child node at a specific index. - *@param nIndex The zero-based index of the child to retreive. - *@returns A pointer to the child, or NULL if you requested an invalid - * index. - */ - XmlNode *getChild( int nIndex ); - /** * Get a child with the specified name, and possibly skip value. For an * explination of skip values see the HashTable. @@ -101,14 +93,14 @@ public: *@returns A pointer to the child, or NULL if no child with that name was * found. */ - XmlNode *getChild( const char *sName, int nSkip=0 ); + XmlNode *getChild( const Bu::FString &sName, int nSkip=0 ); /** * Get a pointer to the name of this node. Do not change this, use setName * instead. *@returns A pointer to the name of this node. */ - const char *getName(); + Bu::FString getName(); /** * Set the content of this node, optionally at a specific index. Using the @@ -116,14 +108,7 @@ public: *@param sContent The content string to use. *@param nIndex The index of the content. */ - void setContent( const char *sContent, int nIndex=-1 ); - - /** - * Get the content string at a given index, or zero for initial content. - *@param nIndex The index of the content. - *@returns A pointer to the content at that location. - */ - const char *getContent( int nIndex = 0 ); + //void setContent( const char *sContent, int nIndex=-1 ); /** * Get the number of properties in this node. @@ -131,37 +116,13 @@ public: */ int getNumProperties(); - /** - * Get a property's name by index. - *@param nIndex The index of the property to examine. - *@returns A pointer to the name of the property specified, or NULL if none - * found. - */ - const char *getPropertyName( int nIndex ); - - /** - * Get a proprty's value by index. - *@param nIndex The index of the property to examine. - *@returns A pointer to the value of the property specified, or NULL if none - * found. - */ - const char *getProperty( int nIndex ); - /** * Get a propery's value by name. *@param sName The name of the property to examine. *@returns A pointer to the value of the property specified, or NULL if none * found. */ - const char *getProperty( const char *sName ); - - /** - * Delete a property by index. - *@param nIndex The index of the property to delete. - *@returns True if the property was found and deleted, false if it wasn't - * found. - */ - void deleteProperty( int nIndex ); + Bu::FString getProperty( const Bu::FString &sName ); /** * Delete a child node, possibly replacing it with some text. This actually @@ -171,7 +132,7 @@ public: *@returns True of the node was found, and deleted, false if it wasn't * found. */ - void deleteNode( int nIndex, const char *sReplacementText = NULL ); + //void deleteNode( int nIndex, const char *sReplacementText = NULL ); /** * Delete a given node, but move all of it's children and content up to @@ -180,7 +141,7 @@ public: *@param nIndex The node to delete. *@returns True if the node was found and deleted, false if it wasn't. */ - void deleteNodeKeepChildren( int nIndex ); + //void deleteNodeKeepChildren( int nIndex ); /** * Detatch a given child node from this node. This effectively works just @@ -192,7 +153,7 @@ public: *@returns A pointer to the newly detatched node, which then passes * ownership to the caller. */ - XmlNode *detatchNode( int nIndex, const char *sReplacementText = NULL ); + //XmlNode *detatchNode( int nIndex, const char *sReplacementText = NULL ); /** * Replace a given node with a different node that is not currently owned by @@ -201,7 +162,7 @@ public: *@param pNewNode The new node to replace the old node with. *@returns True if the node was found and replaced, false if it wasn't. */ - void replaceNode( int nIndex, XmlNode *pNewNode ); + //void replaceNode( int nIndex, XmlNode *pNewNode ); /** * Replace a given node with the children and content of a given node. @@ -210,24 +171,34 @@ public: * replace the node specified by nIndex. *@returns True if the node was found and replaced, false if it wasn't. */ - void replaceNodeWithChildren( int nIndex, XmlNode *pNewNode ); + //void replaceNodeWithChildren( int nIndex, XmlNode *pNewNode ); /** * Get a copy of this node and all children. getCopy is recursive, so * beware copying large trees of xml. *@returns A newly created copy of this node and all of it's children. */ - XmlNode *getCopy(); + //XmlNode *getCopy(); + + enum ChildType + { + typeNode, + typeContent + }; private: - std::string sName; /**< The name of the node. */ - std::string *sPreContent; /**< The content that goes before any node. */ - LinkedList lChildren; /**< The children. */ - LinkedList lPostContent; /**< The content that comes after children. */ - HashTable hProperties; /**< Property hashtable. */ - HashTable hChildren; /**< Children hashtable. */ - LinkedList lPropNames; /**< List of property names. */ - LinkedList lPropValues; /**< List of property values. */ + typedef struct + { + uint8_t nType; + union { + XmlNode *pNode; + Bu::FString *pContent; + }; + } Child; + Bu::FString sName; /**< The name of the node. */ + Bu::List lChildren; /**< The children. */ + Bu::Hash hProperties; /**< Property hashtable. */ + Bu::Hash > hChildren; /**< Children hashtable. */ XmlNode *pParent; /**< A pointer to the parent of this node. */ int nCurContent; /**< The current content we're on, for using the -1 on setContent. */ diff --git a/src/xmlreader.cpp b/src/xmlreader.cpp index 18df69c..38cad5f 100644 --- a/src/xmlreader.cpp +++ b/src/xmlreader.cpp @@ -1,32 +1,49 @@ -#include "xmlreader.h" -#include "exceptions.h" +#include "bu/xmlreader.h" +#include "bu/exceptions.h" #include -#include "hashfunctionstring.h" -XmlReader::XmlReader( bool bStrip ) : - bStrip( bStrip ), - htEntity( new HashFunctionString(), 11 ) +XmlReader::XmlReader( Bu::Stream &sIn, bool bStrip ) : + sIn( sIn ), + bStrip( bStrip ) { + buildDoc(); } XmlReader::~XmlReader() { - void *i = htEntity.getFirstItemPos(); - while( (i = htEntity.getNextItemPos( i ) ) ) +} + +char XmlReader::getChar( int nIndex ) +{ + if( sBuf.getSize() <= nIndex ) { - free( (char *)(htEntity.getItemID( i )) ); - delete (StaticString *)htEntity.getItemData( i ); + int nInc = nIndex-sBuf.getSize()+1; + char *buf = new char[nInc]; + sIn.read( buf, nInc ); + sBuf.append( buf, nInc ); + delete[] buf; } + + return sBuf[nIndex]; } -void XmlReader::addEntity( const char *name, const char *value ) +void XmlReader::usedChar( int nAmnt ) { - if( htEntity[name] ) return; - - char *sName = strdup( name ); - StaticString *sValue = new StaticString( value ); + if( nAmnt >= sBuf.getSize() ) + { + sBuf.clear(); + } + else + { + char *s = sBuf.getStr(); + memcpy( s, s+nAmnt, sBuf.getSize()-nAmnt ); + sBuf.resize( sBuf.getSize()-nAmnt ); + } +} - htEntity.insert( sName, sValue ); +void XmlReader::addEntity( const Bu::FString &name, const Bu::FString &value ) +{ + htEntity[name] = value; } #define gcall( x ) if( x == false ) return false; @@ -99,7 +116,7 @@ void XmlReader::entity() { usedChar( 2 ); ws(); - std::string buf; + Bu::FString buf; for(;;) { char chr = getChar(); @@ -111,7 +128,7 @@ void XmlReader::entity() if( strcmp( buf.c_str(), "ENTITY") == 0 ) { ws(); - std::string name; + Bu::FString name; for(;;) { char chr = getChar(); @@ -124,21 +141,19 @@ void XmlReader::entity() usedChar(); if( quot != '\'' && quot != '\"' ) { - throw XmlException( + throw Bu::XmlException( "Only quoted entity values are supported." ); } - std::string value; + Bu::FString value; for(;;) { char chr = getChar(); usedChar(); if( chr == '&' ) { - StaticString *tmp = getEscape(); - if( tmp == NULL ) throw XmlException("Entity thing"); - value += tmp->getString(); - delete tmp; + Bu::FString tmp = getEscape(); + value += tmp; } else if( chr == quot ) { @@ -158,7 +173,7 @@ void XmlReader::entity() } else { - throw XmlException( + throw Bu::XmlException( "Malformed ENTITY: unexpected '%c' found.", getChar() ); @@ -166,7 +181,7 @@ void XmlReader::entity() } else { - throw XmlException( + throw Bu::XmlException( "Unsupported header symbol: %s", buf.c_str() ); @@ -203,12 +218,12 @@ bool XmlReader::node() } else { - throw XmlException("Close node in singleNode malformed!"); + throw Bu::XmlException("Close node in singleNode malformed!"); } } else { - throw XmlException("Close node expected, but not found."); + throw Bu::XmlException("Close node expected, but not found."); return false; } @@ -224,7 +239,7 @@ bool XmlReader::startNode() if( getChar() == '/' ) { // Heh, it's actually a close node, go figure - FlexBuf fbName; + Bu::FString sName; usedChar(); gcall( ws() ); @@ -235,19 +250,19 @@ bool XmlReader::startNode() { // Here we actually compare the name we got to the name // we already set, they have to match exactly. - if( !strcasecmp( getCurrent()->getName(), fbName.getData() ) ) + if( getCurrent()->getName() == sName ) { closeNode(); break; } else { - throw XmlException("Got a mismatched node close tag."); + throw Bu::XmlException("Got a mismatched node close tag."); } } else { - fbName.appendData( chr ); + sName += chr; usedChar(); } } @@ -260,13 +275,13 @@ bool XmlReader::startNode() } else { - throw XmlException("Got extra junk data instead of node close tag."); + throw Bu::XmlException("Got extra junk data instead of node close tag."); } } else { // We're good, format is consistant - addNode(); + //addNode(); // Skip extra whitespace gcall( ws() ); @@ -278,7 +293,7 @@ bool XmlReader::startNode() } else { - throw XmlException("Expected to find node opening char, '<'."); + throw Bu::XmlException("Expected to find node opening char, '<'."); } return true; @@ -286,19 +301,19 @@ bool XmlReader::startNode() bool XmlReader::name() { - FlexBuf fbName; + Bu::FString sName; while( true ) { char chr = getChar(); if( isws( chr ) || chr == '>' || chr == '/' ) { - setName( fbName.getData() ); + addNode( sName ); return true; } else { - fbName.appendData( chr ); + sName += chr; usedChar(); } } @@ -325,7 +340,7 @@ bool XmlReader::paramlist() return true; } -StaticString *XmlReader::getEscape() +Bu::FString XmlReader::getEscape() { if( getChar( 1 ) == '#' ) { @@ -349,12 +364,12 @@ StaticString *XmlReader::getEscape() buf[0] = (char)strtol( buf, (char **)NULL, base ); buf[1] = '\0'; - return new StaticString( buf ); + return buf; } else { // ...otherwise replace with the appropriate string... - std::string buf; + Bu::FString buf; usedChar(); for(;;) { @@ -364,18 +379,14 @@ StaticString *XmlReader::getEscape() buf += cbuf; } - StaticString *tmp = (StaticString *)htEntity[buf.c_str()]; - if( tmp == NULL ) return NULL; - - StaticString *ret = new StaticString( *tmp ); - return ret; + return htEntity[buf]; } } bool XmlReader::param() { - FlexBuf fbName; - FlexBuf fbValue; + Bu::FString sName; + Bu::FString sValue; while( true ) { @@ -386,7 +397,7 @@ bool XmlReader::param() } else { - fbName.appendData( chr ); + sName.append( chr ); usedChar(); } } @@ -411,21 +422,18 @@ bool XmlReader::param() if( chr == '"' ) { usedChar(); - addProperty( fbName.getData(), fbValue.getData() ); + addProperty( sName.getStr(), sValue.getStr() ); return true; } else { if( chr == '&' ) { - StaticString *tmp = getEscape(); - if( tmp == NULL ) return false; - fbValue.appendData( tmp->getString() ); - delete tmp; + sValue += getEscape(); } else { - fbValue.appendData( chr ); + sValue += chr; usedChar(); } } @@ -439,21 +447,18 @@ bool XmlReader::param() chr = getChar(); if( isws( chr ) || chr == '/' || chr == '>' ) { - addProperty( fbName.getData(), fbValue.getData() ); + addProperty( sName.getStr(), sValue.getStr() ); return true; } else { if( chr == '&' ) { - StaticString *tmp = getEscape(); - if( tmp == NULL ) return false; - fbValue.appendData( tmp->getString() ); - delete tmp; + sValue += getEscape(); } else { - fbValue.appendData( chr ); + sValue += chr; usedChar(); } } @@ -462,7 +467,7 @@ bool XmlReader::param() } else { - throw XmlException("Expected an equals to seperate the params."); + throw Bu::XmlException("Expected an equals to seperate the params."); return false; } @@ -471,7 +476,7 @@ bool XmlReader::param() bool XmlReader::content() { - FlexBuf fbContent; + Bu::FString sContent; if( bStrip ) gcall( ws() ); @@ -482,37 +487,37 @@ bool XmlReader::content() { if( getChar(1) == '/' ) { - if( fbContent.getLength() > 0 ) + if( sContent.getSize() > 0 ) { if( bStrip ) { int j; - for( j = fbContent.getLength()-1; isws(fbContent.getData()[j]); j-- ); - ((char *)fbContent.getData())[j+1] = '\0'; + for( j = sContent.getSize()-1; isws(sContent[j]); j-- ); + sContent[j+1] = '\0'; } - setContent( fbContent.getData() ); + setContent( sContent.getStr() ); } usedChar( 2 ); gcall( ws() ); - FlexBuf fbName; + Bu::FString sName; while( true ) { chr = getChar(); if( isws( chr ) || chr == '>' ) { - if( !strcasecmp( getCurrent()->getName(), fbName.getData() ) ) + if( !strcasecmp( getCurrent()->getName().getStr(), sName.getStr() ) ) { closeNode(); break; } else { - throw XmlException("Mismatched close tag found: <%s> to <%s>.", getCurrent()->getName(), fbName.getData() ); + throw Bu::XmlException("Mismatched close tag found: <%s> to <%s>.", getCurrent()->getName().getStr(), sName.getStr() ); } } else { - fbName.appendData( chr ); + sName += chr; usedChar(); } } @@ -524,7 +529,7 @@ bool XmlReader::content() } else { - throw XmlException("Malformed close tag."); + throw Bu::XmlException("Malformed close tag."); } } else if( getChar(1) == '!' ) @@ -534,7 +539,7 @@ bool XmlReader::content() getChar(3) != '-' ) { // Not a valid XML comment - throw XmlException("Malformed comment start tag found."); + throw Bu::XmlException("Malformed comment start tag found."); } usedChar( 4 ); @@ -549,7 +554,7 @@ bool XmlReader::content() // The next one has to be a '>' now if( getChar( 2 ) != '>' ) { - throw XmlException("Malformed comment close tag found. You cannot have a '--' that isn't followed by a '>' in a comment."); + throw Bu::XmlException("Malformed comment close tag found. You cannot have a '--' that isn't followed by a '>' in a comment."); } usedChar( 3 ); break; @@ -569,16 +574,16 @@ bool XmlReader::content() } else { - if( fbContent.getLength() > 0 ) + if( sContent.getSize() > 0 ) { if( bStrip ) { int j; - for( j = fbContent.getLength()-1; isws(fbContent.getData()[j]); j-- ); - ((char *)fbContent.getData())[j+1] = '\0'; + for( j = sContent.getSize()-1; isws(sContent[j]); j-- ); + sContent[j+1] = '\0'; } - setContent( fbContent.getData() ); - fbContent.clearData(); + setContent( sContent.getStr() ); + sContent.clear(); } gcall( node() ); } @@ -587,14 +592,11 @@ bool XmlReader::content() } else if( chr == '&' ) { - StaticString *tmp = getEscape(); - if( tmp == NULL ) return false; - fbContent.appendData( tmp->getString() ); - delete tmp; + sContent += getEscape(); } else { - fbContent.appendData( chr ); + sContent += chr; usedChar(); } } diff --git a/src/xmlreader.h b/src/xmlreader.h index c8f7202..7c85ddb 100644 --- a/src/xmlreader.h +++ b/src/xmlreader.h @@ -2,10 +2,10 @@ #define XMLREADER #include -#include "xmldocument.h" -#include "flexbuf.h" -#include "hashtable.h" -#include "staticstring.h" +#include "bu/xmldocument.h" +#include "bu/hash.h" +#include "bu/fstring.h" +#include "bu/stream.h" /** * Takes care of reading in xml formatted data from a file. This could/should @@ -32,7 +32,7 @@ public: * in content, a-la html. *@param bStrip Strip out leading and trailing whitespace? */ - XmlReader( bool bStrip=false ); + XmlReader( Bu::Stream &sIn, bool bStrip=false ); /** * Destroy this XmlReader. @@ -54,12 +54,12 @@ private: *@returns A single character at the requested position, or 0 for end of * stream. */ - virtual char getChar( int nIndex = 0 ) = 0; + virtual char getChar( int nIndex = 0 ); /** * Called to increment the current stream position by a single character. */ - virtual void usedChar( int nAmnt = 1) = 0; + virtual void usedChar( int nAmnt = 1 ); /** * Automoton function: is whitespace. @@ -108,9 +108,9 @@ private: *@param name The name of the entity *@param value The value of the entity */ - void addEntity( const char *name, const char *value ); + void addEntity( const Bu::FString &name, const Bu::FString &value ); - StaticString *getEscape(); + Bu::FString getEscape(); /** * Automoton function: paramlist. Processes a list of node params. @@ -130,12 +130,15 @@ private: */ bool content(); - FlexBuf fbContent; /**< buffer for the current node's content. */ - FlexBuf fbParamName; /**< buffer for the current param's name. */ - FlexBuf fbParamValue; /**< buffer for the current param's value. */ - bool bStrip; /**< Are we stripping whitespace? */ + Bu::FString sContent; /**< buffer for the current node's content. */ + Bu::FString sParamName; /**< buffer for the current param's name. */ + Bu::FString sParamValue; /**< buffer for the current param's value. */ + Bu::Stream &sIn; + bool bStrip; /**< Are we stripping whitespace? */ - HashTable htEntity; /**< Entity type definitions. */ + Bu::Hash htEntity; /**< Entity type definitions. */ + + Bu::FString sBuf; }; #endif diff --git a/src/xmlwriter.cpp b/src/xmlwriter.cpp index 56880b6..7dc6ca9 100644 --- a/src/xmlwriter.cpp +++ b/src/xmlwriter.cpp @@ -2,17 +2,10 @@ #include #include "xmlwriter.h" -XmlWriter::XmlWriter( const char *sIndent, XmlNode *pRoot ) : - XmlDocument( pRoot ) +XmlWriter::XmlWriter( const Bu::FString &sIndent, XmlNode *pRoot ) : + XmlDocument( pRoot ), + sIndent( sIndent ) { - if( sIndent == NULL ) - { - this->sIndent = ""; - } - else - { - this->sIndent = sIndent; - } } XmlWriter::~XmlWriter() @@ -24,7 +17,7 @@ void XmlWriter::write() write( getRoot(), sIndent.c_str() ); } -void XmlWriter::write( XmlNode *pRoot, const char *sIndent ) +void XmlWriter::write( XmlNode *pRoot, const Bu::FString &sIndent ) { writeNode( pRoot, 0, sIndent ); } @@ -39,7 +32,7 @@ void XmlWriter::closeNode() } } -void XmlWriter::writeIndent( int nIndent, const char *sIndent ) +void XmlWriter::writeIndent( int nIndent, const Bu::FString &sIndent ) { if( sIndent == NULL ) return; for( int j = 0; j < nIndent; j++ ) @@ -48,26 +41,27 @@ void XmlWriter::writeIndent( int nIndent, const char *sIndent ) } } -std::string XmlWriter::escape( std::string sIn ) +Bu::FString XmlWriter::escape( const Bu::FString &sIn ) { - std::string sOut; + Bu::FString sOut; - std::string::const_iterator i; - for( i = sIn.begin(); i != sIn.end(); i++ ) + int nMax = sIn.getSize(); + for( int j = 0; j < nMax; j++ ) { - if( ((*i >= ' ' && *i <= '9') || - (*i >= 'a' && *i <= 'z') || - (*i >= 'A' && *i <= 'Z') ) && - (*i != '\"' && *i != '\'' && *i != '&') + char c = sIn[j]; + if( ((c >= ' ' && c <= '9') || + (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') ) && + (c != '\"' && c != '\'' && c != '&') ) { - sOut += *i; + sOut += c; } else { sOut += "&#"; char buf[4]; - sprintf( buf, "%u", (unsigned char)*i ); + sprintf( buf, "%u", (unsigned char)c ); sOut += buf; sOut += ';'; } @@ -76,19 +70,19 @@ std::string XmlWriter::escape( std::string sIn ) return sOut; } -void XmlWriter::writeNodeProps( XmlNode *pNode, int nIndent, const char *sIndent ) +void XmlWriter::writeNodeProps( XmlNode *pNode, int nIndent, const Bu::FString &sIndent ) { for( int j = 0; j < pNode->getNumProperties(); j++ ) { writeString(" "); - writeString( pNode->getPropertyName( j ) ); + //writeString( pNode->getPropertyName( j ) ); writeString("=\""); - writeString( escape( pNode->getProperty( j ) ).c_str() ); + //writeString( escape( pNode->getProperty( j ) ).c_str() ); writeString("\""); } } -void XmlWriter::writeNode( XmlNode *pNode, int nIndent, const char *sIndent ) +void XmlWriter::writeNode( XmlNode *pNode, int nIndent, const Bu::FString &sIndent ) { if( pNode->hasChildren() ) { @@ -96,15 +90,15 @@ void XmlWriter::writeNode( XmlNode *pNode, int nIndent, const char *sIndent ) writeString("<"); writeString( pNode->getName() ); writeNodeProps( pNode, nIndent, sIndent ); - if( sIndent ) + if( sIndent != "" ) writeString(">\n"); else writeString(">"); - +/* if( pNode->getContent( 0 ) ) { writeIndent( nIndent+1, sIndent ); - if( sIndent ) + if( sIndent != "" ) { writeString( pNode->getContent( 0 ) ); writeString("\n"); @@ -129,9 +123,9 @@ void XmlWriter::writeNode( XmlNode *pNode, int nIndent, const char *sIndent ) writeString( pNode->getContent( j+1 ) ); } } - +*/ writeIndent( nIndent, sIndent ); - if( sIndent ) + if( sIndent != "" ) { writeString("getName() ); @@ -143,7 +137,7 @@ void XmlWriter::writeNode( XmlNode *pNode, int nIndent, const char *sIndent ) writeString( pNode->getName() ); writeString(">"); } - } + }/* else if( pNode->getContent() ) { writeIndent( nIndent, sIndent ); @@ -157,14 +151,14 @@ void XmlWriter::writeNode( XmlNode *pNode, int nIndent, const char *sIndent ) writeString(">"); if( sIndent ) writeString("\n"); - } + }*/ else { writeIndent( nIndent, sIndent ); writeString("<"); writeString( pNode->getName() ); writeNodeProps( pNode, nIndent, sIndent ); - if( sIndent ) + if( sIndent != "" ) writeString("/>\n"); else writeString("/>"); diff --git a/src/xmlwriter.h b/src/xmlwriter.h index c48e810..7e3c876 100644 --- a/src/xmlwriter.h +++ b/src/xmlwriter.h @@ -31,7 +31,7 @@ public: * this to a tab or some spaces it will never effect the content of your * file. */ - XmlWriter( const char *sIndent=NULL, XmlNode *pRoot=NULL ); + XmlWriter( const Bu::FString &sIndent="", XmlNode *pRoot=NULL ); /** * Destroy the writer. @@ -49,16 +49,16 @@ public: void write(); private: - std::string sIndent; /**< The indent string */ + Bu::FString sIndent; /**< The indent string */ - std::string escape( std::string sIn ); + Bu::FString escape( const Bu::FString &sIn ); /** * Write the file. *@param pNode The root node *@param sIndent The indent text. */ - void write( XmlNode *pNode, const char *sIndent=NULL ); + void write( XmlNode *pNode, const Bu::FString &sIndent ); /** * Write a node in the file, including children. @@ -66,7 +66,7 @@ private: *@param nIndent The indent level (the number of times to include sIndent) *@param sIndent The indent text. */ - void writeNode( XmlNode *pNode, int nIndent, const char *sIndent ); + void writeNode( XmlNode *pNode, int nIndent, const Bu::FString &sIndent ); /** * Write the properties of a node. @@ -74,14 +74,14 @@ private: *@param nIndent The indent level of the containing node *@param sIndent The indent text. */ - void writeNodeProps( XmlNode *pNode, int nIndent, const char *sIndent ); + void writeNodeProps( XmlNode *pNode, int nIndent, const Bu::FString &sIndent ); /** * Called to write the actual indent. *@param nIndent The indent level. *@param sIndent The indent text. */ - void writeIndent( int nIndent, const char *sIndent ); + void writeIndent( int nIndent, const Bu::FString &sIndent ); /** * This is the function that must be overridden in order to use this class. @@ -90,7 +90,7 @@ private: * will break the XML formatting. *@param sString The string data to write to the output. */ - virtual void writeString( const char *sString ) = 0; + virtual void writeString( const Bu::FString &sString ) = 0; }; #endif -- cgit v1.2.3 From 326125aee0b8cd807a6a1d158398078ff6bfb1e1 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Thu, 17 May 2007 21:45:50 +0000 Subject: As evidenced by my latest test, the Bu::FString copy is actually slower than the std::string copy by a rather large margin. This seems very odd, so I'm going to do a few tests, the first one is stripping out the FString shared pointer stuff and seeing if that makes an appreciable difference. --- build.conf | 3 ++ src/fstring.h | 4 +- src/old/tests/fstring.cpp | 48 ----------------- src/tests/fstring.cpp | 130 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 136 insertions(+), 49 deletions(-) delete mode 100644 src/old/tests/fstring.cpp create mode 100644 src/tests/fstring.cpp (limited to 'src/fstring.h') diff --git a/build.conf b/build.conf index c289205..35738e3 100644 --- a/build.conf +++ b/build.conf @@ -6,6 +6,9 @@ default action: check group "lnhdrs", check "libbu++.a" set "CXXFLAGS" += "-ggdb -Wall" +#set "CXXFLAGS" += "-pg" +#set "LDFLAGS" += "-pg" + filesIn("src") filter regexp("^src/(.*)\\.h$", "src/bu/{re:1}.h"): rule "hln", group "lnhdrs", diff --git a/src/fstring.h b/src/fstring.h index f738f63..43033b8 100644 --- a/src/fstring.h +++ b/src/fstring.h @@ -7,6 +7,8 @@ #include "archive.h" #include "hash.h" +#define min( a, b ) ((a @@ -131,7 +133,7 @@ namespace Bu appendChunk( pNew ); } - void append( const chr cData ) + void append( const chr &cData ) { append( &cData, 1 ); } diff --git a/src/old/tests/fstring.cpp b/src/old/tests/fstring.cpp deleted file mode 100644 index 271738c..0000000 --- a/src/old/tests/fstring.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "hash.h" -#include "fstring.h" - -FString genThing() -{ - FString bob; - bob.append("ab "); - bob += "cd "; - bob += "efg"; - - printf("---bob------\n%08X: %s\n", (unsigned int)bob.c_str(), bob.c_str() ); - return bob; -} - -void thing( FString str ) -{ - printf("Hey: %s\n", str.c_str() ); -} - -#define pem printf("---------\n%08X: %s\n%08X: %s\n", (unsigned int)str.c_str(), str.c_str(), (unsigned int)str2.c_str(), str2.c_str() ); -int main( int argc, char *argv ) -{ - FString str("th"); - - str.prepend("Hello "); - str.append("ere."); - - FString str2( str ); - pem; - str += " What's up?"; - pem; - str2 += " How are you?"; - pem; - str = str2; - pem; - - str2 = genThing(); - pem; - - str = str2; - pem; - - thing( str2 ); - thing("test."); - - printf("%d == %d\n", __calcHashCode( str ), __calcHashCode( str.c_str() ) ); -} - diff --git a/src/tests/fstring.cpp b/src/tests/fstring.cpp new file mode 100644 index 0000000..d600be6 --- /dev/null +++ b/src/tests/fstring.cpp @@ -0,0 +1,130 @@ +#include "bu/hash.h" +#include "bu/fstring.h" +#include +#include + +inline double getTime() +{ + struct timeval tv; + gettimeofday( &tv, NULL ); + return ((double)tv.tv_sec) + ((double)tv.tv_usec/1000000.0); +} + +Bu::FString genThing() +{ + Bu::FString bob; + bob.append("ab "); + bob += "cd "; + bob += "efg"; + + printf("---bob------\n%08X: %s\n", (unsigned int)bob.c_str(), bob.c_str() ); + return bob; +} + +void thing( Bu::FString str ) +{ + printf("Hey: %s\n", str.c_str() ); +} + +void copyfunc( std::string temp ) +{ + temp += "Hi"; +} + +void copyfunc( Bu::FString temp ) +{ + temp += "Hi"; +} + +void doTimings() +{ + Bu::FString fs1, fs2; + std::string ss1, ss2; + double dStart, dEnd, tfs1, tfs2, tfs3, tss1, tss2, tss3; + int nChars = 500000, nChunks=5000, nCopies=5000000, nChunkSize=1024*4; + char *buf = new char[nChunkSize]; + memset( buf, '!', nChunkSize ); + + printf("Timing Bu::FString single chars...\n"); + dStart = getTime(); + for( int j = 0; j < nChars; j++ ) fs1 += (char)('a'+(j%26)); + fs1.getStr(); + dEnd = getTime(); + tfs1 = dEnd-dStart; + + printf("Timing std::string single chars...\n"); + dStart = getTime(); + for( int j = 0; j < nChars; j++ ) ss1 += (char)('a'+(j%26)); + ss1.c_str(); + dEnd = getTime(); + tss1 = dEnd-dStart; + + printf("Timing Bu::FString %d char chunks...\n", nChunkSize); + dStart = getTime(); + for( int j = 0; j < nChunks; j++ ) fs2.append(buf, nChunkSize); + fs2.getStr(); + dEnd = getTime(); + tfs2 = dEnd-dStart; + + printf("Timing std::string %d char chunks...\n", nChunkSize); + dStart = getTime(); + for( int j = 0; j < nChunks; j++ ) ss2.append(buf, nChunkSize); + ss2.c_str(); + dEnd = getTime(); + tss2 = dEnd-dStart; + + fs2 = "Hello there."; + ss2 = "Hello there."; + printf("Timing Bu::FString copies...\n"); + dStart = getTime(); + for( int j = 0; j < nCopies; j++ ) Bu::FString stmp = fs2; + dEnd = getTime(); + tfs3 = dEnd-dStart; + + printf("Timing std::string copies...\n"); + dStart = getTime(); + for( int j = 0; j < nCopies; j++ ) std::string stpm = ss2; + dEnd = getTime(); + tss3 = dEnd-dStart; + + printf( + "Results: singles: chunks: copies:\n" + "Bu::FString %10.2f/s %10.2f/s %10.2f/s\n" + "std::string %10.2f/s %10.2f/s %10.2f/s\n", + nChars/tfs1, nChunks/tfs2, nCopies/tfs3, + nChars/tss1, nChunks/tss2, nCopies/tss3 ); + + delete[] buf; +} + +#define pem printf("---------\n%08X: %s\n%08X: %s\n", (unsigned int)str.c_str(), str.c_str(), (unsigned int)str2.c_str(), str2.c_str() ); +int main( int argc, char *argv ) +{ + Bu::FString str("th"); + + str.prepend("Hello "); + str.append("ere."); + + Bu::FString str2( str ); + pem; + str += " What's up?"; + pem; + str2 += " How are you?"; + pem; + str = str2; + pem; + + str2 = genThing(); + pem; + + str = str2; + pem; + + thing( str2 ); + thing("test."); + + printf("%d == %d\n", Bu::__calcHashCode( str ), Bu::__calcHashCode( str.c_str() ) ); + + doTimings(); +} + -- cgit v1.2.3 From 9e8a4944e50fab432012878c66e1bdac20649f76 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Thu, 7 Jun 2007 19:56:20 +0000 Subject: The Stream Filter archetecture is finished, it's actually much cooler than I had anticipated, and much cleaner. I'll have to add some documentation to it, because it's not really obvious how any of it fits together from the outset, although I have to say that the bzip2 test program is the easiest general bzip2 compression program I've ever made...it just goes :) Decompression in Bu::BZip2 isn't finished yet, but that's ok, it's coming soon. --- build.conf | 2 + src/bzip2.cpp | 123 ++++++++++++ src/bzip2.h | 35 ++++ src/entities/bu-class | 4 +- src/filter.cpp | 77 ++++++++ src/filter.h | 59 ++++++ src/fstring.h | 6 +- src/old/paramproc.cpp | 514 -------------------------------------------------- src/old/paramproc.h | 153 --------------- src/paramproc.cpp | 514 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/paramproc.h | 156 +++++++++++++++ src/stream.h | 3 + src/tests/bzip2.cpp | 23 +++ 13 files changed, 998 insertions(+), 671 deletions(-) create mode 100644 src/bzip2.cpp create mode 100644 src/bzip2.h create mode 100644 src/filter.cpp create mode 100644 src/filter.h delete mode 100644 src/old/paramproc.cpp delete mode 100644 src/old/paramproc.h create mode 100644 src/paramproc.cpp create mode 100644 src/paramproc.h create mode 100644 src/tests/bzip2.cpp (limited to 'src/fstring.h') diff --git a/build.conf b/build.conf index 35738e3..f493d67 100644 --- a/build.conf +++ b/build.conf @@ -61,6 +61,8 @@ filesIn("src/unit") filter regexp("^src/unit/(.*)\\.cpp$", "unit/{re:1}"): "tests/plugin": set "LDFLAGS" += "-ldl" +"tests/bzip2": set "LDFLAGS" += "-lbz2" + rule "exe": matches regexp("(.*)\\.o$"), aggregate toString(" "), diff --git a/src/bzip2.cpp b/src/bzip2.cpp new file mode 100644 index 0000000..b8c0f74 --- /dev/null +++ b/src/bzip2.cpp @@ -0,0 +1,123 @@ +#include "bu/bzip2.h" +#include "bu/exceptions.h" + +using namespace Bu; + +Bu::BZip2::BZip2( Bu::Stream &rNext, int nCompression ) : + Bu::Filter( rNext ), + nCompression( nCompression ) +{ + start(); +} + +Bu::BZip2::~BZip2() +{ + printf("-> Bu::BZip2::~BZip2()\n"); + stop(); +} + +void Bu::BZip2::start() +{ + printf("-> Bu::BZip2::start()\n"); + printf("Hey, it's starting...\n"); + bzState.state = NULL; + bzState.bzalloc = NULL; + bzState.bzfree = NULL; + bzState.opaque = NULL; + + nBufSize = 50000; + pBuf = new char[nBufSize]; +} + +void Bu::BZip2::stop() +{ + printf("-> Bu::BZip2::stop()\n"); + if( bzState.state ) + { + if( bReading ) + { + } + else + { + for(;;) + { + bzState.next_in = NULL; + bzState.avail_in = 0; + bzState.avail_out = nBufSize; + bzState.next_out = pBuf; + int res = BZ2_bzCompress( &bzState, BZ_FINISH ); + if( bzState.avail_out < nBufSize ) + { + rNext.write( pBuf, nBufSize-bzState.avail_out ); + } + if( res == BZ_STREAM_END ) + break; + } + BZ2_bzCompressEnd( &bzState ); + } + } +} + +void Bu::BZip2::bzError( int code ) +{ + switch( code ) + { + case BZ_OK: + return; + + case BZ_CONFIG_ERROR: + throw ExceptionBase("The bzip2 library has been miscompiled."); + + case BZ_PARAM_ERROR: + throw ExceptionBase("bzip2 parameter error."); + + case BZ_MEM_ERROR: + throw ExceptionBase("Not enough memory available for bzip2."); + } +} + +size_t Bu::BZip2::read( void *pData, size_t nBytes ) +{ + if( !bzState.state ) + { + bReading = true; + } + if( bReading == false ) + throw ExceptionBase("This bzip2 filter is in writing mode, you can't read."); + //bzState.next_in = pData; + //bzState.avail_in = nSizeIn; + + //printf("%db at [%08X] (%db)\n", bzState.avail_in, (uint32_t)bzState.next_in, bzState.total_in_lo32 ); + return 0; +} + +size_t Bu::BZip2::write( const void *pData, size_t nBytes ) +{ + if( !bzState.state ) + { + bReading = false; + BZ2_bzCompressInit( &bzState, nCompression, 0, 30 ); + } + if( bReading == true ) + throw ExceptionBase("This bzip2 filter is in reading mode, you can't write."); + + bzState.next_in = (char *)pData; + bzState.avail_in = nBytes; + for(;;) + { + bzState.avail_out = nBufSize; + bzState.next_out = pBuf; + + BZ2_bzCompress( &bzState, BZ_RUN ); + + if( bzState.avail_out < nBufSize ) + { + rNext.write( pBuf, nBufSize-bzState.avail_out ); + } + if( bzState.avail_in == 0 ) + break; + } + + return 0; +} + diff --git a/src/bzip2.h b/src/bzip2.h new file mode 100644 index 0000000..056f336 --- /dev/null +++ b/src/bzip2.h @@ -0,0 +1,35 @@ +#ifndef B_ZIP2_H +#define B_ZIP2_H + +#include +#include + +#include "bu/filter.h" + +namespace Bu +{ + /** + * + */ + class BZip2 : public Bu::Filter + { + public: + BZip2( Bu::Stream &rNext, int nCompression=9 ); + virtual ~BZip2(); + + virtual void start(); + virtual void stop(); + virtual size_t read( void *pBuf, size_t nBytes ); + virtual size_t write( const void *pBuf, size_t nBytes ); + + private: + void bzError( int code ); + bz_stream bzState; + bool bReading; + int nCompression; + char *pBuf; + uint32_t nBufSize; + }; +} + +#endif diff --git a/src/entities/bu-class b/src/entities/bu-class index 81e3d25..7b25291 100644 --- a/src/entities/bu-class +++ b/src/entities/bu-class @@ -10,7 +10,7 @@ #include <stdint.h> -{?parent:"#include \"{=parent:%tolower}.h\" +{?parent:"#include \"bu/{=parent:%tolower}.h\" "}namespace Bu { @@ -35,6 +35,8 @@ filename="{=name:%tolower}.cpp" >#include "bu/{=name:%tolower}.h" +using namespace Bu; + Bu::{=name}::{=name}() { } diff --git a/src/filter.cpp b/src/filter.cpp new file mode 100644 index 0000000..d3faa00 --- /dev/null +++ b/src/filter.cpp @@ -0,0 +1,77 @@ +#include "bu/filter.h" + +Bu::Filter::Filter( Bu::Stream &rNext ) : + rNext( rNext ) +{ +} + +Bu::Filter::~Filter() +{ + printf("-> Bu::Filter::~Filter()\n"); +} +/* +void Bu::Filter::start() +{ + printf("-> Bu::Filter::start()\n"); +} + +void Bu::Filter::stop() +{ +}*/ + +void Bu::Filter::close() +{ + stop(); + rNext.close(); +} + +long Bu::Filter::tell() +{ + return rNext.tell(); +} + +void Bu::Filter::seek( long offset ) +{ + rNext.seek( offset ); +} + +void Bu::Filter::setPos( long pos ) +{ + rNext.setPos( pos ); +} + +void Bu::Filter::setPosEnd( long pos ) +{ + rNext.setPosEnd( pos ); +} + +bool Bu::Filter::isEOS() +{ + return rNext.isEOS(); +} + +bool Bu::Filter::canRead() +{ + return rNext.canRead(); +} + +bool Bu::Filter::canWrite() +{ + return rNext.canWrite(); +} + +bool Bu::Filter::canSeek() +{ + return rNext.canSeek(); +} + +bool Bu::Filter::isBlocking() +{ + return rNext.isBlocking(); +} + +void Bu::Filter::setBlocking( bool bBlocking ) +{ + rNext.setBlocking( bBlocking ); +} + diff --git a/src/filter.h b/src/filter.h new file mode 100644 index 0000000..b068206 --- /dev/null +++ b/src/filter.h @@ -0,0 +1,59 @@ +#ifndef FILTER_H +#define FILTER_H + +#include + +#include "bu/stream.h" + +namespace Bu +{ + /** + * Data filter base class. Each data filter should contain a read and write + * section. Effectively, the write applies the filter, the read un-applies + * the filter, if possible. For example, BZip2 is a filter that compresses + * on write and decompresses on read. All bi-directional filters should + * follow: x == read( write( x ) ) (byte-for-byte comparison) + * + * Also, all returned buffers should be owned by the filter, and deleted + * when the filter is deleted. This means that the output of a read or + * write operation must be used before the next call to read or write or the + * data will be destroyed. Also, the internal buffer may be changed or + * recreated between calls, so always get a new pointer from a call to + * read or write. + * + * The close function can also return data, so make sure to check for it, + * many filters such as compression filters will buffer data until they have + * enough to create a compression block, in these cases the leftover data + * will be returned by close. + */ + class Filter : public Bu::Stream + { + public: + Filter( Bu::Stream &rNext ); + virtual ~Filter(); + + virtual void start()=0; + virtual void stop()=0; + virtual void close(); + virtual long tell(); + virtual void seek( long offset ); + virtual void setPos( long pos ); + virtual void setPosEnd( long pos ); + virtual bool isEOS(); + + virtual bool canRead(); + virtual bool canWrite(); + virtual bool canSeek(); + + virtual bool isBlocking(); + virtual void setBlocking( bool bBlocking=true ); + + protected: + Bu::Stream &rNext; + + private: + + }; +} + +#endif diff --git a/src/fstring.h b/src/fstring.h index 43033b8..d0307b5 100644 --- a/src/fstring.h +++ b/src/fstring.h @@ -3,9 +3,9 @@ #include #include -#include "archival.h" -#include "archive.h" -#include "hash.h" +#include "bu/archival.h" +#include "bu/archive.h" +#include "bu/hash.h" #define min( a, b ) ((a - -#define ptrtype( iitype, iiname ) \ - ParamProc::ParamPtr::ParamPtr( iitype *iiname ) : \ - type( vt ##iiname ) { val.iiname = iiname; } - -ParamProc::ParamPtr::ParamPtr() -{ - val.str = NULL; - type = vtunset; -} - -ptrtype( std::string, str ); -ptrtype( uint64_t, uint64 ); -ptrtype( uint32_t, uint32 ); -ptrtype( uint16_t, uint16 ); -ptrtype( uint8_t, uint8 ); -ptrtype( int64_t, int64 ); -ptrtype( int32_t, int32 ); -ptrtype( int16_t, int16 ); -ptrtype( int8_t, int8 ); -ptrtype( float, float32 ); -ptrtype( double, float64 ); -ptrtype( long double, float96 ); -ptrtype( bool, bln ); - -ParamProc::ParamPtr &ParamProc::ParamPtr::operator=( ParamProc::ParamPtr &ptr ) -{ - val = ptr.val; - type = ptr.type; - - return *this; -} - -bool ParamProc::ParamPtr::isSet() -{ - return type != vtunset; -} - -ParamProc::ParamPtr &ParamProc::ParamPtr::operator=( const char *str ) -{ - if( !isSet() ) return *this; - switch( type ) - { - case vtstr: - (*val.str) = str; - break; - - case vtuint64: - (*val.uint64) = strtoull( str, NULL, 10 ); - break; - - case vtuint32: - (*val.uint32) = strtoul( str, NULL, 10 ); - break; - - case vtuint16: - (*val.uint16) = (uint16_t)strtoul( str, NULL, 10 ); - break; - - case vtuint8: - (*val.uint8) = (uint8_t)strtoul( str, NULL, 10 ); - break; - - case vtint64: - (*val.int64) = strtoll( str, NULL, 10 ); - break; - - case vtint32: - (*val.int32) = strtol( str, NULL, 10 ); - break; - - case vtint16: - (*val.int16) = (int16_t)strtol( str, NULL, 10 ); - break; - - case vtint8: - (*val.int8) = (int8_t)strtol( str, NULL, 10 ); - break; - - case vtfloat32: - (*val.float32) = strtof( str, NULL ); - break; - - case vtfloat64: - (*val.float64) = strtod( str, NULL ); - break; - - case vtfloat96: - (*val.float96) = strtold( str, NULL ); - break; - - case vtbln: - if( strcasecmp("yes", str ) == 0 || - strcasecmp("true", str ) == 0 ) - { - (*val.bln) = true; - } - else - { - (*val.bln) = false; - } - break; - } - - return *this; -} - -ParamProc::ParamProc() -{ -} - -ParamProc::~ParamProc() -{ - for( std::list::iterator i = lArg.begin(); - i != lArg.end(); i++ ) - { - delete *i; - } - - for( std::list::iterator i = lBan.begin(); - i != lBan.end(); i++ ) - { - delete *i; - } - -} -/* -void ParamProc::addParam( const char *lpWord, char cChar, Proc proc, ParamPtr val ) -{ - printf("Calling callback...\n"); - val = "Hello there, this is set in the ParamProc"; - (this->*proc)(); -}*/ - -void ParamProc::addParam( const char *lpWord, char cChar, Proc proc, - ParamPtr val, const char *lpDesc, const char *lpExtra, - const char *lpValue ) -{ - ArgSpec *as = new ArgSpec; - if( lpWord ) - as->sWord = lpWord; - - as->cChar = cChar; - as->proc = proc; - as->val = val; - if( lpDesc ) - as->sDesc = lpDesc; - if( lpExtra ) - as->sExtra = lpExtra; - if( lpValue ) - as->sValue = lpValue; - - lArg.push_back( as ); - - if( !lBan.empty() ) - { - if( lBan.back()->pBefore == NULL ) - lBan.back()->pBefore = as; - } -} - -void ParamProc::addParam( const char *lpWord, char cChar, Proc proc, - const char *lpDesc, const char *lpExtra, - const char *lpValue ) -{ - addParam( lpWord, cChar, proc, ParamPtr(), lpDesc, lpExtra, lpValue ); -} - -void ParamProc::addParam( const char *lpWord, char cChar, ParamPtr val, - const char *lpDesc, const char *lpExtra, - const char *lpValue ) -{ - addParam( lpWord, cChar, NULL, val, lpDesc, lpExtra, lpValue ); -} - -void ParamProc::addParam( const char *lpWord, Proc proc, ParamPtr val, - const char *lpDesc, const char *lpExtra, - const char *lpValue ) -{ - addParam( lpWord, '\0', proc, val, lpDesc, lpExtra, lpValue ); -} - -void ParamProc::addParam( const char *lpWord, Proc proc, - const char *lpDesc, const char *lpExtra, - const char *lpValue ) -{ - addParam( lpWord, '\0', proc, ParamPtr(), lpDesc, lpExtra, lpValue ); -} - -void ParamProc::addParam( const char *lpWord, ParamPtr val, - const char *lpDesc, const char *lpExtra, - const char *lpValue ) -{ - addParam( lpWord, '\0', NULL, val, lpDesc, lpExtra, lpValue ); -} - -void ParamProc::addParam( char cChar, Proc proc, ParamPtr val, - const char *lpDesc, const char *lpExtra, - const char *lpValue ) -{ - addParam( NULL, cChar, proc, val, lpDesc, lpExtra, lpValue ); -} - -void ParamProc::addParam( char cChar, Proc proc, - const char *lpDesc, const char *lpExtra, - const char *lpValue ) -{ - addParam( NULL, cChar, proc, ParamPtr(), lpDesc, lpExtra, lpValue ); -} - -void ParamProc::addParam( char cChar, ParamPtr val, - const char *lpDesc, const char *lpExtra, - const char *lpValue ) -{ - addParam( NULL, cChar, NULL, val, lpDesc, lpExtra, lpValue ); -} - -void ParamProc::process( int argc, char *argv[] ) -{ - for( int arg = 1; arg < argc; arg++ ) - { - //printf(":::%d:::%s\n", arg, argv[arg] ); - if( argv[arg][0] == '-' ) - { - if( argv[arg][1] == '-' ) - { - ArgSpec *s = checkWord( argv[arg]+2 ); - if( s ) - { - if( argv[arg][s->sWord.getLength()+2] == '=' ) - { - if( s->val.isSet() ) - { - if( s->sValue.getString() == NULL ) - { - s->val = argv[arg]+s->sWord.getLength()+3; - } - else - { - s->val = s->sValue.getString(); - } - } - if( s->proc ) - { - char **tmp = new char*[argc-arg]; - tmp[0] = argv[arg]+s->sWord.getLength()+3; - for( int k = 1; k < argc-arg; k++ ) - tmp[k] = argv[arg+k]; - int ret = (this->*s->proc)( argc-arg, tmp ); - if( ret > 0 ) - { - arg += ret-1; - } - delete tmp; - } - } - else - { - int add = 0; - if( s->val.isSet() ) - { - if( s->sValue.getString() == NULL ) - { - if( arg+1 >= argc ) - { - return; - } - s->val = argv[arg+1]; - add++; - } - else - { - s->val = s->sValue.getString(); - } - } - if( s->proc ) - { - int ret = (this->*s->proc)( - argc-arg-1, argv+arg+1 ); - - if( ret > add ) - add = 0; - else - add -= ret; - arg += ret; - } - arg += add; - } - continue; - } - else - { - unknownParam( argc-arg, argv+arg ); - } - } - else - { - for( int chr = 1; argv[arg][chr]; chr++ ) - { - ArgSpec *s = checkLetr( argv[arg][chr] ); - if( s ) - { - if( argv[arg][chr+1] != '\0' ) - { - bool bUsed = false; - if( s->val.isSet() ) - { - if( s->sValue.getString() == NULL ) - { - s->val = argv[arg]+chr+1; - bUsed = true; - } - else - { - s->val = s->sValue.getString(); - } - } - if( s->proc ) - { - char **tmp = new char*[argc-arg]; - tmp[0] = argv[arg]+chr+1; - for( int k = 1; k < argc-arg; k++ ) - tmp[k] = argv[arg+k]; - int ret = (this->*s->proc)( argc-arg, tmp ); - if( ret > 0 ) - { - arg += ret - 1; - delete tmp; - break; - } - delete tmp; - } - if( bUsed ) - { - break; - } - } - else - { - bool bUsed = false; - if( s->val.isSet() ) - { - if( s->sValue.getString() == NULL ) - { - s->val = argv[arg+1]; - bUsed = true; - } - else - { - s->val = s->sValue.getString(); - } - } - if( s->proc ) - { - int ret = (this->*s->proc)( - argc-arg-1, argv+arg+1 - ); - if( ret > 0 ) - { - arg += ret; - break; - } - } - if( bUsed ) - { - arg++; - break; - } - } - } - else - { - unknownParam( argc-arg, argv+arg ); - } - } - } - } - else - { - cmdParam( argc-arg, argv+arg ); - } - } -} - -ParamProc::ArgSpec *ParamProc::checkWord( const char *arg ) -{ - //printf("Checking \"%s\"...\n", arg ); - std::list::const_iterator i; - for( i = lArg.begin(); i != lArg.end(); i++ ) - { - if( (*i)->sWord.getString() == NULL ) - continue; - - if( !strcmp( (*i)->sWord, arg ) ) - return *i; - - if( (*i)->val.isSet() ) - { - if( !strncmp( (*i)->sWord, arg, (*i)->sWord.getLength() ) && - arg[(*i)->sWord.getLength()] == '=' ) - { - return *i; - } - } - } - - return NULL; -} - -ParamProc::ArgSpec *ParamProc::checkLetr( const char arg ) -{ - //printf("Checking \'%c\'...\n", arg ); - std::list::const_iterator i; - for( i = lArg.begin(); i != lArg.end(); i++ ) - { - if( (*i)->cChar == '\0' ) - continue; - - if( (*i)->cChar == arg ) - { - return *i; - } - } - - return NULL; -} - -int ParamProc::cmdParam( int argc, char *argv[] ) -{ - printf("Unhandled command parameter \"%s\" found!\n", argv[0] ); - return 0; -} - -int ParamProc::unknownParam( int argc, char *argv[] ) -{ - printf("Unknown parameter \"%s\" found!\n", argv[0] ); - return 0; -} - -int ParamProc::help( int argc, char *argv[] ) -{ - std::list::const_iterator b = lBan.begin(); - std::list::const_iterator i; - int len=0; - for( i = lArg.begin(); i != lArg.end(); i++ ) - { - if( len < (*i)->sWord.getLength() + (*i)->sExtra.getLength() ) - len = (*i)->sWord.getLength() + (*i)->sExtra.getLength(); - } - char fmt[10]; - sprintf( fmt, "%%-%ds ", len ); - - for( i = lArg.begin(); i != lArg.end(); i++ ) - { - if( b != lBan.end() ) - { - if( (*b)->pBefore == (*i) ) - { - printf( (*b)->sBanner.getString() ); - b++; - } - } - printf(" "); - if( (*i)->cChar ) - { - if( (*i)->sWord.getString() ) - { - printf("-%c, ", (*i)->cChar ); - } - else - { - printf("-%c ", (*i)->cChar ); - } - } - else - { - printf(" "); - } - if( (*i)->sWord.getString() ) - { - printf("--"); - std::string sTmp = (*i)->sWord.getString(); - if( (*i)->sExtra.getString() ) - sTmp += (*i)->sExtra.getString(); - printf( fmt, sTmp.c_str() ); - } - else - { - printf(" "); - printf(fmt, "" ); - } - printf("%s\n", (*i)->sDesc.getString() ); - } - if( b != lBan.end() ) - { - if( (*b)->pBefore == NULL ) - { - printf( (*b)->sBanner.getString() ); - } - } - - exit( 0 ); -} - -void ParamProc::addHelpBanner( const char *sHelpBanner ) -{ - Banner *pBan = new Banner; - pBan->sBanner = sHelpBanner; - pBan->pBefore = NULL; - lBan.push_back( pBan ); -} - diff --git a/src/old/paramproc.h b/src/old/paramproc.h deleted file mode 100644 index d857193..0000000 --- a/src/old/paramproc.h +++ /dev/null @@ -1,153 +0,0 @@ -#ifndef PARAM_PROC_H -#define PARAM_PROC_H - -#include -#include -#include -#include "staticstring.h" - -class ParamProc -{ -public: - class ParamPtr - { - public: - ParamPtr(); - ParamPtr( std::string *str ); - ParamPtr( uint64_t *uint64 ); - ParamPtr( uint32_t *uint32 ); - ParamPtr( uint16_t *uint16 ); - ParamPtr( uint8_t *uint8 ); - ParamPtr( int64_t *int64 ); - ParamPtr( int32_t *int32 ); - ParamPtr( int16_t *int16 ); - ParamPtr( int8_t *int8 ); - ParamPtr( float *float32 ); - ParamPtr( double *float64 ); - ParamPtr( long double *float96 ); - ParamPtr( bool *bln ); - - enum - { - vtunset, - vtstr, - vtuint64, - vtuint32, - vtuint16, - vtuint8, - vtint64, - vtint32, - vtint16, - vtint8, - vtfloat32, - vtfloat64, - vtfloat96, - vtbln, - }; - ParamPtr &operator=( ParamPtr &ptr ); - ParamPtr &operator=( const char *str ); - - bool isSet(); - - private: - int type; - union - { - std::string *str; - uint64_t *uint64; - uint32_t *uint32; - uint16_t *uint16; - uint8_t *uint8; - int64_t *int64; - int32_t *int32; - int16_t *int16; - int8_t *int8; - float *float32; - double *float64; - long double *float96; - bool *bln; - } val; - }; - - typedef int (ParamProc::*Proc)( int, char *[] ); - - typedef struct ArgSpec - { - uint8_t nFlags; - StaticString sWord; - char cChar; - Proc proc; - ParamProc::ParamPtr val; - StaticString sExtra; - StaticString sDesc; - StaticString sValue; - } ArgSpec; - -public: - ParamProc(); - virtual ~ParamProc(); - - void addParam( const char *lpWord, char cChar, Proc proc, ParamPtr val, - const char *lpDesc=NULL, const char *lpExtra=NULL, - const char *lpValue=NULL - ); - void addParam( const char *lpWord, char cChar, Proc proc, - const char *lpDesc=NULL, const char *lpExtra=NULL, - const char *lpValue=NULL - ); - void addParam( const char *lpWord, char cChar, ParamPtr val, - const char *lpDesc=NULL, const char *lpExtra=NULL, - const char *lpValue=NULL - ); - - void addParam( const char *lpWord, Proc proc, ParamPtr val, - const char *lpDesc=NULL, const char *lpExtra=NULL, - const char *lpValue=NULL - ); - void addParam( const char *lpWord, Proc proc, - const char *lpDesc=NULL, const char *lpExtra=NULL, - const char *lpValue=NULL - ); - void addParam( const char *lpWord, ParamPtr val, - const char *lpDesc=NULL, const char *lpExtra=NULL, - const char *lpValue=NULL - ); - - void addParam( char cChar, Proc proc, ParamPtr val, - const char *lpDesc=NULL, const char *lpExtra=NULL, - const char *lpValue=NULL - ); - void addParam( char cChar, Proc proc, - const char *lpDesc=NULL, const char *lpExtra=NULL, - const char *lpValue=NULL - ); - void addParam( char cChar, ParamPtr val, - const char *lpDesc=NULL, const char *lpExtra=NULL, - const char *lpValue=NULL - ); - - void process( int argc, char *argv[] ); - void addHelpBanner( const char *sHelpBanner ); - -private: - ArgSpec *checkWord( const char *arg ); - ArgSpec *checkLetr( const char arg ); - -public: - virtual int cmdParam( int argc, char *argv[] ); - virtual int unknownParam( int argc, char *argv[] ); - virtual int help( int argc, char *argv[] ); - -private: - typedef struct Banner - { - StaticString sBanner; - ArgSpec *pBefore; - } Banner; - std::list lBan; - std::list lArg; -}; - -#define mkproc( cls ) static_cast(&cls) - -#endif diff --git a/src/paramproc.cpp b/src/paramproc.cpp new file mode 100644 index 0000000..34e973e --- /dev/null +++ b/src/paramproc.cpp @@ -0,0 +1,514 @@ +#include "paramproc.h" +#include + +#define ptrtype( iitype, iiname ) \ + Bu::ParamProc::ParamPtr::ParamPtr( iitype *iiname ) : \ + type( vt ##iiname ) { val.iiname = iiname; } + +Bu::ParamProc::ParamPtr::ParamPtr() +{ + val.str = NULL; + type = vtunset; +} + +ptrtype( std::string, str ); +ptrtype( uint64_t, uint64 ); +ptrtype( uint32_t, uint32 ); +ptrtype( uint16_t, uint16 ); +ptrtype( uint8_t, uint8 ); +ptrtype( int64_t, int64 ); +ptrtype( int32_t, int32 ); +ptrtype( int16_t, int16 ); +ptrtype( int8_t, int8 ); +ptrtype( float, float32 ); +ptrtype( double, float64 ); +ptrtype( long double, float96 ); +ptrtype( bool, bln ); + +Bu::ParamProc::ParamPtr &Bu::ParamProc::ParamPtr::operator=( ParamProc::ParamPtr &ptr ) +{ + val = ptr.val; + type = ptr.type; + + return *this; +} + +bool Bu::ParamProc::ParamPtr::isSet() +{ + return type != vtunset; +} + +Bu::ParamProc::ParamPtr &Bu::ParamProc::ParamPtr::operator=( const char *str ) +{ + if( !isSet() ) return *this; + switch( type ) + { + case vtstr: + (*val.str) = str; + break; + + case vtuint64: + (*val.uint64) = strtoull( str, NULL, 10 ); + break; + + case vtuint32: + (*val.uint32) = strtoul( str, NULL, 10 ); + break; + + case vtuint16: + (*val.uint16) = (uint16_t)strtoul( str, NULL, 10 ); + break; + + case vtuint8: + (*val.uint8) = (uint8_t)strtoul( str, NULL, 10 ); + break; + + case vtint64: + (*val.int64) = strtoll( str, NULL, 10 ); + break; + + case vtint32: + (*val.int32) = strtol( str, NULL, 10 ); + break; + + case vtint16: + (*val.int16) = (int16_t)strtol( str, NULL, 10 ); + break; + + case vtint8: + (*val.int8) = (int8_t)strtol( str, NULL, 10 ); + break; + + case vtfloat32: + (*val.float32) = strtof( str, NULL ); + break; + + case vtfloat64: + (*val.float64) = strtod( str, NULL ); + break; + + case vtfloat96: + (*val.float96) = strtold( str, NULL ); + break; + + case vtbln: + if( strcasecmp("yes", str ) == 0 || + strcasecmp("true", str ) == 0 ) + { + (*val.bln) = true; + } + else + { + (*val.bln) = false; + } + break; + } + + return *this; +} + +Bu::ParamProc::ParamProc() +{ +} + +Bu::ParamProc::~ParamProc() +{ + for( std::list::iterator i = lArg.begin(); + i != lArg.end(); i++ ) + { + delete *i; + } + + for( std::list::iterator i = lBan.begin(); + i != lBan.end(); i++ ) + { + delete *i; + } + +} +/* +void Bu::ParamProc::addParam( const char *lpWord, char cChar, Proc proc, ParamPtr val ) +{ + printf("Calling callback...\n"); + val = "Hello there, this is set in the ParamProc"; + (this->*proc)(); +}*/ + +void Bu::ParamProc::addParam( const char *lpWord, char cChar, Proc proc, + ParamPtr val, const char *lpDesc, const char *lpExtra, + const char *lpValue ) +{ + ArgSpec *as = new ArgSpec; + if( lpWord ) + as->sWord = lpWord; + + as->cChar = cChar; + as->proc = proc; + as->val = val; + if( lpDesc ) + as->sDesc = lpDesc; + if( lpExtra ) + as->sExtra = lpExtra; + if( lpValue ) + as->sValue = lpValue; + + lArg.push_back( as ); + + if( !lBan.empty() ) + { + if( lBan.back()->pBefore == NULL ) + lBan.back()->pBefore = as; + } +} + +void Bu::ParamProc::addParam( const char *lpWord, char cChar, Proc proc, + const char *lpDesc, const char *lpExtra, + const char *lpValue ) +{ + addParam( lpWord, cChar, proc, ParamPtr(), lpDesc, lpExtra, lpValue ); +} + +void Bu::ParamProc::addParam( const char *lpWord, char cChar, ParamPtr val, + const char *lpDesc, const char *lpExtra, + const char *lpValue ) +{ + addParam( lpWord, cChar, NULL, val, lpDesc, lpExtra, lpValue ); +} + +void Bu::ParamProc::addParam( const char *lpWord, Proc proc, ParamPtr val, + const char *lpDesc, const char *lpExtra, + const char *lpValue ) +{ + addParam( lpWord, '\0', proc, val, lpDesc, lpExtra, lpValue ); +} + +void Bu::ParamProc::addParam( const char *lpWord, Proc proc, + const char *lpDesc, const char *lpExtra, + const char *lpValue ) +{ + addParam( lpWord, '\0', proc, ParamPtr(), lpDesc, lpExtra, lpValue ); +} + +void Bu::ParamProc::addParam( const char *lpWord, ParamPtr val, + const char *lpDesc, const char *lpExtra, + const char *lpValue ) +{ + addParam( lpWord, '\0', NULL, val, lpDesc, lpExtra, lpValue ); +} + +void Bu::ParamProc::addParam( char cChar, Proc proc, ParamPtr val, + const char *lpDesc, const char *lpExtra, + const char *lpValue ) +{ + addParam( NULL, cChar, proc, val, lpDesc, lpExtra, lpValue ); +} + +void Bu::ParamProc::addParam( char cChar, Proc proc, + const char *lpDesc, const char *lpExtra, + const char *lpValue ) +{ + addParam( NULL, cChar, proc, ParamPtr(), lpDesc, lpExtra, lpValue ); +} + +void Bu::ParamProc::addParam( char cChar, ParamPtr val, + const char *lpDesc, const char *lpExtra, + const char *lpValue ) +{ + addParam( NULL, cChar, NULL, val, lpDesc, lpExtra, lpValue ); +} + +void Bu::ParamProc::process( int argc, char *argv[] ) +{ + for( int arg = 1; arg < argc; arg++ ) + { + //printf(":::%d:::%s\n", arg, argv[arg] ); + if( argv[arg][0] == '-' ) + { + if( argv[arg][1] == '-' ) + { + ArgSpec *s = checkWord( argv[arg]+2 ); + if( s ) + { + if( argv[arg][s->sWord.getSize()+2] == '=' ) + { + if( s->val.isSet() ) + { + if( s->sValue.getStr() == NULL ) + { + s->val = argv[arg]+s->sWord.getSize()+3; + } + else + { + s->val = s->sValue.getStr(); + } + } + if( s->proc ) + { + char **tmp = new char*[argc-arg]; + tmp[0] = argv[arg]+s->sWord.getSize()+3; + for( int k = 1; k < argc-arg; k++ ) + tmp[k] = argv[arg+k]; + int ret = (this->*s->proc)( argc-arg, tmp ); + if( ret > 0 ) + { + arg += ret-1; + } + delete tmp; + } + } + else + { + int add = 0; + if( s->val.isSet() ) + { + if( s->sValue.getStr() == NULL ) + { + if( arg+1 >= argc ) + { + return; + } + s->val = argv[arg+1]; + add++; + } + else + { + s->val = s->sValue.getStr(); + } + } + if( s->proc ) + { + int ret = (this->*s->proc)( + argc-arg-1, argv+arg+1 ); + + if( ret > add ) + add = 0; + else + add -= ret; + arg += ret; + } + arg += add; + } + continue; + } + else + { + unknownParam( argc-arg, argv+arg ); + } + } + else + { + for( int chr = 1; argv[arg][chr]; chr++ ) + { + ArgSpec *s = checkLetr( argv[arg][chr] ); + if( s ) + { + if( argv[arg][chr+1] != '\0' ) + { + bool bUsed = false; + if( s->val.isSet() ) + { + if( s->sValue.getStr() == NULL ) + { + s->val = argv[arg]+chr+1; + bUsed = true; + } + else + { + s->val = s->sValue.getStr(); + } + } + if( s->proc ) + { + char **tmp = new char*[argc-arg]; + tmp[0] = argv[arg]+chr+1; + for( int k = 1; k < argc-arg; k++ ) + tmp[k] = argv[arg+k]; + int ret = (this->*s->proc)( argc-arg, tmp ); + if( ret > 0 ) + { + arg += ret - 1; + delete tmp; + break; + } + delete tmp; + } + if( bUsed ) + { + break; + } + } + else + { + bool bUsed = false; + if( s->val.isSet() ) + { + if( s->sValue.getStr() == NULL ) + { + s->val = argv[arg+1]; + bUsed = true; + } + else + { + s->val = s->sValue.getStr(); + } + } + if( s->proc ) + { + int ret = (this->*s->proc)( + argc-arg-1, argv+arg+1 + ); + if( ret > 0 ) + { + arg += ret; + break; + } + } + if( bUsed ) + { + arg++; + break; + } + } + } + else + { + unknownParam( argc-arg, argv+arg ); + } + } + } + } + else + { + cmdParam( argc-arg, argv+arg ); + } + } +} + +Bu::ParamProc::ArgSpec *Bu::ParamProc::checkWord( const char *arg ) +{ + //printf("Checking \"%s\"...\n", arg ); + std::list::const_iterator i; + for( i = lArg.begin(); i != lArg.end(); i++ ) + { + if( (*i)->sWord.getStr() == NULL ) + continue; + + if( !strcmp( (*i)->sWord.getStr(), arg ) ) + return *i; + + if( (*i)->val.isSet() ) + { + if( !strncmp( (*i)->sWord.getStr(), arg, (*i)->sWord.getSize() ) && + arg[(*i)->sWord.getSize()] == '=' ) + { + return *i; + } + } + } + + return NULL; +} + +Bu::ParamProc::ArgSpec *Bu::ParamProc::checkLetr( const char arg ) +{ + //printf("Checking \'%c\'...\n", arg ); + std::list::const_iterator i; + for( i = lArg.begin(); i != lArg.end(); i++ ) + { + if( (*i)->cChar == '\0' ) + continue; + + if( (*i)->cChar == arg ) + { + return *i; + } + } + + return NULL; +} + +int Bu::ParamProc::cmdParam( int argc, char *argv[] ) +{ + printf("Unhandled command parameter \"%s\" found!\n", argv[0] ); + return 0; +} + +int Bu::ParamProc::unknownParam( int argc, char *argv[] ) +{ + printf("Unknown parameter \"%s\" found!\n", argv[0] ); + return 0; +} + +int Bu::ParamProc::help( int argc, char *argv[] ) +{ + std::list::const_iterator b = lBan.begin(); + std::list::const_iterator i; + int len=0; + for( i = lArg.begin(); i != lArg.end(); i++ ) + { + if( len < (*i)->sWord.getSize() + (*i)->sExtra.getSize() ) + len = (*i)->sWord.getSize() + (*i)->sExtra.getSize(); + } + char fmt[10]; + sprintf( fmt, "%%-%ds ", len ); + + for( i = lArg.begin(); i != lArg.end(); i++ ) + { + if( b != lBan.end() ) + { + if( (*b)->pBefore == (*i) ) + { + printf( (*b)->sBanner.getStr() ); + b++; + } + } + printf(" "); + if( (*i)->cChar ) + { + if( (*i)->sWord.getStr() ) + { + printf("-%c, ", (*i)->cChar ); + } + else + { + printf("-%c ", (*i)->cChar ); + } + } + else + { + printf(" "); + } + if( (*i)->sWord.getStr() ) + { + printf("--"); + std::string sTmp = (*i)->sWord.getStr(); + if( (*i)->sExtra.getStr() ) + sTmp += (*i)->sExtra.getStr(); + printf( fmt, sTmp.c_str() ); + } + else + { + printf(" "); + printf(fmt, "" ); + } + printf("%s\n", (*i)->sDesc.getStr() ); + } + if( b != lBan.end() ) + { + if( (*b)->pBefore == NULL ) + { + printf( (*b)->sBanner.getStr() ); + } + } + + exit( 0 ); +} + +void Bu::ParamProc::addHelpBanner( const char *sHelpBanner ) +{ + Banner *pBan = new Banner; + pBan->sBanner = sHelpBanner; + pBan->pBefore = NULL; + lBan.push_back( pBan ); +} + diff --git a/src/paramproc.h b/src/paramproc.h new file mode 100644 index 0000000..beee4a0 --- /dev/null +++ b/src/paramproc.h @@ -0,0 +1,156 @@ +#ifndef PARAM_PROC_H +#define PARAM_PROC_H + +#include +#include +#include +#include "bu/fstring.h" + +namespace Bu +{ + class ParamProc + { + public: + class ParamPtr + { + public: + ParamPtr(); + ParamPtr( std::string *str ); + ParamPtr( uint64_t *uint64 ); + ParamPtr( uint32_t *uint32 ); + ParamPtr( uint16_t *uint16 ); + ParamPtr( uint8_t *uint8 ); + ParamPtr( int64_t *int64 ); + ParamPtr( int32_t *int32 ); + ParamPtr( int16_t *int16 ); + ParamPtr( int8_t *int8 ); + ParamPtr( float *float32 ); + ParamPtr( double *float64 ); + ParamPtr( long double *float96 ); + ParamPtr( bool *bln ); + + enum + { + vtunset, + vtstr, + vtuint64, + vtuint32, + vtuint16, + vtuint8, + vtint64, + vtint32, + vtint16, + vtint8, + vtfloat32, + vtfloat64, + vtfloat96, + vtbln, + }; + ParamPtr &operator=( ParamPtr &ptr ); + ParamPtr &operator=( const char *str ); + + bool isSet(); + + private: + int type; + union + { + std::string *str; + uint64_t *uint64; + uint32_t *uint32; + uint16_t *uint16; + uint8_t *uint8; + int64_t *int64; + int32_t *int32; + int16_t *int16; + int8_t *int8; + float *float32; + double *float64; + long double *float96; + bool *bln; + } val; + }; + + typedef int (ParamProc::*Proc)( int, char *[] ); + + typedef struct ArgSpec + { + uint8_t nFlags; + Bu::FString sWord; + char cChar; + Proc proc; + ParamProc::ParamPtr val; + Bu::FString sExtra; + Bu::FString sDesc; + Bu::FString sValue; + } ArgSpec; + + public: + ParamProc(); + virtual ~ParamProc(); + + void addParam( const char *lpWord, char cChar, Proc proc, ParamPtr val, + const char *lpDesc=NULL, const char *lpExtra=NULL, + const char *lpValue=NULL + ); + void addParam( const char *lpWord, char cChar, Proc proc, + const char *lpDesc=NULL, const char *lpExtra=NULL, + const char *lpValue=NULL + ); + void addParam( const char *lpWord, char cChar, ParamPtr val, + const char *lpDesc=NULL, const char *lpExtra=NULL, + const char *lpValue=NULL + ); + + void addParam( const char *lpWord, Proc proc, ParamPtr val, + const char *lpDesc=NULL, const char *lpExtra=NULL, + const char *lpValue=NULL + ); + void addParam( const char *lpWord, Proc proc, + const char *lpDesc=NULL, const char *lpExtra=NULL, + const char *lpValue=NULL + ); + void addParam( const char *lpWord, ParamPtr val, + const char *lpDesc=NULL, const char *lpExtra=NULL, + const char *lpValue=NULL + ); + + void addParam( char cChar, Proc proc, ParamPtr val, + const char *lpDesc=NULL, const char *lpExtra=NULL, + const char *lpValue=NULL + ); + void addParam( char cChar, Proc proc, + const char *lpDesc=NULL, const char *lpExtra=NULL, + const char *lpValue=NULL + ); + void addParam( char cChar, ParamPtr val, + const char *lpDesc=NULL, const char *lpExtra=NULL, + const char *lpValue=NULL + ); + + void process( int argc, char *argv[] ); + void addHelpBanner( const char *sHelpBanner ); + + private: + ArgSpec *checkWord( const char *arg ); + ArgSpec *checkLetr( const char arg ); + + public: + virtual int cmdParam( int argc, char *argv[] ); + virtual int unknownParam( int argc, char *argv[] ); + virtual int help( int argc, char *argv[] ); + + private: + typedef struct Banner + { + Bu::FString sBanner; + ArgSpec *pBefore; + } Banner; + std::list lBan; + std::list lArg; + }; +} + +#define mkproc( cls ) static_cast(&cls) + +#endif diff --git a/src/stream.h b/src/stream.h index 5f586e6..fa0a606 100644 --- a/src/stream.h +++ b/src/stream.h @@ -39,6 +39,9 @@ namespace Bu virtual bool isBlocking() = 0; virtual void setBlocking( bool bBlocking=true ) = 0; + public: // Filters + + private: }; diff --git a/src/tests/bzip2.cpp b/src/tests/bzip2.cpp new file mode 100644 index 0000000..683d3d7 --- /dev/null +++ b/src/tests/bzip2.cpp @@ -0,0 +1,23 @@ +#include "bu/bzip2.h" +#include "bu/file.h" + +int main( int argc, char *argv[] ) +{ + char buf[1024]; + size_t nRead; + + Bu::File f( "test.bz2", "wb" ); + Bu::BZip2 bz2( f ); + + Bu::File fin( argv[1], "rb"); + + for(;;) + { + nRead = fin.read( buf, 1024 ); + if( nRead > 0 ) + bz2.write( buf, nRead ); + if( fin.isEOS() ) + break; + } +} + -- cgit v1.2.3 From 7ba47b5b688afd7e04b38a3e0e4aa018c10a9a59 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Mon, 11 Jun 2007 16:03:46 +0000 Subject: Corrected another issue with the prefix * iterator operator in Bu::Hash, it was still trying to use a pair internally. Also added more helpers to FString. --- src/fstring.h | 19 ++++++++++++++----- src/hash.h | 2 +- 2 files changed, 15 insertions(+), 6 deletions(-) (limited to 'src/fstring.h') diff --git a/src/fstring.h b/src/fstring.h index d0307b5..7dda87c 100644 --- a/src/fstring.h +++ b/src/fstring.h @@ -138,6 +138,11 @@ namespace Bu append( &cData, 1 ); } + void prepend( const MyType & sData ) + { + prepend( sData.getStr(), sData.getSize() ); + } + void prepend( const chr *pData ) { long nLen; @@ -413,17 +418,21 @@ namespace Bu clear(); long nLen; ar >> nLen; - - Chunk *pNew = newChunk( nLen ); - ar.read( pNew->pData, nLen*sizeof(chr) ); - appendChunk( pNew ); + + if( nLen > 0 ) + { + Chunk *pNew = newChunk( nLen ); + ar.read( pNew->pData, nLen*sizeof(chr) ); + appendChunk( pNew ); + } } else { flatten(); ar << nLength; - ar.write( pFirst->pData, nLength*sizeof(chr) ); + if( nLength ) + ar.write( pFirst->pData, nLength*sizeof(chr) ); } } diff --git a/src/hash.h b/src/hash.h index f6c207f..1bb25c9 100644 --- a/src/hash.h +++ b/src/hash.h @@ -458,7 +458,7 @@ namespace Bu value &operator *() { - return hsh.getAtPos( nPos ); + return hsh.getValueAtPos( nPos ); } key &getKey() -- cgit v1.2.3 From b6f50f249ba3b18c597531a2d5dbc45f7bfa3eaa Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Mon, 11 Jun 2007 21:58:10 +0000 Subject: Another few fixes for zero-length strings in fstring. --- src/fstring.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/fstring.h') diff --git a/src/fstring.h b/src/fstring.h index 7dda87c..93a0042 100644 --- a/src/fstring.h +++ b/src/fstring.h @@ -117,6 +117,8 @@ namespace Bu { long nLen; for( nLen = 0; pData[nLen] != (chr)0; nLen++ ); + if( nLen == 0 ) + return; Chunk *pNew = newChunk( nLen ); cpy( pNew->pData, pData, nLen ); @@ -126,6 +128,9 @@ namespace Bu void append( const chr *pData, long nLen ) { + if( nLen == 0 ) + return; + Chunk *pNew = newChunk( nLen ); cpy( pNew->pData, pData, nLen ); @@ -235,6 +240,8 @@ namespace Bu MyType &operator +=( const MyType &rSrc ) { + if( rSrc.nLength == 0 ) + return (*this); rSrc.flatten(); append( rSrc.pFirst->pData, rSrc.nLength ); @@ -612,6 +619,8 @@ namespace Bu { if( isShared() == false ) return; + if( pFirst == NULL ) + return; Chunk *pNew = newChunk( nLength ); chr *pos = pNew->pData; -- cgit v1.2.3 From 5292e5831934dc719d1ac06332bd252abe4ac3bc Mon Sep 17 00:00:00 2001 From: David Date: Mon, 18 Jun 2007 19:41:34 +0000 Subject: david - writing code documentation... --- src/fstring.h | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/hash.h | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/list.h | 15 ++++++ 3 files changed, 306 insertions(+) (limited to 'src/fstring.h') diff --git a/src/fstring.h b/src/fstring.h index 93a0042..9d88bd4 100644 --- a/src/fstring.h +++ b/src/fstring.h @@ -29,6 +29,11 @@ namespace Bu * almost no overhead in time or memory since a reference is created and no * data is actually copied. This also means that you never need to put any * FBasicString into a ref-counting container class. + * + *@param chr (typename) Type of character (i.e. char) + *@param nMinSize (int) Chunk size (default: 256) + *@param chralloc (typename) Memory Allocator for chr + *@param chunkalloc (typename) Memory Allocator for chr chunks */ template< typename chr, int nMinSize=256, typename chralloc=std::allocator, typename chunkalloc=std::allocator > > class FBasicString : public Archival @@ -113,6 +118,14 @@ namespace Bu clear(); } + /** + *@todo void append( const MyType & sData ) + */ + + /** + * Append data to your string. + *@param pData (const chr *) The data to append. + */ void append( const chr *pData ) { long nLen; @@ -126,6 +139,11 @@ namespace Bu appendChunk( pNew ); } + /** + * Append data to your string. + *@param pData (const chr *) The data to append. + *@param nLen (long) The length of the data to append. + */ void append( const chr *pData, long nLen ) { if( nLen == 0 ) @@ -138,16 +156,28 @@ namespace Bu appendChunk( pNew ); } + /** + * Append a single chr to your string. + *@param cData (const chr &) The character to append. + */ void append( const chr &cData ) { append( &cData, 1 ); } + /** + * Prepend another FString to this one. + *@param sData (MyType &) The FString to prepend. + */ void prepend( const MyType & sData ) { prepend( sData.getStr(), sData.getSize() ); } + /** + * Prepend data to your string. + *@param pData (const chr *) The data to prepend. + */ void prepend( const chr *pData ) { long nLen; @@ -159,6 +189,11 @@ namespace Bu prependChunk( pNew ); } + /** + * Prepend data to your string. + *@param pData (const chr *) The data to prepend. + *@param nLen (long) The length of the data to prepend. + */ void prepend( const chr *pData, long nLen ) { Chunk *pNew = newChunk( nLen ); @@ -168,11 +203,22 @@ namespace Bu prependChunk( pNew ); } + /** + *@todo void prepend( const chr &cData ) + */ + + /** + * Clear all data from the string. + */ void clear() { realClear(); } + /** + * Force the string to resize + *@param nNewSize (long) The new size of the string. + */ void resize( long nNewSize ) { if( nLength == nNewSize ) @@ -190,11 +236,19 @@ namespace Bu nLength = nNewSize; } + /** + * Get the current size of the string. + *@returns (long) The current size of the string. + */ long getSize() const { return nLength; } + /** + * Get a pointer to the string array. + *@returns (chr *) The string data. + */ chr *getStr() { if( pFirst == NULL ) @@ -204,6 +258,10 @@ namespace Bu return pFirst->pData; } + /** + * Get a const pointer to the string array. + *@returns (const chr *) The string data. + */ const chr *getStr() const { if( pFirst == NULL ) @@ -213,6 +271,10 @@ namespace Bu return pFirst->pData; } + /** + * (std::string compatability) Get a pointer to the string array. + *@returns (chr *) The string data. + */ chr *c_str() { if( pFirst == NULL ) @@ -222,6 +284,10 @@ namespace Bu return pFirst->pData; } + /** + * (std::string compatability) Get a const pointer to the string array. + *@returns (const chr *) The string data. + */ const chr *c_str() const { if( pFirst == NULL ) @@ -231,6 +297,10 @@ namespace Bu return pFirst->pData; } + /** + * Plus equals operator for FString. + *@param pData (const chr *) The data to append to your FString. + */ MyType &operator +=( const chr *pData ) { append( pData ); @@ -238,6 +308,10 @@ namespace Bu return (*this); } + /** + * Plus equals operator for FString. + *@param pData (const MyType &) The FString to append to your FString. + */ MyType &operator +=( const MyType &rSrc ) { if( rSrc.nLength == 0 ) @@ -248,6 +322,10 @@ namespace Bu return (*this); } + /** + * Plus equals operator for FString. + *@param pData (const chr) The character to append to your FString. + */ MyType &operator +=( const chr pData ) { append( &pData, 1 ); @@ -255,6 +333,11 @@ namespace Bu return (*this); } + /** + * Assignment operator. + *@param pData (const chr *) The character array to append to your + * FString. + */ MyType &operator =( const chr *pData ) { clear(); @@ -263,18 +346,31 @@ namespace Bu return (*this); } + /** + * Reset your FString to this character array. + *@param pData (const chr *) The character array to set your FString to. + */ void set( const chr *pData ) { clear(); append( pData ); } + /** + * Reset your FString to this character array. + *@param pData (const chr *) The character array to set your FString to. + *@param nSize (long) The length of the inputted character array. + */ void set( const chr *pData, long nSize ) { clear(); append( pData, nSize ); } + /** + * Assignment operator. + *@param rSrc (const MyType &) The FString to set your FString to. + */ MyType &operator =( const MyType &rSrc ) { //if( rSrc.isFlat() ) @@ -290,6 +386,11 @@ namespace Bu return (*this); } + /** + * Equals comparison operator. + *@param pData (const chr *) The character array to compare your FString + * to. + */ bool operator ==( const chr *pData ) const { if( pFirst == NULL ) { @@ -310,6 +411,10 @@ namespace Bu return true; } + /** + * Equals comparison operator. + *@param pData (const MyType &) The FString to compare your FString to. + */ bool operator ==( const MyType &pData ) const { if( pFirst == pData.pFirst ) @@ -330,16 +435,30 @@ namespace Bu return true; } + /** + * Not equals comparison operator. + *@param pData (const chr *) The character array to compare your FString + * to. + */ bool operator !=(const chr *pData ) const { return !(*this == pData); } + /** + * Not equals comparison operator. + *@param pData (const MyType &) The FString to compare your FString to. + */ bool operator !=(const MyType &pData ) const { return !(*this == pData); } + /** + * Indexing operator + *@param nIndex (long) The index of the character you want. + *@returns (chr &) The character at position (nIndex). + */ chr &operator[]( long nIndex ) { flatten(); @@ -347,6 +466,11 @@ namespace Bu return pFirst->pData[nIndex]; } + /** + * Const indexing operator + *@param nIndex (long) The index of the character you want. + *@returns (const chr &) The character at position (nIndex). + */ const chr &operator[]( long nIndex ) const { flatten(); @@ -354,6 +478,11 @@ namespace Bu return pFirst->pData[nIndex]; } + /** + * Is the character at index (nIndex) white space? + *@param nIndex (long) The index of the character you want to check. + *@returns (bool) Is it white space? + */ bool isWS( long nIndex ) const { flatten(); @@ -362,6 +491,11 @@ namespace Bu || pFirst->pData[nIndex]=='\r' || pFirst->pData[nIndex]=='\n'; } + /** + * Is the character at index (nIndex) a letter? + *@param nIndex (long) The index of the character you want to check. + *@returns (bool) Is it a letter? + */ bool isAlpha( long nIndex ) const { flatten(); @@ -370,6 +504,9 @@ namespace Bu || (pFirst->pData[nIndex] >= 'A' && pFirst->pData[nIndex] <= 'Z'); } + /** + * Convert your alpha characters to lower case. + */ void toLower() { flatten(); @@ -382,6 +519,9 @@ namespace Bu } } + /** + * Convert your alpha characters to upper case. + */ void toUpper() { flatten(); @@ -394,6 +534,11 @@ namespace Bu } } + /** + * Find the index of the first occurrance of (sText) + *@param sText (const char *) The string to search for. + *@returns (long) The index of the first occurrance. -1 for not found. + */ long find( const char *sText ) { long nTLen = strlen( sText ); @@ -406,6 +551,11 @@ namespace Bu return -1; } + /** + * Do a reverse search for (sText) + *@param sText (const char *) The string to search for. + *@returns (long) The index of the last occurrance. -1 for not found. + */ long rfind( const char *sText ) { long nTLen = strlen( sText ); @@ -418,6 +568,10 @@ namespace Bu return -1; } + /** + * Function the archiver calls to archive your FString. + *@param ar (Archive) The archive which is archiving your FString. + */ void archive( class Archive &ar ) { if( ar.isLoading() ) diff --git a/src/hash.h b/src/hash.h index 1bb25c9..6c4a443 100644 --- a/src/hash.h +++ b/src/hash.h @@ -71,6 +71,10 @@ namespace Bu bool bFilled; public: + /** + * Cast operator for HashProxy. + *@returns (value_type &) The value the HashProxy is pointing to. + */ operator _value &() { if( bFilled == false ) @@ -81,6 +85,10 @@ namespace Bu return *pValue; } + /** + * Direct function for retrieving a value out of the HashProxy. + *@returns (value_type &) The value pointed to by this HashProxy. + */ _value &value() { if( bFilled == false ) @@ -91,11 +99,17 @@ namespace Bu return *pValue; } + /** + * Whether this HashProxy points to something real or not. + */ bool isFilled() { return bFilled; } + /** + * Erase the data pointed to by this HashProxy. + */ void erase() { if( bFilled ) @@ -105,6 +119,10 @@ namespace Bu } } + /** + * Assign data to this point in the hash table. + *@param nval (value_type) the data to assign. + */ _value operator=( _value nval ) { if( bFilled ) @@ -122,6 +140,11 @@ namespace Bu return nval; } + /** + * Pointer extraction operator. Access to members of data pointed to + * by HashProxy. + *@returns (value_type *) + */ _value *operator->() { if( bFilled == false ) @@ -133,6 +156,15 @@ namespace Bu } }; + /** + * Libbu Template Hash Table + *@param key (typename) The datatype of the hashtable keys + *@param value (typename) The datatype of the hashtable data + *@param sizecalc (typename) Functor to compute new table size on rehash + *@param keyalloc (typename) Memory allocator for hashtable keys + *@param valuealloc (typename) Memory allocator for hashtable values + *@param challoc (typename) Byte allocator for bitflags + */ template class Hash { @@ -186,6 +218,10 @@ namespace Bu } } + /** + * Hashtable assignment operator. Clears this hashtable and + * copies RH into it. + */ Hash &operator=( const Hash &src ) { for( uint32_t j = 0; j < nCapacity; j++ ) @@ -244,26 +280,49 @@ namespace Bu ca.deallocate( aHashCodes, nCapacity ); } + /** + * Get the current hash table capacity. (Changes at re-hash) + *@returns (uint32_t) The current capacity. + */ uint32_t getCapacity() { return nCapacity; } + /** + * Get the number of hash locations spoken for. (Including + * not-yet-cleaned-up deleted items.) + *@returns (uint32_t) The current fill state. + */ uint32_t getFill() { return nFilled; } + /** + * Get the number of items stored in the hash table. + *@returns (uint32_t) The number of items stored in the hash table. + */ uint32_t size() { return nFilled-nDeleted; } + /** + * Get the number of items which have been deleted, but not yet + * cleaned up. + *@returns (uint32_t) The number of deleted items. + */ uint32_t getDeleted() { return nDeleted; } + /** + * Hash table index operator + *@param k (key_type) Key of data to be retrieved. + *@returns (HashProxy) Proxy pointing to the data. + */ virtual HashProxy operator[]( key k ) { uint32_t hash = __calcHashCode( k ); @@ -280,6 +339,11 @@ namespace Bu } } + /** + * Insert a value (v) under key (k) into the hash table + *@param k (key_type) Key to list the value under. + *@param v (value_type) Value to store in the hash table. + */ virtual void insert( key k, value v ) { uint32_t hash = __calcHashCode( k ); @@ -299,6 +363,10 @@ namespace Bu } } + /** + * Remove a value from the hash table. + *@param k (key_type) The data under this key will be erased. + */ virtual void erase( key k ) { uint32_t hash = __calcHashCode( k ); @@ -313,6 +381,11 @@ namespace Bu } struct iterator; + + /** + * Remove a value from the hash pointed to from an iterator. + *@param i (iterator &) The data to be erased. + */ virtual void erase( struct iterator &i ) { if( this != &i.hsh ) @@ -324,6 +397,9 @@ namespace Bu } } + /** + * Remove all data from the hash table. + */ virtual void clear() { for( uint32_t j = 0; j < nCapacity; j++ ) @@ -340,6 +416,11 @@ namespace Bu clearBits(); } + /** + * Get an item of data from the hash table. + *@param k (key_type) Key pointing to the data to be retrieved. + *@returns (value_type &) The data pointed to by (k). + */ virtual value &get( key k ) { uint32_t hash = __calcHashCode( k ); @@ -359,6 +440,12 @@ namespace Bu } } + /** + * Get a const item of data from the hash table. + *@param k (key_type) Key pointing to the data to be retrieved. + *@returns (const value_type &) A const version of the data pointed + * to by (k). + */ virtual const value &get( key k ) const { uint32_t hash = __calcHashCode( k ); @@ -378,6 +465,11 @@ namespace Bu } } + /** + * Does the hash table contain an item under key (k). + *@param k (key_type) The key to check. + *@returns (bool) Whether there was an item in the hash under key (k). + */ virtual bool has( key k ) { bool bFill; @@ -386,6 +478,9 @@ namespace Bu return bFill; } + /** + * Iteration structure for iterating through the hash. + */ typedef struct iterator { friend class Hash; @@ -410,6 +505,9 @@ namespace Bu bool bFinished; public: + /** + * Iterator incrementation operator. Move the iterator forward. + */ iterator operator++( int ) { if( bFinished == false ) @@ -418,6 +516,9 @@ namespace Bu return *this; } + /** + * Iterator incrementation operator. Move the iterator forward. + */ iterator operator++() { if( bFinished == false ) @@ -426,6 +527,9 @@ namespace Bu return *this; } + /** + * Iterator equality comparison operator. Iterators the same? + */ bool operator==( const iterator &oth ) { if( bFinished != oth.bFinished ) @@ -442,11 +546,17 @@ namespace Bu } } + /** + * Iterator not equality comparison operator. Not the same? + */ bool operator!=( const iterator &oth ) { return !(*this == oth ); } + /** + * Iterator assignment operator. + */ iterator operator=( const iterator &oth ) { if( &hsh != &oth.hsh ) @@ -456,32 +566,59 @@ namespace Bu bFinished = oth.bFinished; } + /** + * Iterator dereference operator... err.. get the value + *@returns (value_type &) The value behind this iterator. + */ value &operator *() { return hsh.getValueAtPos( nPos ); } + /** + * Get the key behind this iterator. + *@returns (key_type &) The key behind this iterator. + */ key &getKey() { return hsh.getKeyAtPos( nPos ); } + /** + * Get the value behind this iterator. + *@returs (value_type &) The value behind this iterator. + */ value &getValue() { return hsh.getValueAtPos( nPos ); } }; + /** + * Get an iterator pointing to the first item in the hash table. + *@returns (iterator) An iterator pointing to the first item in the + * hash table. + */ iterator begin() { return iterator( *this ); } + /** + * Get an iterator pointing to a point just past the last item in the + * hash table. + *@returns (iterator) An iterator pointing to a point just past the + * last item in the hash table. + */ iterator end() { return iterator( *this, true ); } + /** + * Get a list of all the keys in the hash table. + *@returns (std::list) The list of keys in the hash table. + */ std::list getKeys() { std::list lKeys; diff --git a/src/list.h b/src/list.h index 4131987..9d1f904 100644 --- a/src/list.h +++ b/src/list.h @@ -21,6 +21,10 @@ namespace Bu * members are only accessable const. Third, erasing a location does not * invalidate the iterator, it simply points to the next valid location, or * end() if there are no more. + * + *@param value (typename) The type of data to store in your list + *@param valuealloc (typename) Memory Allocator for your value type + *@param linkalloc (typename) Memory Allocator for the list links. */ template, typename linkalloc=std::allocator > > class List @@ -53,6 +57,10 @@ namespace Bu clear(); } + /** + * Assignment operator. + *@param src (const MyType &) The list to assign to your list. + */ MyType &operator=( const MyType &src ) { clear(); @@ -62,6 +70,9 @@ namespace Bu } } + /** + * Clear the data from the list. + */ void clear() { Link *pCur = pFirst; @@ -79,6 +90,10 @@ namespace Bu nSize = 0; } + /** + * Append a value to the list. + *@param v (const value_type &) The value to append. + */ void append( const value &v ) { Link *pNew = la.allocate( 1 ); -- cgit v1.2.3 From aa82dc64b397b6ca0d336d91638d4f4b849e3667 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Tue, 26 Jun 2007 05:10:58 +0000 Subject: Fixed a minor bug in FString, and added the Logger and a test...it's cool, and a decent replacement for multilog now that we use runit. --- src/fstring.h | 1 + src/logger.cpp | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/logger.h | 112 ++++++++++++++++++++++++++++++++++++++++++++++ src/tests/logger.cpp | 28 ++++++++++++ 4 files changed, 264 insertions(+) create mode 100644 src/logger.cpp create mode 100644 src/logger.h create mode 100644 src/tests/logger.cpp (limited to 'src/fstring.h') diff --git a/src/fstring.h b/src/fstring.h index 9d88bd4..fe34804 100644 --- a/src/fstring.h +++ b/src/fstring.h @@ -128,6 +128,7 @@ namespace Bu */ void append( const chr *pData ) { + if( !pData ) return; long nLen; for( nLen = 0; pData[nLen] != (chr)0; nLen++ ); if( nLen == 0 ) diff --git a/src/logger.cpp b/src/logger.cpp new file mode 100644 index 0000000..848dfb1 --- /dev/null +++ b/src/logger.cpp @@ -0,0 +1,123 @@ +#include "bu/logger.h" +#include +#include +#include + +Bu::Logger::Logger() +{ +} + +Bu::Logger::~Logger() +{ +} + +void Bu::Logger::log( int nLevel, const char *sFile, const char *sFunction, int nLine, const char *sFormat, ...) +{ + if( (nLevel&nLevelMask) == 0 ) + return; + + va_list ap; + va_start( ap, sFormat ); + char *text; + vasprintf( &text, sFormat, ap ); + va_end(ap); + + time_t t = time(NULL); + + char *line = NULL; + struct tm *pTime; + pTime = localtime( &t ); + asprintf( + &line, + sLogFormat.getStr(), + pTime->tm_year+1900, + pTime->tm_mon+1, + pTime->tm_mday, + pTime->tm_hour, + pTime->tm_min, + pTime->tm_sec, + nLevel, + sFile, + nLine, + text, + sFunction + ); + write( fileno(stdout), line, strlen(line) ); + free( text ); + free( line ); +} + +void Bu::Logger::setFormat( const Bu::FString &str ) +{ + sLogFormat = ""; + + static char fmts[][4]={ + {'y', 'd', '0', '1'}, + {'m', 'd', '0', '2'}, + {'d', 'd', '0', '3'}, + {'h', 'd', '0', '4'}, + {'M', 'd', '0', '5'}, + {'s', 'd', '0', '6'}, + {'L', 'd', '0', '7'}, + {'f', 's', '0', '8'}, + {'l', 'd', '0', '9'}, + {'t', 's', '1', '0'}, + {'F', 's', '1', '1'}, + {'\0', '\0', '\0', '\0'}, + }; + + for( const char *s = str.getStr(); *s; s++ ) + { + if( *s == '%' ) + { + sLogFormat += '%'; + s++; + for( int l = 0;; l++ ) + { + if( fmts[l][0] == '\0' ) + { + sLogFormat += *s; + break; + } + else if( *s == fmts[l][0] ) + { + sLogFormat += fmts[l][2]; + sLogFormat += fmts[l][3]; + sLogFormat += '$'; + sLogFormat += fmts[l][1]; + break; + } + } + } + else + { + sLogFormat += *s; + } + } + sLogFormat += '\n'; + + write( fileno(stdout), sLogFormat.getStr(), sLogFormat.getSize() ); +} + +void Bu::Logger::setMask( int n ) +{ + nLevelMask = n; +} + +void Bu::Logger::setLevel( int n ) +{ + int j; + for( j = 31; j > 0; j-- ) + { + if( (n&(1<= 0; j-- ) + { + n |= (1< + { + friend class Bu::Singleton; + private: + Logger(); + virtual ~Logger(); + + public: + void log( int nLevel, const char *sFile, const char *sFunction, int nLine, const char *sFormat, ...); + + void setFormat( const Bu::FString &str ); + void setMask( int n ); + void setLevel( int n ); + + private: + Bu::FString sLogFormat; + int nLevelMask; + }; +} + +/** + * Use Bu::Logger to log a message at the given level and with the given message + * using printf style formatting, and include extra data such as the current + * file, line number, and function. + */ +#define lineLog( nLevel, sFrmt, ...) \ + Bu::Logger::getInstance().log( nLevel, __FILE__, __PRETTY_FUNCTION__, __LINE__, sFrmt, ##__VA_ARGS__ ) + +/** + * Set the Bu::Logger logging mask directly. See Bu::Logger::setMask for + * details. + */ +#define setLogMask( nLevel ) \ + Bu::Logger::getInstance().setMask( nLevel ) + +/** + * Set the Bu::Logger format. See Bu::Logger::setFormat for details. + */ +#define setLogFormat( sFrmt ) \ + Bu::Logger::getInstance().setFormat( sFrmt ) + +/** + * Set the Bu::Logger logging mask simulating levels. See Bu::Logger::setLevel + * for details. + */ +#define setLogLevel( nLevel ) \ + Bu::Logger::getInstance().setLevel( nLevel ) + +#endif diff --git a/src/tests/logger.cpp b/src/tests/logger.cpp new file mode 100644 index 0000000..a271443 --- /dev/null +++ b/src/tests/logger.cpp @@ -0,0 +1,28 @@ +#include "bu/logger.h" +#include +#include + +class Thing +{ + public: + Thing() + { + lineLog( 2, "Want a thing?"); + } + + void go( int i ) + { + lineLog( 1, "GO!!!!"); + } +}; + +int main() +{ + setLogLevel( 4 ); + setLogFormat("%L: %y-%m-%d %h:%M:%s %f:%l:%F: %t"); + lineLog( 5, "Hey, error: %s", strerror( errno ) ); + + Thing gh; + gh.go( 6); +} + -- cgit v1.2.3 From 686ed62f519d66ac43315fb20dfb7233b839411d Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Wed, 27 Jun 2007 19:57:23 +0000 Subject: Added more functions to fstring, now it has isSet and a bool cast operator. These allow you to see if there is anything set in the fstring. --- src/fstring.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/fstring.h') diff --git a/src/fstring.h b/src/fstring.h index fe34804..21a07ce 100644 --- a/src/fstring.h +++ b/src/fstring.h @@ -479,6 +479,16 @@ namespace Bu return pFirst->pData[nIndex]; } + operator bool() const + { + return (pFirst != NULL); + } + + bool isSet() const + { + return (pFirst != NULL); + } + /** * Is the character at index (nIndex) white space? *@param nIndex (long) The index of the character you want to check. -- cgit v1.2.3 From d79253e87306607a0985abaeba0b87242f3532b7 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Wed, 27 Jun 2007 21:58:51 +0000 Subject: More fstring stuff. --- src/fstring.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/fstring.h') diff --git a/src/fstring.h b/src/fstring.h index 21a07ce..7180f5f 100644 --- a/src/fstring.h +++ b/src/fstring.h @@ -479,6 +479,13 @@ namespace Bu return pFirst->pData[nIndex]; } + operator const chr *() const + { + if( !pFirst ) return NULL; + flatten(); + return pFirst->pData; + } + operator bool() const { return (pFirst != NULL); -- cgit v1.2.3 From 932677862376e9642a496a15b7f09f1106f495a5 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Thu, 28 Jun 2007 20:49:39 +0000 Subject: Many minor changes, hopefully the header fixes will keep future header macro conflicts from happening. And, from now on, other projects should do -Ilibbu++ not -Ilibbu++/src so we can get ready for an installed version of libbu++. --- bu | 1 + src/archival.h | 4 ++-- src/archive.h | 4 ++-- src/atom.h | 4 ++-- src/bzip2.h | 4 ++-- src/client.h | 4 ++-- src/exceptionbase.h | 4 ++-- src/exceptions.h | 4 ++-- src/file.h | 4 ++-- src/filter.h | 4 ++-- src/fstring.h | 4 ++-- src/hash.h | 4 ++-- src/ito.h | 4 ++-- src/itoatom.h | 4 ++-- src/itocondition.h | 4 ++-- src/itomutex.h | 4 ++-- src/itoqueue.h | 4 ++-- src/linkmessage.h | 4 ++-- src/list.h | 4 ++-- src/membuf.h | 4 ++-- src/paramproc.h | 4 ++-- src/plugger.h | 4 ++-- src/programchain.h | 4 ++-- src/programlink.h | 4 ++-- src/protocol.h | 4 ++-- src/ringbuffer.h | 4 ++-- src/server.h | 4 ++-- src/serversocket.h | 4 ++-- src/singleton.h | 4 ++-- src/socket.h | 4 ++-- src/sptr.h | 4 ++-- src/stream.h | 4 ++-- src/unitsuite.h | 4 ++-- 33 files changed, 65 insertions(+), 64 deletions(-) create mode 120000 bu (limited to 'src/fstring.h') diff --git a/bu b/bu new file mode 120000 index 0000000..02b8847 --- /dev/null +++ b/bu @@ -0,0 +1 @@ +src/bu/ \ No newline at end of file diff --git a/src/archival.h b/src/archival.h index e2c803c..8be3308 100644 --- a/src/archival.h +++ b/src/archival.h @@ -1,5 +1,5 @@ -#ifndef ARCHIVAL_H -#define ARCHIVAL_H +#ifndef BU_ARCHIVAL_H +#define BU_ARCHIVAL_H namespace Bu { diff --git a/src/archive.h b/src/archive.h index 05c6f57..6c0c1df 100644 --- a/src/archive.h +++ b/src/archive.h @@ -1,5 +1,5 @@ -#ifndef ARCHIVE_H -#define ARCHIVE_H +#ifndef BU_ARCHIVE_H +#define BU_ARCHIVE_H #include #include diff --git a/src/atom.h b/src/atom.h index a0469b6..fad47eb 100644 --- a/src/atom.h +++ b/src/atom.h @@ -1,5 +1,5 @@ -#ifndef ATOM_H -#define ATOM_H +#ifndef BU_ATOM_H +#define BU_ATOM_H #include #include diff --git a/src/bzip2.h b/src/bzip2.h index 25f10c5..0a111e8 100644 --- a/src/bzip2.h +++ b/src/bzip2.h @@ -1,5 +1,5 @@ -#ifndef B_ZIP2_H -#define B_ZIP2_H +#ifndef BU_BZIP2_H +#define BU_BZIP2_H #include #include diff --git a/src/client.h b/src/client.h index 02ba077..cee558d 100644 --- a/src/client.h +++ b/src/client.h @@ -1,5 +1,5 @@ -#ifndef CLIENT_H -#define CLIENT_H +#ifndef BU_CLIENT_H +#define BU_CLIENT_H #include diff --git a/src/exceptionbase.h b/src/exceptionbase.h index fd78089..24e4bbf 100644 --- a/src/exceptionbase.h +++ b/src/exceptionbase.h @@ -1,5 +1,5 @@ -#ifndef EXCEPTION_BASE_H -#define EXCEPTION_BASE_H +#ifndef BU_EXCEPTION_BASE_H +#define BU_EXCEPTION_BASE_H #include #include diff --git a/src/exceptions.h b/src/exceptions.h index d5a9d39..b824b91 100644 --- a/src/exceptions.h +++ b/src/exceptions.h @@ -1,5 +1,5 @@ -#ifndef EXCEPTIONS_H -#define EXCEPTIONS_H +#ifndef BU_EXCEPTIONS_H +#define BU_EXCEPTIONS_H #include "exceptionbase.h" #include diff --git a/src/file.h b/src/file.h index 0f638a7..d4e43eb 100644 --- a/src/file.h +++ b/src/file.h @@ -1,5 +1,5 @@ -#ifndef FILE_H -#define FILE_H +#ifndef BU_FILE_H +#define BU_FILE_H #include diff --git a/src/filter.h b/src/filter.h index 7bb04bc..bd557b2 100644 --- a/src/filter.h +++ b/src/filter.h @@ -1,5 +1,5 @@ -#ifndef FILTER_H -#define FILTER_H +#ifndef BU_FILTER_H +#define BU_FILTER_H #include diff --git a/src/fstring.h b/src/fstring.h index 7180f5f..bf6518b 100644 --- a/src/fstring.h +++ b/src/fstring.h @@ -1,5 +1,5 @@ -#ifndef F_STRING_H -#define F_STRING_H +#ifndef BU_F_STRING_H +#define BU_F_STRING_H #include #include diff --git a/src/hash.h b/src/hash.h index 6c4a443..0fa3af7 100644 --- a/src/hash.h +++ b/src/hash.h @@ -1,5 +1,5 @@ -#ifndef HASH_H -#define HASH_H +#ifndef BU_HASH_H +#define BU_HASH_H #include #include diff --git a/src/ito.h b/src/ito.h index 01253f5..c062052 100644 --- a/src/ito.h +++ b/src/ito.h @@ -1,5 +1,5 @@ -#ifndef ITO_H -#define ITO_H +#ifndef BU_ITO_H +#define BU_ITO_H #include diff --git a/src/itoatom.h b/src/itoatom.h index 96090f2..7fc9090 100644 --- a/src/itoatom.h +++ b/src/itoatom.h @@ -1,5 +1,5 @@ -#ifndef ITO_QUEUE_H -#define ITO_QUEUE_H +#ifndef BU_ITO_QUEUE_H +#define BU_ITO_QUEUE_H #include diff --git a/src/itocondition.h b/src/itocondition.h index 4771b22..1793f81 100644 --- a/src/itocondition.h +++ b/src/itocondition.h @@ -1,5 +1,5 @@ -#ifndef ITO_CONDITION_H -#define ITO_CONDITION_H +#ifndef BU_ITO_CONDITION_H +#define BU_ITO_CONDITION_H #include diff --git a/src/itomutex.h b/src/itomutex.h index 80956b8..9c9d205 100644 --- a/src/itomutex.h +++ b/src/itomutex.h @@ -1,5 +1,5 @@ -#ifndef ITO_MUTEX_H -#define ITO_MUTEX_H +#ifndef BU_ITO_MUTEX_H +#define BU_ITO_MUTEX_H #include diff --git a/src/itoqueue.h b/src/itoqueue.h index 322698d..75a2f27 100644 --- a/src/itoqueue.h +++ b/src/itoqueue.h @@ -1,5 +1,5 @@ -#ifndef ITO_QUEUE_H -#define ITO_QUEUE_H +#ifndef BU_ITO_QUEUE_H +#define BU_ITO_QUEUE_H #include diff --git a/src/linkmessage.h b/src/linkmessage.h index 64b8bc2..baa22a6 100644 --- a/src/linkmessage.h +++ b/src/linkmessage.h @@ -1,8 +1,8 @@ /**\file linkmessage.h */ -#ifndef LINKMESSAGE_H -#define LINKMESSAGE_H +#ifndef BU_LINKMESSAGE_H +#define BU_LINKMESSAGE_H namespace Bu { diff --git a/src/list.h b/src/list.h index 314459e..6235619 100644 --- a/src/list.h +++ b/src/list.h @@ -1,5 +1,5 @@ -#ifndef LIST_H -#define LIST_H +#ifndef BU_LIST_H +#define BU_LIST_H #include #include "bu/exceptionbase.h" diff --git a/src/membuf.h b/src/membuf.h index 877b35e..b82f943 100644 --- a/src/membuf.h +++ b/src/membuf.h @@ -1,5 +1,5 @@ -#ifndef MEM_BUF_H -#define MEM_BUF_H +#ifndef BU_MEM_BUF_H +#define BU_MEM_BUF_H #include diff --git a/src/paramproc.h b/src/paramproc.h index beee4a0..2bca588 100644 --- a/src/paramproc.h +++ b/src/paramproc.h @@ -1,5 +1,5 @@ -#ifndef PARAM_PROC_H -#define PARAM_PROC_H +#ifndef BU_PARAM_PROC_H +#define BU_PARAM_PROC_H #include #include diff --git a/src/plugger.h b/src/plugger.h index 4d2e7af..79a3271 100644 --- a/src/plugger.h +++ b/src/plugger.h @@ -1,5 +1,5 @@ -#ifndef PLUGGER_H -#define PLUGGER_H +#ifndef BU_PLUGGER_H +#define BU_PLUGGER_H #include "bu/hash.h" diff --git a/src/programchain.h b/src/programchain.h index e73d659..336a9f1 100644 --- a/src/programchain.h +++ b/src/programchain.h @@ -1,5 +1,5 @@ -#ifndef PROGRAMCHAIN_H -#define PROGRAMCHAIN_H +#ifndef BU_PROGRAMCHAIN_H +#define BU_PROGRAMCHAIN_H #include "bu/list.h" #include "bu/linkmessage.h" diff --git a/src/programlink.h b/src/programlink.h index 7c31a18..07d7489 100644 --- a/src/programlink.h +++ b/src/programlink.h @@ -1,5 +1,5 @@ -#ifndef PROGRAMLINK_H -#define PROGRAMLINK_H +#ifndef BU_PROGRAMLINK_H +#define BU_PROGRAMLINK_H #include "bu/linkmessage.h" #include "bu/programchain.h" diff --git a/src/protocol.h b/src/protocol.h index 3accd99..c7a9275 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -1,5 +1,5 @@ -#ifndef PROTOCOL_H -#define PROTOCOL_H +#ifndef BU_PROTOCOL_H +#define BU_PROTOCOL_H #include diff --git a/src/ringbuffer.h b/src/ringbuffer.h index 625f65b..be80e2f 100644 --- a/src/ringbuffer.h +++ b/src/ringbuffer.h @@ -1,5 +1,5 @@ -#ifndef RING_BUFFER_H -#define RING_BUFFER_H +#ifndef BU_RING_BUFFER_H +#define BU_RING_BUFFER_H #include #include "bu/exceptionbase.h" diff --git a/src/server.h b/src/server.h index 07eef95..302b6e3 100644 --- a/src/server.h +++ b/src/server.h @@ -1,5 +1,5 @@ -#ifndef SERVER_H -#define SERVER_H +#ifndef BU_SERVER_H +#define BU_SERVER_H #include diff --git a/src/serversocket.h b/src/serversocket.h index cb86078..b4ee247 100644 --- a/src/serversocket.h +++ b/src/serversocket.h @@ -1,5 +1,5 @@ -#ifndef SERVER_SOCKET_H -#define SERVER_SOCKET_H +#ifndef BU_SERVER_SOCKET_H +#define BU_SERVER_SOCKET_H #include #include "bu/fstring.h" diff --git a/src/singleton.h b/src/singleton.h index 4976a61..c43d71b 100644 --- a/src/singleton.h +++ b/src/singleton.h @@ -1,5 +1,5 @@ -#ifndef SINGLETON_H -#define SINGLETON_H +#ifndef BU_SINGLETON_H +#define BU_SINGLETON_H #include diff --git a/src/socket.h b/src/socket.h index c9dbd8d..0ccee3b 100644 --- a/src/socket.h +++ b/src/socket.h @@ -1,5 +1,5 @@ -#ifndef SOCKET_H -#define SOCKET_H +#ifndef BU_SOCKET_H +#define BU_SOCKET_H #include diff --git a/src/sptr.h b/src/sptr.h index 4baa697..75851a6 100644 --- a/src/sptr.h +++ b/src/sptr.h @@ -1,5 +1,5 @@ -#ifndef SPTR_H -#define SPTR_H +#ifndef BU_SPTR_H +#define BU_SPTR_H #include #include diff --git a/src/stream.h b/src/stream.h index 056de0c..1e236a6 100644 --- a/src/stream.h +++ b/src/stream.h @@ -1,5 +1,5 @@ -#ifndef STREAM_H -#define STREAM_H +#ifndef BU_STREAM_H +#define BU_STREAM_H #include #include diff --git a/src/unitsuite.h b/src/unitsuite.h index 6e9270a..578b4cc 100644 --- a/src/unitsuite.h +++ b/src/unitsuite.h @@ -1,5 +1,5 @@ -#ifndef UNIT_SUITE_H -#define UNIT_SUITE_H +#ifndef BU_UNIT_SUITE_H +#define BU_UNIT_SUITE_H #include #include -- cgit v1.2.3 From afb50f535dd60b485a38f1f1f692b3303e28fecc Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Thu, 28 Jun 2007 21:58:47 +0000 Subject: The FString has more things that it can do...now. --- src/client.h | 1 + src/fstring.cpp | 6 ++++++ src/fstring.h | 17 +++++++++++++++++ 3 files changed, 24 insertions(+) (limited to 'src/fstring.h') diff --git a/src/client.h b/src/client.h index cee558d..f228e96 100644 --- a/src/client.h +++ b/src/client.h @@ -25,6 +25,7 @@ namespace Bu Bu::FString &getInput(); Bu::FString &getOutput(); void write( const char *pData, int nBytes ); + void read( const char *pData, int nBytes ); void setProtocol( Protocol *pProto ); Bu::Protocol *getProtocol(); diff --git a/src/fstring.cpp b/src/fstring.cpp index 56d2173..0b5a970 100644 --- a/src/fstring.cpp +++ b/src/fstring.cpp @@ -12,3 +12,9 @@ template<> bool Bu::__cmpHashKeys( return a == b; } +std::ostream& operator<< (std::ostream &os, Bu::FString &val ) +{ + os.write( val.getStr(), val.getSize() ); + return os; +} + diff --git a/src/fstring.h b/src/fstring.h index bf6518b..1f21b5f 100644 --- a/src/fstring.h +++ b/src/fstring.h @@ -586,6 +586,20 @@ namespace Bu return -1; } + /** + * Remove nAmnt bytes from the front of the string. This function + * operates in O(n) time and should be used sparingly. + */ + void trimFront( long nAmnt ) + { + long nNewLen = nLength - nAmnt; + flatten(); + Chunk *pNew = newChunk( nNewLen ); + cpy( pNew->pData, pFirst->pData, nNewLen ); + clear(); + appendChunk( pNew ); + } + /** * Function the archiver calls to archive your FString. *@param ar (Archive) The archive which is archiving your FString. @@ -882,4 +896,7 @@ namespace Bu template<> bool __cmpHashKeys( const FString &a, const FString &b ); } +#include +std::ostream& operator<< (std::ostream &os, Bu::FString &val ); + #endif -- cgit v1.2.3 From ec8ed8b4b44c7b039e87faaa50bb4d503393d336 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Fri, 29 Jun 2007 00:48:32 +0000 Subject: A few changes here and there, mainly related to getting the new Server system working in optimal condition... --- src/client.cpp | 35 ++++++++++++++++++++++++++++++++--- src/client.h | 11 +++++++++-- src/fstring.cpp | 2 +- src/fstring.h | 2 +- src/membuf.cpp | 11 +++++++++++ src/membuf.h | 3 +++ 6 files changed, 57 insertions(+), 7 deletions(-) (limited to 'src/fstring.h') diff --git a/src/client.cpp b/src/client.cpp index 2f293b7..8077b3d 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -99,9 +99,9 @@ bool Bu::Client::isOpen() return pSocket->isOpen(); } -void Bu::Client::write( const char *pData, int nBytes ) +void Bu::Client::write( const void *pData, int nBytes ) { - sWriteBuf.append( pData, nBytes ); + sWriteBuf.append( (const char *)pData, nBytes ); } void Bu::Client::write( int8_t nData ) @@ -144,7 +144,7 @@ void Bu::Client::write( uint64_t nData ) sWriteBuf.append( (const char *)&nData, sizeof(nData) ); } -void Bu::Client::read( char *pData, int nBytes ) +void Bu::Client::read( void *pData, int nBytes ) { memcpy( pData, sReadBuf.getStr()+nRBOffset, nBytes ); nRBOffset += nBytes; @@ -165,6 +165,31 @@ void Bu::Client::read( char *pData, int nBytes ) } } +void Bu::Client::peek( void *pData, int nBytes ) +{ + memcpy( pData, sReadBuf.getStr()+nRBOffset, nBytes ); +} + +void Bu::Client::seek( int nBytes ) +{ + nRBOffset += nBytes; + if( sReadBuf.getSize()-nRBOffset == 0 ) + { + sReadBuf.clear(); + nRBOffset = 0; + } + // This is an experimental threshold, maybe I'll make this configurable + // later on. + else if( + (sReadBuf.getSize() >= 1024 && nRBOffset >= sReadBuf.getSize()/2) || + (nRBOffset >= sReadBuf.getSize()/4) + ) + { + sReadBuf.trimFront( nRBOffset ); + nRBOffset = 0; + } +} + long Bu::Client::getInputSize() { return sReadBuf.getSize()-nRBOffset; @@ -175,3 +200,7 @@ const Bu::Socket *Bu::Client::getSocket() const return pSocket; } +void Bu::Client::disconnect() +{ +} + diff --git a/src/client.h b/src/client.h index 1253dcd..5947521 100644 --- a/src/client.h +++ b/src/client.h @@ -24,7 +24,7 @@ namespace Bu Bu::FString &getInput(); Bu::FString &getOutput(); - void write( const char *pData, int nBytes ); + void write( const void *pData, int nBytes ); void write( int8_t nData ); void write( int16_t nData ); void write( int32_t nData ); @@ -33,7 +33,9 @@ namespace Bu void write( uint16_t nData ); void write( uint32_t nData ); void write( uint64_t nData ); - void read( char *pData, int nBytes ); + void read( void *pData, int nBytes ); + void peek( void *pData, int nBytes ); + void seek( int nBytes ); long getInputSize(); void setProtocol( Protocol *pProto ); @@ -44,6 +46,11 @@ namespace Bu const Bu::Socket *getSocket() const; + /** + *@todo Make this not suck. + */ + void disconnect(); + private: Bu::Socket *pSocket; Bu::Protocol *pProto; diff --git a/src/fstring.cpp b/src/fstring.cpp index 0b5a970..f71d6c1 100644 --- a/src/fstring.cpp +++ b/src/fstring.cpp @@ -12,7 +12,7 @@ template<> bool Bu::__cmpHashKeys( return a == b; } -std::ostream& operator<< (std::ostream &os, Bu::FString &val ) +std::basic_ostream& operator<< (std::basic_ostream &os, const Bu::FString &val ) { os.write( val.getStr(), val.getSize() ); return os; diff --git a/src/fstring.h b/src/fstring.h index 1f21b5f..f06c362 100644 --- a/src/fstring.h +++ b/src/fstring.h @@ -897,6 +897,6 @@ namespace Bu } #include -std::ostream& operator<< (std::ostream &os, Bu::FString &val ); +std::basic_ostream& operator<< (std::basic_ostream &os, const Bu::FString &val ); #endif diff --git a/src/membuf.cpp b/src/membuf.cpp index 3c394b0..45ff5bd 100644 --- a/src/membuf.cpp +++ b/src/membuf.cpp @@ -7,6 +7,12 @@ Bu::MemBuf::MemBuf() : { } +Bu::MemBuf::MemBuf( const Bu::FString &str ) : + sBuf( str ), + nPos( 0 ) +{ +} + Bu::MemBuf::~MemBuf() { } @@ -107,3 +113,8 @@ void Bu::MemBuf::setBlocking( bool bBlocking ) { } +Bu::FString &Bu::MemBuf::getString() +{ + return sBuf; +} + diff --git a/src/membuf.h b/src/membuf.h index b82f943..8f53d4b 100644 --- a/src/membuf.h +++ b/src/membuf.h @@ -15,6 +15,7 @@ namespace Bu { public: MemBuf(); + MemBuf( const Bu::FString &str ); virtual ~MemBuf(); virtual void close(); @@ -41,6 +42,8 @@ namespace Bu virtual bool isBlocking(); virtual void setBlocking( bool bBlocking=true ); + Bu::FString &getString(); + private: Bu::FString sBuf; long nPos; -- cgit v1.2.3 From cfcfbf452a96da757420ad87a22c9e25409c975e Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Sat, 30 Jun 2007 06:24:15 +0000 Subject: For now we have no const char * cast operator on FString, ISO C++ says that we can't have that and an indexing operator. More research with other compilers needs to be done if we want to try just having the cast operator. I would rather be able to index than auto-cast. --- src/fstring.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/fstring.h') diff --git a/src/fstring.h b/src/fstring.h index f06c362..1e1fc02 100644 --- a/src/fstring.h +++ b/src/fstring.h @@ -478,13 +478,14 @@ namespace Bu return pFirst->pData[nIndex]; } - +/* operator const chr *() const { if( !pFirst ) return NULL; flatten(); return pFirst->pData; } + */ operator bool() const { -- cgit v1.2.3