1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
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>
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;
50 StreamStr::Advance(size_type i_nAddedSize
)
51 { pCur
+= i_nAddedSize
; }
55 StreamStr::StreamStr( size_type i_nCapacity
)
57 nCapacity1( i_nCapacity
+ 1 ),
58 dpData( new char [i_nCapacity
+ 1] ),
66 StreamStr::StreamStr( const self
& i_rOther
)
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() ),
74 strcpy( dpData
, i_rOther
.dpData
); // SAFE STRCPY (#100211# - checked)
77 StreamStr::~StreamStr()
84 StreamStr::operator=( const self
& i_rOther
)
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
;
99 StreamStr::operator<<( const char * i_s
)
101 size_type nLength
= strlen(i_s
);
103 ProvideAddingSize( nLength
);
104 memcpy( pCur
, i_s
, nLength
);
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
);
123 StreamStr::operator<<( char i_c
)
125 ProvideAddingSize( 1 );
133 StreamStr::operator<<( unsigned char i_c
)
135 return operator<<( char(i_c
) );
139 StreamStr::operator<<( signed char i_c
)
141 return operator<<( char(i_c
) );
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
];
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
];
279 StreamStr::resize( size_type i_nMinimumCapacity
)
281 if ( i_nMinimumCapacity
<= capacity() )
284 Resize(i_nMinimumCapacity
);
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
;
298 case ::csv::cur
: nNewPos
+= i_nCount
;
300 case ::csv::end
: nNewPos
= nLength
+ i_nCount
;
304 if ( in_range
<seek_type
>(0, nNewPos
, nLength
+ 1) )
306 pCur
= dpData
+ nNewPos
;
307 if (eMode
== str::overwrite
)
318 StreamStr::set_insert_mode( insert_mode i_eMode
)
325 StreamStr::pop_front( size_type i_nCount
)
327 size_type nCount
= min(i_nCount
, length());
329 MoveData( dpData
+ nCount
, pEnd
, -(seek_type(nCount
)) );
337 StreamStr::pop_back( size_type i_nCount
)
339 size_type nCount
= min(i_nCount
, length());
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
;
355 for ( ++it
; it
!= i_rEnd
; ++it
)
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
);
378 StreamStr::operator_add_token( const char * i_sText
,
381 const char * pTokenEnd
= strchr(i_sText
, i_cDelimiter
);
385 operator_add_substr(i_sText
, pTokenEnd
-i_sText
);
390 StreamStr::operator_read_line( bstream
& i_src
)
394 for ( nCount
= i_src
.read(&c
, 1);
395 nCount
== 1 AND c
!= 13 AND c
!= 10;
396 nCount
= i_src
.read(&c
, 1) )
401 // Check for line-end:
402 if ( NOT (nCount
== 0) AND c
!= 0 )
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
);
415 StreamStr::strip_front_whitespace()
417 const_iterator it
= begin();
419 it
!= end() ? *it
< 33 : false;
421 pop_front(it
- begin());
425 StreamStr::strip_back_whitespace()
427 const_iterator it
= end();
429 it
!= begin() ? *(it
-1) < 33 : false;
431 pop_back(end() - it
);
435 StreamStr::strip_frontback_whitespace()
437 strip_front_whitespace();
438 strip_back_whitespace();
442 StreamStr::replace_all( char i_cCarToSearch
,
443 char i_cReplacement
)
445 for ( char * p
= dpData
; p
!= pEnd
; ++p
)
447 if (*p
== i_cCarToSearch
)
459 StreamStrPool(StreamStrPool
&); // not defined
460 void operator =(StreamStrPool
&); // not defined
463 friend class StreamStrLock
;
464 static StreamStr
& AcquireFromPool_(
465 uintt i_nMinimalSize
);
466 static void ReleaseToPool_(
467 DYN StreamStr
* let_dpUsedStr
);
470 SweList
< DYN StreamStr
* >
474 StreamStrPool::StreamStrPool()
478 StreamStrPool::~StreamStrPool()
480 for ( SweList
< DYN StreamStr
* >::iterator it
= aPool
.begin();
490 static StreamStrPool aPool_
;
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
);
506 ret
.set_insert_mode(str::overwrite
);
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
);
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
);
539 StreamStr::ProvideAddingSize( size_type i_nSize2Add
)
541 size_type nLength
= length();
542 if ( capacity() - nLength
< i_nSize2Add
)
543 Resize( nLength
+ i_nSize2Add
);
548 if (eMode
== str::insert AND pCur
!= pEnd
)
550 MoveData( pCur
, pCur
+ i_nSize2Add
, seek_type(i_nSize2Add
) );
555 StreamStr::Resize( size_type i_nMinimumCapacity
)
557 size_type nNewSize
= nCapacity1
< 128
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
);
572 StreamStr::MoveData( char * i_pStart
,
578 register const char * pSrc
= i_pEnd
;
579 register char * pDest
= i_pEnd
+ i_nDiff
;
580 for ( ; pSrc
!= i_pStart
; --pSrc
, --pDest
)
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
)
597 // Does nothing, only the name of this function is needed.
606 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */