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
Advance(size_type i_nAddedSize)49 StreamStr::Advance(size_type i_nAddedSize)
50 { pCur += i_nAddedSize; }
51 
52 
53 
StreamStr(size_type i_nCapacity)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 
StreamStr(const char * i_sInitStr,size_type i_nCapacity)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 
StreamStr(size_type i_nGuessedCapacity,const char * str1,const char * str2,...)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 
StreamStr(const self & i_rOther)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 
StreamStr(csv::bstream & i_source)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 
~StreamStr()143 StreamStr::~StreamStr()
144 {
145     delete [] dpData;
146 }
147 
148 
149 StreamStr &
operator =(const self & i_rOther)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 &
operator <<(const char * i_s)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 &
operator <<(const String & i_s)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 &
operator <<(char i_c)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 &
operator <<(unsigned char i_c)199 StreamStr::operator<<( unsigned char i_c )
200 {
201     return operator<<( char(i_c) );
202 }
203 
204 StreamStr &
operator <<(signed char i_c)205 StreamStr::operator<<( signed char i_c )
206 {
207     return operator<<( char(i_c) );
208 }
209 
210 StreamStr &
operator <<(short i_n)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 &
operator <<(unsigned short i_n)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 &
operator <<(int i_n)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 &
operator <<(unsigned int i_n)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 &
operator <<(long i_n)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 &
operator <<(unsigned long i_n)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 &
operator <<(float i_n)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 &
operator <<(double i_n)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 &
operator [](position_type i_nPosition) const325 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 &
operator [](position_type i_nPosition)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
resize(size_type i_nMinimumCapacity)345 StreamStr::resize( size_type i_nMinimumCapacity )
346 {
347     if ( i_nMinimumCapacity <= capacity() )
348         return;
349 
350     Resize(i_nMinimumCapacity);
351 }
352 
353 void
swap(StreamStr & io_swap)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 &
seekp(seek_type i_nCount,seek_dir i_eDirection)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 &
set_insert_mode(insert_mode i_eMode)411 StreamStr::set_insert_mode( insert_mode i_eMode )
412 {
413     eMode = i_eMode;
414     return *this;
415 }
416 
417 void
push_front(const char * i_str)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
push_front(char i_c)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
push_back(const char * i_str)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
push_back(char i_c)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
pop_front(size_type i_nCount)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
pop_back(size_type i_nCount)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 &
operator_join(std::vector<String>::const_iterator i_rBegin,std::vector<String>::const_iterator i_rEnd,const char * i_sLink)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 &
operator_add_substr(const char * i_sText,size_type i_nLength)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 &
operator_add_token(const char * i_sText,char i_cDelimiter)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 &
operator_read_line(bstream & i_src)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
strip_front(char i_cToRemove)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
strip_back(char i_cToRemove)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
strip_frontback(char i_cToRemove)579 StreamStr::strip_frontback(char i_cToRemove)
580 {
581     strip_front(i_cToRemove);
582     strip_back(i_cToRemove);
583 }
584 
585 void
strip_front_whitespace()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
strip_back_whitespace()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
strip_frontback_whitespace()606 StreamStr::strip_frontback_whitespace()
607 {
608     strip_front_whitespace();
609     strip_back_whitespace();
610 }
611 
612 void
remove(iterator i_begin,iterator i_end)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
replace(position_type i_nStart,size_type i_nSize,Area i_aReplacement)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
replace_all(char i_cCarToSearch,char i_cReplacement)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
replace_all(Area i_aStrToSearch,Area i_aReplacement)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 &
to_lower(position_type i_nStart,size_type i_nLength)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 &
to_upper(position_type i_nStart,size_type i_nLength)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
token_count(char i_cSplit) const759 StreamStr::token_count( char i_cSplit ) const
760 {
761     return count_chars(dpData, i_cSplit) + 1;
762 }
763 
764 String
token(position_type i_nNr,char i_cSplit) const765 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 
StreamStrPool()810 StreamStrPool::StreamStrPool()
811 {
812 }
813 
~StreamStrPool()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 &
AcquireFromPool_(uintt i_nMinimalSize)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
ReleaseToPool_(DYN StreamStr * let_dpUsedStr)847 StreamStrPool::ReleaseToPool_( DYN StreamStr * let_dpUsedStr )
848 {
849     aPool_.aPool.push_back( let_dpUsedStr );
850 }
851 
StreamStrLock(uintt i_nMinimalSize)852 StreamStrLock::StreamStrLock( uintt i_nMinimalSize )
853     :   pStr( &StreamStrPool::AcquireFromPool_(i_nMinimalSize) )
854 {
855 }
856 
~StreamStrLock()857 StreamStrLock::~StreamStrLock()
858 {
859     StreamStrPool::ReleaseToPool_(pStr);
860 }
861 
862 
863 UINT32
do_write(const void * i_pSrc,UINT32 i_nNrofBytes)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
ProvideAddingSize(size_type i_nSize2Add)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
Resize(size_type i_nMinimumCapacity)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
MoveData(char * i_pStart,char * i_pEnd,seek_type i_nDiff)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
c_str()935 c_str()
936 {
937     // Does nothing.
938 }
939 
940 
941 
942 void
Split(std::vector<String> & o_list,const char * i_text)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