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>
37const 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);
43bool lclIsWhiteSpace(
char cChar )
45 return cChar >= 0 && cChar <= 32;
48const char* lclFindWhiteSpace(
const char* pcBeg,
const char* pcEnd )
50 for( ; pcBeg < pcEnd; ++pcBeg )
51 if( lclIsWhiteSpace( *pcBeg ) )
56const char* lclFindNonWhiteSpace(
const char* pcBeg,
const char* pcEnd )
58 for( ; pcBeg < pcEnd; ++pcBeg )
59 if( !lclIsWhiteSpace( *pcBeg ) )
64const char* lclTrimWhiteSpaceFromEnd(
const char* pcBeg,
const char* pcEnd )
66 while( (pcBeg < pcEnd) && lclIsWhiteSpace( pcEnd[ -1 ] ) )
71void lclAppendToBuffer( OStringBuffer& rBuffer,
const char* pcBeg,
const char* pcEnd )
73 rBuffer.append( pcBeg,
static_cast< sal_Int32
>( pcEnd - pcBeg ) );
76void 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(
" " + attrib.second );
144 lclAppendToBuffer( rBuffer, pcBeg, pcEnd );
147void 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 );
209bool 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 );
269InputStream::InputStream(
const Reference< XComponentContext >& rxContext,
const Reference< XInputStream >& rxInStrm ) :
271 mxTextStrm(
TextInputStream::createXTextInputStream( rxContext, rxInStrm, RTL_TEXTENCODING_ISO_8859_1 ) ),
272 maOpeningBracket{
'<' },
273 maClosingBracket{
'>' },
276 if (!mxTextStrm.is())
280InputStream::~InputStream()
286 if( nBytesToRead < 0 )
289 rData.realloc( nBytesToRead );
290 sal_Int8* pcDest = rData.getArray();
292 while( (nBytesToRead > 0) && !mxTextStrm->isEOF() )
295 sal_Int32 nReadSize = ::std::min( nBytesToRead, maBuffer.getLength() - mnBufferPos );
298 memcpy( pcDest + nRet, maBuffer.getStr() + mnBufferPos,
static_cast< size_t >( nReadSize ) );
299 mnBufferPos += nReadSize;
300 nBytesToRead -= nReadSize;
304 if( nRet < rData.getLength() )
305 rData.realloc( nRet );
309sal_Int32 SAL_CALL InputStream::readSomeBytes(
Sequence< sal_Int8 >& rData, sal_Int32 nMaxBytesToRead )
311 return readBytes( rData, nMaxBytesToRead );
314void SAL_CALL InputStream::skipBytes( sal_Int32 nBytesToSkip )
316 if( nBytesToSkip < 0 )
319 while( (nBytesToSkip > 0) && !mxTextStrm->isEOF() )
322 sal_Int32 nSkipSize = ::std::min( nBytesToSkip, maBuffer.getLength() - mnBufferPos );
323 mnBufferPos += nSkipSize;
324 nBytesToSkip -= nSkipSize;
328sal_Int32 SAL_CALL InputStream::available()
331 return maBuffer.getLength() - mnBufferPos;
334void SAL_CALL InputStream::closeInput()
336 mxTextStrm->closeInput();
341void InputStream::updateBuffer()
343 while( (mnBufferPos >= maBuffer.getLength()) && !mxTextStrm->isEOF() )
349 OString aChars = readToElementBegin();
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() )
357 OString aElement =
"<" + readToElementEnd();
363 aElement += readToElementEnd();
370 lclProcessElement(
aBuffer, aElement );
374 maBuffer =
aBuffer.makeStringAndClear();
379OString InputStream::readToElementBegin()
381 return OUStringToOString( mxTextStrm->readString( maOpeningBracket,
false ), RTL_TEXTENCODING_ISO_8859_1 );
384OString InputStream::readToElementEnd()
386 OString aText =
OUStringToOString( mxTextStrm->readString( maClosingBracket,
false ), RTL_TEXTENCODING_ISO_8859_1 );
387 OSL_ENSURE( aText.endsWith(
">"),
"InputStream::readToElementEnd - missing closing bracket of XML element" );
constexpr OStringLiteral gaOpeningCData("<![CDATA[")
constexpr OStringLiteral gaClosingCData("]]>")
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
std::unique_ptr< char[]> aBuffer