update credits
[LibreOffice.git] / cosv / source / strings / streamstr.cxx
blob809379be0eff203474b2d0ed0448dfd96088c914
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #define CSV_USE_CSV_ASSERTIONS
21 #include <cosv/csv_env.hxx>
23 #include <cosv/comfunc.hxx>
24 #include <cosv/string.hxx>
25 #include <cosv/streamstr.hxx>
26 #include <cosv/std_outp.hxx>
27 #include <cosv/tpl/dyn.hxx>
29 // NOT FULLY DECLARED SERVICES
30 #include <string.h>
31 #include <stdio.h>
32 #include <stdarg.h> // both are needed to satisfy all compilers
33 #include <cstdarg> // std::va_list and friends
35 #include <cosv/tpl/swelist.hxx>
39 namespace csv
43 // Maximal sizes of resulting integers in text form:
44 const uintt C_short_max_size = sizeof(short) * 3;
45 const uintt C_int_max_size = sizeof(int) * 3;
46 const uintt C_long_max_size = sizeof(long) * 3;
49 inline void
50 StreamStr::Advance(size_type i_nAddedSize)
51 { pCur += i_nAddedSize; }
55 StreamStr::StreamStr( size_type i_nCapacity )
56 : bostream(),
57 nCapacity1( i_nCapacity + 1 ),
58 dpData( new char [i_nCapacity + 1] ),
59 pEnd(dpData),
60 pCur(dpData),
61 eMode(str::overwrite)
63 *pEnd = '\0';
66 StreamStr::StreamStr( const self & i_rOther )
67 : bostream(),
68 nCapacity1( i_rOther.nCapacity1 ),
69 dpData( new char [i_rOther.nCapacity1] ),
70 pEnd( dpData + strlen(i_rOther.dpData) ),
71 pCur( dpData + i_rOther.tellp() ),
72 eMode(i_rOther.eMode)
74 strcpy( dpData, i_rOther.dpData ); // SAFE STRCPY (#100211# - checked)
77 StreamStr::~StreamStr()
79 delete [] dpData;
83 StreamStr &
84 StreamStr::operator=( const self & i_rOther )
86 delete [] dpData;
88 nCapacity1 = i_rOther.nCapacity1;
89 dpData = new char [i_rOther.nCapacity1];
90 pEnd = dpData + strlen(i_rOther.dpData);
91 strcpy( dpData, i_rOther.dpData ); // SAFE STRCPY (#100211# - checked)
92 pCur = dpData + i_rOther.tellp();
93 eMode = i_rOther.eMode;
95 return *this;
98 StreamStr &
99 StreamStr::operator<<( const char * i_s )
101 size_type nLength = strlen(i_s);
103 ProvideAddingSize( nLength );
104 memcpy( pCur, i_s, nLength );
105 Advance(nLength);
107 return *this;
110 StreamStr &
111 StreamStr::operator<<( const String & i_s )
113 size_type nLength = i_s.length();
115 ProvideAddingSize( nLength );
116 memcpy( pCur, i_s.c_str(), nLength );
117 Advance(nLength);
119 return *this;
122 StreamStr &
123 StreamStr::operator<<( char i_c )
125 ProvideAddingSize( 1 );
126 *pCur = i_c;
127 Advance(1);
129 return *this;
132 StreamStr &
133 StreamStr::operator<<( unsigned char i_c )
135 return operator<<( char(i_c) );
138 StreamStr &
139 StreamStr::operator<<( signed char i_c )
141 return operator<<( char(i_c) );
144 StreamStr &
145 StreamStr::operator<<( short i_n )
147 char buf[C_short_max_size] = "";
148 sprintf( buf, "%hi", i_n ); // SAFE SPRINTF (#100211# - checked)
150 size_type nLength = strlen(buf);
151 ProvideAddingSize( nLength );
152 memcpy( pCur, buf, nLength );
153 Advance( nLength );
155 return *this;
158 StreamStr &
159 StreamStr::operator<<( unsigned short i_n )
161 char buf[C_short_max_size] = "";
162 sprintf( buf, "%hu", i_n ); // SAFE SPRINTF (#100211# - checked)
164 size_type nLength = strlen(buf);
165 ProvideAddingSize( nLength );
166 memcpy( pCur, buf, nLength );
167 Advance( nLength );
169 return *this;
172 StreamStr &
173 StreamStr::operator<<( int i_n )
175 char buf[C_int_max_size] = "";
176 sprintf( buf, "%i", i_n ); // SAFE SPRINTF (#100211# - checked)
178 size_type nLength = strlen(buf);
179 ProvideAddingSize( nLength );
180 memcpy( pCur, buf, nLength );
181 Advance( nLength );
183 return *this;
186 StreamStr &
187 StreamStr::operator<<( unsigned int i_n )
189 char buf[C_int_max_size] = "";
190 sprintf( buf, "%u", i_n ); // SAFE SPRINTF (#100211# - checked)
192 size_type nLength = strlen(buf);
193 ProvideAddingSize( nLength );
194 memcpy( pCur, buf, nLength );
195 Advance( nLength );
197 return *this;
200 StreamStr &
201 StreamStr::operator<<( long i_n )
203 char buf[C_long_max_size] = "";
204 sprintf( buf, "%li", i_n ); // SAFE SPRINTF (#100211# - checked)
206 size_type nLength = strlen(buf);
207 ProvideAddingSize( nLength );
208 memcpy( pCur, buf, nLength );
209 Advance( nLength );
211 return *this;
214 StreamStr &
215 StreamStr::operator<<( unsigned long i_n )
217 char buf[C_long_max_size] = "";
218 sprintf( buf, "%lu", i_n ); // SAFE SPRINTF (#100211# - checked)
220 size_type nLength = strlen(buf);
221 ProvideAddingSize( nLength );
222 memcpy( pCur, buf, nLength );
223 Advance( nLength );
225 return *this;
228 StreamStr &
229 StreamStr::operator<<( float i_n )
231 const int C_float_max_size = 20;
232 char buf[C_float_max_size] = "";
233 sprintf( buf, "%.*g", C_float_max_size-8, i_n ); // SAFE SPRINTF (#100211# - checked)
235 size_type nLength = strlen(buf);
236 ProvideAddingSize( nLength );
237 memcpy( pCur, buf, nLength );
238 Advance( nLength );
240 return *this;
243 StreamStr &
244 StreamStr::operator<<( double i_n )
246 const int C_double_max_size = 30;
247 char buf[C_double_max_size] = "";
248 sprintf( buf, "%.*lg", C_double_max_size-8, i_n ); // SAFE SPRINTF (#100211# - checked)
250 size_type nLength = strlen(buf);
251 ProvideAddingSize( nLength );
252 memcpy( pCur, buf, nLength );
253 Advance( nLength );
255 return *this;
258 const char &
259 StreamStr::operator[]( position_type i_nPosition ) const
261 static const char aNull_ = '\0';
263 if ( position_type(pEnd - dpData) > i_nPosition )
264 return dpData[i_nPosition];
265 return aNull_;
268 char &
269 StreamStr::operator[]( position_type i_nPosition )
271 static char aDummy_ = '\0';
273 if ( position_type(pEnd - dpData) > i_nPosition )
274 return dpData[i_nPosition];
275 return aDummy_;
278 void
279 StreamStr::resize( size_type i_nMinimumCapacity )
281 if ( i_nMinimumCapacity <= capacity() )
282 return;
284 Resize(i_nMinimumCapacity);
287 StreamStr &
288 StreamStr::seekp( seek_type i_nCount,
289 seek_dir i_eDirection )
291 seek_type nLength = seek_type( length() );
292 seek_type nNewPos = tellp();
294 switch ( i_eDirection )
296 case ::csv::beg: nNewPos = i_nCount;
297 break;
298 case ::csv::cur: nNewPos += i_nCount;
299 break;
300 case ::csv::end: nNewPos = nLength + i_nCount;
301 break;
304 if ( in_range<seek_type>(0, nNewPos, nLength + 1) )
306 pCur = dpData + nNewPos;
307 if (eMode == str::overwrite)
309 pEnd = pCur;
310 *pEnd = '\0';
314 return *this;
317 StreamStr &
318 StreamStr::set_insert_mode( insert_mode i_eMode )
320 eMode = i_eMode;
321 return *this;
324 void
325 StreamStr::pop_front( size_type i_nCount )
327 size_type nCount = min(i_nCount, length());
329 MoveData( dpData + nCount, pEnd, -(seek_type(nCount)) );
331 pCur -= nCount;
332 pEnd -= nCount;
333 *pEnd = '\0';
336 void
337 StreamStr::pop_back( size_type i_nCount )
339 size_type nCount = min(i_nCount, length());
340 pEnd -= nCount;
341 if (pCur > pEnd)
342 pCur = pEnd;
343 *pEnd = '\0';
346 StreamStr &
347 StreamStr::operator_join( std::vector<String>::const_iterator i_rBegin,
348 std::vector<String>::const_iterator i_rEnd,
349 const char * i_sLink )
351 std::vector<String>::const_iterator it = i_rBegin;
352 if ( it != i_rEnd )
354 operator<<(*it);
355 for ( ++it; it != i_rEnd; ++it )
357 operator<<(i_sLink);
358 operator<<(*it);
361 return *this;
364 StreamStr &
365 StreamStr::operator_add_substr( const char * i_sText,
366 size_type i_nLength )
368 size_type nLength = csv::min<size_type>(i_nLength, strlen(i_sText));
370 ProvideAddingSize( nLength );
371 memcpy( pCur, i_sText, nLength );
372 Advance(nLength);
374 return *this;
377 StreamStr &
378 StreamStr::operator_add_token( const char * i_sText,
379 char i_cDelimiter )
381 const char * pTokenEnd = strchr(i_sText, i_cDelimiter);
382 if (pTokenEnd == 0)
383 operator<<(i_sText);
384 else
385 operator_add_substr(i_sText, pTokenEnd-i_sText);
386 return *this;
389 StreamStr &
390 StreamStr::operator_read_line( bstream & i_src )
392 char c = 0;
393 intt nCount = 0;
394 for ( nCount = i_src.read(&c, 1);
395 nCount == 1 AND c != 13 AND c != 10;
396 nCount = i_src.read(&c, 1) )
398 operator<<(c);
401 // Check for line-end:
402 if ( NOT (nCount == 0) AND c != 0 )
404 char oldc = c;
405 if (i_src.read(&c, 1) == 1)
407 if ( (c != 13 AND c != 10) OR c == oldc)
408 i_src.seek(-1,::csv::cur);
411 return *this;
414 void
415 StreamStr::strip_front_whitespace()
417 const_iterator it = begin();
418 for ( ;
419 it != end() ? *it < 33 : false;
420 ++it ) ;
421 pop_front(it - begin());
424 void
425 StreamStr::strip_back_whitespace()
427 const_iterator it = end();
428 for ( ;
429 it != begin() ? *(it-1) < 33 : false;
430 --it ) ;
431 pop_back(end() - it);
434 void
435 StreamStr::strip_frontback_whitespace()
437 strip_front_whitespace();
438 strip_back_whitespace();
441 void
442 StreamStr::replace_all( char i_cCarToSearch,
443 char i_cReplacement )
445 for ( char * p = dpData; p != pEnd; ++p )
447 if (*p == i_cCarToSearch)
448 *p = i_cReplacement;
452 class StreamStrPool
454 public:
455 StreamStrPool();
456 ~StreamStrPool();
457 private:
458 // Non-copyable
459 StreamStrPool(StreamStrPool &); // not defined
460 void operator =(StreamStrPool &); // not defined
462 // Interface to:
463 friend class StreamStrLock;
464 static StreamStr & AcquireFromPool_(
465 uintt i_nMinimalSize );
466 static void ReleaseToPool_(
467 DYN StreamStr * let_dpUsedStr );
469 // DATA
470 SweList< DYN StreamStr* >
471 aPool;
474 StreamStrPool::StreamStrPool()
478 StreamStrPool::~StreamStrPool()
480 for ( SweList< DYN StreamStr* >::iterator it = aPool.begin();
481 it != aPool.end();
482 ++it )
484 delete (*it);
488 namespace
490 static StreamStrPool aPool_;
494 StreamStr &
495 StreamStrPool::AcquireFromPool_( uintt i_nMinimalSize )
497 if ( aPool_.aPool.empty() )
499 return *new StreamStr(i_nMinimalSize);
502 StreamStr & ret = *aPool_.aPool.front();
503 aPool_.aPool.pop_front();
504 ret.resize(i_nMinimalSize);
505 ret.seekp(0);
506 ret.set_insert_mode(str::overwrite);
507 return ret;
510 void
511 StreamStrPool::ReleaseToPool_( DYN StreamStr * let_dpUsedStr )
513 aPool_.aPool.push_back( let_dpUsedStr );
516 StreamStrLock::StreamStrLock( uintt i_nMinimalSize )
517 : pStr( &StreamStrPool::AcquireFromPool_(i_nMinimalSize) )
521 StreamStrLock::~StreamStrLock()
523 StreamStrPool::ReleaseToPool_(pStr);
527 UINT32
528 StreamStr::do_write( const void * i_pSrc,
529 UINT32 i_nNrofBytes )
531 ProvideAddingSize( i_nNrofBytes );
532 memcpy( pCur, i_pSrc, i_nNrofBytes );
533 Advance(i_nNrofBytes);
535 return i_nNrofBytes;
538 void
539 StreamStr::ProvideAddingSize( size_type i_nSize2Add )
541 size_type nLength = length();
542 if ( capacity() - nLength < i_nSize2Add )
543 Resize( nLength + i_nSize2Add );
545 pEnd += i_nSize2Add;
546 *pEnd = '\0';
548 if (eMode == str::insert AND pCur != pEnd)
550 MoveData( pCur, pCur + i_nSize2Add, seek_type(i_nSize2Add) );
554 void
555 StreamStr::Resize( size_type i_nMinimumCapacity )
557 size_type nNewSize = nCapacity1 < 128
558 ? nCapacity1 << 1
559 : (nCapacity1 << 1) - (nCapacity1 >> 1);
560 nCapacity1 = csv::max( nNewSize, size_type(i_nMinimumCapacity + 1) );
562 char * pNew = new char[nCapacity1];
563 strcpy ( pNew, dpData ); // SAFE STRCPY (#100211# - checked)
564 pEnd = pNew + (pEnd - dpData);
565 pCur = pNew + (pCur - dpData);
567 delete [] dpData;
568 dpData = pNew;
571 void
572 StreamStr::MoveData( char * i_pStart,
573 char * i_pEnd,
574 seek_type i_nDiff )
576 if (i_nDiff > 0)
578 register const char * pSrc = i_pEnd;
579 register char * pDest = i_pEnd + i_nDiff;
580 for ( ; pSrc != i_pStart; --pSrc, --pDest )
582 *pDest = *pSrc;
584 *pDest = *pSrc;
586 else if (i_nDiff < 0)
588 const char * pSrc = i_pStart;
589 char * pDest = i_pStart + i_nDiff;
590 for ( ; pSrc != i_pEnd; ++pSrc, ++pDest )
592 *pDest = *pSrc;
597 // Does nothing, only the name of this function is needed.
598 void
599 c_str()
601 // Does nothing.
604 } // namespace csv
606 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */