diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/array.h | 28 | ||||
-rw-r--r-- | src/fbasicstring.h | 720 | ||||
-rw-r--r-- | src/hash.h | 35 | ||||
-rw-r--r-- | src/list.h | 20 | ||||
-rw-r--r-- | src/minimacro.cpp | 2 | ||||
-rw-r--r-- | src/set.h | 33 | ||||
-rw-r--r-- | src/tafwriter.cpp | 5 | ||||
-rw-r--r-- | src/tests/rh.cpp | 52 | ||||
-rw-r--r-- | src/tests/url.cpp | 32 | ||||
-rw-r--r-- | src/unit/fstring.unit | 155 | ||||
-rw-r--r-- | src/unitsuite.cpp | 2 | ||||
-rw-r--r-- | src/url.cpp | 237 | ||||
-rw-r--r-- | src/url.h | 74 |
13 files changed, 1280 insertions, 115 deletions
diff --git a/src/array.h b/src/array.h index 0fb0df3..e717fd5 100644 --- a/src/array.h +++ b/src/array.h | |||
@@ -219,12 +219,12 @@ namespace Bu | |||
219 | return *this; | 219 | return *this; |
220 | } | 220 | } |
221 | 221 | ||
222 | bool operator==( const iterator &oth ) | 222 | bool operator==( const iterator &oth ) const |
223 | { | 223 | { |
224 | return iPos == oth.iPos; | 224 | return iPos == oth.iPos; |
225 | } | 225 | } |
226 | 226 | ||
227 | bool operator!=( const iterator &oth ) | 227 | bool operator!=( const iterator &oth ) const |
228 | { | 228 | { |
229 | return iPos != oth.iPos; | 229 | return iPos != oth.iPos; |
230 | } | 230 | } |
@@ -244,6 +244,16 @@ namespace Bu | |||
244 | "Cannot dereference finished iterator."); | 244 | "Cannot dereference finished iterator."); |
245 | return src[iPos]; | 245 | return src[iPos]; |
246 | } | 246 | } |
247 | |||
248 | operator bool() const | ||
249 | { | ||
250 | return iPos < 0; | ||
251 | } | ||
252 | |||
253 | bool isValid() const | ||
254 | { | ||
255 | return iPos < 0; | ||
256 | } | ||
247 | } iterator; | 257 | } iterator; |
248 | 258 | ||
249 | typedef struct const_iterator | 259 | typedef struct const_iterator |
@@ -302,12 +312,12 @@ namespace Bu | |||
302 | return *this; | 312 | return *this; |
303 | } | 313 | } |
304 | 314 | ||
305 | bool operator==( const const_iterator &oth ) | 315 | bool operator==( const const_iterator &oth ) const |
306 | { | 316 | { |
307 | return iPos == oth.iPos; | 317 | return iPos == oth.iPos; |
308 | } | 318 | } |
309 | 319 | ||
310 | bool operator!=( const const_iterator &oth ) | 320 | bool operator!=( const const_iterator &oth ) const |
311 | { | 321 | { |
312 | return iPos != oth.iPos; | 322 | return iPos != oth.iPos; |
313 | } | 323 | } |
@@ -327,6 +337,16 @@ namespace Bu | |||
327 | "Cannot dereference finished iterator."); | 337 | "Cannot dereference finished iterator."); |
328 | return src[iPos]; | 338 | return src[iPos]; |
329 | } | 339 | } |
340 | |||
341 | operator bool() const | ||
342 | { | ||
343 | return iPos < 0; | ||
344 | } | ||
345 | |||
346 | bool isValid() const | ||
347 | { | ||
348 | return iPos < 0; | ||
349 | } | ||
330 | } const_iterator; | 350 | } const_iterator; |
331 | 351 | ||
332 | iterator begin() | 352 | iterator begin() |
diff --git a/src/fbasicstring.h b/src/fbasicstring.h index 669784b..8303b5a 100644 --- a/src/fbasicstring.h +++ b/src/fbasicstring.h | |||
@@ -122,6 +122,481 @@ namespace Bu | |||
122 | { | 122 | { |
123 | pFirst = pLast = newChunk( nSize ); | 123 | pFirst = pLast = newChunk( nSize ); |
124 | } | 124 | } |
125 | |||
126 | struct iterator; | ||
127 | typedef struct const_iterator | ||
128 | { | ||
129 | friend class FBasicString<chr, nMinSize, chralloc, chunkalloc>; | ||
130 | private: | ||
131 | const_iterator( Chunk *pChunk, int iPos ) : | ||
132 | pChunk( pChunk ), | ||
133 | iPos( iPos ) | ||
134 | { | ||
135 | } | ||
136 | |||
137 | Chunk *pChunk; | ||
138 | int iPos; | ||
139 | |||
140 | public: | ||
141 | const_iterator( const const_iterator &i ) : | ||
142 | pChunk( i.pChunk ), | ||
143 | iPos( i.iPos ) | ||
144 | { | ||
145 | } | ||
146 | |||
147 | const_iterator( const iterator &i ) : | ||
148 | pChunk( i.pChunk ), | ||
149 | iPos( i.iPos ) | ||
150 | { | ||
151 | } | ||
152 | |||
153 | bool operator==( const const_iterator &i ) const | ||
154 | { | ||
155 | return pChunk == i.pChunk && iPos == i.iPos; | ||
156 | } | ||
157 | |||
158 | bool operator!=( const const_iterator &i ) const | ||
159 | { | ||
160 | return !(*this == i); | ||
161 | } | ||
162 | |||
163 | const_iterator &operator=( const const_iterator &i ) | ||
164 | { | ||
165 | pChunk = i.pChunk; | ||
166 | iPos = i.iPos; | ||
167 | return *this; | ||
168 | } | ||
169 | |||
170 | const_iterator &operator++() | ||
171 | { | ||
172 | if( !pChunk ) return *this; | ||
173 | iPos++; | ||
174 | if( iPos >= pChunk->nLength ) | ||
175 | { | ||
176 | iPos = 0; | ||
177 | pChunk = pChunk->pNext; | ||
178 | } | ||
179 | return *this; | ||
180 | } | ||
181 | |||
182 | const_iterator &operator++( int ) | ||
183 | { | ||
184 | if( !pChunk ) return *this; | ||
185 | iPos++; | ||
186 | if( iPos >= pChunk->nLength ) | ||
187 | { | ||
188 | iPos = 0; | ||
189 | pChunk = pChunk->pNext; | ||
190 | } | ||
191 | return *this; | ||
192 | } | ||
193 | |||
194 | const_iterator &operator+=( int iAmnt ) | ||
195 | { | ||
196 | if( !pChunk ) return *this; | ||
197 | iPos += iAmnt; | ||
198 | while( iPos >= pChunk->nLength ) | ||
199 | { | ||
200 | iPos -= pChunk->nLength; | ||
201 | pChunk = pChunk->pNext; | ||
202 | if( pChunk == NULL ) | ||
203 | break; | ||
204 | } | ||
205 | return *this; | ||
206 | } | ||
207 | |||
208 | const_iterator operator+( int iAmnt ) const | ||
209 | { | ||
210 | if( !pChunk ) return *this; | ||
211 | const_iterator ret( *this ); | ||
212 | ret += iAmnt; | ||
213 | return ret; | ||
214 | } | ||
215 | |||
216 | const chr &operator *() const | ||
217 | { | ||
218 | if( !pChunk ) throw Bu::ExceptionBase("Not a valid const_iterator."); | ||
219 | return pChunk->pData[iPos]; | ||
220 | } | ||
221 | |||
222 | bool operator==( const chr &c ) const | ||
223 | { | ||
224 | if( !pChunk ) return false; | ||
225 | return pChunk->pData[iPos] == c; | ||
226 | } | ||
227 | |||
228 | operator bool() const | ||
229 | { | ||
230 | return pChunk != NULL; | ||
231 | } | ||
232 | |||
233 | bool isValid() const | ||
234 | { | ||
235 | return pChunk != NULL; | ||
236 | } | ||
237 | |||
238 | bool compare( const const_iterator &c ) const | ||
239 | { | ||
240 | const_iterator a = *this; | ||
241 | const_iterator b = c; | ||
242 | if( a == b ) | ||
243 | return true; | ||
244 | for(; a && b; a++, b++ ) | ||
245 | { | ||
246 | if( *a != *b ) | ||
247 | return false; | ||
248 | } | ||
249 | return true; | ||
250 | } | ||
251 | |||
252 | bool compare( const const_iterator &c, int nLen ) const | ||
253 | { | ||
254 | const_iterator a = *this; | ||
255 | const_iterator b = c; | ||
256 | if( a == b ) | ||
257 | return true; | ||
258 | for(int j = 0; a && b && j < nLen; a++, b++, j++ ) | ||
259 | { | ||
260 | if( *a != *b ) | ||
261 | return false; | ||
262 | } | ||
263 | return true; | ||
264 | } | ||
265 | |||
266 | bool compare( const chr *c ) const | ||
267 | { | ||
268 | if( !pChunk ) return false; | ||
269 | const_iterator a = *this; | ||
270 | for(; a && *c; a++, c++ ) | ||
271 | { | ||
272 | if( *a != *c ) | ||
273 | return false; | ||
274 | } | ||
275 | if( a.isValid() != (*c!=(chr)0) ) | ||
276 | return false; | ||
277 | return true; | ||
278 | } | ||
279 | |||
280 | bool compare( const chr *c, int nLen ) const | ||
281 | { | ||
282 | if( !pChunk ) return false; | ||
283 | const_iterator a = *this; | ||
284 | int j = 0; | ||
285 | for(; a && j < nLen; a++, c++, j++ ) | ||
286 | { | ||
287 | if( *a != *c ) | ||
288 | return false; | ||
289 | } | ||
290 | if( j < nLen ) | ||
291 | return false; | ||
292 | return true; | ||
293 | } | ||
294 | |||
295 | bool compare( const MyType &s ) const | ||
296 | { | ||
297 | if( !pChunk ) return false; | ||
298 | return compare( s.begin() ); | ||
299 | } | ||
300 | |||
301 | bool compare( const MyType &s, int nLen ) const | ||
302 | { | ||
303 | if( !pChunk ) return false; | ||
304 | return compare( s.begin(), nLen ); | ||
305 | } | ||
306 | |||
307 | const_iterator find( const chr c ) const | ||
308 | { | ||
309 | for( const_iterator i = *this; i; i++ ) | ||
310 | { | ||
311 | if( *i == c ) | ||
312 | return i; | ||
313 | } | ||
314 | return const_iterator( NULL, 0 ); | ||
315 | } | ||
316 | |||
317 | const_iterator find( const chr *pStr, int nLen ) const | ||
318 | { | ||
319 | for( const_iterator i = *this; i; i++ ) | ||
320 | { | ||
321 | if( i.compare( pStr, nLen ) ) | ||
322 | return i; | ||
323 | } | ||
324 | return const_iterator( NULL, 0 ); | ||
325 | } | ||
326 | |||
327 | const_iterator find( const MyType &s ) const | ||
328 | { | ||
329 | for( const_iterator i = *this; i; i++ ) | ||
330 | { | ||
331 | if( i.compare( s ) ) | ||
332 | return i; | ||
333 | } | ||
334 | return const_iterator( NULL, 0 ); | ||
335 | } | ||
336 | |||
337 | const_iterator find( const MyType &s, int nLen ) const | ||
338 | { | ||
339 | for( const_iterator i = *this; i; i++ ) | ||
340 | { | ||
341 | if( i.compare( s, nLen ) ) | ||
342 | return i; | ||
343 | } | ||
344 | return const_iterator( NULL, 0 ); | ||
345 | } | ||
346 | } const_iterator; | ||
347 | |||
348 | typedef struct iterator | ||
349 | { | ||
350 | friend class FBasicString<chr, nMinSize, chralloc, chunkalloc>; | ||
351 | private: | ||
352 | iterator( Chunk *pChunk, int iPos ) : | ||
353 | pChunk( pChunk ), | ||
354 | iPos( iPos ) | ||
355 | { | ||
356 | } | ||
357 | |||
358 | Chunk *pChunk; | ||
359 | int iPos; | ||
360 | |||
361 | public: | ||
362 | iterator( const iterator &i ) : | ||
363 | pChunk( i.pChunk ), | ||
364 | iPos( i.iPos ) | ||
365 | { | ||
366 | } | ||
367 | |||
368 | operator const_iterator() const | ||
369 | { | ||
370 | return const_iterator( pChunk, iPos ); | ||
371 | } | ||
372 | |||
373 | bool operator==( const iterator &i ) const | ||
374 | { | ||
375 | return pChunk == i.pChunk && iPos == i.iPos; | ||
376 | } | ||
377 | |||
378 | bool operator!=( const iterator &i ) const | ||
379 | { | ||
380 | return !(*this == i); | ||
381 | } | ||
382 | |||
383 | iterator &operator=( const iterator &i ) | ||
384 | { | ||
385 | pChunk = i.pChunk; | ||
386 | iPos = i.iPos; | ||
387 | return *this; | ||
388 | } | ||
389 | |||
390 | iterator &operator++() | ||
391 | { | ||
392 | if( !pChunk ) return *this; | ||
393 | iPos++; | ||
394 | if( iPos >= pChunk->nLength ) | ||
395 | { | ||
396 | iPos = 0; | ||
397 | pChunk = pChunk->pNext; | ||
398 | } | ||
399 | return *this; | ||
400 | } | ||
401 | |||
402 | iterator &operator++( int ) | ||
403 | { | ||
404 | if( !pChunk ) return *this; | ||
405 | iPos++; | ||
406 | if( iPos >= pChunk->nLength ) | ||
407 | { | ||
408 | iPos = 0; | ||
409 | pChunk = pChunk->pNext; | ||
410 | } | ||
411 | return *this; | ||
412 | } | ||
413 | |||
414 | iterator &operator+=( int iAmnt ) | ||
415 | { | ||
416 | if( !pChunk ) return *this; | ||
417 | iPos += iAmnt; | ||
418 | while( iPos >= pChunk->nLength ) | ||
419 | { | ||
420 | iPos -= pChunk->nLength; | ||
421 | pChunk = pChunk->pNext; | ||
422 | if( pChunk == NULL ) | ||
423 | break; | ||
424 | } | ||
425 | return *this; | ||
426 | } | ||
427 | |||
428 | iterator operator+( int iAmnt ) const | ||
429 | { | ||
430 | if( !pChunk ) return *this; | ||
431 | iterator ret( *this ); | ||
432 | ret += iAmnt; | ||
433 | return ret; | ||
434 | } | ||
435 | |||
436 | chr &operator*() | ||
437 | { | ||
438 | if( !pChunk ) throw Bu::ExceptionBase("Not a valid iterator."); | ||
439 | return pChunk->pData[iPos]; | ||
440 | } | ||
441 | |||
442 | const chr &operator*() const | ||
443 | { | ||
444 | if( !pChunk ) throw Bu::ExceptionBase("Not a valid iterator."); | ||
445 | return pChunk->pData[iPos]; | ||
446 | } | ||
447 | |||
448 | bool operator==( const chr &c ) const | ||
449 | { | ||
450 | if( !pChunk ) return false; | ||
451 | return pChunk->pData[iPos] == c; | ||
452 | } | ||
453 | |||
454 | iterator &operator=( const chr &c ) | ||
455 | { | ||
456 | if( !pChunk ) throw Bu::ExceptionBase("Not a valid iterator."); | ||
457 | pChunk->pData[iPos] = c; | ||
458 | return *this; | ||
459 | } | ||
460 | |||
461 | operator bool() const | ||
462 | { | ||
463 | return pChunk != NULL; | ||
464 | } | ||
465 | |||
466 | bool isValid() const | ||
467 | { | ||
468 | return pChunk != NULL; | ||
469 | } | ||
470 | |||
471 | bool compare( const iterator &c ) const | ||
472 | { | ||
473 | iterator a = *this; | ||
474 | iterator b = c; | ||
475 | if( a == b ) | ||
476 | return true; | ||
477 | for(; a && b; a++, b++ ) | ||
478 | { | ||
479 | if( *a != *b ) | ||
480 | return false; | ||
481 | } | ||
482 | return true; | ||
483 | } | ||
484 | |||
485 | bool compare( const iterator &c, int nLen ) const | ||
486 | { | ||
487 | iterator a = *this; | ||
488 | iterator b = c; | ||
489 | if( a == b ) | ||
490 | return true; | ||
491 | for(int j = 0; a && b && j < nLen; a++, b++, j++ ) | ||
492 | { | ||
493 | if( *a != *b ) | ||
494 | return false; | ||
495 | } | ||
496 | return true; | ||
497 | } | ||
498 | |||
499 | bool compare( const chr *c ) const | ||
500 | { | ||
501 | if( !pChunk ) return false; | ||
502 | iterator a = *this; | ||
503 | for(; a && *c; a++, c++ ) | ||
504 | { | ||
505 | if( *a != *c ) | ||
506 | return false; | ||
507 | } | ||
508 | if( a.isValid() != (*c!=(chr)0) ) | ||
509 | return false; | ||
510 | return true; | ||
511 | } | ||
512 | |||
513 | bool compare( const chr *c, int nLen ) const | ||
514 | { | ||
515 | if( !pChunk ) return false; | ||
516 | iterator a = *this; | ||
517 | int j = 0; | ||
518 | for(; a && j < nLen; a++, c++, j++ ) | ||
519 | { | ||
520 | if( *a != *c ) | ||
521 | return false; | ||
522 | } | ||
523 | if( j < nLen ) | ||
524 | return false; | ||
525 | return true; | ||
526 | } | ||
527 | |||
528 | bool compare( const MyType &s ) const | ||
529 | { | ||
530 | if( !pChunk ) return false; | ||
531 | return compare( s.begin() ); | ||
532 | } | ||
533 | |||
534 | bool compare( const MyType &s, int nLen ) const | ||
535 | { | ||
536 | if( !pChunk ) return false; | ||
537 | return compare( s.begin(), nLen ); | ||
538 | } | ||
539 | |||
540 | iterator find( const chr c ) const | ||
541 | { | ||
542 | for( iterator i = *this; i; i++ ) | ||
543 | { | ||
544 | if( *i == c ) | ||
545 | return i; | ||
546 | } | ||
547 | return iterator( NULL, 0 ); | ||
548 | } | ||
549 | |||
550 | iterator find( const chr *pStr, int nLen ) const | ||
551 | { | ||
552 | for( iterator i = *this; i; i++ ) | ||
553 | { | ||
554 | if( i.compare( pStr, nLen ) ) | ||
555 | return i; | ||
556 | } | ||
557 | return iterator( NULL, 0 ); | ||
558 | } | ||
559 | |||
560 | iterator find( const MyType &s ) const | ||
561 | { | ||
562 | for( iterator i = *this; i; i++ ) | ||
563 | { | ||
564 | if( i.compare( s ) ) | ||
565 | return i; | ||
566 | } | ||
567 | return iterator( NULL, 0 ); | ||
568 | } | ||
569 | |||
570 | iterator find( const MyType &s, int nLen ) const | ||
571 | { | ||
572 | for( iterator i = *this; i; i++ ) | ||
573 | { | ||
574 | if( i.compare( s, nLen ) ) | ||
575 | return i; | ||
576 | } | ||
577 | return iterator( NULL, 0 ); | ||
578 | } | ||
579 | } iterator; | ||
580 | |||
581 | //typedef chr *iterator; | ||
582 | // typedef const chr *const_iterator; | ||
583 | // typedef iterator const_iterator; | ||
584 | |||
585 | FBasicString( const const_iterator &s ) : | ||
586 | nLength( 0 ), | ||
587 | pFirst( NULL ), | ||
588 | pLast( NULL ) | ||
589 | { | ||
590 | append( s ); | ||
591 | } | ||
592 | |||
593 | FBasicString( const const_iterator &s, const const_iterator &e ) : | ||
594 | nLength( 0 ), | ||
595 | pFirst( NULL ), | ||
596 | pLast( NULL ) | ||
597 | { | ||
598 | append( s, e ); | ||
599 | } | ||
125 | 600 | ||
126 | virtual ~FBasicString() | 601 | virtual ~FBasicString() |
127 | { | 602 | { |
@@ -129,10 +604,6 @@ namespace Bu | |||
129 | } | 604 | } |
130 | 605 | ||
131 | /** | 606 | /** |
132 | *@todo void append( const MyType & sData ) | ||
133 | */ | ||
134 | |||
135 | /** | ||
136 | * Append data to your string. | 607 | * Append data to your string. |
137 | *@param pData (const chr *) The data to append. | 608 | *@param pData (const chr *) The data to append. |
138 | */ | 609 | */ |
@@ -205,6 +676,74 @@ namespace Bu | |||
205 | } | 676 | } |
206 | 677 | ||
207 | /** | 678 | /** |
679 | * Append another FString to this one. | ||
680 | *@param sData (MyType &) The FString to append. | ||
681 | *@param nLen How much data to append. | ||
682 | */ | ||
683 | void append( const MyType & sData, long nStart, long nLen ) | ||
684 | { | ||
685 | if( nLen < 0 ) | ||
686 | nLen = sData.getSize() - nStart; | ||
687 | append( sData.getStr(), nStart, nLen ); | ||
688 | } | ||
689 | |||
690 | void append( const const_iterator &s ) | ||
691 | { | ||
692 | if( !s.isValid() ) | ||
693 | return; | ||
694 | Chunk *pSrc = s.pChunk; | ||
695 | |||
696 | Chunk *pNew = newChunk( pSrc->nLength-s.iPos ); | ||
697 | cpy( pNew->pData, pSrc->pData+s.iPos, pSrc->nLength-s.iPos ); | ||
698 | appendChunk( pNew ); | ||
699 | |||
700 | while( (pSrc = pSrc->pNext) ) | ||
701 | { | ||
702 | appendChunk( copyChunk( pSrc ) ); | ||
703 | } | ||
704 | } | ||
705 | |||
706 | void append( const iterator &s ) // I get complainst without this one | ||
707 | { | ||
708 | append( const_iterator( s ) ); | ||
709 | } | ||
710 | |||
711 | void append( const const_iterator &s, const const_iterator &e ) | ||
712 | { | ||
713 | if( !s.isValid() ) | ||
714 | return; | ||
715 | if( !e.isValid() ) | ||
716 | { | ||
717 | append( s ); | ||
718 | return; | ||
719 | } | ||
720 | if( s.pChunk == e.pChunk ) | ||
721 | { | ||
722 | // Simple case, they're the same chunk | ||
723 | Chunk *pNew = newChunk( e.iPos-s.iPos ); | ||
724 | cpy( pNew->pData, s.pChunk->pData+s.iPos, e.iPos-s.iPos ); | ||
725 | appendChunk( pNew ); | ||
726 | } | ||
727 | else | ||
728 | { | ||
729 | // A little trickier, scan the blocks... | ||
730 | Chunk *pSrc = s.pChunk; | ||
731 | Chunk *pNew = newChunk( pSrc->nLength-s.iPos ); | ||
732 | cpy( pNew->pData, pSrc->pData+s.iPos, pSrc->nLength-s.iPos ); | ||
733 | appendChunk( pNew ); | ||
734 | |||
735 | while( (pSrc = pSrc->pNext) != e.pChunk ) | ||
736 | { | ||
737 | appendChunk( copyChunk( pSrc ) ); | ||
738 | } | ||
739 | |||
740 | pNew = newChunk( e.iPos ); | ||
741 | cpy( pNew->pData, pSrc->pData, e.iPos ); | ||
742 | appendChunk( pNew ); | ||
743 | } | ||
744 | } | ||
745 | |||
746 | /** | ||
208 | * Prepend another FString to this one. | 747 | * Prepend another FString to this one. |
209 | *@param sData (MyType &) The FString to prepend. | 748 | *@param sData (MyType &) The FString to prepend. |
210 | */ | 749 | */ |
@@ -549,6 +1088,42 @@ namespace Bu | |||
549 | append( pData, nSize ); | 1088 | append( pData, nSize ); |
550 | } | 1089 | } |
551 | 1090 | ||
1091 | void set( const chr *pData, long nStart, long nSize ) | ||
1092 | { | ||
1093 | clear(); | ||
1094 | append( pData, nStart, nSize ); | ||
1095 | } | ||
1096 | |||
1097 | void set( const MyType &rData ) | ||
1098 | { | ||
1099 | clear(); | ||
1100 | append( rData ); | ||
1101 | } | ||
1102 | |||
1103 | void set( const MyType &rData, long nSize ) | ||
1104 | { | ||
1105 | clear(); | ||
1106 | append( rData, nSize ); | ||
1107 | } | ||
1108 | |||
1109 | void set( const MyType &rData, long nStart, long nSize ) | ||
1110 | { | ||
1111 | clear(); | ||
1112 | append( rData, nStart, nSize ); | ||
1113 | } | ||
1114 | |||
1115 | void set( const_iterator s ) | ||
1116 | { | ||
1117 | clear(); | ||
1118 | append( s ); | ||
1119 | } | ||
1120 | |||
1121 | void set( const_iterator s, const_iterator e ) | ||
1122 | { | ||
1123 | clear(); | ||
1124 | append( s, e ); | ||
1125 | } | ||
1126 | |||
552 | void expand() | 1127 | void expand() |
553 | { | 1128 | { |
554 | flatten(); | 1129 | flatten(); |
@@ -704,6 +1279,55 @@ namespace Bu | |||
704 | return (pFirst != NULL); | 1279 | return (pFirst != NULL); |
705 | } | 1280 | } |
706 | 1281 | ||
1282 | bool compareSub( const chr *pData, long nIndex, long nLen ) | ||
1283 | { | ||
1284 | if( pFirst == NULL ) { | ||
1285 | if( pData == NULL ) | ||
1286 | return true; | ||
1287 | if( pData[0] == (chr)0 ) | ||
1288 | return true; | ||
1289 | return false; | ||
1290 | } | ||
1291 | if( nIndex+nLen > nLength ) | ||
1292 | return false; | ||
1293 | |||
1294 | flatten(); | ||
1295 | pFirst->pData[nLength] = (chr)0; | ||
1296 | const chr *a = pData; | ||
1297 | chr *b = pFirst->pData+nIndex; | ||
1298 | for( long j = 0; j < nLen; j++, a++, b++ ) | ||
1299 | { | ||
1300 | if( *a != *b ) | ||
1301 | return false; | ||
1302 | if( *a == (chr)0 && j < nLength ) | ||
1303 | return false; | ||
1304 | } | ||
1305 | |||
1306 | return true; | ||
1307 | } | ||
1308 | |||
1309 | bool compareSub( const MyType &rData, long nIndex, long nLen ) | ||
1310 | { | ||
1311 | if( pFirst == NULL || rData.pFirst == NULL ) | ||
1312 | return false; | ||
1313 | if( nLen < 0 ) | ||
1314 | nLen = rData.nLength; | ||
1315 | if( nIndex+nLen > nLength ) | ||
1316 | return false; | ||
1317 | |||
1318 | flatten(); | ||
1319 | rData.flatten(); | ||
1320 | const chr *a = rData.pFirst->pData; | ||
1321 | chr *b = pFirst->pData + nIndex; | ||
1322 | for( long j = 0; j < nLen; j++, a++, b++ ) | ||
1323 | { | ||
1324 | if( *a != *b ) | ||
1325 | return false; | ||
1326 | } | ||
1327 | |||
1328 | return true; | ||
1329 | } | ||
1330 | |||
707 | /** | 1331 | /** |
708 | * Is the character at index (nIndex) white space? | 1332 | * Is the character at index (nIndex) white space? |
709 | *@param nIndex (long) The index of the character you want to check. | 1333 | *@param nIndex (long) The index of the character you want to check. |
@@ -758,45 +1382,56 @@ namespace Bu | |||
758 | } | 1382 | } |
759 | } | 1383 | } |
760 | 1384 | ||
761 | /** | 1385 | const_iterator find( const chr cChar, |
762 | * Find the index of the first occurrance of (sText) | 1386 | const_iterator iStart=begin() ) const |
763 | *@param sText (const chr *) The string to search for. | ||
764 | *@returns (long) The index of the first occurrance. -1 for not found. | ||
765 | */ | ||
766 | long find( const chr cChar ) const | ||
767 | { | 1387 | { |
768 | flatten(); | 1388 | for( ; iStart; iStart++ ) |
769 | for( long j = 0; j < pFirst->nLength; j++ ) | ||
770 | { | 1389 | { |
771 | if( pFirst->pData[j] == cChar ) | 1390 | if( cChar == *iStart ) |
772 | return j; | 1391 | return iStart; |
773 | } | 1392 | } |
774 | return -1; | 1393 | return end(); |
775 | } | 1394 | } |
776 | 1395 | ||
777 | /** | 1396 | const_iterator find( const chr *sText, int nLen, |
778 | * Find the index of the first occurrance of cChar | 1397 | const_iterator iStart=begin() ) const |
779 | *@param cChar (const chr) The character to search for. | ||
780 | *@returns (long) The index of the first occurrance. -1 for not found. | ||
781 | */ | ||
782 | long find( const chr *sText ) const | ||
783 | { | 1398 | { |
784 | long nTLen = strlen( sText ); | 1399 | for( ; iStart; iStart++ ) |
785 | flatten(); | ||
786 | for( long j = 0; j < pFirst->nLength-nTLen; j++ ) | ||
787 | { | 1400 | { |
788 | if( !strncmp( sText, pFirst->pData+j, nTLen ) ) | 1401 | if( iStart.compare( sText, nLen ) ) |
789 | return j; | 1402 | return iStart; |
790 | } | 1403 | } |
791 | return -1; | 1404 | return end(); |
792 | } | 1405 | } |
793 | 1406 | ||
1407 | const_iterator find( const MyType &rStr, | ||
1408 | const_iterator iStart=begin() ) const | ||
1409 | { | ||
1410 | for( ; iStart; iStart++ ) | ||
1411 | { | ||
1412 | if( iStart.compare( rStr ) ) | ||
1413 | return iStart; | ||
1414 | } | ||
1415 | return end(); | ||
1416 | } | ||
1417 | |||
1418 | const_iterator find( const MyType &rStr, int nLen, | ||
1419 | const_iterator iStart=begin() ) const | ||
1420 | { | ||
1421 | for( ; iStart; iStart++ ) | ||
1422 | { | ||
1423 | if( iStart.compare( rStr, nLen ) ) | ||
1424 | return iStart; | ||
1425 | } | ||
1426 | return end(); | ||
1427 | } | ||
1428 | |||
794 | /** | 1429 | /** |
795 | * Find the index of the first occurrance of cChar | 1430 | * Find the index of the first occurrance of cChar |
796 | *@param sText (const chr *) The string to search for. | 1431 | *@param sText (const chr *) The string to search for. |
797 | *@returns (long) The index of the first occurrance. -1 for not found. | 1432 | *@returns (long) The index of the first occurrance. -1 for not found. |
798 | */ | 1433 | */ |
799 | long find( long iStart, const chr cChar ) const | 1434 | long findIdx( const chr cChar, long iStart=0 ) const |
800 | { | 1435 | { |
801 | flatten(); | 1436 | flatten(); |
802 | for( long j = iStart; j < pFirst->nLength; j++ ) | 1437 | for( long j = iStart; j < pFirst->nLength; j++ ) |
@@ -812,7 +1447,7 @@ namespace Bu | |||
812 | *@param cChar (const chr) The character to search for. | 1447 | *@param cChar (const chr) The character to search for. |
813 | *@returns (long) The index of the first occurrance. -1 for not found. | 1448 | *@returns (long) The index of the first occurrance. -1 for not found. |
814 | */ | 1449 | */ |
815 | long find( long iStart, const chr *sText ) const | 1450 | long findIdx( const chr *sText, long iStart=0 ) const |
816 | { | 1451 | { |
817 | long nTLen = strlen( sText ); | 1452 | long nTLen = strlen( sText ); |
818 | flatten(); | 1453 | flatten(); |
@@ -829,7 +1464,7 @@ namespace Bu | |||
829 | *@param sText (const chr *) The string to search for. | 1464 | *@param sText (const chr *) The string to search for. |
830 | *@returns (long) The index of the last occurrance. -1 for not found. | 1465 | *@returns (long) The index of the last occurrance. -1 for not found. |
831 | */ | 1466 | */ |
832 | long rfind( const chr *sText ) const | 1467 | long rfindIdx( const chr *sText ) const |
833 | { | 1468 | { |
834 | long nTLen = strlen( sText ); | 1469 | long nTLen = strlen( sText ); |
835 | flatten(); | 1470 | flatten(); |
@@ -928,37 +1563,28 @@ namespace Bu | |||
928 | } | 1563 | } |
929 | } | 1564 | } |
930 | 1565 | ||
931 | typedef chr *iterator; | ||
932 | typedef const chr *const_iterator; | ||
933 | |||
934 | iterator begin() | 1566 | iterator begin() |
935 | { | 1567 | { |
936 | if( nLength == 0 ) | 1568 | if( nLength == 0 ) |
937 | return NULL; | 1569 | return iterator( NULL, 0 ); |
938 | flatten(); | 1570 | return iterator( pFirst, 0 ); |
939 | return pFirst->pData; | ||
940 | } | 1571 | } |
941 | 1572 | ||
942 | const_iterator begin() const | 1573 | const_iterator begin() const |
943 | { | 1574 | { |
944 | if( nLength == 0 ) | 1575 | if( nLength == 0 ) |
945 | return NULL; | 1576 | return const_iterator( NULL, 0 ); |
946 | flatten(); | 1577 | return iterator( pFirst, 0 ); |
947 | return pFirst->pData; | ||
948 | } | 1578 | } |
949 | 1579 | ||
950 | iterator end() | 1580 | iterator end() |
951 | { | 1581 | { |
952 | if( nLength == 0 ) | 1582 | return iterator( NULL, 0 ); |
953 | return NULL; | ||
954 | return pFirst->pData+pFirst->nLength; | ||
955 | } | 1583 | } |
956 | 1584 | ||
957 | const_iterator end() const | 1585 | const_iterator end() const |
958 | { | 1586 | { |
959 | if( nLength == 0 ) | 1587 | return const_iterator( NULL, 0 ); |
960 | return NULL; | ||
961 | return pFirst->pData+pFirst->nLength; | ||
962 | } | 1588 | } |
963 | 1589 | ||
964 | bool isEmpty() const | 1590 | bool isEmpty() const |
@@ -575,7 +575,17 @@ namespace Bu | |||
575 | { | 575 | { |
576 | } | 576 | } |
577 | 577 | ||
578 | bool isActive() | 578 | DEPRECATED bool isActive() const |
579 | { | ||
580 | return !bFinished; | ||
581 | } | ||
582 | |||
583 | bool isValid() const | ||
584 | { | ||
585 | return !bFinished; | ||
586 | } | ||
587 | |||
588 | operator bool() const | ||
579 | { | 589 | { |
580 | return !bFinished; | 590 | return !bFinished; |
581 | } | 591 | } |
@@ -605,7 +615,7 @@ namespace Bu | |||
605 | /** | 615 | /** |
606 | * Iterator equality comparison operator. Iterators the same? | 616 | * Iterator equality comparison operator. Iterators the same? |
607 | */ | 617 | */ |
608 | bool operator==( const iterator &oth ) | 618 | bool operator==( const iterator &oth ) const |
609 | { | 619 | { |
610 | if( bFinished != oth.bFinished ) | 620 | if( bFinished != oth.bFinished ) |
611 | return false; | 621 | return false; |
@@ -624,7 +634,7 @@ namespace Bu | |||
624 | /** | 634 | /** |
625 | * Iterator not equality comparison operator. Not the same? | 635 | * Iterator not equality comparison operator. Not the same? |
626 | */ | 636 | */ |
627 | bool operator!=( const iterator &oth ) | 637 | bool operator!=( const iterator &oth ) const |
628 | { | 638 | { |
629 | return !(*this == oth ); | 639 | return !(*this == oth ); |
630 | } | 640 | } |
@@ -650,6 +660,11 @@ namespace Bu | |||
650 | { | 660 | { |
651 | return hsh.getValueAtPos( nPos ); | 661 | return hsh.getValueAtPos( nPos ); |
652 | } | 662 | } |
663 | |||
664 | const value &operator *() const | ||
665 | { | ||
666 | return hsh.getValueAtPos( nPos ); | ||
667 | } | ||
653 | 668 | ||
654 | /** | 669 | /** |
655 | * Get the key behind this iterator. | 670 | * Get the key behind this iterator. |
@@ -697,6 +712,16 @@ namespace Bu | |||
697 | bool bFinished; | 712 | bool bFinished; |
698 | 713 | ||
699 | public: | 714 | public: |
715 | bool isValid() const | ||
716 | { | ||
717 | return !bFinished; | ||
718 | } | ||
719 | |||
720 | operator bool() const | ||
721 | { | ||
722 | return !bFinished; | ||
723 | } | ||
724 | |||
700 | /** | 725 | /** |
701 | * Iterator incrementation operator. Move the iterator forward. | 726 | * Iterator incrementation operator. Move the iterator forward. |
702 | */ | 727 | */ |
@@ -722,7 +747,7 @@ namespace Bu | |||
722 | /** | 747 | /** |
723 | * Iterator equality comparison operator. Iterators the same? | 748 | * Iterator equality comparison operator. Iterators the same? |
724 | */ | 749 | */ |
725 | bool operator==( const const_iterator &oth ) | 750 | bool operator==( const const_iterator &oth ) const |
726 | { | 751 | { |
727 | if( bFinished != oth.bFinished ) | 752 | if( bFinished != oth.bFinished ) |
728 | return false; | 753 | return false; |
@@ -741,7 +766,7 @@ namespace Bu | |||
741 | /** | 766 | /** |
742 | * Iterator not equality comparison operator. Not the same? | 767 | * Iterator not equality comparison operator. Not the same? |
743 | */ | 768 | */ |
744 | bool operator!=( const const_iterator &oth ) | 769 | bool operator!=( const const_iterator &oth ) const |
745 | { | 770 | { |
746 | return !(*this == oth ); | 771 | return !(*this == oth ); |
747 | } | 772 | } |
@@ -377,6 +377,16 @@ namespace Bu | |||
377 | return *this; | 377 | return *this; |
378 | } | 378 | } |
379 | 379 | ||
380 | operator bool() | ||
381 | { | ||
382 | return pLink != NULL; | ||
383 | } | ||
384 | |||
385 | bool isValid() | ||
386 | { | ||
387 | return pLink != NULL; | ||
388 | } | ||
389 | |||
380 | /** | 390 | /** |
381 | * Assignment operator. | 391 | * Assignment operator. |
382 | *@param oth (const iterator &) The other iterator to set this | 392 | *@param oth (const iterator &) The other iterator to set this |
@@ -499,6 +509,16 @@ namespace Bu | |||
499 | pLink = oth.pLink; | 509 | pLink = oth.pLink; |
500 | return *this; | 510 | return *this; |
501 | } | 511 | } |
512 | |||
513 | operator bool() | ||
514 | { | ||
515 | return pLink != NULL; | ||
516 | } | ||
517 | |||
518 | bool isValid() | ||
519 | { | ||
520 | return pLink != NULL; | ||
521 | } | ||
502 | } const_iterator; | 522 | } const_iterator; |
503 | 523 | ||
504 | /** | 524 | /** |
diff --git a/src/minimacro.cpp b/src/minimacro.cpp index b97cefc..0d524a9 100644 --- a/src/minimacro.cpp +++ b/src/minimacro.cpp | |||
@@ -141,7 +141,7 @@ Bu::FString Bu::MiniMacro::parseCmd() | |||
141 | Bu::FString Bu::MiniMacro::callFunc( | 141 | Bu::FString Bu::MiniMacro::callFunc( |
142 | const Bu::FString &sIn, const Bu::FString &sFunc ) | 142 | const Bu::FString &sIn, const Bu::FString &sFunc ) |
143 | { | 143 | { |
144 | int i = sFunc.find('('); | 144 | int i = sFunc.findIdx('('); |
145 | if( i < 0 ) | 145 | if( i < 0 ) |
146 | throw Bu::ExceptionBase("That doesn't look like a function call"); | 146 | throw Bu::ExceptionBase("That doesn't look like a function call"); |
147 | Bu::FString sName( sFunc.getStr(), i ); | 147 | Bu::FString sName( sFunc.getStr(), i ); |
@@ -322,7 +322,7 @@ namespace Bu | |||
322 | /** | 322 | /** |
323 | * Iterator equality comparison operator. Iterators the same? | 323 | * Iterator equality comparison operator. Iterators the same? |
324 | */ | 324 | */ |
325 | bool operator==( const iterator &oth ) | 325 | bool operator==( const iterator &oth ) const |
326 | { | 326 | { |
327 | if( bFinished != oth.bFinished ) | 327 | if( bFinished != oth.bFinished ) |
328 | return false; | 328 | return false; |
@@ -341,7 +341,7 @@ namespace Bu | |||
341 | /** | 341 | /** |
342 | * Iterator not equality comparison operator. Not the same? | 342 | * Iterator not equality comparison operator. Not the same? |
343 | */ | 343 | */ |
344 | bool operator!=( const iterator &oth ) | 344 | bool operator!=( const iterator &oth ) const |
345 | { | 345 | { |
346 | return !(*this == oth ); | 346 | return !(*this == oth ); |
347 | } | 347 | } |
@@ -366,6 +366,21 @@ namespace Bu | |||
366 | { | 366 | { |
367 | return hsh.getKeyAtPos( nPos ); | 367 | return hsh.getKeyAtPos( nPos ); |
368 | } | 368 | } |
369 | |||
370 | const key &operator *() const | ||
371 | { | ||
372 | return hsh.getKeyAtPos( nPos ); | ||
373 | } | ||
374 | |||
375 | bool isValid() const | ||
376 | { | ||
377 | return !bFinished; | ||
378 | } | ||
379 | |||
380 | operator bool() const | ||
381 | { | ||
382 | return !bFinished; | ||
383 | } | ||
369 | } iterator; | 384 | } iterator; |
370 | 385 | ||
371 | /** | 386 | /** |
@@ -420,7 +435,7 @@ namespace Bu | |||
420 | /** | 435 | /** |
421 | * Iterator equality comparison operator. Iterators the same? | 436 | * Iterator equality comparison operator. Iterators the same? |
422 | */ | 437 | */ |
423 | bool operator==( const const_iterator &oth ) | 438 | bool operator==( const const_iterator &oth ) const |
424 | { | 439 | { |
425 | if( bFinished != oth.bFinished ) | 440 | if( bFinished != oth.bFinished ) |
426 | return false; | 441 | return false; |
@@ -439,7 +454,7 @@ namespace Bu | |||
439 | /** | 454 | /** |
440 | * Iterator not equality comparison operator. Not the same? | 455 | * Iterator not equality comparison operator. Not the same? |
441 | */ | 456 | */ |
442 | bool operator!=( const const_iterator &oth ) | 457 | bool operator!=( const const_iterator &oth ) const |
443 | { | 458 | { |
444 | return !(*this == oth ); | 459 | return !(*this == oth ); |
445 | } | 460 | } |
@@ -464,6 +479,16 @@ namespace Bu | |||
464 | { | 479 | { |
465 | return hsh.getKeyAtPos( nPos ); | 480 | return hsh.getKeyAtPos( nPos ); |
466 | } | 481 | } |
482 | |||
483 | bool isValid() const | ||
484 | { | ||
485 | return !bFinished; | ||
486 | } | ||
487 | |||
488 | operator bool() const | ||
489 | { | ||
490 | return !bFinished; | ||
491 | } | ||
467 | } const_iterator; | 492 | } const_iterator; |
468 | 493 | ||
469 | /** | 494 | /** |
diff --git a/src/tafwriter.cpp b/src/tafwriter.cpp index b0f5def..82d39e5 100644 --- a/src/tafwriter.cpp +++ b/src/tafwriter.cpp | |||
@@ -104,7 +104,10 @@ void Bu::TafWriter::writeString( const Bu::FString &str ) | |||
104 | sOut.write(buf, 4 ); | 104 | sOut.write(buf, 4 ); |
105 | } | 105 | } |
106 | else | 106 | else |
107 | sOut.write( s, 1 ); | 107 | { |
108 | const char buf = *s; | ||
109 | sOut.write( &buf, 1 ); | ||
110 | } | ||
108 | } | 111 | } |
109 | sOut.write("\"", 1 ); | 112 | sOut.write("\"", 1 ); |
110 | } | 113 | } |
diff --git a/src/tests/rh.cpp b/src/tests/rh.cpp deleted file mode 100644 index 70abcb7..0000000 --- a/src/tests/rh.cpp +++ /dev/null | |||
@@ -1,52 +0,0 @@ | |||
1 | #include "bu/file.h" | ||
2 | #include "bu/hash.h" | ||
3 | #include "bu/archive.h" | ||
4 | #include "bu/fstring.h" | ||
5 | #include "bu/nids.h" | ||
6 | #include "bu/nidsstream.h" | ||
7 | |||
8 | int main( int argc, char *argv[] ) | ||
9 | { | ||
10 | if( argv[1][0] == 'r' ) | ||
11 | { | ||
12 | typedef Bu::Hash<Bu::FString, int> Hsh; | ||
13 | |||
14 | Bu::File fIn( argv[2], Bu::File::Read ); | ||
15 | Bu::Archive ar( fIn, Bu::Archive::load ); | ||
16 | |||
17 | Hsh h; | ||
18 | ar >> h; | ||
19 | |||
20 | printf("Read %d.\n", h.getSize() ); | ||
21 | for( Hsh::iterator i = h.begin(); i != h.end(); i++ ) | ||
22 | { | ||
23 | printf(" - \"%s\" = %d\n", i.getKey().getStr(), i.getValue() ); | ||
24 | } | ||
25 | |||
26 | printf("%d vs. %d\n", h.getSize(), h.getKeys().getSize() ); | ||
27 | } | ||
28 | else if( argv[1][0] == 'n' ) | ||
29 | { | ||
30 | typedef Bu::Hash<Bu::FString, int> Hsh; | ||
31 | |||
32 | Bu::File fIn( argv[2], Bu::File::Read ); | ||
33 | Bu::Nids n( fIn ); | ||
34 | n.initialize(); | ||
35 | Bu::NidsStream sIn = n.openStream( 0 ); | ||
36 | Bu::Archive ar( sIn, Bu::Archive::load ); | ||
37 | |||
38 | Hsh h; | ||
39 | ar >> h; | ||
40 | |||
41 | printf("Read %d.\n", h.getSize() ); | ||
42 | for( Hsh::iterator i = h.begin(); i != h.end(); i++ ) | ||
43 | { | ||
44 | printf(" - \"%s\" = %d\n", i.getKey().getStr(), i.getValue() ); | ||
45 | } | ||
46 | |||
47 | printf("%d vs. %d\n", h.getSize(), h.getKeys().getSize() ); | ||
48 | } | ||
49 | |||
50 | return 0; | ||
51 | } | ||
52 | |||
diff --git a/src/tests/url.cpp b/src/tests/url.cpp new file mode 100644 index 0000000..c9af676 --- /dev/null +++ b/src/tests/url.cpp | |||
@@ -0,0 +1,32 @@ | |||
1 | #include "bu/url.h" | ||
2 | |||
3 | #include <stdio.h> | ||
4 | |||
5 | int main( int argc, char *argv[] ) | ||
6 | { | ||
7 | printf("encodede: %s\n", Bu::Url::encode( argv[1] ).getStr() ); | ||
8 | printf("decodede: %s\n", Bu::Url::decode( argv[1] ).getStr() ); | ||
9 | Bu::Url u( argv[1] ); | ||
10 | |||
11 | printf("Protocol: %s\n", u.getProtocol().getStr() ); | ||
12 | printf("User: %s\n", u.getUser().getStr() ); | ||
13 | printf("Pass: %s\n", u.getPass().getStr() ); | ||
14 | printf("Host: %s\n", u.getHost().getStr() ); | ||
15 | printf("Path: %s\n", u.getPath().getStr() ); | ||
16 | try | ||
17 | { | ||
18 | printf("Port: %d\n", u.getPort() ); | ||
19 | } catch( Bu::ExceptionBase &e ) | ||
20 | { | ||
21 | printf("Port: not set.\n"); | ||
22 | } | ||
23 | printf("Parameters:\n"); | ||
24 | for( Bu::Url::ParamList::const_iterator i = u.getParamBegin(); i; i++ ) | ||
25 | { | ||
26 | printf(" \"%s\" = \"%s\"\n", | ||
27 | (*i).sName.getStr(), (*i).sValue.getStr() | ||
28 | ); | ||
29 | } | ||
30 | |||
31 | return 0; | ||
32 | } | ||
diff --git a/src/unit/fstring.unit b/src/unit/fstring.unit index 3912de2..a0d62da 100644 --- a/src/unit/fstring.unit +++ b/src/unit/fstring.unit | |||
@@ -138,3 +138,158 @@ | |||
138 | unitTest( a.getSubStr( -10 ) == "abcdefghijklmnop" ); | 138 | unitTest( a.getSubStr( -10 ) == "abcdefghijklmnop" ); |
139 | unitTest( a.getSubStr( -15, 4 ) == "abcd" ); | 139 | unitTest( a.getSubStr( -15, 4 ) == "abcd" ); |
140 | } | 140 | } |
141 | |||
142 | {%compareSub1} | ||
143 | { | ||
144 | Bu::FString a("just a string."); | ||
145 | unitTest( a.compareSub("a ", 5, 2) == true ); | ||
146 | unitTest( a.compareSub("string.aoeu", 7, 11 ) == false ); | ||
147 | unitTest( a.compareSub("string.aoeu", 7, 3 ) == true ); | ||
148 | } | ||
149 | |||
150 | {%compareSub2} | ||
151 | { | ||
152 | Bu::FString a("just a string."); | ||
153 | unitTest( a.compareSub(Bu::FString("a "), 5, 2) == true ); | ||
154 | unitTest( a.compareSub(Bu::FString("string.aoeu"), 7, 11 ) == false ); | ||
155 | unitTest( a.compareSub(Bu::FString("string.aoeu"), 7, 3 ) == true ); | ||
156 | } | ||
157 | |||
158 | {%iterator1} | ||
159 | { | ||
160 | Bu::FString a("This is a test."); | ||
161 | Bu::FString b; | ||
162 | for( Bu::FString::iterator i = a.begin(); i; i++ ) | ||
163 | { | ||
164 | b += *i; | ||
165 | } | ||
166 | unitTest( a == b ); | ||
167 | } | ||
168 | |||
169 | {%iterator2} | ||
170 | { | ||
171 | Bu::FString a("This is a test."); | ||
172 | Bu::FString b("--This is a test."); | ||
173 | Bu::FString::iterator ai = a.begin(); | ||
174 | Bu::FString::iterator bi = b.begin(); | ||
175 | unitTest( ai.compare( bi ) == false ); | ||
176 | unitTest( bi.compare( ai ) == false ); | ||
177 | bi++; bi++; | ||
178 | unitTest( ai.compare( bi ) == true ); | ||
179 | unitTest( bi.compare( ai ) == true ); | ||
180 | } | ||
181 | |||
182 | {%iterator3} | ||
183 | { | ||
184 | Bu::FString a("1234honour"); | ||
185 | Bu::FString b("--1234ueje"); | ||
186 | Bu::FString::iterator ai = a.begin(); | ||
187 | Bu::FString::iterator bi = b.begin(); | ||
188 | unitTest( ai.compare( bi, 4 ) == false ); | ||
189 | unitTest( bi.compare( ai, 4 ) == false ); | ||
190 | bi++; bi++; | ||
191 | unitTest( ai.compare( bi, 4 ) == true ); | ||
192 | unitTest( bi.compare( ai, 4 ) == true ); | ||
193 | unitTest( ai.compare( bi, 5 ) == false ); | ||
194 | unitTest( bi.compare( ai, 5 ) == false ); | ||
195 | |||
196 | } | ||
197 | |||
198 | {%iterator4} | ||
199 | { | ||
200 | Bu::FString a("1234aoeu"); | ||
201 | Bu::FString::iterator ai = a.begin(); | ||
202 | unitTest( ai.compare("1234") == false ); | ||
203 | unitTest( ai.compare("1234aoeu") == true ); | ||
204 | unitTest( ai.compare("1234aoeuee") == false ); | ||
205 | } | ||
206 | |||
207 | {%iterator5} | ||
208 | { | ||
209 | Bu::FString a("1234aoeu"); | ||
210 | Bu::FString::iterator ai = a.begin(); | ||
211 | unitTest( ai.compare("1234", 4) == true ); | ||
212 | unitTest( ai.compare("1234aoeu", 8) == true ); | ||
213 | unitTest( ai.compare("1234aoeuee", 10) == false ); | ||
214 | } | ||
215 | |||
216 | {%iterator6} | ||
217 | { | ||
218 | Bu::FString a("just ->this part"); | ||
219 | Bu::FString b; | ||
220 | Bu::FString::iterator s = a.begin(); | ||
221 | for(; s; s++ ) | ||
222 | { | ||
223 | if( *s == '>' ) | ||
224 | { | ||
225 | s++; | ||
226 | b.set( s ); | ||
227 | break; | ||
228 | } | ||
229 | } | ||
230 | unitTest( b == "this part" ); | ||
231 | |||
232 | b.append( s ); | ||
233 | |||
234 | Bu::FString c; | ||
235 | c.set( b.begin() ); | ||
236 | |||
237 | // This is here because the comparison operator used to cause flattening. | ||
238 | unitTest( b == "this partthis part" ); | ||
239 | unitTest( c == b ); | ||
240 | } | ||
241 | |||
242 | {%iterator7} | ||
243 | { | ||
244 | Bu::FString a("just [this] part"); | ||
245 | Bu::FString b; | ||
246 | Bu::FString::iterator s = a.begin(); | ||
247 | for(; s; s++ ) | ||
248 | { | ||
249 | if( *s == '[' ) | ||
250 | { | ||
251 | s++; | ||
252 | break; | ||
253 | } | ||
254 | } | ||
255 | Bu::FString::iterator e = s; | ||
256 | for(; e; e++ ) | ||
257 | { | ||
258 | if( *e == ']' ) | ||
259 | { | ||
260 | b.set( s, e ); | ||
261 | break; | ||
262 | } | ||
263 | } | ||
264 | unitTest( b == "this" ); | ||
265 | |||
266 | b.append( s, e ); | ||
267 | |||
268 | for( Bu::FString::iterator i = b.begin(); i;) | ||
269 | { | ||
270 | Bu::FString::iterator k = i; | ||
271 | k++; | ||
272 | if( !k ) | ||
273 | { | ||
274 | b.append( b.begin(), i ); | ||
275 | break; | ||
276 | } | ||
277 | i = k; | ||
278 | } | ||
279 | Bu::FString l; | ||
280 | l.set( b.begin() ); | ||
281 | unitTest( l == "thisthisthisthi" ); | ||
282 | for( Bu::FString::iterator i = b.begin(); i;) | ||
283 | { | ||
284 | Bu::FString::iterator k = i; | ||
285 | k++; | ||
286 | if( !k ) | ||
287 | { | ||
288 | b.append( b.begin(), i ); | ||
289 | break; | ||
290 | } | ||
291 | i = k; | ||
292 | } | ||
293 | l.set( b.begin() ); | ||
294 | unitTest( l == "thisthisthisthithisthisthisth" ); | ||
295 | } | ||
diff --git a/src/unitsuite.cpp b/src/unitsuite.cpp index 7421496..cdd6a2a 100644 --- a/src/unitsuite.cpp +++ b/src/unitsuite.cpp | |||
@@ -110,7 +110,7 @@ void Bu::UnitSuite::add( Test fTest, const Bu::FString &sName, Expect e ) | |||
110 | TestInfo ti; | 110 | TestInfo ti; |
111 | ti.sName = sName; | 111 | ti.sName = sName; |
112 | ti.eExpect = e; | 112 | ti.eExpect = e; |
113 | long index = ti.sName.rfind("::"); | 113 | long index = ti.sName.rfindIdx("::"); |
114 | if( index != -1 ) | 114 | if( index != -1 ) |
115 | { | 115 | { |
116 | FString tmp = sSuiteName; | 116 | FString tmp = sSuiteName; |
diff --git a/src/url.cpp b/src/url.cpp new file mode 100644 index 0000000..7cc4263 --- /dev/null +++ b/src/url.cpp | |||
@@ -0,0 +1,237 @@ | |||
1 | #include "bu/url.h" | ||
2 | #ifndef WIN32 | ||
3 | # include <netdb.h> | ||
4 | # include <netinet/in.h> | ||
5 | #endif | ||
6 | #include <stdlib.h> | ||
7 | |||
8 | char Bu::Url::hexcode[] = { | ||
9 | '0', '1', '2', '3', '4', '5', '6', '7', | ||
10 | '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' | ||
11 | }; | ||
12 | |||
13 | Bu::Url::Url() | ||
14 | { | ||
15 | } | ||
16 | |||
17 | Bu::Url::Url( const Bu::FString &sUrl ) | ||
18 | { | ||
19 | parseUrl( sUrl ); | ||
20 | } | ||
21 | |||
22 | Bu::Url::~Url() | ||
23 | { | ||
24 | } | ||
25 | |||
26 | void Bu::Url::parseUrl( const Bu::FString &sUrl ) | ||
27 | { | ||
28 | clear(); | ||
29 | |||
30 | Bu::FString::const_iterator i = sUrl.begin(); | ||
31 | parseProtocol( i ); | ||
32 | parseUserPass( i ); | ||
33 | parseHost( i ); | ||
34 | parsePath( i ); | ||
35 | } | ||
36 | |||
37 | Bu::FString Bu::Url::decode( const Bu::FString &sStr ) | ||
38 | { | ||
39 | Bu::FString sRet; | ||
40 | char buf[3] = {0, 0, 0}; | ||
41 | for( Bu::FString::const_iterator i = sStr.begin(); i; i++ ) | ||
42 | { | ||
43 | if( *i == '+' ) | ||
44 | { | ||
45 | sRet += ' '; | ||
46 | } | ||
47 | else if( *i == '%' ) | ||
48 | { | ||
49 | i++; | ||
50 | buf[0] = *i; | ||
51 | i++; | ||
52 | buf[1] = *i; | ||
53 | sRet += (char)((unsigned char)strtol( buf, NULL, 16 )); | ||
54 | } | ||
55 | else | ||
56 | { | ||
57 | sRet += *i; | ||
58 | } | ||
59 | } | ||
60 | return sRet; | ||
61 | } | ||
62 | |||
63 | Bu::FString Bu::Url::encode( const Bu::FString &sStr ) | ||
64 | { | ||
65 | Bu::FString sRet; | ||
66 | for( Bu::FString::const_iterator i = sStr.begin(); i; i++ ) | ||
67 | { | ||
68 | if( *i == ' ' ) | ||
69 | { | ||
70 | sRet += '+'; | ||
71 | } | ||
72 | else if( | ||
73 | (*i >= 'A' && *i <= 'Z') || | ||
74 | (*i >= 'a' && *i <= 'z') || | ||
75 | (*i >= '0' && *i <= '9') || | ||
76 | (*i == '-' || *i == '_' || *i == '.' || *i == '~') | ||
77 | ) | ||
78 | { | ||
79 | sRet += *i; | ||
80 | } | ||
81 | else | ||
82 | { | ||
83 | unsigned char b = *i; | ||
84 | sRet += '%'; | ||
85 | sRet += hexcode[(b>>4)&0xF]; | ||
86 | sRet += hexcode[b&0xF]; | ||
87 | } | ||
88 | } | ||
89 | return sRet; | ||
90 | } | ||
91 | |||
92 | void Bu::Url::parseProtocol( Bu::FString::const_iterator &i ) | ||
93 | { | ||
94 | Bu::FString::const_iterator s = i.find("://", 3); | ||
95 | if( !s ) | ||
96 | throw Bu::ExceptionBase("No :// in url"); | ||
97 | Bu::FString sTmp( i, s ); | ||
98 | setProtocol( sTmp ); | ||
99 | i = s + 3; | ||
100 | } | ||
101 | |||
102 | void Bu::Url::setProtocol( const Bu::FString &sNewProto, bool bAutoSetPort ) | ||
103 | { | ||
104 | sProtocol = sNewProto; | ||
105 | #ifndef WIN32 | ||
106 | if( bAutoSetPort ) | ||
107 | { | ||
108 | struct servent *se = getservbyname( sProtocol.getStr(), "tcp" ); | ||
109 | if( se ) | ||
110 | { | ||
111 | iPort = ntohs( se->s_port ); | ||
112 | } | ||
113 | } | ||
114 | #endif | ||
115 | } | ||
116 | |||
117 | void Bu::Url::parseUserPass( Bu::FString::const_iterator &i ) | ||
118 | { | ||
119 | Bu::FString::const_iterator s = i.find('@'); | ||
120 | if( !s ) | ||
121 | return; | ||
122 | |||
123 | Bu::FString::const_iterator p = i.find(':'); | ||
124 | if( p ) | ||
125 | { | ||
126 | sUser.set( i, p ); | ||
127 | sPass.set( p+1, s ); | ||
128 | } | ||
129 | else | ||
130 | { | ||
131 | sUser.set( i, s ); | ||
132 | } | ||
133 | |||
134 | i = s + 1; | ||
135 | } | ||
136 | |||
137 | void Bu::Url::parseHost( Bu::FString::const_iterator &i ) | ||
138 | { | ||
139 | Bu::FString::const_iterator s = i; | ||
140 | for( ; s && *s != '/'; s++ ) | ||
141 | { | ||
142 | if( *s == ':' ) | ||
143 | { | ||
144 | sHost.set( i, s ); | ||
145 | i = s + 1; | ||
146 | s = i.find('/'); | ||
147 | Bu::FString sPort( i, s ); | ||
148 | iPort = strtol( sPort.getStr(), NULL, 10 ); | ||
149 | i = s; | ||
150 | return; | ||
151 | } | ||
152 | } | ||
153 | sHost.set( i, s ); | ||
154 | i = s; | ||
155 | } | ||
156 | |||
157 | void Bu::Url::parsePath( Bu::FString::const_iterator &i ) | ||
158 | { | ||
159 | if( i ) | ||
160 | { | ||
161 | Bu::FString::const_iterator s = i.find('?'); | ||
162 | sPath.set( i, s ); | ||
163 | i = s + 1; | ||
164 | if( s ) | ||
165 | { | ||
166 | parseParams( i ); | ||
167 | } | ||
168 | } | ||
169 | else | ||
170 | { | ||
171 | sPath = "/"; | ||
172 | } | ||
173 | } | ||
174 | |||
175 | void Bu::Url::parseParams( Bu::FString::const_iterator &i ) | ||
176 | { | ||
177 | bool bName = true; | ||
178 | Bu::FString sName, sValue; | ||
179 | for( Bu::FString::const_iterator s = i; s; s++ ) | ||
180 | { | ||
181 | if( bName ) | ||
182 | { | ||
183 | if( *s == '&' ) | ||
184 | { | ||
185 | sName.set( i, s ); | ||
186 | sValue.clear(); | ||
187 | i = s + 1; | ||
188 | addParam( decode( sName ), decode( sValue ) ); | ||
189 | } | ||
190 | else if( *s == '=' ) | ||
191 | { | ||
192 | sName.set( i, s ); | ||
193 | i = s + 1; | ||
194 | bName = false; | ||
195 | } | ||
196 | } | ||
197 | else | ||
198 | { | ||
199 | if( *s == '&' ) | ||
200 | { | ||
201 | sValue.set( i, s ); | ||
202 | i = s + 1; | ||
203 | bName = true; | ||
204 | addParam( decode( sName ), decode( sValue ) ); | ||
205 | } | ||
206 | } | ||
207 | } | ||
208 | if( i ) | ||
209 | { | ||
210 | if( bName ) | ||
211 | { | ||
212 | sName.set( i ); | ||
213 | sValue.clear(); | ||
214 | } | ||
215 | else | ||
216 | { | ||
217 | sValue.set( i ); | ||
218 | } | ||
219 | addParam( decode( sName ), decode( sValue ) ); | ||
220 | } | ||
221 | } | ||
222 | |||
223 | void Bu::Url::addParam( const Bu::FString &n, const Bu::FString &v ) | ||
224 | { | ||
225 | lParam.append( Param( n, v ) ); | ||
226 | } | ||
227 | |||
228 | void Bu::Url::clear() | ||
229 | { | ||
230 | sProtocol.clear(); | ||
231 | sUser.clear(); | ||
232 | sPass.clear(); | ||
233 | sHost.clear(); | ||
234 | sPath.clear(); | ||
235 | iPort.clear(); | ||
236 | } | ||
237 | |||
diff --git a/src/url.h b/src/url.h new file mode 100644 index 0000000..861bb9f --- /dev/null +++ b/src/url.h | |||
@@ -0,0 +1,74 @@ | |||
1 | #ifndef BU_URL_H | ||
2 | #define BU_URL_H | ||
3 | |||
4 | #include "bu/fstring.h" | ||
5 | #include "bu/atom.h" | ||
6 | |||
7 | namespace Bu | ||
8 | { | ||
9 | class Url | ||
10 | { | ||
11 | public: | ||
12 | typedef struct Param | ||
13 | { | ||
14 | Param() { } | ||
15 | Param( const Param &r ) : sName( r.sName ), sValue( r.sValue ) { } | ||
16 | Param( const Bu::FString &n, const Bu::FString &v ) : | ||
17 | sName( n ), sValue( v ) { } | ||
18 | Bu::FString sName; | ||
19 | Bu::FString sValue; | ||
20 | } Param; | ||
21 | typedef Bu::List<Param> ParamList; | ||
22 | |||
23 | public: | ||
24 | Url(); | ||
25 | Url( const Bu::FString &sUrl ); | ||
26 | virtual ~Url(); | ||
27 | |||
28 | void parseUrl( const Bu::FString &sUrl ); | ||
29 | void parseParams( Bu::FString::const_iterator &i ); | ||
30 | void clear(); | ||
31 | |||
32 | Bu::FString getUrl(); | ||
33 | |||
34 | const Bu::FString &getProtocol() { return sProtocol; } | ||
35 | const Bu::FString &getUser() { return sUser; } | ||
36 | const Bu::FString &getPass() { return sPass; } | ||
37 | const Bu::FString &getHost() { return sHost; } | ||
38 | const Bu::FString &getPath() { return sPath; } | ||
39 | int getPort() { return iPort; } | ||
40 | ParamList::const_iterator getParamBegin() { return lParam.begin(); } | ||
41 | |||
42 | void setProtocol( const Bu::FString &sNewHost, bool bAutoSetPort=true ); | ||
43 | void setUser( const Bu::FString &s ) { sUser = s; } | ||
44 | void setPass( const Bu::FString &s ) { sPass = s; } | ||
45 | void setHost( const Bu::FString &s ) { sHost = s; } | ||
46 | void setPath( const Bu::FString &s ) { sPath = s; } | ||
47 | void setPort( int i ) { iPort = i; } | ||
48 | void addParam( const Bu::FString &n, const Bu::FString &v ); | ||
49 | |||
50 | bool hasPort() { return iPort.has(); } | ||
51 | |||
52 | static Bu::FString decode( const Bu::FString &sStr ); | ||
53 | static Bu::FString encode( const Bu::FString &sStr ); | ||
54 | |||
55 | private: // Parsing code | ||
56 | void parseProtocol( Bu::FString::const_iterator &i ); | ||
57 | void parseUserPass( Bu::FString::const_iterator &i ); | ||
58 | void parseHost( Bu::FString::const_iterator &i ); | ||
59 | void parsePath( Bu::FString::const_iterator &i ); | ||
60 | |||
61 | private: | ||
62 | Bu::FString sProtocol; | ||
63 | Bu::FString sUser; | ||
64 | Bu::FString sPass; | ||
65 | Bu::FString sHost; | ||
66 | Bu::FString sPath; | ||
67 | Bu::Atom<int> iPort; | ||
68 | ParamList lParam; | ||
69 | |||
70 | static char hexcode[16]; | ||
71 | }; | ||
72 | }; | ||
73 | |||
74 | #endif | ||