xref: /aoo41x/main/cosv/source/strings/streamstr.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include <precomp.h>
29 #include <cosv/streamstr.hxx>
30 
31 // NOT FULLY DECLARED SERVICES
32 #include <string.h>
33 #include <stdio.h>
34 #include <stdarg.h> // both are needed to satisfy all compilers
35 #include <cstdarg> 	// std::va_list and friends
36 
37 #include <cosv/comfunc.hxx>
38 #include <cosv/tpl/swelist.hxx>
39 
40 
41 
42 namespace csv
43 {
44 
45 
46 // Maximal sizes of resulting integers in text form:
47 const uintt C_short_max_size    = sizeof(short) * 3;
48 const uintt C_int_max_size      = sizeof(int) * 3;
49 const uintt C_long_max_size     = sizeof(long) * 3;
50 
51 
52 inline void
53 StreamStr::Advance(size_type i_nAddedSize)
54 { pCur += i_nAddedSize; }
55 
56 
57 
58 StreamStr::StreamStr( size_type     i_nCapacity )
59     :   bostream(),
60         nCapacity1( i_nCapacity + 1 ),
61         dpData( new char [i_nCapacity + 1] ),
62         pEnd(dpData),
63         pCur(dpData),
64         eMode(str::overwrite)
65 {
66     *pEnd = '\0';
67 }
68 
69 StreamStr::StreamStr( const char *  i_sInitStr,
70                       size_type     i_nCapacity )
71     :   bostream(),
72         nCapacity1(0),
73         dpData(0),
74         pEnd(0),
75         pCur(0),
76         eMode(str::overwrite)
77 {
78     size_type nLength = strlen(i_sInitStr);
79     nCapacity1 = csv::max(nLength, i_nCapacity) + 1;
80     dpData = new char [nCapacity1];
81     strcpy(dpData, i_sInitStr);     // SAFE STRCPY (#100211# - checked)
82     pCur = dpData + nLength;
83     pEnd = pCur;
84 }
85 
86 StreamStr::StreamStr( size_type         i_nGuessedCapacity,
87                       const char * 		str1,
88 					  const char *      str2,
89 					                    ... )
90     :   bostream(),
91         nCapacity1( i_nGuessedCapacity + 1 ),
92         dpData( new char [i_nGuessedCapacity + 1] ),
93         pEnd(dpData),
94         pCur(dpData),
95         eMode(str::overwrite)
96 {
97     *pEnd = '\0';
98 
99     operator<<(str1);
100     operator<<(str2);
101 
102 	::va_list ap;
103 
104 	va_start(ap, str2);
105 	for ( const char * strAdd = va_arg(ap,const char*);
106 		  strAdd != 0;
107 		  strAdd = va_arg(ap,const char*) )
108 	{
109         size_type nLen = strlen(strAdd);
110         ProvideAddingSize( nLen );
111 		memcpy(pCur, strAdd, nLen);
112         Advance(nLen);
113 	}  // end for
114 	va_end(ap);
115 }
116 
117 StreamStr::StreamStr( const self & i_rOther )
118     :   bostream(),
119         nCapacity1( i_rOther.nCapacity1 ),
120         dpData( new char [i_rOther.nCapacity1] ),
121         pEnd( dpData + strlen(i_rOther.dpData) ),
122         pCur( dpData + i_rOther.tellp() ),
123         eMode(i_rOther.eMode)
124 {
125     strcpy( dpData, i_rOther.dpData );      // SAFE STRCPY (#100211# - checked)
126 }
127 
128 StreamStr::StreamStr(csv::bstream & i_source)
129     :   bostream(),
130         nCapacity1(0),
131         dpData(0),
132         pEnd(0),
133         pCur(0),
134         eMode(str::overwrite)
135 {
136 	i_source.seek(0, csv::end);
137 	nCapacity1 = static_cast<size_type>(i_source.position()) + 1;
138 	i_source.seek(0);
139 
140 	dpData = new char[nCapacity1];
141 	i_source.read(dpData, nCapacity1 - 1);
142     pCur = dpData + nCapacity1 - 1;
143     pEnd = pCur;
144     *pCur = '\0';
145 }
146 
147 StreamStr::~StreamStr()
148 {
149     delete [] dpData;
150 }
151 
152 
153 StreamStr &
154 StreamStr::operator=( const self & i_rOther )
155 {
156     delete [] dpData;
157 
158     nCapacity1 = i_rOther.nCapacity1;
159     dpData = new char [i_rOther.nCapacity1];
160     pEnd = dpData + strlen(i_rOther.dpData);
161     strcpy( dpData, i_rOther.dpData );          // SAFE STRCPY (#100211# - checked)
162     pCur = dpData + i_rOther.tellp();
163     eMode = i_rOther.eMode;
164 
165     return *this;
166 }
167 
168 StreamStr &
169 StreamStr::operator<<( const char * i_s )
170 {
171     size_type nLength = strlen(i_s);
172 
173     ProvideAddingSize( nLength );
174     memcpy( pCur, i_s, nLength );
175     Advance(nLength);
176 
177     return *this;
178 }
179 
180 StreamStr &
181 StreamStr::operator<<( const String & i_s )
182 {
183     size_type nLength = i_s.length();
184 
185     ProvideAddingSize( nLength );
186     memcpy( pCur, i_s.c_str(), nLength );
187     Advance(nLength);
188 
189     return *this;
190 }
191 
192 StreamStr &
193 StreamStr::operator<<( char i_c )
194 {
195     ProvideAddingSize( 1 );
196     *pCur = i_c;
197     Advance(1);
198 
199     return *this;
200 }
201 
202 StreamStr &
203 StreamStr::operator<<( unsigned char i_c )
204 {
205     return operator<<( char(i_c) );
206 }
207 
208 StreamStr &
209 StreamStr::operator<<( signed char i_c )
210 {
211     return operator<<( char(i_c) );
212 }
213 
214 StreamStr &
215 StreamStr::operator<<( short i_n )
216 {
217     char buf[C_short_max_size] = "";
218     sprintf( buf, "%hi", i_n );         // SAFE SPRINTF (#100211# - checked)
219 
220     size_type nLength = strlen(buf);
221     ProvideAddingSize( nLength );
222     memcpy( pCur, buf, nLength );
223     Advance( nLength );
224 
225     return *this;
226 }
227 
228 StreamStr &
229 StreamStr::operator<<( unsigned short i_n )
230 {
231     char buf[C_short_max_size] = "";
232     sprintf( buf, "%hu", i_n );         // SAFE SPRINTF (#100211# - checked)
233 
234     size_type nLength = strlen(buf);
235     ProvideAddingSize( nLength );
236     memcpy( pCur, buf, nLength );
237     Advance( nLength );
238 
239     return *this;
240 }
241 
242 StreamStr &
243 StreamStr::operator<<( int i_n )
244 {
245     char buf[C_int_max_size] = "";
246     sprintf( buf, "%i", i_n );          // SAFE SPRINTF (#100211# - checked)
247 
248     size_type nLength = strlen(buf);
249     ProvideAddingSize( nLength );
250     memcpy( pCur, buf, nLength );
251     Advance( nLength );
252 
253     return *this;
254 }
255 
256 StreamStr &
257 StreamStr::operator<<( unsigned int i_n )
258 {
259     char buf[C_int_max_size] = "";
260     sprintf( buf, "%u", i_n );          // SAFE SPRINTF (#100211# - checked)
261 
262     size_type nLength = strlen(buf);
263     ProvideAddingSize( nLength );
264     memcpy( pCur, buf, nLength );
265     Advance( nLength );
266 
267     return *this;
268 }
269 
270 StreamStr &
271 StreamStr::operator<<( long i_n )
272 {
273     char buf[C_long_max_size] = "";
274     sprintf( buf, "%li", i_n );         // SAFE SPRINTF (#100211# - checked)
275 
276     size_type nLength = strlen(buf);
277     ProvideAddingSize( nLength );
278     memcpy( pCur, buf, nLength );
279     Advance( nLength );
280 
281     return *this;
282 }
283 
284 StreamStr &
285 StreamStr::operator<<( unsigned long i_n )
286 {
287     char buf[C_long_max_size] = "";
288     sprintf( buf, "%lu", i_n );         // SAFE SPRINTF (#100211# - checked)
289 
290     size_type nLength = strlen(buf);
291     ProvideAddingSize( nLength );
292     memcpy( pCur, buf, nLength );
293     Advance( nLength );
294 
295     return *this;
296 }
297 
298 StreamStr &
299 StreamStr::operator<<( float i_n )
300 {
301     const int C_float_max_size = 20;
302     char buf[C_float_max_size] = "";
303     sprintf( buf, "%.*g", C_float_max_size-8, i_n );    // SAFE SPRINTF (#100211# - checked)
304 
305     size_type nLength = strlen(buf);
306     ProvideAddingSize( nLength );
307     memcpy( pCur, buf, nLength );
308     Advance( nLength );
309 
310     return *this;
311 }
312 
313 StreamStr &
314 StreamStr::operator<<( double i_n )
315 {
316     const int C_double_max_size = 30;
317     char buf[C_double_max_size] = "";
318     sprintf( buf, "%.*lg", C_double_max_size-8, i_n );  // SAFE SPRINTF (#100211# - checked)
319 
320     size_type nLength = strlen(buf);
321     ProvideAddingSize( nLength );
322     memcpy( pCur, buf, nLength );
323     Advance( nLength );
324 
325     return *this;
326 }
327 
328 const char &
329 StreamStr::operator[]( position_type i_nPosition ) const
330 {
331     static const char aNull_ = '\0';
332 
333     if ( position_type(pEnd - dpData) > i_nPosition )
334         return dpData[i_nPosition];
335     return aNull_;
336 }
337 
338 char &
339 StreamStr::operator[]( position_type i_nPosition )
340 {
341     static char aDummy_ = '\0';
342 
343     if ( position_type(pEnd - dpData) > i_nPosition )
344         return dpData[i_nPosition];
345     return aDummy_;
346 }
347 
348 void
349 StreamStr::resize( size_type i_nMinimumCapacity )
350 {
351     if ( i_nMinimumCapacity <= capacity() )
352         return;
353 
354     Resize(i_nMinimumCapacity);
355 }
356 
357 void
358 StreamStr::swap( StreamStr & io_swap )
359 {
360     size_type
361         n = io_swap.nCapacity1;
362     io_swap.nCapacity1 = nCapacity1;
363     nCapacity1 = n;
364 
365     char *
366         p = io_swap.dpData;
367     io_swap.dpData = dpData;
368     dpData = p;
369 
370     p = io_swap.pEnd;
371     io_swap.pEnd = pEnd;
372     pEnd = p;
373 
374     p = io_swap.pCur;
375     io_swap.pCur = pCur;
376     pCur = p;
377 
378     insert_mode
379         m = io_swap.eMode;
380     io_swap.eMode = eMode;
381     eMode = m;
382 }
383 
384 StreamStr &
385 StreamStr::seekp( seek_type           i_nCount,
386                   seek_dir            i_eDirection )
387 {
388     seek_type nLength = seek_type( length() );
389     seek_type nNewPos = tellp();
390 
391     switch ( i_eDirection )
392     {
393      	case ::csv::beg:  nNewPos = i_nCount;
394                           break;
395         case ::csv::cur:  nNewPos += i_nCount;
396                           break;
397         case ::csv::end:  nNewPos = nLength + i_nCount;
398                           break;
399     }
400 
401     if ( in_range<seek_type>(0, nNewPos, nLength + 1) )
402     {
403         pCur = dpData + nNewPos;
404         if (eMode == str::overwrite)
405         {
406          	pEnd = pCur;
407             *pEnd = '\0';
408         }
409     }
410 
411     return *this;
412 }
413 
414 StreamStr &
415 StreamStr::set_insert_mode( insert_mode i_eMode )
416 {
417     eMode = i_eMode;
418     return *this;
419 }
420 
421 void
422 StreamStr::push_front( const char * i_str )
423 {
424     insert_mode eOriginalMode = eMode;
425     char * pOriginalCur = pCur;
426     eMode = str::insert;
427     pCur = dpData;
428 
429     operator<<(i_str);
430 
431     eMode = eOriginalMode;
432     pCur = pOriginalCur + strlen(i_str);
433 }
434 
435 void
436 StreamStr::push_front( char i_c )
437 {
438     insert_mode eOriginalMode = eMode;
439     char * pOriginalCur = pCur;
440     eMode = str::insert;
441     pCur = dpData;
442 
443     operator<<(i_c);
444 
445     eMode = eOriginalMode;
446     pCur = pOriginalCur + 1;
447 }
448 
449 void
450 StreamStr::push_back( const char * i_str )
451 {
452     insert_mode eOriginalMode = eMode;
453     eMode = str::overwrite;
454 
455     operator<<(i_str);
456 
457     eMode = eOriginalMode;
458 }
459 
460 void
461 StreamStr::push_back( char i_c )
462 {
463     insert_mode eOriginalMode = eMode;
464     eMode = str::overwrite;
465 
466     operator<<(i_c);
467 
468     eMode = eOriginalMode;
469 }
470 
471 void
472 StreamStr::pop_front( size_type i_nCount )
473 {
474     size_type nCount = min(i_nCount, length());
475 
476     MoveData( dpData + nCount, pEnd, -(seek_type(nCount)) );
477 
478     pCur -= nCount;
479     pEnd -= nCount;
480     *pEnd = '\0';
481 }
482 
483 void
484 StreamStr::pop_back( size_type i_nCount )
485 {
486     size_type nCount = min(i_nCount, length());
487     pEnd -= nCount;
488     if (pCur > pEnd)
489         pCur = pEnd;
490     *pEnd = '\0';
491 }
492 
493 StreamStr &
494 StreamStr::operator_join( std::vector<String>::const_iterator i_rBegin,
495                           std::vector<String>::const_iterator i_rEnd,
496                           const char *                        i_sLink )
497 {
498     std::vector<String>::const_iterator it = i_rBegin;
499     if ( it != i_rEnd )
500     {
501         operator<<(*it);
502         for ( ++it; it != i_rEnd; ++it )
503         {
504             operator<<(i_sLink);
505             operator<<(*it);
506         }
507     }
508     return *this;
509 }
510 
511 StreamStr &
512 StreamStr::operator_add_substr( const char *        i_sText,
513                                 size_type           i_nLength )
514 {
515     size_type nLength = csv::min<size_type>(i_nLength, strlen(i_sText));
516 
517     ProvideAddingSize( nLength );
518     memcpy( pCur, i_sText, nLength );
519     Advance(nLength);
520 
521     return *this;
522 }
523 
524 StreamStr &
525 StreamStr::operator_add_token( const char *        i_sText,
526                                char                i_cDelimiter )
527 {
528     const char * pTokenEnd = strchr(i_sText, i_cDelimiter);
529     if (pTokenEnd == 0)
530         operator<<(i_sText);
531     else
532         operator_add_substr(i_sText, pTokenEnd-i_sText);
533     return *this;
534 }
535 
536 StreamStr &
537 StreamStr::operator_read_line( bstream & i_src )
538 {
539     char c = 0;
540 	intt nCount = 0;
541     for ( nCount = i_src.read(&c, 1);
542 		  nCount == 1 AND c != 13 AND c != 10;
543 		  nCount = i_src.read(&c, 1) )
544     {
545         operator<<(c);
546     }
547 
548     bool bEndOfStream = nCount == 0;
549     // Check for line-end:
550     if ( NOT bEndOfStream AND c != 0 )
551     {
552         char oldc = c;
553       	if (i_src.read(&c, 1) == 1)
554         {
555             if ( (c != 13 AND c != 10) OR c == oldc)
556                 i_src.seek(-1,::csv::cur);
557         }
558     }
559     return *this;
560 }
561 
562 void
563 StreamStr::strip_front(char i_cToRemove)
564 {
565     const_iterator it = begin();
566     for ( ;
567           it != end() ? *it == i_cToRemove : false;
568           ++it ) ;
569     pop_front(it - begin());
570 }
571 
572 void
573 StreamStr::strip_back(char i_cToRemove)
574 {
575     const_iterator it = end();
576     for ( ;
577           it != begin() ? *(it-1) == i_cToRemove : false;
578           --it ) ;
579     pop_back(end() - it);
580 }
581 
582 void
583 StreamStr::strip_frontback(char i_cToRemove)
584 {
585     strip_front(i_cToRemove);
586     strip_back(i_cToRemove);
587 }
588 
589 void
590 StreamStr::strip_front_whitespace()
591 {
592     const_iterator it = begin();
593     for ( ;
594           it != end() ? *it < 33 : false;
595           ++it ) ;
596     pop_front(it - begin());
597 }
598 
599 void
600 StreamStr::strip_back_whitespace()
601 {
602     const_iterator it = end();
603     for ( ;
604           it != begin() ? *(it-1) < 33 : false;
605           --it ) ;
606     pop_back(end() - it);
607 }
608 
609 void
610 StreamStr::strip_frontback_whitespace()
611 {
612     strip_front_whitespace();
613     strip_back_whitespace();
614 }
615 
616 void
617 StreamStr::remove(  iterator            i_begin,
618                     iterator            i_end )
619 {
620     csv_assert(i_begin >= dpData AND i_begin <= pEnd);
621     csv_assert(i_end >= dpData AND i_end <= pEnd);
622     csv_assert(i_end >= i_begin);
623     MoveData(i_end, pEnd, i_begin - i_end);
624     pCur = pEnd;
625 }
626 
627 void
628 StreamStr::replace( position_type       i_nStart,
629                     size_type           i_nSize,
630                     Area                i_aReplacement )
631 {
632     if (i_nStart >= length() OR i_nSize < 1)
633       return;
634 
635     insert_mode eOldMode = eMode;
636     eMode = str::insert;
637     pCur = dpData + i_nStart;
638 
639     size_type anz = min( length() - i_nStart, i_nSize );
640 
641     if ( anz < i_aReplacement.nLength )
642     {
643     	ProvideAddingSize( i_aReplacement.nLength - anz );
644     }
645     else if ( anz > i_aReplacement.nLength )
646     {
647     	seek_type nMove = seek_type(anz - i_aReplacement.nLength);
648 
649     	MoveData( dpData + i_nStart + anz,
650     			  pEnd,
651     			  -nMove );
652     	pEnd -= nMove;
653     	*pEnd = '\0';
654     }
655 
656     if (i_aReplacement.nLength > 0)
657     {
658         memcpy( dpData + i_nStart, i_aReplacement.sStr, i_aReplacement.nLength );
659         Advance(i_aReplacement.nLength);
660     }
661 
662     eMode = eOldMode;
663     pCur = pEnd;
664 }
665 
666 void
667 StreamStr::replace_all( char i_cCarToSearch,
668                         char i_cReplacement )
669 {
670    for ( char * p = dpData; p != pEnd; ++p )
671    {
672     	if (*p == i_cCarToSearch)
673             *p = i_cReplacement;
674    }
675 }
676 
677 void
678 StreamStr::replace_all( Area                i_aStrToSearch,
679                         Area                i_aReplacement )
680 {
681     position_type p = 0;
682     const char *  pSearch = i_aStrToSearch.sStr;
683     size_type     nSearch = i_aStrToSearch.nLength;
684 
685 	while ( p <= length() - nSearch )
686     {
687         if ( strncmp(dpData+p, pSearch, nSearch) == 0 )
688         {
689             replace( p, nSearch, i_aReplacement );
690             p += i_aReplacement.nLength;
691         }
692         else
693         {
694             ++p;
695         }
696    }    // end while
697 }
698 
699 StreamStr &
700 StreamStr::to_lower( position_type       i_nStart,
701 					 size_type           i_nLength )
702 {
703 	static char cLower[128] =
704 	{ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
705 	 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
706 	 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
707 	 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
708 	 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
709 	112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95,
710 	 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
711 	112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127 };
712 
713 	if ( i_nStart < length() )
714 	{
715 		char * pStop = i_nStart + i_nLength < length()
716 							?	dpData + i_nStart + i_nLength
717 							:	pEnd;
718 		for ( char * pChange = dpData + i_nStart;
719 			  pChange != pStop;
720 			  ++pChange )
721 		{
722 			*pChange =  (static_cast< unsigned char >(*pChange) & 0x80) == 0
723 							?   cLower[ UINT8(*pChange) ]
724 							:   *pChange;
725 		}
726 	}
727 	return *this;
728 }
729 
730 StreamStr &
731 StreamStr::to_upper( position_type       i_nStart,
732 					 size_type           i_nLength )
733 {
734 	static char cUpper[128] =
735 	{ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
736 	 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
737 	 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
738 	 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
739 	 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
740 	 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
741 	 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
742 	 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123,124,125,126,127 };
743 
744 	if ( i_nStart < length() )
745 	{
746 		char * pStop = i_nStart + i_nLength < length()
747 							?	dpData + i_nStart + i_nLength
748 							:	pEnd;
749 		for ( char * pChange = dpData + i_nStart;
750 			  pChange != pStop;
751 			  ++pChange )
752 		{
753 			*pChange =  (static_cast< unsigned char >(*pChange) & 0x80) == 0
754 							?   cUpper[ UINT8(*pChange) ]
755 							:   *pChange;
756 		}
757 	}
758 	return *this;
759 }
760 
761 
762 StreamStr::size_type
763 StreamStr::token_count( char i_cSplit ) const
764 {
765     return count_chars(dpData, i_cSplit) + 1;
766 }
767 
768 String
769 StreamStr::token( position_type i_nNr,
770                   char          i_cSplit ) const
771 {
772     // Find begin:
773     const char * pTokenBegin = dpData;
774    	for ( position_type nNr = i_nNr;
775           nNr > 0;
776           --nNr )
777     {
778         pTokenBegin = strchr(pTokenBegin,i_cSplit);
779         if (pTokenBegin == 0)
780             return String("");
781         ++pTokenBegin;
782     }
783 
784     // Find end:
785     const char * pTokenEnd = strchr(pTokenBegin, i_cSplit);
786     if (pTokenEnd == 0)
787         pTokenEnd = pEnd;
788 
789     return String(pTokenBegin, size_type(pTokenEnd-pTokenBegin) );
790 }
791 
792 class StreamStrPool
793 {
794   public:
795                         StreamStrPool();
796                         ~StreamStrPool();
797   private:
798     // Non-copyable
799     StreamStrPool(StreamStrPool &); // not defined
800     void operator =(StreamStrPool &); // not defined
801 
802     // Interface to:
803     friend class StreamStrLock;
804     static StreamStr &  AcquireFromPool_(
805                             uintt               i_nMinimalSize );
806     static void         ReleaseToPool_(
807                             DYN StreamStr *     let_dpUsedStr );
808 
809     // DATA
810     SweList< DYN StreamStr* >
811                         aPool;
812 };
813 
814 StreamStrPool::StreamStrPool()
815 {
816 }
817 
818 StreamStrPool::~StreamStrPool()
819 {
820     for ( SweList< DYN StreamStr* >::iterator it = aPool.begin();
821           it != aPool.end();
822           ++it )
823     {
824      	delete (*it);
825     }
826 }
827 
828 namespace
829 {
830     static StreamStrPool aPool_;
831 }
832 
833 
834 StreamStr &
835 StreamStrPool::AcquireFromPool_( uintt i_nMinimalSize )
836 {
837     if ( aPool_.aPool.empty() )
838     {
839         return *new StreamStr(i_nMinimalSize);
840     }
841 
842     StreamStr & ret = *aPool_.aPool.front();
843     aPool_.aPool.pop_front();
844     ret.resize(i_nMinimalSize);
845     ret.seekp(0);
846     ret.set_insert_mode(str::overwrite);
847     return ret;
848 }
849 
850 void
851 StreamStrPool::ReleaseToPool_( DYN StreamStr * let_dpUsedStr )
852 {
853     aPool_.aPool.push_back( let_dpUsedStr );
854 }
855 
856 StreamStrLock::StreamStrLock( uintt i_nMinimalSize )
857     :   pStr( &StreamStrPool::AcquireFromPool_(i_nMinimalSize) )
858 {
859 }
860 
861 StreamStrLock::~StreamStrLock()
862 {
863     StreamStrPool::ReleaseToPool_(pStr);
864 }
865 
866 
867 UINT32
868 StreamStr::do_write( const void *    i_pSrc,
869 					 UINT32          i_nNrofBytes )
870 {
871     ProvideAddingSize( i_nNrofBytes );
872     memcpy( pCur, i_pSrc, i_nNrofBytes );
873     Advance(i_nNrofBytes);
874 
875     return i_nNrofBytes;
876 }
877 
878 void
879 StreamStr::ProvideAddingSize( size_type i_nSize2Add )
880 {
881     size_type nLength = length();
882     if ( capacity() - nLength < i_nSize2Add )
883         Resize( nLength + i_nSize2Add );
884 
885     pEnd += i_nSize2Add;
886   	*pEnd = '\0';
887 
888     if (eMode == str::insert AND pCur != pEnd)
889     {
890         MoveData( pCur, pCur + i_nSize2Add, seek_type(i_nSize2Add) );
891     }
892 }
893 
894 void
895 StreamStr::Resize( size_type i_nMinimumCapacity )
896 {
897     size_type nNewSize = nCapacity1 < 128
898                             ?   nCapacity1 << 1
899                             :   (nCapacity1 << 1) - (nCapacity1 >> 1);
900     nCapacity1 = csv::max( nNewSize, size_type(i_nMinimumCapacity + 1) );
901 
902     char * pNew = new char[nCapacity1];
903     strcpy ( pNew, dpData );            // SAFE STRCPY (#100211# - checked)
904     pEnd = pNew + (pEnd - dpData);
905 	pCur = pNew + (pCur - dpData);
906 
907     delete [] dpData;
908     dpData = pNew;
909 }
910 
911 void
912 StreamStr::MoveData( char *        i_pStart,
913                      char *        i_pEnd,
914                      seek_type     i_nDiff )
915 {
916     if (i_nDiff > 0)
917     {
918         register const char * pSrc  = i_pEnd;
919         register char * pDest = i_pEnd + i_nDiff;
920         for ( ; pSrc != i_pStart; --pSrc, --pDest )
921         {
922             *pDest = *pSrc;
923         }
924         *pDest = *pSrc;
925     }
926     else if (i_nDiff < 0)
927     {
928         const char * pSrc  = i_pStart;
929         char * pDest = i_pStart + i_nDiff;
930         for ( ; pSrc != i_pEnd; ++pSrc, ++pDest )
931         {
932             *pDest = *pSrc;
933         }
934     }
935 }
936 
937 // Does nothing, only the name of this function is needed.
938 void
939 c_str()
940 {
941     // Does nothing.
942 }
943 
944 
945 
946 void
947 Split( std::vector<String> &    o_list,
948        const char *             i_text )
949 {
950     const char *
951         pCurrentToken = 0;
952     bool
953         white = false;
954     for (const char * p = i_text; *p != '\0'; ++p)
955     {
956         white = UINT8(*p) > 32;
957         if (pCurrentToken != 0)
958         {
959             if (white)
960             {
961                 o_list.push_back(String(pCurrentToken, p));
962                 pCurrentToken = 0;
963             }
964         }
965         else
966         {
967             if ( NOT white)
968                 pCurrentToken = p;
969         }   // endif (bInToken) else
970     }   // end for
971 
972     if (pCurrentToken != 0)
973     {
974         o_list.push_back(String(pCurrentToken));
975     }
976 }
977 
978 
979 
980 
981 }   // namespace csv
982