From c4c34c1bfe568b653399cb5349ce54b5ee1c519b Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Sat, 25 May 2019 15:47:58 -0700 Subject: Augmented UnitSuite, added more to Blob, and added tests. --- src/stable/exceptionindexoutofbounds.cpp | 14 ++ src/stable/exceptionindexoutofbounds.h | 18 ++ src/stable/unitsuite.h | 10 ++ src/unit/blob.unit | 118 ++++++++++++++ src/unstable/blob.cpp | 271 +++++++++++++++++++++++++++++++ src/unstable/blob.h | 37 ++++- 6 files changed, 467 insertions(+), 1 deletion(-) create mode 100644 src/stable/exceptionindexoutofbounds.cpp create mode 100644 src/stable/exceptionindexoutofbounds.h create mode 100644 src/unit/blob.unit diff --git a/src/stable/exceptionindexoutofbounds.cpp b/src/stable/exceptionindexoutofbounds.cpp new file mode 100644 index 0000000..eb6d589 --- /dev/null +++ b/src/stable/exceptionindexoutofbounds.cpp @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2007-2019 Xagasoft, All rights reserved. + * + * This file is part of the libbu++ library and is released under the + * terms of the license contained in the file LICENSE. + */ + +#include "exceptionindexoutofbounds.h" + +namespace Bu +{ + subExceptionDef( ExceptionIndexOutOfBounds ); +} + diff --git a/src/stable/exceptionindexoutofbounds.h b/src/stable/exceptionindexoutofbounds.h new file mode 100644 index 0000000..fbb2a04 --- /dev/null +++ b/src/stable/exceptionindexoutofbounds.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2007-2019 Xagasoft, All rights reserved. + * + * This file is part of the libbu++ library and is released under the + * terms of the license contained in the file LICENSE. + */ + +#ifndef BU_EXCEPTION_INDEX_OUT_OF_BOUNDS_H +#define BU_EXCEPTION_INDEX_OUT_OF_BOUNDS_H + +#include "bu/exceptionbase.h" + +namespace Bu +{ + subExceptionDecl( ExceptionIndexOutOfBounds ); +} + +#endif diff --git a/src/stable/unitsuite.h b/src/stable/unitsuite.h index 85060c0..5f84058 100644 --- a/src/stable/unitsuite.h +++ b/src/stable/unitsuite.h @@ -138,6 +138,16 @@ Bu::Formatter &operator<<( Bu::Formatter &f, const Bu::UnitSuite::Expect &e ); { \ throw Bu::UnitSuite::Failed( #tst, __FILE__, __LINE__ ); \ } else (void)0 + +#define unitTestCatch( tst, exception ) try \ +{ \ + tst; \ + throw Bu::UnitSuite::Failed( #tst, __FILE__, __LINE__ ); \ +} catch( exception & ) { } \ +catch(...) { \ + throw Bu::UnitSuite::Failed( #tst, __FILE__, __LINE__ ); \ +} (void)0 + #define unitFailed( msg ) throw Bu::UnitSuite::Failed(msg, __FILE__, __LINE__) #endif diff --git a/src/unit/blob.unit b/src/unit/blob.unit new file mode 100644 index 0000000..645052b --- /dev/null +++ b/src/unit/blob.unit @@ -0,0 +1,118 @@ +// vim: syntax=cpp +/* + * Copyright (C) 2007-2019 Xagasoft, All rights reserved. + * + * This file is part of the libbu++ library and is released under the + * terms of the license contained in the file LICENSE. + */ + +#include "bu/blob.h" +#include "bu/exceptionindexoutofbounds.h" +#include "bu/sio.h" + +#include + +suite Blob +{ + test set + { + Bu::Blob a("hello there"); + unitTest( !strcmp( a.getData(), "hello there") ); + Bu::Blob b( a ); + a = "New string"; + unitTest( !strcmp( a.getData(), "New string") ); + unitTest( !strcmp( b.getData(), "hello there") ); + b = a; + unitTest( !strcmp( b.getData(), "New string") ); + } + + test index + { + Bu::Blob a("hello there"); + unitTest( a[5] == ' ' ); + unitTest( a[6] == 't' ); + unitTestCatch( a[-1], Bu::ExceptionIndexOutOfBounds ); + unitTestCatch( a[-100], Bu::ExceptionIndexOutOfBounds ); + unitTest( a[10] == 'e' ); + unitTestCatch( a[11], Bu::ExceptionIndexOutOfBounds ); + unitTestCatch( a[12], Bu::ExceptionIndexOutOfBounds ); + } + + test compare + { + Bu::Blob a("cat"), b("dog"), c("cattail"), d("dog"); + + unitTest( a != b ); + unitTest( a != c ); + unitTest( a != "catt" ); + unitTest( a != "ca" ); + unitTest( !(a == c) ); + unitTest( !(a == d) ); + unitTest( a == a ); + unitTest( !(a != a) ); + unitTest( !(b != d) ); + + unitTest( a < b ); + unitTest( a <= b ); + unitTest( a < c ); + unitTest( a <= c ); + unitTest( !(b < d) ); + unitTest( b <= d ); + unitTest( !(c < a) ); + + unitTest( a < "dog" ); + unitTest( a <= "dog" ); + unitTest( a < "cattail" ); + unitTest( a <= "cattail" ); + unitTest( !(b < "dog") ); + unitTest( b <= "dog" ); + unitTest( !(c < "cattail") ); + + unitTest( b > a ); + unitTest( b >= a ); + unitTest( c > a ); + unitTest( c >= a ); + unitTest( !(d > b) ); + unitTest( d <= b ); + unitTest( !(a > c) ); + + unitTest( b > "cat" ); + unitTest( b >= "cat" ); + unitTest( c > "cat" ); + unitTest( c >= "cat" ); + unitTest( !(d > "dog") ); + unitTest( d <= "dog" ); + unitTest( !(a > "cattail") ); + } + + test iterator + { + } + + test const_iterator + { + } + + test sort + { + Bu::List lList; + lList.append("Moose"); + lList.append("Cattail"); + lList.append("Cat"); + lList.append("Cattxil"); + lList.append("Moo"); + lList.append("Cattails"); + lList.append("Dog"); + + lList.sort(); + + Bu::List::iterator i = lList.begin(); + unitTest( *i == "Cat" && i++ ); + unitTest( *i == "Cattail" && i++ ); + unitTest( *i == "Cattails" && i++ ); + unitTest( *i == "Cattxil" && i++ ); + unitTest( *i == "Dog" && i++ ); + unitTest( *i == "Moo" && i++ ); + unitTest( *i == "Moose" && !(i++) ); + } +} diff --git a/src/unstable/blob.cpp b/src/unstable/blob.cpp index 51a3b93..f8cf1b0 100644 --- a/src/unstable/blob.cpp +++ b/src/unstable/blob.cpp @@ -7,6 +7,7 @@ #include "bu/blob.h" #include "bu/exceptioninvaliditerator.h" +#include "bu/exceptionindexoutofbounds.h" #include @@ -63,6 +64,37 @@ char *Bu::Blob::c_str() const return pData; } +char &Bu::Blob::operator[]( int32_t iIndex ) +{ + if( iIndex < 0 || iIndex >= iSize || pData == NULL ) + throw Bu::ExceptionIndexOutOfBounds(); + + return pData[iIndex]; +} + +char Bu::Blob::operator[]( int32_t iIndex ) const +{ + if( iIndex < 0 || iIndex >= iSize || pData == NULL ) + throw Bu::ExceptionIndexOutOfBounds(); + + return pData[iIndex]; +} + +bool Bu::Blob::isEmpty() const +{ + return pData != NULL && iSize == 0; +} + +bool Bu::Blob::isNull() const +{ + return pData == NULL; +} + +bool Bu::Blob::isNullOrEmpty() const +{ + return pData == NULL || iSize == 0; +} + Bu::Blob &Bu::Blob::operator=( const Bu::Blob &rRhs ) { delete[] pData; @@ -85,6 +117,210 @@ Bu::Blob &Bu::Blob::operator=( const char *pRhs ) return *this; } +bool Bu::Blob::operator==( const Bu::Blob &rRhs ) const +{ + if( pData == rRhs.pData ) + return true; + + if( iSize != rRhs.iSize ) + return false; + + for( int32_t j = 0; j < iSize; j++ ) + { + if( pData[j] != rRhs.pData[j] ) + return false; + } + + return true; +} + +bool Bu::Blob::operator==( const char *pRhs ) const +{ + if( pData == pRhs ) + return true; + + for( int32_t j = 0; j < iSize && pRhs[j]; j++ ) + { + if( pData[j] != pRhs[j] ) + return false; + } + + if( pRhs[iSize] == '\0' ) + return true; + + return false; +} + +bool Bu::Blob::operator!=( const Bu::Blob &rRhs ) const +{ + if( pData == rRhs.pData ) + return false; + + if( iSize != rRhs.iSize ) + return true; + + for( int32_t j = 0; j < iSize; j++ ) + { + if( pData[j] != rRhs.pData[j] ) + return true; + } + + return false; +} + +bool Bu::Blob::operator!=( const char *pRhs ) const +{ + if( pData == pRhs ) + return false; + + for( int32_t j = 0; j < iSize && pRhs[j]; j++ ) + { + if( pData[j] != pRhs[j] ) + return true; + } + + if( pRhs[iSize] == '\0' ) + return false; + + return true; +} + +bool Bu::Blob::operator<( const Bu::Blob &rRhs ) const +{ + if( pData == rRhs.pData ) + return false; + + for( int32_t j = 0; j < iSize && j < rRhs.iSize; j++ ) + { + if( pData[j] != rRhs.pData[j] ) + return pData[j] < rRhs.pData[j]; + } + + if( iSize < rRhs.iSize ) + return true; + + return false; +} + +bool Bu::Blob::operator<( const char *pRhs ) const +{ + if( pData == pRhs ) + return false; + + for( int32_t j = 0; j < iSize && pRhs[j]; j++ ) + { + if( pData[j] != pRhs[j] ) + return pData[j] < pRhs[j]; + } + + if( pRhs[iSize] == '\0' ) + return false; + + return true; +} + +bool Bu::Blob::operator<=( const Bu::Blob &rRhs ) const +{ + if( pData == rRhs.pData ) + return true; + + for( int32_t j = 0; j < iSize && j < rRhs.iSize; j++ ) + { + if( pData[j] != rRhs.pData[j] ) + return pData[j] < rRhs.pData[j]; + } + + return iSize <= rRhs.iSize; +} + +bool Bu::Blob::operator<=( const char *pRhs ) const +{ + if( pData == pRhs ) + return true; + + for( int32_t j = 0; j < iSize && pRhs[j]; j++ ) + { + if( pData[j] != pRhs[j] ) + return pData[j] < pRhs[j]; + } + + if( pRhs[iSize] == '\0' ) + return true; + + return true; +} + +bool Bu::Blob::operator>( const Bu::Blob &rRhs ) const +{ + if( pData == rRhs.pData ) + return false; + + for( int32_t j = 0; j < iSize && j < rRhs.iSize; j++ ) + { + if( pData[j] != rRhs.pData[j] ) + return pData[j] > rRhs.pData[j]; + } + + if( iSize > rRhs.iSize ) + return true; + + return false; +} + +bool Bu::Blob::operator>( const char *pRhs ) const +{ + if( pData == pRhs ) + return false; + + int32_t j; + for( j = 0; j < iSize && pRhs[j]; j++ ) + { + if( pData[j] != pRhs[j] ) + return pData[j] > pRhs[j]; + } + + if( pRhs[iSize] == '\0' && iSize-1 > j ) + return true; + + return false; +} + +bool Bu::Blob::operator>=( const Bu::Blob &rRhs ) const +{ + if( pData == rRhs.pData ) + return true; + + for( int32_t j = 0; j < iSize && j < rRhs.iSize; j++ ) + { + if( pData[j] != rRhs.pData[j] ) + return pData[j] > rRhs.pData[j]; + } + + return iSize >= rRhs.iSize; +} + +bool Bu::Blob::operator>=( const char *pRhs ) const +{ + if( pData == pRhs ) + return true; + + for( int32_t j = 0; j < iSize && pRhs[j]; j++ ) + { + if( pData[j] != pRhs[j] ) + return pData[j] > pRhs[j]; + } + + if( pRhs[iSize] == '\0' ) + return true; + + return true; +} + + +///// +// Iterators +// + Bu::Blob::iterator::iterator( Bu::Blob *pBlob, bool bForward ) : pBlob( pBlob ), iIndex( bForward?0:pBlob->iSize-1 ), @@ -400,4 +636,39 @@ Bu::Blob::const_iterator Bu::Blob::rend() const return const_iterator(); } +//// +// Helper functions +// +template<> uint32_t Bu::__calcHashCode( const Bu::Blob &k ) +{ + int32_t sz = k.getSize(); + const char *s = k.getData(); + + uint32_t iPos = 0; + for( int32_t j = 0; j < sz; j++, s++ ) + { + iPos = *s + (iPos << 6) + (iPos << 16) - iPos; + } + + return iPos; +} + +template<> bool Bu::__cmpHashKeys( + const Bu::Blob &a, const Bu::Blob &b ) +{ + return a == b; +} + +#include +template<> void Bu::__tracer_format( const Bu::Blob &v ) +{ + printf("(%d)\"%s\"", v.getSize(), v.getData() ); +} + +#include "bu/formatter.h" +Bu::Formatter &Bu::operator<<( Bu::Formatter &rOut, const Bu::Blob &b ) +{ + rOut.write( b.getData(), b.getSize() ); + return rOut; +} diff --git a/src/unstable/blob.h b/src/unstable/blob.h index 5b8cabd..6ce0c67 100644 --- a/src/unstable/blob.h +++ b/src/unstable/blob.h @@ -33,12 +33,31 @@ namespace Bu int32_t getSize() const; char *getData() const; - char *c_str() const; + char &operator[]( int32_t iIndex ); + char operator[]( int32_t iIndex ) const; + + bool isEmpty() const; + bool isNull() const; + bool isNullOrEmpty() const; + Blob &operator=( const Blob &rRhs ); Blob &operator=( const char *pRhs ); + bool operator==( const Blob &rRhs ) const; + bool operator==( const char *rRhs ) const; + bool operator!=( const Blob &rRhs ) const; + bool operator!=( const char *rRhs ) const; + bool operator<( const Blob &rRhs ) const; + bool operator<( const char *rRhs ) const; + bool operator<=( const Blob &rRhs ) const; + bool operator<=( const char *rRhs ) const; + bool operator>( const Blob &rRhs ) const; + bool operator>( const char *rRhs ) const; + bool operator>=( const Blob &rRhs ) const; + bool operator>=( const char *rRhs ) const; + class const_iterator; class iterator { @@ -119,6 +138,22 @@ namespace Bu char *pData; int32_t iSize; }; + + template + uint32_t __calcHashCode( const T &k ); + + template + bool __cmpHashKeys( const T &a, const T &b ); + + template<> uint32_t __calcHashCode( const Blob &k ); + template<> bool __cmpHashKeys( + const Blob &a, const Blob &b ); + + template void __tracer_format( const t &v ); + template<> void __tracer_format( const Blob &v ); + + class Formatter; + Formatter &operator<<( Formatter &rOut, const Blob &b ); } #endif -- cgit v1.2.3