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