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