1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: streamstr.cxx,v $
10 * $Revision: 1.14.10.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
32 #include <cosv/streamstr.hxx>
34 // NOT FULLY DECLARED SERVICES
37 #include <stdarg.h> // both are needed to satisfy all compilers
38 #include <cstdarg> // std::va_list and friends
40 #include <cosv/comfunc.hxx>
41 #include <cosv/tpl/swelist.hxx>
49 // Maximal sizes of resulting integers in text form:
50 const uintt C_short_max_size
= sizeof(short) * 3;
51 const uintt C_int_max_size
= sizeof(int) * 3;
52 const uintt C_long_max_size
= sizeof(long) * 3;
56 StreamStr::Advance(size_type i_nAddedSize
)
57 { pCur
+= i_nAddedSize
; }
61 StreamStr::StreamStr( size_type i_nCapacity
)
63 nCapacity1( i_nCapacity
+ 1 ),
64 dpData( new char [i_nCapacity
+ 1] ),
72 StreamStr::StreamStr( const char * i_sInitStr
,
73 size_type i_nCapacity
)
81 size_type nLength
= strlen(i_sInitStr
);
82 nCapacity1
= csv::max(nLength
, i_nCapacity
) + 1;
83 dpData
= new char [nCapacity1
];
84 strcpy(dpData
, i_sInitStr
); // SAFE STRCPY (#100211# - checked)
85 pCur
= dpData
+ nLength
;
89 StreamStr::StreamStr( size_type i_nGuessedCapacity
,
94 nCapacity1( i_nGuessedCapacity
+ 1 ),
95 dpData( new char [i_nGuessedCapacity
+ 1] ),
108 for ( const char * strAdd
= va_arg(ap
,const char*);
110 strAdd
= va_arg(ap
,const char*) )
112 size_type nLen
= strlen(strAdd
);
113 ProvideAddingSize( nLen
);
114 memcpy(pCur
, strAdd
, nLen
);
120 StreamStr::StreamStr( const self
& i_rOther
)
122 nCapacity1( i_rOther
.nCapacity1
),
123 dpData( new char [i_rOther
.nCapacity1
] ),
124 pEnd( dpData
+ strlen(i_rOther
.dpData
) ),
125 pCur( dpData
+ i_rOther
.tellp() ),
126 eMode(i_rOther
.eMode
)
128 strcpy( dpData
, i_rOther
.dpData
); // SAFE STRCPY (#100211# - checked)
131 StreamStr::StreamStr(csv::bstream
& i_source
)
137 eMode(str::overwrite
)
139 i_source
.seek(0, csv::end
);
140 nCapacity1
= static_cast<size_type
>(i_source
.position()) + 1;
143 dpData
= new char[nCapacity1
];
144 i_source
.read(dpData
, nCapacity1
- 1);
145 pCur
= dpData
+ nCapacity1
- 1;
150 StreamStr::~StreamStr()
157 StreamStr::operator=( const self
& i_rOther
)
161 nCapacity1
= i_rOther
.nCapacity1
;
162 dpData
= new char [i_rOther
.nCapacity1
];
163 pEnd
= dpData
+ strlen(i_rOther
.dpData
);
164 strcpy( dpData
, i_rOther
.dpData
); // SAFE STRCPY (#100211# - checked)
165 pCur
= dpData
+ i_rOther
.tellp();
166 eMode
= i_rOther
.eMode
;
172 StreamStr::operator<<( const char * i_s
)
174 size_type nLength
= strlen(i_s
);
176 ProvideAddingSize( nLength
);
177 memcpy( pCur
, i_s
, nLength
);
184 StreamStr::operator<<( const String
& i_s
)
186 size_type nLength
= i_s
.length();
188 ProvideAddingSize( nLength
);
189 memcpy( pCur
, i_s
.c_str(), nLength
);
196 StreamStr::operator<<( char i_c
)
198 ProvideAddingSize( 1 );
206 StreamStr::operator<<( unsigned char i_c
)
208 return operator<<( char(i_c
) );
212 StreamStr::operator<<( signed char i_c
)
214 return operator<<( char(i_c
) );
218 StreamStr::operator<<( short i_n
)
220 char buf
[C_short_max_size
] = "";
221 sprintf( buf
, "%hi", i_n
); // SAFE SPRINTF (#100211# - checked)
223 size_type nLength
= strlen(buf
);
224 ProvideAddingSize( nLength
);
225 memcpy( pCur
, buf
, nLength
);
232 StreamStr::operator<<( unsigned short i_n
)
234 char buf
[C_short_max_size
] = "";
235 sprintf( buf
, "%hu", i_n
); // SAFE SPRINTF (#100211# - checked)
237 size_type nLength
= strlen(buf
);
238 ProvideAddingSize( nLength
);
239 memcpy( pCur
, buf
, nLength
);
246 StreamStr::operator<<( int i_n
)
248 char buf
[C_int_max_size
] = "";
249 sprintf( buf
, "%i", i_n
); // SAFE SPRINTF (#100211# - checked)
251 size_type nLength
= strlen(buf
);
252 ProvideAddingSize( nLength
);
253 memcpy( pCur
, buf
, nLength
);
260 StreamStr::operator<<( unsigned int i_n
)
262 char buf
[C_int_max_size
] = "";
263 sprintf( buf
, "%u", i_n
); // SAFE SPRINTF (#100211# - checked)
265 size_type nLength
= strlen(buf
);
266 ProvideAddingSize( nLength
);
267 memcpy( pCur
, buf
, nLength
);
274 StreamStr::operator<<( long i_n
)
276 char buf
[C_long_max_size
] = "";
277 sprintf( buf
, "%li", i_n
); // SAFE SPRINTF (#100211# - checked)
279 size_type nLength
= strlen(buf
);
280 ProvideAddingSize( nLength
);
281 memcpy( pCur
, buf
, nLength
);
288 StreamStr::operator<<( unsigned long i_n
)
290 char buf
[C_long_max_size
] = "";
291 sprintf( buf
, "%lu", i_n
); // SAFE SPRINTF (#100211# - checked)
293 size_type nLength
= strlen(buf
);
294 ProvideAddingSize( nLength
);
295 memcpy( pCur
, buf
, nLength
);
302 StreamStr::operator<<( float i_n
)
304 const int C_float_max_size
= 20;
305 char buf
[C_float_max_size
] = "";
306 sprintf( buf
, "%.*g", C_float_max_size
-8, i_n
); // SAFE SPRINTF (#100211# - checked)
308 size_type nLength
= strlen(buf
);
309 ProvideAddingSize( nLength
);
310 memcpy( pCur
, buf
, nLength
);
317 StreamStr::operator<<( double i_n
)
319 const int C_double_max_size
= 30;
320 char buf
[C_double_max_size
] = "";
321 sprintf( buf
, "%.*lg", C_double_max_size
-8, i_n
); // SAFE SPRINTF (#100211# - checked)
323 size_type nLength
= strlen(buf
);
324 ProvideAddingSize( nLength
);
325 memcpy( pCur
, buf
, nLength
);
332 StreamStr::operator[]( position_type i_nPosition
) const
334 static const char aNull_
= '\0';
336 if ( position_type(pEnd
- dpData
) > i_nPosition
)
337 return dpData
[i_nPosition
];
342 StreamStr::operator[]( position_type i_nPosition
)
344 static char aDummy_
= '\0';
346 if ( position_type(pEnd
- dpData
) > i_nPosition
)
347 return dpData
[i_nPosition
];
352 StreamStr::resize( size_type i_nMinimumCapacity
)
354 if ( i_nMinimumCapacity
<= capacity() )
357 Resize(i_nMinimumCapacity
);
361 StreamStr::swap( StreamStr
& io_swap
)
364 n
= io_swap
.nCapacity1
;
365 io_swap
.nCapacity1
= nCapacity1
;
370 io_swap
.dpData
= dpData
;
383 io_swap
.eMode
= eMode
;
388 StreamStr::seekp( seek_type i_nCount
,
389 seek_dir i_eDirection
)
391 seek_type nLength
= seek_type( length() );
392 seek_type nNewPos
= tellp();
394 switch ( i_eDirection
)
396 case ::csv::beg
: nNewPos
= i_nCount
;
398 case ::csv::cur
: nNewPos
+= i_nCount
;
400 case ::csv::end
: nNewPos
= nLength
+ i_nCount
;
404 if ( in_range
<seek_type
>(0, nNewPos
, nLength
+ 1) )
406 pCur
= dpData
+ nNewPos
;
407 if (eMode
== str::overwrite
)
418 StreamStr::set_insert_mode( insert_mode i_eMode
)
425 StreamStr::push_front( const char * i_str
)
427 insert_mode eOriginalMode
= eMode
;
428 char * pOriginalCur
= pCur
;
434 eMode
= eOriginalMode
;
435 pCur
= pOriginalCur
+ strlen(i_str
);
439 StreamStr::push_front( char i_c
)
441 insert_mode eOriginalMode
= eMode
;
442 char * pOriginalCur
= pCur
;
448 eMode
= eOriginalMode
;
449 pCur
= pOriginalCur
+ 1;
453 StreamStr::push_back( const char * i_str
)
455 insert_mode eOriginalMode
= eMode
;
456 eMode
= str::overwrite
;
460 eMode
= eOriginalMode
;
464 StreamStr::push_back( char i_c
)
466 insert_mode eOriginalMode
= eMode
;
467 eMode
= str::overwrite
;
471 eMode
= eOriginalMode
;
475 StreamStr::pop_front( size_type i_nCount
)
477 size_type nCount
= min(i_nCount
, length());
479 MoveData( dpData
+ nCount
, pEnd
, -(seek_type(nCount
)) );
487 StreamStr::pop_back( size_type i_nCount
)
489 size_type nCount
= min(i_nCount
, length());
497 StreamStr::operator_join( std::vector
<String
>::const_iterator i_rBegin
,
498 std::vector
<String
>::const_iterator i_rEnd
,
499 const char * i_sLink
)
501 std::vector
<String
>::const_iterator it
= i_rBegin
;
505 for ( ++it
; it
!= i_rEnd
; ++it
)
515 StreamStr::operator_add_substr( const char * i_sText
,
516 size_type i_nLength
)
518 size_type nLength
= csv::min
<size_type
>(i_nLength
, strlen(i_sText
));
520 ProvideAddingSize( nLength
);
521 memcpy( pCur
, i_sText
, nLength
);
528 StreamStr::operator_add_token( const char * i_sText
,
531 const char * pTokenEnd
= strchr(i_sText
, i_cDelimiter
);
535 operator_add_substr(i_sText
, pTokenEnd
-i_sText
);
540 StreamStr::operator_read_line( bstream
& i_src
)
544 for ( nCount
= i_src
.read(&c
, 1);
545 nCount
== 1 AND c
!= 13 AND c
!= 10;
546 nCount
= i_src
.read(&c
, 1) )
551 bool bEndOfStream
= nCount
== 0;
552 // Check for line-end:
553 if ( NOT bEndOfStream AND c
!= 0 )
556 if (i_src
.read(&c
, 1) == 1)
558 if ( (c
!= 13 AND c
!= 10) OR c
== oldc
)
559 i_src
.seek(-1,::csv::cur
);
566 StreamStr::strip_front(char i_cToRemove
)
568 const_iterator it
= begin();
570 it
!= end() ? *it
== i_cToRemove
: false;
572 pop_front(it
- begin());
576 StreamStr::strip_back(char i_cToRemove
)
578 const_iterator it
= end();
580 it
!= begin() ? *(it
-1) == i_cToRemove
: false;
582 pop_back(end() - it
);
586 StreamStr::strip_frontback(char i_cToRemove
)
588 strip_front(i_cToRemove
);
589 strip_back(i_cToRemove
);
593 StreamStr::strip_front_whitespace()
595 const_iterator it
= begin();
597 it
!= end() ? *it
< 33 : false;
599 pop_front(it
- begin());
603 StreamStr::strip_back_whitespace()
605 const_iterator it
= end();
607 it
!= begin() ? *(it
-1) < 33 : false;
609 pop_back(end() - it
);
613 StreamStr::strip_frontback_whitespace()
615 strip_front_whitespace();
616 strip_back_whitespace();
620 StreamStr::remove( iterator i_begin
,
623 csv_assert(i_begin
>= dpData AND i_begin
<= pEnd
);
624 csv_assert(i_end
>= dpData AND i_end
<= pEnd
);
625 csv_assert(i_end
>= i_begin
);
626 MoveData(i_end
, pEnd
, i_begin
- i_end
);
631 StreamStr::replace( position_type i_nStart
,
633 Area i_aReplacement
)
635 if (i_nStart
>= length() OR i_nSize
< 1)
638 insert_mode eOldMode
= eMode
;
640 pCur
= dpData
+ i_nStart
;
642 size_type anz
= min( length() - i_nStart
, i_nSize
);
644 if ( anz
< i_aReplacement
.nLength
)
646 ProvideAddingSize( i_aReplacement
.nLength
- anz
);
648 else if ( anz
> i_aReplacement
.nLength
)
650 seek_type nMove
= seek_type(anz
- i_aReplacement
.nLength
);
652 MoveData( dpData
+ i_nStart
+ anz
,
659 if (i_aReplacement
.nLength
> 0)
661 memcpy( dpData
+ i_nStart
, i_aReplacement
.sStr
, i_aReplacement
.nLength
);
662 Advance(i_aReplacement
.nLength
);
670 StreamStr::replace_all( char i_cCarToSearch
,
671 char i_cReplacement
)
673 for ( char * p
= dpData
; p
!= pEnd
; ++p
)
675 if (*p
== i_cCarToSearch
)
681 StreamStr::replace_all( Area i_aStrToSearch
,
682 Area i_aReplacement
)
685 const char * pSearch
= i_aStrToSearch
.sStr
;
686 size_type nSearch
= i_aStrToSearch
.nLength
;
688 while ( p
<= length() - nSearch
)
690 if ( strncmp(dpData
+p
, pSearch
, nSearch
) == 0 )
692 replace( p
, nSearch
, i_aReplacement
);
693 p
+= i_aReplacement
.nLength
;
703 StreamStr::to_lower( position_type i_nStart
,
704 size_type i_nLength
)
706 static char cLower
[128] =
707 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
708 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
709 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
710 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
711 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
712 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95,
713 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
714 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127 };
716 if ( i_nStart
< length() )
718 char * pStop
= i_nStart
+ i_nLength
< length()
719 ? dpData
+ i_nStart
+ i_nLength
721 for ( char * pChange
= dpData
+ i_nStart
;
725 *pChange
= (static_cast< unsigned char >(*pChange
) & 0x80) == 0
726 ? cLower
[ UINT8(*pChange
) ]
734 StreamStr::to_upper( position_type i_nStart
,
735 size_type i_nLength
)
737 static char cUpper
[128] =
738 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
739 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
740 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
741 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
742 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
743 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
744 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
745 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123,124,125,126,127 };
747 if ( i_nStart
< length() )
749 char * pStop
= i_nStart
+ i_nLength
< length()
750 ? dpData
+ i_nStart
+ i_nLength
752 for ( char * pChange
= dpData
+ i_nStart
;
756 *pChange
= (static_cast< unsigned char >(*pChange
) & 0x80) == 0
757 ? cUpper
[ UINT8(*pChange
) ]
766 StreamStr::token_count( char i_cSplit
) const
768 return count_chars(dpData
, i_cSplit
) + 1;
772 StreamStr::token( position_type i_nNr
,
773 char i_cSplit
) const
776 const char * pTokenBegin
= dpData
;
777 for ( position_type nNr
= i_nNr
;
781 pTokenBegin
= strchr(pTokenBegin
,i_cSplit
);
782 if (pTokenBegin
== 0)
788 const char * pTokenEnd
= strchr(pTokenBegin
, i_cSplit
);
792 return String(pTokenBegin
, size_type(pTokenEnd
-pTokenBegin
) );
802 StreamStrPool(StreamStrPool
&); // not defined
803 void operator =(StreamStrPool
&); // not defined
806 friend class StreamStrLock
;
807 static StreamStr
& AcquireFromPool_(
808 uintt i_nMinimalSize
);
809 static void ReleaseToPool_(
810 DYN StreamStr
* let_dpUsedStr
);
813 SweList
< DYN StreamStr
* >
817 StreamStrPool::StreamStrPool()
821 StreamStrPool::~StreamStrPool()
823 for ( SweList
< DYN StreamStr
* >::iterator it
= aPool
.begin();
833 static StreamStrPool aPool_
;
838 StreamStrPool::AcquireFromPool_( uintt i_nMinimalSize
)
840 if ( aPool_
.aPool
.empty() )
842 return *new StreamStr(i_nMinimalSize
);
845 StreamStr
& ret
= *aPool_
.aPool
.front();
846 aPool_
.aPool
.pop_front();
847 ret
.resize(i_nMinimalSize
);
849 ret
.set_insert_mode(str::overwrite
);
854 StreamStrPool::ReleaseToPool_( DYN StreamStr
* let_dpUsedStr
)
856 aPool_
.aPool
.push_back( let_dpUsedStr
);
859 StreamStrLock::StreamStrLock( uintt i_nMinimalSize
)
860 : pStr( &StreamStrPool::AcquireFromPool_(i_nMinimalSize
) )
864 StreamStrLock::~StreamStrLock()
866 StreamStrPool::ReleaseToPool_(pStr
);
871 StreamStr::do_write( const void * i_pSrc
,
872 UINT32 i_nNrofBytes
)
874 ProvideAddingSize( i_nNrofBytes
);
875 memcpy( pCur
, i_pSrc
, i_nNrofBytes
);
876 Advance(i_nNrofBytes
);
882 StreamStr::ProvideAddingSize( size_type i_nSize2Add
)
884 size_type nLength
= length();
885 if ( capacity() - nLength
< i_nSize2Add
)
886 Resize( nLength
+ i_nSize2Add
);
891 if (eMode
== str::insert AND pCur
!= pEnd
)
893 MoveData( pCur
, pCur
+ i_nSize2Add
, seek_type(i_nSize2Add
) );
898 StreamStr::Resize( size_type i_nMinimumCapacity
)
900 size_type nNewSize
= nCapacity1
< 128
902 : (nCapacity1
<< 1) - (nCapacity1
>> 1);
903 nCapacity1
= csv::max( nNewSize
, size_type(i_nMinimumCapacity
+ 1) );
905 char * pNew
= new char[nCapacity1
];
906 strcpy ( pNew
, dpData
); // SAFE STRCPY (#100211# - checked)
907 pEnd
= pNew
+ (pEnd
- dpData
);
908 pCur
= pNew
+ (pCur
- dpData
);
915 StreamStr::MoveData( char * i_pStart
,
921 register const char * pSrc
= i_pEnd
;
922 register char * pDest
= i_pEnd
+ i_nDiff
;
923 for ( ; pSrc
!= i_pStart
; --pSrc
, --pDest
)
929 else if (i_nDiff
< 0)
931 const char * pSrc
= i_pStart
;
932 char * pDest
= i_pStart
+ i_nDiff
;
933 for ( ; pSrc
!= i_pEnd
; ++pSrc
, ++pDest
)
940 // Does nothing, only the name of this function is needed.
950 Split( std::vector
<String
> & o_list
,
951 const char * i_text
)
957 for (const char * p
= i_text
; *p
!= '\0'; ++p
)
959 white
= UINT8(*p
) > 32;
960 if (pCurrentToken
!= 0)
964 o_list
.push_back(String(pCurrentToken
, p
));
972 } // endif (bInToken) else
975 if (pCurrentToken
!= 0)
977 o_list
.push_back(String(pCurrentToken
));