aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/stable/exceptionindexoutofbounds.cpp14
-rw-r--r--src/stable/exceptionindexoutofbounds.h18
-rw-r--r--src/stable/unitsuite.h10
-rw-r--r--src/unit/blob.unit118
-rw-r--r--src/unstable/blob.cpp271
-rw-r--r--src/unstable/blob.h37
6 files changed, 467 insertions, 1 deletions
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 @@
1/*
2 * Copyright (C) 2007-2019 Xagasoft, All rights reserved.
3 *
4 * This file is part of the libbu++ library and is released under the
5 * terms of the license contained in the file LICENSE.
6 */
7
8#include "exceptionindexoutofbounds.h"
9
10namespace Bu
11{
12 subExceptionDef( ExceptionIndexOutOfBounds );
13}
14
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 @@
1/*
2 * Copyright (C) 2007-2019 Xagasoft, All rights reserved.
3 *
4 * This file is part of the libbu++ library and is released under the
5 * terms of the license contained in the file LICENSE.
6 */
7
8#ifndef BU_EXCEPTION_INDEX_OUT_OF_BOUNDS_H
9#define BU_EXCEPTION_INDEX_OUT_OF_BOUNDS_H
10
11#include "bu/exceptionbase.h"
12
13namespace Bu
14{
15 subExceptionDecl( ExceptionIndexOutOfBounds );
16}
17
18#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 );
138{ \ 138{ \
139 throw Bu::UnitSuite::Failed( #tst, __FILE__, __LINE__ ); \ 139 throw Bu::UnitSuite::Failed( #tst, __FILE__, __LINE__ ); \
140} else (void)0 140} else (void)0
141
142#define unitTestCatch( tst, exception ) try \
143{ \
144 tst; \
145 throw Bu::UnitSuite::Failed( #tst, __FILE__, __LINE__ ); \
146} catch( exception & ) { } \
147catch(...) { \
148 throw Bu::UnitSuite::Failed( #tst, __FILE__, __LINE__ ); \
149} (void)0
150
141#define unitFailed( msg ) throw Bu::UnitSuite::Failed(msg, __FILE__, __LINE__) 151#define unitFailed( msg ) throw Bu::UnitSuite::Failed(msg, __FILE__, __LINE__)
142 152
143#endif 153#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 @@
1// vim: syntax=cpp
2/*
3 * Copyright (C) 2007-2019 Xagasoft, All rights reserved.
4 *
5 * This file is part of the libbu++ library and is released under the
6 * terms of the license contained in the file LICENSE.
7 */
8
9#include "bu/blob.h"
10#include "bu/exceptionindexoutofbounds.h"
11#include "bu/sio.h"
12
13#include <string.h>
14
15suite Blob
16{
17 test set
18 {
19 Bu::Blob a("hello there");
20 unitTest( !strcmp( a.getData(), "hello there") );
21 Bu::Blob b( a );
22 a = "New string";
23 unitTest( !strcmp( a.getData(), "New string") );
24 unitTest( !strcmp( b.getData(), "hello there") );
25 b = a;
26 unitTest( !strcmp( b.getData(), "New string") );
27 }
28
29 test index
30 {
31 Bu::Blob a("hello there");
32 unitTest( a[5] == ' ' );
33 unitTest( a[6] == 't' );
34 unitTestCatch( a[-1], Bu::ExceptionIndexOutOfBounds );
35 unitTestCatch( a[-100], Bu::ExceptionIndexOutOfBounds );
36 unitTest( a[10] == 'e' );
37 unitTestCatch( a[11], Bu::ExceptionIndexOutOfBounds );
38 unitTestCatch( a[12], Bu::ExceptionIndexOutOfBounds );
39 }
40
41 test compare
42 {
43 Bu::Blob a("cat"), b("dog"), c("cattail"), d("dog");
44
45 unitTest( a != b );
46 unitTest( a != c );
47 unitTest( a != "catt" );
48 unitTest( a != "ca" );
49 unitTest( !(a == c) );
50 unitTest( !(a == d) );
51 unitTest( a == a );
52 unitTest( !(a != a) );
53 unitTest( !(b != d) );
54
55 unitTest( a < b );
56 unitTest( a <= b );
57 unitTest( a < c );
58 unitTest( a <= c );
59 unitTest( !(b < d) );
60 unitTest( b <= d );
61 unitTest( !(c < a) );
62
63 unitTest( a < "dog" );
64 unitTest( a <= "dog" );
65 unitTest( a < "cattail" );
66 unitTest( a <= "cattail" );
67 unitTest( !(b < "dog") );
68 unitTest( b <= "dog" );
69 unitTest( !(c < "cattail") );
70
71 unitTest( b > a );
72 unitTest( b >= a );
73 unitTest( c > a );
74 unitTest( c >= a );
75 unitTest( !(d > b) );
76 unitTest( d <= b );
77 unitTest( !(a > c) );
78
79 unitTest( b > "cat" );
80 unitTest( b >= "cat" );
81 unitTest( c > "cat" );
82 unitTest( c >= "cat" );
83 unitTest( !(d > "dog") );
84 unitTest( d <= "dog" );
85 unitTest( !(a > "cattail") );
86 }
87
88 test iterator
89 {
90 }
91
92 test const_iterator
93 {
94 }
95
96 test sort
97 {
98 Bu::List<Bu::Blob> lList;
99 lList.append("Moose");
100 lList.append("Cattail");
101 lList.append("Cat");
102 lList.append("Cattxil");
103 lList.append("Moo");
104 lList.append("Cattails");
105 lList.append("Dog");
106
107 lList.sort();
108
109 Bu::List<Bu::Blob>::iterator i = lList.begin();
110 unitTest( *i == "Cat" && i++ );
111 unitTest( *i == "Cattail" && i++ );
112 unitTest( *i == "Cattails" && i++ );
113 unitTest( *i == "Cattxil" && i++ );
114 unitTest( *i == "Dog" && i++ );
115 unitTest( *i == "Moo" && i++ );
116 unitTest( *i == "Moose" && !(i++) );
117 }
118}
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 @@
7 7
8#include "bu/blob.h" 8#include "bu/blob.h"
9#include "bu/exceptioninvaliditerator.h" 9#include "bu/exceptioninvaliditerator.h"
10#include "bu/exceptionindexoutofbounds.h"
10 11
11#include <string.h> 12#include <string.h>
12 13
@@ -63,6 +64,37 @@ char *Bu::Blob::c_str() const
63 return pData; 64 return pData;
64} 65}
65 66
67char &Bu::Blob::operator[]( int32_t iIndex )
68{
69 if( iIndex < 0 || iIndex >= iSize || pData == NULL )
70 throw Bu::ExceptionIndexOutOfBounds();
71
72 return pData[iIndex];
73}
74
75char Bu::Blob::operator[]( int32_t iIndex ) const
76{
77 if( iIndex < 0 || iIndex >= iSize || pData == NULL )
78 throw Bu::ExceptionIndexOutOfBounds();
79
80 return pData[iIndex];
81}
82
83bool Bu::Blob::isEmpty() const
84{
85 return pData != NULL && iSize == 0;
86}
87
88bool Bu::Blob::isNull() const
89{
90 return pData == NULL;
91}
92
93bool Bu::Blob::isNullOrEmpty() const
94{
95 return pData == NULL || iSize == 0;
96}
97
66Bu::Blob &Bu::Blob::operator=( const Bu::Blob &rRhs ) 98Bu::Blob &Bu::Blob::operator=( const Bu::Blob &rRhs )
67{ 99{
68 delete[] pData; 100 delete[] pData;
@@ -85,6 +117,210 @@ Bu::Blob &Bu::Blob::operator=( const char *pRhs )
85 return *this; 117 return *this;
86} 118}
87 119
120bool Bu::Blob::operator==( const Bu::Blob &rRhs ) const
121{
122 if( pData == rRhs.pData )
123 return true;
124
125 if( iSize != rRhs.iSize )
126 return false;
127
128 for( int32_t j = 0; j < iSize; j++ )
129 {
130 if( pData[j] != rRhs.pData[j] )
131 return false;
132 }
133
134 return true;
135}
136
137bool Bu::Blob::operator==( const char *pRhs ) const
138{
139 if( pData == pRhs )
140 return true;
141
142 for( int32_t j = 0; j < iSize && pRhs[j]; j++ )
143 {
144 if( pData[j] != pRhs[j] )
145 return false;
146 }
147
148 if( pRhs[iSize] == '\0' )
149 return true;
150
151 return false;
152}
153
154bool Bu::Blob::operator!=( const Bu::Blob &rRhs ) const
155{
156 if( pData == rRhs.pData )
157 return false;
158
159 if( iSize != rRhs.iSize )
160 return true;
161
162 for( int32_t j = 0; j < iSize; j++ )
163 {
164 if( pData[j] != rRhs.pData[j] )
165 return true;
166 }
167
168 return false;
169}
170
171bool Bu::Blob::operator!=( const char *pRhs ) const
172{
173 if( pData == pRhs )
174 return false;
175
176 for( int32_t j = 0; j < iSize && pRhs[j]; j++ )
177 {
178 if( pData[j] != pRhs[j] )
179 return true;
180 }
181
182 if( pRhs[iSize] == '\0' )
183 return false;
184
185 return true;
186}
187
188bool Bu::Blob::operator<( const Bu::Blob &rRhs ) const
189{
190 if( pData == rRhs.pData )
191 return false;
192
193 for( int32_t j = 0; j < iSize && j < rRhs.iSize; j++ )
194 {
195 if( pData[j] != rRhs.pData[j] )
196 return pData[j] < rRhs.pData[j];
197 }
198
199 if( iSize < rRhs.iSize )
200 return true;
201
202 return false;
203}
204
205bool Bu::Blob::operator<( const char *pRhs ) const
206{
207 if( pData == pRhs )
208 return false;
209
210 for( int32_t j = 0; j < iSize && pRhs[j]; j++ )
211 {
212 if( pData[j] != pRhs[j] )
213 return pData[j] < pRhs[j];
214 }
215
216 if( pRhs[iSize] == '\0' )
217 return false;
218
219 return true;
220}
221
222bool Bu::Blob::operator<=( const Bu::Blob &rRhs ) const
223{
224 if( pData == rRhs.pData )
225 return true;
226
227 for( int32_t j = 0; j < iSize && j < rRhs.iSize; j++ )
228 {
229 if( pData[j] != rRhs.pData[j] )
230 return pData[j] < rRhs.pData[j];
231 }
232
233 return iSize <= rRhs.iSize;
234}
235
236bool Bu::Blob::operator<=( const char *pRhs ) const
237{
238 if( pData == pRhs )
239 return true;
240
241 for( int32_t j = 0; j < iSize && pRhs[j]; j++ )
242 {
243 if( pData[j] != pRhs[j] )
244 return pData[j] < pRhs[j];
245 }
246
247 if( pRhs[iSize] == '\0' )
248 return true;
249
250 return true;
251}
252
253bool Bu::Blob::operator>( const Bu::Blob &rRhs ) const
254{
255 if( pData == rRhs.pData )
256 return false;
257
258 for( int32_t j = 0; j < iSize && j < rRhs.iSize; j++ )
259 {
260 if( pData[j] != rRhs.pData[j] )
261 return pData[j] > rRhs.pData[j];
262 }
263
264 if( iSize > rRhs.iSize )
265 return true;
266
267 return false;
268}
269
270bool Bu::Blob::operator>( const char *pRhs ) const
271{
272 if( pData == pRhs )
273 return false;
274
275 int32_t j;
276 for( j = 0; j < iSize && pRhs[j]; j++ )
277 {
278 if( pData[j] != pRhs[j] )
279 return pData[j] > pRhs[j];
280 }
281
282 if( pRhs[iSize] == '\0' && iSize-1 > j )
283 return true;
284
285 return false;
286}
287
288bool Bu::Blob::operator>=( const Bu::Blob &rRhs ) const
289{
290 if( pData == rRhs.pData )
291 return true;
292
293 for( int32_t j = 0; j < iSize && j < rRhs.iSize; j++ )
294 {
295 if( pData[j] != rRhs.pData[j] )
296 return pData[j] > rRhs.pData[j];
297 }
298
299 return iSize >= rRhs.iSize;
300}
301
302bool Bu::Blob::operator>=( const char *pRhs ) const
303{
304 if( pData == pRhs )
305 return true;
306
307 for( int32_t j = 0; j < iSize && pRhs[j]; j++ )
308 {
309 if( pData[j] != pRhs[j] )
310 return pData[j] > pRhs[j];
311 }
312
313 if( pRhs[iSize] == '\0' )
314 return true;
315
316 return true;
317}
318
319
320/////
321// Iterators
322//
323
88Bu::Blob::iterator::iterator( Bu::Blob *pBlob, bool bForward ) : 324Bu::Blob::iterator::iterator( Bu::Blob *pBlob, bool bForward ) :
89 pBlob( pBlob ), 325 pBlob( pBlob ),
90 iIndex( bForward?0:pBlob->iSize-1 ), 326 iIndex( bForward?0:pBlob->iSize-1 ),
@@ -400,4 +636,39 @@ Bu::Blob::const_iterator Bu::Blob::rend() const
400 return const_iterator(); 636 return const_iterator();
401} 637}
402 638
639////
640// Helper functions
641//
642template<> uint32_t Bu::__calcHashCode<Bu::Blob>( const Bu::Blob &k )
643{
644 int32_t sz = k.getSize();
645 const char *s = k.getData();
646
647 uint32_t iPos = 0;
648 for( int32_t j = 0; j < sz; j++, s++ )
649 {
650 iPos = *s + (iPos << 6) + (iPos << 16) - iPos;
651 }
652
653 return iPos;
654}
655
656template<> bool Bu::__cmpHashKeys<Bu::Blob>(
657 const Bu::Blob &a, const Bu::Blob &b )
658{
659 return a == b;
660}
661
662#include <stdio.h>
663template<> void Bu::__tracer_format<Bu::Blob>( const Bu::Blob &v )
664{
665 printf("(%d)\"%s\"", v.getSize(), v.getData() );
666}
667
668#include "bu/formatter.h"
669Bu::Formatter &Bu::operator<<( Bu::Formatter &rOut, const Bu::Blob &b )
670{
671 rOut.write( b.getData(), b.getSize() );
672 return rOut;
673}
403 674
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
33 33
34 int32_t getSize() const; 34 int32_t getSize() const;
35 char *getData() const; 35 char *getData() const;
36
37 char *c_str() const; 36 char *c_str() const;
38 37
38 char &operator[]( int32_t iIndex );
39 char operator[]( int32_t iIndex ) const;
40
41 bool isEmpty() const;
42 bool isNull() const;
43 bool isNullOrEmpty() const;
44
39 Blob &operator=( const Blob &rRhs ); 45 Blob &operator=( const Blob &rRhs );
40 Blob &operator=( const char *pRhs ); 46 Blob &operator=( const char *pRhs );
41 47
48 bool operator==( const Blob &rRhs ) const;
49 bool operator==( const char *rRhs ) const;
50 bool operator!=( const Blob &rRhs ) const;
51 bool operator!=( const char *rRhs ) const;
52 bool operator<( const Blob &rRhs ) const;
53 bool operator<( const char *rRhs ) const;
54 bool operator<=( const Blob &rRhs ) const;
55 bool operator<=( const char *rRhs ) const;
56 bool operator>( const Blob &rRhs ) const;
57 bool operator>( const char *rRhs ) const;
58 bool operator>=( const Blob &rRhs ) const;
59 bool operator>=( const char *rRhs ) const;
60
42 class const_iterator; 61 class const_iterator;
43 class iterator 62 class iterator
44 { 63 {
@@ -119,6 +138,22 @@ namespace Bu
119 char *pData; 138 char *pData;
120 int32_t iSize; 139 int32_t iSize;
121 }; 140 };
141
142 template<typename T>
143 uint32_t __calcHashCode( const T &k );
144
145 template<typename T>
146 bool __cmpHashKeys( const T &a, const T &b );
147
148 template<> uint32_t __calcHashCode<Blob>( const Blob &k );
149 template<> bool __cmpHashKeys<Blob>(
150 const Blob &a, const Blob &b );
151
152 template<typename t> void __tracer_format( const t &v );
153 template<> void __tracer_format<Blob>( const Blob &v );
154
155 class Formatter;
156 Formatter &operator<<( Formatter &rOut, const Blob &b );
122} 157}
123 158
124#endif 159#endif