22 #include <com/sun/star/io/IOException.hpp>
23 #include <com/sun/star/io/XTextInputStream2.hpp>
26 #include <rtl/strbuf.hxx>
27 #include <osl/diagnose.h>
37 const char* lclFindCharacter(
const char* pcBeg,
const char* pcEnd,
char cChar )
39 sal_Int32
nIndex = rtl_str_indexOfChar_WithLength( pcBeg, static_cast< sal_Int32 >( pcEnd - pcBeg ), cChar );
40 return (nIndex < 0) ? pcEnd : (pcBeg + nIndex);
43 bool lclIsWhiteSpace(
char cChar )
48 const char* lclFindWhiteSpace(
const char* pcBeg,
const char* pcEnd )
50 for( ; pcBeg < pcEnd; ++pcBeg )
51 if( lclIsWhiteSpace( *pcBeg ) )
56 const char* lclFindNonWhiteSpace(
const char* pcBeg,
const char* pcEnd )
58 for( ; pcBeg < pcEnd; ++pcBeg )
59 if( !lclIsWhiteSpace( *pcBeg ) )
64 const char* lclTrimWhiteSpaceFromEnd(
const char* pcBeg,
const char* pcEnd )
66 while( (pcBeg < pcEnd) && lclIsWhiteSpace( pcEnd[ -1 ] ) )
71 void lclAppendToBuffer( OStringBuffer& rBuffer,
const char* pcBeg,
const char* pcEnd )
73 rBuffer.append( pcBeg, static_cast< sal_Int32 >( pcEnd - pcBeg ) );
76 void lclProcessAttribs( OStringBuffer& rBuffer,
const char* pcBeg,
const char* pcEnd )
81 typedef ::std::map< OString, const char* > AttributeNameMap;
82 AttributeNameMap aAttributeNames;
86 typedef ::std::map< const char*, OString > AttributeDataMap;
87 AttributeDataMap aAttributes;
90 const char* pcNameBeg = pcBeg;
91 while( bOk && (pcNameBeg < pcEnd) )
94 const char* pcEqualSign = lclFindCharacter( pcNameBeg, pcEnd,
'=' );
95 bOk = (pcEqualSign < pcEnd);
99 const char* pcNameEnd = lclTrimWhiteSpaceFromEnd( pcNameBeg, pcEqualSign );
100 bOk = (pcNameBeg < pcNameEnd);
104 const char* pcValueBeg = lclFindNonWhiteSpace( pcEqualSign + 1, pcEnd );
105 bOk = (pcValueBeg < pcEnd) && ((*pcValueBeg ==
'\'') || (*pcValueBeg ==
'"'));
109 const char* pcValueEnd = lclFindCharacter( pcValueBeg + 1, pcEnd, *pcValueBeg );
110 bOk = (pcValueEnd < pcEnd);
114 OString aAttribName( pcNameBeg, static_cast< sal_Int32 >( pcNameEnd - pcNameBeg ) );
115 OString aAttribData( pcNameBeg, static_cast< sal_Int32 >( pcValueEnd - pcNameBeg ) );
117 AttributeNameMap::iterator aIt = aAttributeNames.find( aAttribName );
119 if( aIt != aAttributeNames.end() )
120 aAttributes.erase( aIt->second );
122 aAttributeNames[ aAttribName ] = pcNameBeg;
123 aAttributes[ pcNameBeg ] = aAttribData;
125 pcNameBeg = pcValueEnd;
126 if( pcNameBeg < pcEnd )
128 bOk = lclIsWhiteSpace( *pcNameBeg );
130 pcNameBeg = lclFindNonWhiteSpace( pcNameBeg + 1, pcEnd );
140 for (
auto const& attrib : aAttributes)
141 rBuffer.append(
' ' ).append( attrib.second );
144 lclAppendToBuffer( rBuffer, pcBeg, pcEnd );
147 void lclProcessElement( OStringBuffer& rBuffer,
const OString& rElement )
150 sal_Int32 nElementLen = rElement.getLength();
151 if( nElementLen == 0 )
154 const char* pcOpen = rElement.getStr();
155 const char* pcClose = pcOpen + nElementLen - 1;
158 if( (pcOpen >= pcClose) || (*pcOpen !=
'<') || (*pcClose !=
'>') )
161 rBuffer.append( rElement );
165 else if( (nElementLen >= 5) && (pcOpen[ 1 ] ==
'!') && (pcOpen[ 2 ] ==
'[') && (pcClose[ -1 ] ==
']') )
171 else if( (nElementLen >= 4) && (pcOpen[ 1 ] ==
'?') && (pcClose[ -1 ] ==
'?') )
173 rBuffer.append( rElement );
177 else if( (nElementLen >= 4) && (pcOpen[ 1 ] ==
'b') && (pcOpen[ 2 ] ==
'r') && (lclFindNonWhiteSpace( pcOpen + 3, pcClose ) == pcClose) )
179 rBuffer.append(
'\n' );
183 else if( pcOpen[ 1 ] !=
'/' )
186 const char* pcContentBeg = pcOpen + 1;
187 bool bIsEmptyElement = pcClose[ -1 ] ==
'/';
188 const char* pcContentEnd = bIsEmptyElement ? (pcClose - 1) : pcClose;
190 const char* pcWhiteSpace = lclFindWhiteSpace( pcContentBeg, pcContentEnd );
191 lclAppendToBuffer( rBuffer, pcOpen, pcWhiteSpace );
193 const char* pcAttribBeg = lclFindNonWhiteSpace( pcWhiteSpace, pcContentEnd );
194 if( pcAttribBeg < pcContentEnd )
195 lclProcessAttribs( rBuffer, pcAttribBeg, pcContentEnd );
197 if( bIsEmptyElement )
198 rBuffer.append(
'/' );
199 rBuffer.append(
'>' );
205 rBuffer.append( rElement );
209 bool lclProcessCharacters( OStringBuffer& rBuffer,
const OString& rChars )
245 const char* pcBeg = rChars.getStr();
246 const char* pcEnd = pcBeg + rChars.getLength();
247 bool bHasBracket = (pcBeg < pcEnd) && (pcEnd[ -1 ] ==
'<');
248 if( bHasBracket ) --pcEnd;
251 const char* pcContentsBeg = lclFindNonWhiteSpace( pcBeg, pcEnd );
252 while( pcContentsBeg < pcEnd )
254 const char* pcWhitespaceBeg = lclFindWhiteSpace( pcContentsBeg + 1, pcEnd );
255 lclAppendToBuffer( rBuffer, pcContentsBeg, pcWhitespaceBeg );
256 if( pcWhitespaceBeg < pcEnd )
257 rBuffer.append(
' ' );
258 pcContentsBeg = lclFindNonWhiteSpace( pcWhitespaceBeg, pcEnd );
271 mxTextStrm( TextInputStream::createXTextInputStream( rxContext, rxInStrm, RTL_TEXTENCODING_ISO_8859_1 ) ),
272 maOpeningBracket{
'<' },
273 maClosingBracket{
'>' },
276 if (!mxTextStrm.is())
286 if( nBytesToRead < 0 )
289 rData.realloc( nBytesToRead );
290 sal_Int8* pcDest = rData.getArray();
292 while( (nBytesToRead > 0) && !
mxTextStrm->isEOF() )
298 memcpy( pcDest + nRet,
maBuffer.getStr() +
mnBufferPos,
static_cast< size_t >( nReadSize ) );
300 nBytesToRead -= nReadSize;
304 if( nRet < rData.getLength() )
305 rData.realloc( nRet );
311 return readBytes( rData, nMaxBytesToRead );
316 if( nBytesToSkip < 0 )
319 while( (nBytesToSkip > 0) && !
mxTextStrm->isEOF() )
324 nBytesToSkip -= nSkipSize;
350 bool bHasOpeningBracket = lclProcessCharacters( aBuffer, aChars );
353 OSL_ENSURE( bHasOpeningBracket ||
mxTextStrm->isEOF(),
"InputStream::updateBuffer - missing opening bracket of XML element" );
354 if( bHasOpeningBracket && !
mxTextStrm->isEOF() )
365 aBuffer.append( aElement );
370 lclProcessElement( aBuffer, aElement );
374 maBuffer = aBuffer.makeStringAndClear();
387 OSL_ENSURE( aText.endsWith(
">"),
"InputStream::readToElementEnd - missing closing bracket of XML element" );
constexpr OStringLiteral gaOpeningCData("<![CDATA[")
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
std::unique_ptr< char[]> aBuffer
constexpr OStringLiteral gaClosingCData("]]>")