1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
29 #include <cosv/streamstr.hxx>
31 // NOT FULLY DECLARED SERVICES
34 #include <stdarg.h> // both are needed to satisfy all compilers
35 #include <cstdarg> // std::va_list and friends
37 #include <cosv/comfunc.hxx>
38 #include <cosv/tpl/swelist.hxx>
46 // Maximal sizes of resulting integers in text form:
47 const uintt C_short_max_size
= sizeof(short) * 3;
48 const uintt C_int_max_size
= sizeof(int) * 3;
49 const uintt C_long_max_size
= sizeof(long) * 3;
53 StreamStr::Advance(size_type i_nAddedSize
)
54 { pCur
+= i_nAddedSize
; }
58 StreamStr::StreamStr( size_type i_nCapacity
)
60 nCapacity1( i_nCapacity
+ 1 ),
61 dpData( new char [i_nCapacity
+ 1] ),
69 StreamStr::StreamStr( const char * i_sInitStr
,
70 size_type i_nCapacity
)
78 size_type nLength
= strlen(i_sInitStr
);
79 nCapacity1
= csv::max(nLength
, i_nCapacity
) + 1;
80 dpData
= new char [nCapacity1
];
81 strcpy(dpData
, i_sInitStr
); // SAFE STRCPY (#100211# - checked)
82 pCur
= dpData
+ nLength
;
86 StreamStr::StreamStr( size_type i_nGuessedCapacity
,
91 nCapacity1( i_nGuessedCapacity
+ 1 ),
92 dpData( new char [i_nGuessedCapacity
+ 1] ),
105 for ( const char * strAdd
= va_arg(ap
,const char*);
107 strAdd
= va_arg(ap
,const char*) )
109 size_type nLen
= strlen(strAdd
);
110 ProvideAddingSize( nLen
);
111 memcpy(pCur
, strAdd
, nLen
);
117 StreamStr::StreamStr( const self
& i_rOther
)
119 nCapacity1( i_rOther
.nCapacity1
),
120 dpData( new char [i_rOther
.nCapacity1
] ),
121 pEnd( dpData
+ strlen(i_rOther
.dpData
) ),
122 pCur( dpData
+ i_rOther
.tellp() ),
123 eMode(i_rOther
.eMode
)
125 strcpy( dpData
, i_rOther
.dpData
); // SAFE STRCPY (#100211# - checked)
128 StreamStr::StreamStr(csv::bstream
& i_source
)
134 eMode(str::overwrite
)
136 i_source
.seek(0, csv::end
);
137 nCapacity1
= static_cast<size_type
>(i_source
.position()) + 1;
140 dpData
= new char[nCapacity1
];
141 i_source
.read(dpData
, nCapacity1
- 1);
142 pCur
= dpData
+ nCapacity1
- 1;
147 StreamStr::~StreamStr()
154 StreamStr::operator=( const self
& i_rOther
)
158 nCapacity1
= i_rOther
.nCapacity1
;
159 dpData
= new char [i_rOther
.nCapacity1
];
160 pEnd
= dpData
+ strlen(i_rOther
.dpData
);
161 strcpy( dpData
, i_rOther
.dpData
); // SAFE STRCPY (#100211# - checked)
162 pCur
= dpData
+ i_rOther
.tellp();
163 eMode
= i_rOther
.eMode
;
169 StreamStr::operator<<( const char * i_s
)
171 size_type nLength
= strlen(i_s
);
173 ProvideAddingSize( nLength
);
174 memcpy( pCur
, i_s
, nLength
);
181 StreamStr::operator<<( const String
& i_s
)
183 size_type nLength
= i_s
.length();
185 ProvideAddingSize( nLength
);
186 memcpy( pCur
, i_s
.c_str(), nLength
);
193 StreamStr::operator<<( char i_c
)
195 ProvideAddingSize( 1 );
203 StreamStr::operator<<( unsigned char i_c
)
205 return operator<<( char(i_c
) );
209 StreamStr::operator<<( signed char i_c
)
211 return operator<<( char(i_c
) );
215 StreamStr::operator<<( short i_n
)
217 char buf
[C_short_max_size
] = "";
218 sprintf( buf
, "%hi", i_n
); // SAFE SPRINTF (#100211# - checked)
220 size_type nLength
= strlen(buf
);
221 ProvideAddingSize( nLength
);
222 memcpy( pCur
, buf
, nLength
);
229 StreamStr::operator<<( unsigned short i_n
)
231 char buf
[C_short_max_size
] = "";
232 sprintf( buf
, "%hu", i_n
); // SAFE SPRINTF (#100211# - checked)
234 size_type nLength
= strlen(buf
);
235 ProvideAddingSize( nLength
);
236 memcpy( pCur
, buf
, nLength
);
243 StreamStr::operator<<( int i_n
)
245 char buf
[C_int_max_size
] = "";
246 sprintf( buf
, "%i", i_n
); // SAFE SPRINTF (#100211# - checked)
248 size_type nLength
= strlen(buf
);
249 ProvideAddingSize( nLength
);
250 memcpy( pCur
, buf
, nLength
);
257 StreamStr::operator<<( unsigned int i_n
)
259 char buf
[C_int_max_size
] = "";
260 sprintf( buf
, "%u", i_n
); // SAFE SPRINTF (#100211# - checked)
262 size_type nLength
= strlen(buf
);
263 ProvideAddingSize( nLength
);
264 memcpy( pCur
, buf
, nLength
);
271 StreamStr::operator<<( long i_n
)
273 char buf
[C_long_max_size
] = "";
274 sprintf( buf
, "%li", i_n
); // SAFE SPRINTF (#100211# - checked)
276 size_type nLength
= strlen(buf
);
277 ProvideAddingSize( nLength
);
278 memcpy( pCur
, buf
, nLength
);
285 StreamStr::operator<<( unsigned long i_n
)
287 char buf
[C_long_max_size
] = "";
288 sprintf( buf
, "%lu", i_n
); // SAFE SPRINTF (#100211# - checked)
290 size_type nLength
= strlen(buf
);
291 ProvideAddingSize( nLength
);
292 memcpy( pCur
, buf
, nLength
);
299 StreamStr::operator<<( float i_n
)
301 const int C_float_max_size
= 20;
302 char buf
[C_float_max_size
] = "";
303 sprintf( buf
, "%.*g", C_float_max_size
-8, i_n
); // SAFE SPRINTF (#100211# - checked)
305 size_type nLength
= strlen(buf
);
306 ProvideAddingSize( nLength
);
307 memcpy( pCur
, buf
, nLength
);
314 StreamStr::operator<<( double i_n
)
316 const int C_double_max_size
= 30;
317 char buf
[C_double_max_size
] = "";
318 sprintf( buf
, "%.*lg", C_double_max_size
-8, i_n
); // SAFE SPRINTF (#100211# - checked)
320 size_type nLength
= strlen(buf
);
321 ProvideAddingSize( nLength
);
322 memcpy( pCur
, buf
, nLength
);
329 StreamStr::operator[]( position_type i_nPosition
) const
331 static const char aNull_
= '\0';
333 if ( position_type(pEnd
- dpData
) > i_nPosition
)
334 return dpData
[i_nPosition
];
339 StreamStr::operator[]( position_type i_nPosition
)
341 static char aDummy_
= '\0';
343 if ( position_type(pEnd
- dpData
) > i_nPosition
)
344 return dpData
[i_nPosition
];
349 StreamStr::resize( size_type i_nMinimumCapacity
)
351 if ( i_nMinimumCapacity
<= capacity() )
354 Resize(i_nMinimumCapacity
);
358 StreamStr::swap( StreamStr
& io_swap
)
361 n
= io_swap
.nCapacity1
;
362 io_swap
.nCapacity1
= nCapacity1
;
367 io_swap
.dpData
= dpData
;
380 io_swap
.eMode
= eMode
;
385 StreamStr::seekp( seek_type i_nCount
,
386 seek_dir i_eDirection
)
388 seek_type nLength
= seek_type( length() );
389 seek_type nNewPos
= tellp();
391 switch ( i_eDirection
)
393 case ::csv::beg
: nNewPos
= i_nCount
;
395 case ::csv::cur
: nNewPos
+= i_nCount
;
397 case ::csv::end
: nNewPos
= nLength
+ i_nCount
;
401 if ( in_range
<seek_type
>(0, nNewPos
, nLength
+ 1) )
403 pCur
= dpData
+ nNewPos
;
404 if (eMode
== str::overwrite
)
415 StreamStr::set_insert_mode( insert_mode i_eMode
)
422 StreamStr::push_front( const char * i_str
)
424 insert_mode eOriginalMode
= eMode
;
425 char * pOriginalCur
= pCur
;
431 eMode
= eOriginalMode
;
432 pCur
= pOriginalCur
+ strlen(i_str
);
436 StreamStr::push_front( char i_c
)
438 insert_mode eOriginalMode
= eMode
;
439 char * pOriginalCur
= pCur
;
445 eMode
= eOriginalMode
;
446 pCur
= pOriginalCur
+ 1;
450 StreamStr::push_back( const char * i_str
)
452 insert_mode eOriginalMode
= eMode
;
453 eMode
= str::overwrite
;
457 eMode
= eOriginalMode
;
461 StreamStr::push_back( char i_c
)
463 insert_mode eOriginalMode
= eMode
;
464 eMode
= str::overwrite
;
468 eMode
= eOriginalMode
;
472 StreamStr::pop_front( size_type i_nCount
)
474 size_type nCount
= min(i_nCount
, length());
476 MoveData( dpData
+ nCount
, pEnd
, -(seek_type(nCount
)) );
484 StreamStr::pop_back( size_type i_nCount
)
486 size_type nCount
= min(i_nCount
, length());
494 StreamStr::operator_join( std::vector
<String
>::const_iterator i_rBegin
,
495 std::vector
<String
>::const_iterator i_rEnd
,
496 const char * i_sLink
)
498 std::vector
<String
>::const_iterator it
= i_rBegin
;
502 for ( ++it
; it
!= i_rEnd
; ++it
)
512 StreamStr::operator_add_substr( const char * i_sText
,
513 size_type i_nLength
)
515 size_type nLength
= csv::min
<size_type
>(i_nLength
, strlen(i_sText
));
517 ProvideAddingSize( nLength
);
518 memcpy( pCur
, i_sText
, nLength
);
525 StreamStr::operator_add_token( const char * i_sText
,
528 const char * pTokenEnd
= strchr(i_sText
, i_cDelimiter
);
532 operator_add_substr(i_sText
, pTokenEnd
-i_sText
);
537 StreamStr::operator_read_line( bstream
& i_src
)
541 for ( nCount
= i_src
.read(&c
, 1);
542 nCount
== 1 AND c
!= 13 AND c
!= 10;
543 nCount
= i_src
.read(&c
, 1) )
548 bool bEndOfStream
= nCount
== 0;
549 // Check for line-end:
550 if ( NOT bEndOfStream AND c
!= 0 )
553 if (i_src
.read(&c
, 1) == 1)
555 if ( (c
!= 13 AND c
!= 10) OR c
== oldc
)
556 i_src
.seek(-1,::csv::cur
);
563 StreamStr::strip_front(char i_cToRemove
)
565 const_iterator it
= begin();
567 it
!= end() ? *it
== i_cToRemove
: false;
569 pop_front(it
- begin());
573 StreamStr::strip_back(char i_cToRemove
)
575 const_iterator it
= end();
577 it
!= begin() ? *(it
-1) == i_cToRemove
: false;
579 pop_back(end() - it
);
583 StreamStr::strip_frontback(char i_cToRemove
)
585 strip_front(i_cToRemove
);
586 strip_back(i_cToRemove
);
590 StreamStr::strip_front_whitespace()
592 const_iterator it
= begin();
594 it
!= end() ? *it
< 33 : false;
596 pop_front(it
- begin());
600 StreamStr::strip_back_whitespace()
602 const_iterator it
= end();
604 it
!= begin() ? *(it
-1) < 33 : false;
606 pop_back(end() - it
);
610 StreamStr::strip_frontback_whitespace()
612 strip_front_whitespace();
613 strip_back_whitespace();
617 StreamStr::remove( iterator i_begin
,
620 csv_assert(i_begin
>= dpData AND i_begin
<= pEnd
);
621 csv_assert(i_end
>= dpData AND i_end
<= pEnd
);
622 csv_assert(i_end
>= i_begin
);
623 MoveData(i_end
, pEnd
, i_begin
- i_end
);
628 StreamStr::replace( position_type i_nStart
,
630 Area i_aReplacement
)
632 if (i_nStart
>= length() OR i_nSize
< 1)
635 insert_mode eOldMode
= eMode
;
637 pCur
= dpData
+ i_nStart
;
639 size_type anz
= min( length() - i_nStart
, i_nSize
);
641 if ( anz
< i_aReplacement
.nLength
)
643 ProvideAddingSize( i_aReplacement
.nLength
- anz
);
645 else if ( anz
> i_aReplacement
.nLength
)
647 seek_type nMove
= seek_type(anz
- i_aReplacement
.nLength
);
649 MoveData( dpData
+ i_nStart
+ anz
,
656 if (i_aReplacement
.nLength
> 0)
658 memcpy( dpData
+ i_nStart
, i_aReplacement
.sStr
, i_aReplacement
.nLength
);
659 Advance(i_aReplacement
.nLength
);
667 StreamStr::replace_all( char i_cCarToSearch
,
668 char i_cReplacement
)
670 for ( char * p
= dpData
; p
!= pEnd
; ++p
)
672 if (*p
== i_cCarToSearch
)
678 StreamStr::replace_all( Area i_aStrToSearch
,
679 Area i_aReplacement
)
682 const char * pSearch
= i_aStrToSearch
.sStr
;
683 size_type nSearch
= i_aStrToSearch
.nLength
;
685 while ( p
<= length() - nSearch
)
687 if ( strncmp(dpData
+p
, pSearch
, nSearch
) == 0 )
689 replace( p
, nSearch
, i_aReplacement
);
690 p
+= i_aReplacement
.nLength
;
700 StreamStr::to_lower( position_type i_nStart
,
701 size_type i_nLength
)
703 static char cLower
[128] =
704 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
705 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
706 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
707 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
708 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
709 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95,
710 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
711 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127 };
713 if ( i_nStart
< length() )
715 char * pStop
= i_nStart
+ i_nLength
< length()
716 ? dpData
+ i_nStart
+ i_nLength
718 for ( char * pChange
= dpData
+ i_nStart
;
722 *pChange
= (static_cast< unsigned char >(*pChange
) & 0x80) == 0
723 ? cLower
[ UINT8(*pChange
) ]
731 StreamStr::to_upper( position_type i_nStart
,
732 size_type i_nLength
)
734 static char cUpper
[128] =
735 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
736 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
737 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
738 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
739 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
740 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
741 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
742 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123,124,125,126,127 };
744 if ( i_nStart
< length() )
746 char * pStop
= i_nStart
+ i_nLength
< length()
747 ? dpData
+ i_nStart
+ i_nLength
749 for ( char * pChange
= dpData
+ i_nStart
;
753 *pChange
= (static_cast< unsigned char >(*pChange
) & 0x80) == 0
754 ? cUpper
[ UINT8(*pChange
) ]
763 StreamStr::token_count( char i_cSplit
) const
765 return count_chars(dpData
, i_cSplit
) + 1;
769 StreamStr::token( position_type i_nNr
,
770 char i_cSplit
) const
773 const char * pTokenBegin
= dpData
;
774 for ( position_type nNr
= i_nNr
;
778 pTokenBegin
= strchr(pTokenBegin
,i_cSplit
);
779 if (pTokenBegin
== 0)
785 const char * pTokenEnd
= strchr(pTokenBegin
, i_cSplit
);
789 return String(pTokenBegin
, size_type(pTokenEnd
-pTokenBegin
) );
799 StreamStrPool(StreamStrPool
&); // not defined
800 void operator =(StreamStrPool
&); // not defined
803 friend class StreamStrLock
;
804 static StreamStr
& AcquireFromPool_(
805 uintt i_nMinimalSize
);
806 static void ReleaseToPool_(
807 DYN StreamStr
* let_dpUsedStr
);
810 SweList
< DYN StreamStr
* >
814 StreamStrPool::StreamStrPool()
818 StreamStrPool::~StreamStrPool()
820 for ( SweList
< DYN StreamStr
* >::iterator it
= aPool
.begin();
830 static StreamStrPool aPool_
;
835 StreamStrPool::AcquireFromPool_( uintt i_nMinimalSize
)
837 if ( aPool_
.aPool
.empty() )
839 return *new StreamStr(i_nMinimalSize
);
842 StreamStr
& ret
= *aPool_
.aPool
.front();
843 aPool_
.aPool
.pop_front();
844 ret
.resize(i_nMinimalSize
);
846 ret
.set_insert_mode(str::overwrite
);
851 StreamStrPool::ReleaseToPool_( DYN StreamStr
* let_dpUsedStr
)
853 aPool_
.aPool
.push_back( let_dpUsedStr
);
856 StreamStrLock::StreamStrLock( uintt i_nMinimalSize
)
857 : pStr( &StreamStrPool::AcquireFromPool_(i_nMinimalSize
) )
861 StreamStrLock::~StreamStrLock()
863 StreamStrPool::ReleaseToPool_(pStr
);
868 StreamStr::do_write( const void * i_pSrc
,
869 UINT32 i_nNrofBytes
)
871 ProvideAddingSize( i_nNrofBytes
);
872 memcpy( pCur
, i_pSrc
, i_nNrofBytes
);
873 Advance(i_nNrofBytes
);
879 StreamStr::ProvideAddingSize( size_type i_nSize2Add
)
881 size_type nLength
= length();
882 if ( capacity() - nLength
< i_nSize2Add
)
883 Resize( nLength
+ i_nSize2Add
);
888 if (eMode
== str::insert AND pCur
!= pEnd
)
890 MoveData( pCur
, pCur
+ i_nSize2Add
, seek_type(i_nSize2Add
) );
895 StreamStr::Resize( size_type i_nMinimumCapacity
)
897 size_type nNewSize
= nCapacity1
< 128
899 : (nCapacity1
<< 1) - (nCapacity1
>> 1);
900 nCapacity1
= csv::max( nNewSize
, size_type(i_nMinimumCapacity
+ 1) );
902 char * pNew
= new char[nCapacity1
];
903 strcpy ( pNew
, dpData
); // SAFE STRCPY (#100211# - checked)
904 pEnd
= pNew
+ (pEnd
- dpData
);
905 pCur
= pNew
+ (pCur
- dpData
);
912 StreamStr::MoveData( char * i_pStart
,
918 register const char * pSrc
= i_pEnd
;
919 register char * pDest
= i_pEnd
+ i_nDiff
;
920 for ( ; pSrc
!= i_pStart
; --pSrc
, --pDest
)
926 else if (i_nDiff
< 0)
928 const char * pSrc
= i_pStart
;
929 char * pDest
= i_pStart
+ i_nDiff
;
930 for ( ; pSrc
!= i_pEnd
; ++pSrc
, ++pDest
)
937 // Does nothing, only the name of this function is needed.
947 Split( std::vector
<String
> & o_list
,
948 const char * i_text
)
954 for (const char * p
= i_text
; *p
!= '\0'; ++p
)
956 white
= UINT8(*p
) > 32;
957 if (pCurrentToken
!= 0)
961 o_list
.push_back(String(pCurrentToken
, p
));
969 } // endif (bInToken) else
972 if (pCurrentToken
!= 0)
974 o_list
.push_back(String(pCurrentToken
));