aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2009-02-08 00:44:10 +0000
committerMike Buland <eichlan@xagasoft.com>2009-02-08 00:44:10 +0000
commit366a8063730aa7ae696bcb9cf56eafd13d43dfc0 (patch)
tree42e3597edfde0c183506ad0d452f045cb7726137
parent4f59dec6bad120b72f1bc075715d79bfbe881f7e (diff)
downloadlibbu++-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.
Diffstat (limited to '')
-rw-r--r--src/array.h28
-rw-r--r--src/fbasicstring.h720
-rw-r--r--src/hash.h35
-rw-r--r--src/list.h20
-rw-r--r--src/minimacro.cpp2
-rw-r--r--src/set.h33
-rw-r--r--src/tafwriter.cpp5
-rw-r--r--src/tests/rh.cpp52
-rw-r--r--src/tests/url.cpp32
-rw-r--r--src/unit/fstring.unit155
-rw-r--r--src/unitsuite.cpp2
-rw-r--r--src/url.cpp237
-rw-r--r--src/url.h74
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
diff --git a/src/hash.h b/src/hash.h
index 8856860..3868a4e 100644
--- a/src/hash.h
+++ b/src/hash.h
@@ -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 }
diff --git a/src/list.h b/src/list.h
index d16e606..f11336e 100644
--- a/src/list.h
+++ b/src/list.h
@@ -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()
141Bu::FString Bu::MiniMacro::callFunc( 141Bu::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 );
diff --git a/src/set.h b/src/set.h
index 42f9eb8..a25b0bf 100644
--- a/src/set.h
+++ b/src/set.h
@@ -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
8int 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
5int 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
8char Bu::Url::hexcode[] = {
9 '0', '1', '2', '3', '4', '5', '6', '7',
10 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
11};
12
13Bu::Url::Url()
14{
15}
16
17Bu::Url::Url( const Bu::FString &sUrl )
18{
19 parseUrl( sUrl );
20}
21
22Bu::Url::~Url()
23{
24}
25
26void 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
37Bu::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
63Bu::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
92void 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
102void 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
117void 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
137void 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
157void 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
175void 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
223void Bu::Url::addParam( const Bu::FString &n, const Bu::FString &v )
224{
225 lParam.append( Param( n, v ) );
226}
227
228void 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
7namespace 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