Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #define CSV_USE_CSV_ASSERTIONS
21 : #include <cosv/csv_env.hxx>
22 :
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>
28 :
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
34 :
35 : #include <cosv/tpl/swelist.hxx>
36 :
37 :
38 :
39 : namespace csv
40 : {
41 :
42 :
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;
47 :
48 :
49 : inline void
50 14561963 : StreamStr::Advance(size_type i_nAddedSize)
51 14561963 : { pCur += i_nAddedSize; }
52 :
53 :
54 :
55 12589 : StreamStr::StreamStr( size_type i_nCapacity )
56 : : bostream(),
57 : nCapacity1( i_nCapacity + 1 ),
58 12589 : dpData( new char [i_nCapacity + 1] ),
59 : pEnd(dpData),
60 : pCur(dpData),
61 25178 : eMode(str::overwrite)
62 : {
63 12589 : *pEnd = '\0';
64 12589 : }
65 :
66 0 : StreamStr::StreamStr( const self & i_rOther )
67 : : bostream(),
68 : nCapacity1( i_rOther.nCapacity1 ),
69 0 : dpData( new char [i_rOther.nCapacity1] ),
70 0 : pEnd( dpData + strlen(i_rOther.dpData) ),
71 0 : pCur( dpData + i_rOther.tellp() ),
72 0 : eMode(i_rOther.eMode)
73 : {
74 0 : strcpy( dpData, i_rOther.dpData ); // SAFE STRCPY (#100211# - checked)
75 0 : }
76 :
77 25183 : StreamStr::~StreamStr()
78 : {
79 12589 : delete [] dpData;
80 12594 : }
81 :
82 :
83 : StreamStr &
84 0 : StreamStr::operator=( const self & i_rOther )
85 : {
86 0 : delete [] dpData;
87 :
88 0 : nCapacity1 = i_rOther.nCapacity1;
89 0 : dpData = new char [i_rOther.nCapacity1];
90 0 : pEnd = dpData + strlen(i_rOther.dpData);
91 0 : strcpy( dpData, i_rOther.dpData ); // SAFE STRCPY (#100211# - checked)
92 0 : pCur = dpData + i_rOther.tellp();
93 0 : eMode = i_rOther.eMode;
94 :
95 0 : return *this;
96 : }
97 :
98 : StreamStr &
99 393022 : StreamStr::operator<<( const char * i_s )
100 : {
101 393022 : size_type nLength = strlen(i_s);
102 :
103 393022 : ProvideAddingSize( nLength );
104 393022 : memcpy( pCur, i_s, nLength );
105 393022 : Advance(nLength);
106 :
107 393022 : return *this;
108 : }
109 :
110 : StreamStr &
111 640953 : StreamStr::operator<<( const String & i_s )
112 : {
113 640953 : size_type nLength = i_s.length();
114 :
115 640953 : ProvideAddingSize( nLength );
116 640953 : memcpy( pCur, i_s.c_str(), nLength );
117 640953 : Advance(nLength);
118 :
119 640953 : return *this;
120 : }
121 :
122 : StreamStr &
123 441324 : StreamStr::operator<<( char i_c )
124 : {
125 441324 : ProvideAddingSize( 1 );
126 441324 : *pCur = i_c;
127 441324 : Advance(1);
128 :
129 441324 : return *this;
130 : }
131 :
132 : StreamStr &
133 0 : StreamStr::operator<<( unsigned char i_c )
134 : {
135 0 : return operator<<( char(i_c) );
136 : }
137 :
138 : StreamStr &
139 0 : StreamStr::operator<<( signed char i_c )
140 : {
141 0 : return operator<<( char(i_c) );
142 : }
143 :
144 : StreamStr &
145 0 : StreamStr::operator<<( short i_n )
146 : {
147 0 : char buf[C_short_max_size] = "";
148 0 : sprintf( buf, "%hi", i_n ); // SAFE SPRINTF (#100211# - checked)
149 :
150 0 : size_type nLength = strlen(buf);
151 0 : ProvideAddingSize( nLength );
152 0 : memcpy( pCur, buf, nLength );
153 0 : Advance( nLength );
154 :
155 0 : return *this;
156 : }
157 :
158 : StreamStr &
159 0 : StreamStr::operator<<( unsigned short i_n )
160 : {
161 0 : char buf[C_short_max_size] = "";
162 0 : sprintf( buf, "%hu", i_n ); // SAFE SPRINTF (#100211# - checked)
163 :
164 0 : size_type nLength = strlen(buf);
165 0 : ProvideAddingSize( nLength );
166 0 : memcpy( pCur, buf, nLength );
167 0 : Advance( nLength );
168 :
169 0 : return *this;
170 : }
171 :
172 : StreamStr &
173 6083 : StreamStr::operator<<( int i_n )
174 : {
175 6083 : char buf[C_int_max_size] = "";
176 6083 : sprintf( buf, "%i", i_n ); // SAFE SPRINTF (#100211# - checked)
177 :
178 6083 : size_type nLength = strlen(buf);
179 6083 : ProvideAddingSize( nLength );
180 6083 : memcpy( pCur, buf, nLength );
181 6083 : Advance( nLength );
182 :
183 6083 : return *this;
184 : }
185 :
186 : StreamStr &
187 0 : StreamStr::operator<<( unsigned int i_n )
188 : {
189 0 : char buf[C_int_max_size] = "";
190 0 : sprintf( buf, "%u", i_n ); // SAFE SPRINTF (#100211# - checked)
191 :
192 0 : size_type nLength = strlen(buf);
193 0 : ProvideAddingSize( nLength );
194 0 : memcpy( pCur, buf, nLength );
195 0 : Advance( nLength );
196 :
197 0 : return *this;
198 : }
199 :
200 : StreamStr &
201 0 : StreamStr::operator<<( long i_n )
202 : {
203 0 : char buf[C_long_max_size] = "";
204 0 : sprintf( buf, "%li", i_n ); // SAFE SPRINTF (#100211# - checked)
205 :
206 0 : size_type nLength = strlen(buf);
207 0 : ProvideAddingSize( nLength );
208 0 : memcpy( pCur, buf, nLength );
209 0 : Advance( nLength );
210 :
211 0 : return *this;
212 : }
213 :
214 : StreamStr &
215 2858 : StreamStr::operator<<( unsigned long i_n )
216 : {
217 2858 : char buf[C_long_max_size] = "";
218 2858 : sprintf( buf, "%lu", i_n ); // SAFE SPRINTF (#100211# - checked)
219 :
220 2858 : size_type nLength = strlen(buf);
221 2858 : ProvideAddingSize( nLength );
222 2858 : memcpy( pCur, buf, nLength );
223 2858 : Advance( nLength );
224 :
225 2858 : return *this;
226 : }
227 :
228 : StreamStr &
229 0 : StreamStr::operator<<( float i_n )
230 : {
231 0 : const int C_float_max_size = 20;
232 0 : char buf[C_float_max_size] = "";
233 0 : sprintf( buf, "%.*g", C_float_max_size-8, i_n ); // SAFE SPRINTF (#100211# - checked)
234 :
235 0 : size_type nLength = strlen(buf);
236 0 : ProvideAddingSize( nLength );
237 0 : memcpy( pCur, buf, nLength );
238 0 : Advance( nLength );
239 :
240 0 : return *this;
241 : }
242 :
243 : StreamStr &
244 0 : StreamStr::operator<<( double i_n )
245 : {
246 0 : const int C_double_max_size = 30;
247 0 : char buf[C_double_max_size] = "";
248 0 : sprintf( buf, "%.*lg", C_double_max_size-8, i_n ); // SAFE SPRINTF (#100211# - checked)
249 :
250 0 : size_type nLength = strlen(buf);
251 0 : ProvideAddingSize( nLength );
252 0 : memcpy( pCur, buf, nLength );
253 0 : Advance( nLength );
254 :
255 0 : return *this;
256 : }
257 :
258 : const char &
259 0 : StreamStr::operator[]( position_type i_nPosition ) const
260 : {
261 : static const char aNull_ = '\0';
262 :
263 0 : if ( position_type(pEnd - dpData) > i_nPosition )
264 0 : return dpData[i_nPosition];
265 0 : return aNull_;
266 : }
267 :
268 : char &
269 0 : StreamStr::operator[]( position_type i_nPosition )
270 : {
271 : static char aDummy_ = '\0';
272 :
273 0 : if ( position_type(pEnd - dpData) > i_nPosition )
274 0 : return dpData[i_nPosition];
275 0 : return aDummy_;
276 : }
277 :
278 : void
279 208525 : StreamStr::resize( size_type i_nMinimumCapacity )
280 : {
281 208525 : if ( i_nMinimumCapacity <= capacity() )
282 417044 : return;
283 :
284 6 : Resize(i_nMinimumCapacity);
285 : }
286 :
287 : StreamStr &
288 538061 : StreamStr::seekp( seek_type i_nCount,
289 : seek_dir i_eDirection )
290 : {
291 538061 : seek_type nLength = seek_type( length() );
292 538061 : seek_type nNewPos = tellp();
293 :
294 538061 : switch ( i_eDirection )
295 : {
296 538061 : case ::csv::beg: nNewPos = i_nCount;
297 538061 : break;
298 0 : case ::csv::cur: nNewPos += i_nCount;
299 0 : break;
300 0 : case ::csv::end: nNewPos = nLength + i_nCount;
301 0 : break;
302 : }
303 :
304 538061 : if ( in_range<seek_type>(0, nNewPos, nLength + 1) )
305 : {
306 538061 : pCur = dpData + nNewPos;
307 538061 : if (eMode == str::overwrite)
308 : {
309 538061 : pEnd = pCur;
310 538061 : *pEnd = '\0';
311 : }
312 : }
313 :
314 538061 : return *this;
315 : }
316 :
317 : StreamStr &
318 208525 : StreamStr::set_insert_mode( insert_mode i_eMode )
319 : {
320 208525 : eMode = i_eMode;
321 208525 : return *this;
322 : }
323 :
324 : void
325 0 : StreamStr::pop_front( size_type i_nCount )
326 : {
327 0 : size_type nCount = min(i_nCount, length());
328 :
329 0 : MoveData( dpData + nCount, pEnd, -(seek_type(nCount)) );
330 :
331 0 : pCur -= nCount;
332 0 : pEnd -= nCount;
333 0 : *pEnd = '\0';
334 0 : }
335 :
336 : void
337 250 : StreamStr::pop_back( size_type i_nCount )
338 : {
339 250 : size_type nCount = min(i_nCount, length());
340 250 : pEnd -= nCount;
341 250 : if (pCur > pEnd)
342 250 : pCur = pEnd;
343 250 : *pEnd = '\0';
344 250 : }
345 :
346 : StreamStr &
347 118 : StreamStr::operator_join( std::vector<String>::const_iterator i_rBegin,
348 : std::vector<String>::const_iterator i_rEnd,
349 : const char * i_sLink )
350 : {
351 118 : std::vector<String>::const_iterator it = i_rBegin;
352 118 : if ( it != i_rEnd )
353 : {
354 118 : operator<<(*it);
355 475 : for ( ++it; it != i_rEnd; ++it )
356 : {
357 357 : operator<<(i_sLink);
358 357 : operator<<(*it);
359 : }
360 : }
361 118 : return *this;
362 : }
363 :
364 : StreamStr &
365 0 : StreamStr::operator_add_substr( const char * i_sText,
366 : size_type i_nLength )
367 : {
368 0 : size_type nLength = csv::min<size_type>(i_nLength, strlen(i_sText));
369 :
370 0 : ProvideAddingSize( nLength );
371 0 : memcpy( pCur, i_sText, nLength );
372 0 : Advance(nLength);
373 :
374 0 : return *this;
375 : }
376 :
377 : StreamStr &
378 0 : StreamStr::operator_add_token( const char * i_sText,
379 : char i_cDelimiter )
380 : {
381 0 : const char * pTokenEnd = strchr(i_sText, i_cDelimiter);
382 0 : if (pTokenEnd == 0)
383 0 : operator<<(i_sText);
384 : else
385 0 : operator_add_substr(i_sText, pTokenEnd-i_sText);
386 0 : return *this;
387 : }
388 :
389 : StreamStr &
390 7336 : StreamStr::operator_read_line( bstream & i_src )
391 : {
392 7336 : char c = 0;
393 7336 : intt nCount = 0;
394 218654 : for ( nCount = i_src.read(&c, 1);
395 : nCount == 1 AND c != 13 AND c != 10;
396 211318 : nCount = i_src.read(&c, 1) )
397 : {
398 211318 : operator<<(c);
399 : }
400 :
401 : // Check for line-end:
402 7336 : if ( NOT (nCount == 0) AND c != 0 )
403 : {
404 7336 : char oldc = c;
405 7336 : if (i_src.read(&c, 1) == 1)
406 : {
407 7335 : if ( (c != 13 AND c != 10) OR c == oldc)
408 7335 : i_src.seek(-1,::csv::cur);
409 : }
410 : }
411 7336 : return *this;
412 : }
413 :
414 : void
415 0 : StreamStr::strip_front_whitespace()
416 : {
417 0 : const_iterator it = begin();
418 0 : for ( ;
419 0 : it != end() ? *it < 33 : false;
420 : ++it ) ;
421 0 : pop_front(it - begin());
422 0 : }
423 :
424 : void
425 0 : StreamStr::strip_back_whitespace()
426 : {
427 0 : const_iterator it = end();
428 0 : for ( ;
429 0 : it != begin() ? *(it-1) < 33 : false;
430 : --it ) ;
431 0 : pop_back(end() - it);
432 0 : }
433 :
434 : void
435 0 : StreamStr::strip_frontback_whitespace()
436 : {
437 0 : strip_front_whitespace();
438 0 : strip_back_whitespace();
439 0 : }
440 :
441 : void
442 0 : StreamStr::replace_all( char i_cCarToSearch,
443 : char i_cReplacement )
444 : {
445 0 : for ( char * p = dpData; p != pEnd; ++p )
446 : {
447 0 : if (*p == i_cCarToSearch)
448 0 : *p = i_cReplacement;
449 : }
450 0 : }
451 :
452 : class StreamStrPool
453 : {
454 : public:
455 : StreamStrPool();
456 : ~StreamStrPool();
457 : private:
458 : // Non-copyable
459 : StreamStrPool(StreamStrPool &); // not defined
460 : void operator =(StreamStrPool &); // not defined
461 :
462 : // Interface to:
463 : friend class StreamStrLock;
464 : static StreamStr & AcquireFromPool_(
465 : uintt i_nMinimalSize );
466 : static void ReleaseToPool_(
467 : DYN StreamStr * let_dpUsedStr );
468 :
469 : // DATA
470 : SweList< DYN StreamStr* >
471 : aPool;
472 : };
473 :
474 1 : StreamStrPool::StreamStrPool()
475 : {
476 1 : }
477 :
478 2 : StreamStrPool::~StreamStrPool()
479 : {
480 18 : for ( SweList< DYN StreamStr* >::iterator it = aPool.begin();
481 12 : it != aPool.end();
482 : ++it )
483 : {
484 5 : delete (*it);
485 : }
486 1 : }
487 :
488 : namespace
489 : {
490 1 : static StreamStrPool aPool_;
491 : }
492 :
493 :
494 : StreamStr &
495 208530 : StreamStrPool::AcquireFromPool_( uintt i_nMinimalSize )
496 : {
497 208530 : if ( aPool_.aPool.empty() )
498 : {
499 5 : return *new StreamStr(i_nMinimalSize);
500 : }
501 :
502 208525 : StreamStr & ret = *aPool_.aPool.front();
503 208525 : aPool_.aPool.pop_front();
504 208525 : ret.resize(i_nMinimalSize);
505 208525 : ret.seekp(0);
506 208525 : ret.set_insert_mode(str::overwrite);
507 208525 : return ret;
508 : }
509 :
510 : void
511 208530 : StreamStrPool::ReleaseToPool_( DYN StreamStr * let_dpUsedStr )
512 : {
513 208530 : aPool_.aPool.push_back( let_dpUsedStr );
514 208530 : }
515 :
516 208530 : StreamStrLock::StreamStrLock( uintt i_nMinimalSize )
517 208530 : : pStr( &StreamStrPool::AcquireFromPool_(i_nMinimalSize) )
518 : {
519 208530 : }
520 :
521 208530 : StreamStrLock::~StreamStrLock()
522 : {
523 208530 : StreamStrPool::ReleaseToPool_(pStr);
524 208530 : }
525 :
526 :
527 : UINT32
528 13077723 : StreamStr::do_write( const void * i_pSrc,
529 : UINT32 i_nNrofBytes )
530 : {
531 13077723 : ProvideAddingSize( i_nNrofBytes );
532 13077723 : memcpy( pCur, i_pSrc, i_nNrofBytes );
533 13077723 : Advance(i_nNrofBytes);
534 :
535 13077723 : return i_nNrofBytes;
536 : }
537 :
538 : void
539 14561963 : StreamStr::ProvideAddingSize( size_type i_nSize2Add )
540 : {
541 14561963 : size_type nLength = length();
542 14561963 : if ( capacity() - nLength < i_nSize2Add )
543 24365 : Resize( nLength + i_nSize2Add );
544 :
545 14561963 : pEnd += i_nSize2Add;
546 14561963 : *pEnd = '\0';
547 :
548 14561963 : if (eMode == str::insert AND pCur != pEnd)
549 : {
550 0 : MoveData( pCur, pCur + i_nSize2Add, seek_type(i_nSize2Add) );
551 : }
552 14561963 : }
553 :
554 : void
555 24371 : StreamStr::Resize( size_type i_nMinimumCapacity )
556 : {
557 : size_type nNewSize = nCapacity1 < 128
558 : ? nCapacity1 << 1
559 24371 : : (nCapacity1 << 1) - (nCapacity1 >> 1);
560 24371 : nCapacity1 = csv::max( nNewSize, size_type(i_nMinimumCapacity + 1) );
561 :
562 24371 : char * pNew = new char[nCapacity1];
563 24371 : strcpy ( pNew, dpData ); // SAFE STRCPY (#100211# - checked)
564 24371 : pEnd = pNew + (pEnd - dpData);
565 24371 : pCur = pNew + (pCur - dpData);
566 :
567 24371 : delete [] dpData;
568 24371 : dpData = pNew;
569 24371 : }
570 :
571 : void
572 0 : StreamStr::MoveData( char * i_pStart,
573 : char * i_pEnd,
574 : seek_type i_nDiff )
575 : {
576 0 : if (i_nDiff > 0)
577 : {
578 0 : register const char * pSrc = i_pEnd;
579 0 : register char * pDest = i_pEnd + i_nDiff;
580 0 : for ( ; pSrc != i_pStart; --pSrc, --pDest )
581 : {
582 0 : *pDest = *pSrc;
583 : }
584 0 : *pDest = *pSrc;
585 : }
586 0 : else if (i_nDiff < 0)
587 : {
588 0 : const char * pSrc = i_pStart;
589 0 : char * pDest = i_pStart + i_nDiff;
590 0 : for ( ; pSrc != i_pEnd; ++pSrc, ++pDest )
591 : {
592 0 : *pDest = *pSrc;
593 : }
594 : }
595 0 : }
596 :
597 : // Does nothing, only the name of this function is needed.
598 : void
599 0 : c_str()
600 : {
601 : // Does nothing.
602 0 : }
603 :
604 3 : } // namespace csv
605 :
606 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|