From 46725741fc82866e41652dee7adeddf376fde618 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Thu, 15 Mar 2007 04:03:52 +0000 Subject: FString is totally usable, a few more helpers must be written before it surpases the other classes in functionality. It's already rather fast. --- build.conf | 1 + src/fstring.h | 239 ++++++++++++++++++++++++++++++++++++++++++++++++-- src/tests/fstring.cpp | 28 ++++++ 3 files changed, 260 insertions(+), 8 deletions(-) create mode 100644 src/tests/fstring.cpp diff --git a/build.conf b/build.conf index a9c6d49..5c4dbb6 100644 --- a/build.conf +++ b/build.conf @@ -4,6 +4,7 @@ default action: check "libbu++.a" "clean" action: clean targets() "tests" action: check targets() filter regexp("^tests/.*$") "all" action: check targets() +"fstring" action: check "tests/fstring" set "CXXFLAGS" += "-ggdb -Wall" diff --git a/src/fstring.h b/src/fstring.h index 2eaa4ba..287641f 100644 --- a/src/fstring.h +++ b/src/fstring.h @@ -4,28 +4,251 @@ #include #include +template< typename chr=char > +struct FStringChunk +{ + long nLength; + chr *pData; + FStringChunk *pNext; +}; + /** * */ -template< typename chr, typename chralloc = std::allocator > -class FString +template< typename chr=char, typename chralloc=std::allocator, typename chunkalloc=std::allocator > > +class FBasicString { +private: + typedef struct FStringChunk Chunk; + public: - FString() : - pData( NULL ), - pnRefs( NULL ) + 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 ); + } + + virtual ~FBasicString() + { + } + + void append( const chr *pData ) + { + long nLen; + for( nLen = 0; pData[nLen] != (chr)0; nLen++ ); + + Chunk *pNew = newChunk( nLen ); + memcpy( pNew->pData, pData, nLen * sizeof(chr) ); + + appendChunk( pNew ); + } + + void append( const chr *pData, long nLen ) + { + Chunk *pNew = newChunk( nLen ); + + memcpy( pNew->pData, pData, nLen * sizeof(chr) ); + + appendChunk( pNew ); + } + + void prepend( const chr *pData ) + { + long nLen; + for( nLen = 0; pData[nLen] != (chr)0; nLen++ ); + + Chunk *pNew = newChunk( nLen ); + memcpy( pNew->pData, pData, nLen * sizeof(chr) ); + + prependChunk( pNew ); + } + + void prepend( const chr *pData, long nLen ) + { + Chunk *pNew = newChunk( nLen ); + + memcpy( pNew->pData, pData, nLen * sizeof(chr) ); + + prependChunk( pNew ); + } + + void clear() + { + if( pFirst == NULL ) + return; + + 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; + } + + chr *c_str() + { + if( pFirst == NULL ) + return NULL; + + flatten(); + return pFirst->pData; + } + + FBasicString &operator +=( const chr *pData ) { + append( pData ); + + return (*this); } - virtual ~FString() + FBasicString &operator =( const chr *pData ) { + clear(); + append( pData ); + + return (*this); + } + + bool operator ==( const chr *pData ) + { + 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 chr *pData ) + { + return !(*this == pData); + } + + + +private: + void flatten() + { + if( isFlat() ) + return; + + if( pFirst == NULL ) + return; + + Chunk *pNew = newChunk( nLength ); + chr *pos = pNew->pData; + Chunk *i = pFirst; + for(;;) + { + memcpy( pos, i->pData, i->nLength*sizeof(chr) ); + pos += i->nLength; + i = i->pNext; + if( i == NULL ) + break; + } + clear(); + + appendChunk( pNew ); + } + + bool isFlat() + { + return (pFirst == pLast); + } + + bool isShared() + { + return (pnRefs != NULL); + } + + Chunk *newChunk() + { + Chunk *pNew = aChunk.allocate( 1 ); + pNew->pNext = NULL; + return pNew; + } + + Chunk *newChunk( long nLen ) + { + Chunk *pNew = aChunk.allocate( 1 ); + pNew->pNext = NULL; + pNew->nLength = nLen; + pNew->pData = aChr.allocate( nLen+1 ); + return pNew; + } + + void appendChunk( Chunk *pNewChunk ) + { + if( pFirst == NULL ) + pLast = pFirst = pNewChunk; + else + { + pLast->pNext = pNewChunk; + pLast = pNewChunk; + } + + nLength += pNewChunk->nLength; + } + + void prependChunk( Chunk *pNewChunk ) + { + if( pFirst == NULL ) + pLast = pFirst = pNewChunk; + else + { + pNewChunk->pNext = pFirst; + pFirst = pNewChunk; + } + + nLength += pNewChunk->nLength; } private: long nLength; - chr *pData; uint32_t *pnRefs; - chralloc aChars; + Chunk *pFirst; + Chunk *pLast; + + chralloc aChr; + chunkalloc aChunk; }; +typedef FBasicString FString; + #endif diff --git a/src/tests/fstring.cpp b/src/tests/fstring.cpp new file mode 100644 index 0000000..26905ac --- /dev/null +++ b/src/tests/fstring.cpp @@ -0,0 +1,28 @@ +#include "fstring.h" + +int main( int argc, char *argv ) +{ + FString str("[] this won't be in there", 3); + + str.append("Hello"); + str.append(" th"); + str.append("ere."); + + if( str == "[] Hello there." ) + printf("1) check\n"); + + if( str != "[] Hello there. " ) + printf("2) check\n"); + + if( str != "[] Hello there." ) + printf("3) failed\n"); + else + printf("3) check\n"); + + str += " How are you?"; + + str.prepend("Bob says: "); + + printf("%s\n", str.c_str() ); +} + -- cgit v1.2.3