diff options
author | Mike Buland <eichlan@xagasoft.com> | 2009-02-08 00:44:10 +0000 |
---|---|---|
committer | Mike Buland <eichlan@xagasoft.com> | 2009-02-08 00:44:10 +0000 |
commit | 366a8063730aa7ae696bcb9cf56eafd13d43dfc0 (patch) | |
tree | 42e3597edfde0c183506ad0d452f045cb7726137 | |
parent | 4f59dec6bad120b72f1bc075715d79bfbe881f7e (diff) | |
download | libbu++-366a8063730aa7ae696bcb9cf56eafd13d43dfc0.tar.gz libbu++-366a8063730aa7ae696bcb9cf56eafd13d43dfc0.tar.bz2 libbu++-366a8063730aa7ae696bcb9cf56eafd13d43dfc0.tar.xz libbu++-366a8063730aa7ae696bcb9cf56eafd13d43dfc0.zip |
So many updates. I recommend using the new FString iterators instead of direct
indexing. It is now many times faster, and requires less overhead. Also,
more stuff iterator related in every class. More on that later.
-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 | ||