Bug Summary

File:home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx
Warning:line 145, column 22
Array access (from variable 'pStr') results in a null pointer dereference

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name fastserializer.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D SAX_DLLIMPLEMENTATION -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/sax/inc -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx
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#include "fastserializer.hxx"
21
22#include <com/sun/star/xml/sax/FastTokenHandler.hpp>
23#include <rtl/math.h>
24#include <sal/log.hxx>
25#include <comphelper/processfactory.hxx>
26#include <comphelper/sequence.hxx>
27
28#include <string.h>
29
30#if OSL_DEBUG_LEVEL1 > 0
31#include <iostream>
32#include <set>
33#endif
34
35using ::std::vector;
36using ::com::sun::star::uno::Sequence;
37using ::com::sun::star::io::XOutputStream;
38
39#define HAS_NAMESPACE(x)((x & 0xffff0000) != 0) ((x & 0xffff0000) != 0)
40#define NAMESPACE(x)(x >> 16) (x >> 16)
41#define TOKEN(x)(x & 0xffff) (x & 0xffff)
42// number of characters without terminating 0
43#define N_CHARS(string)((sizeof(sal_n_array_size(string))) - 1) (SAL_N_ELEMENTS(string)(sizeof(sal_n_array_size(string))) - 1)
44
45const char sClosingBracket[] = ">";
46const char sSlashAndClosingBracket[] = "/>";
47const char sColon[] = ":";
48const char sOpeningBracket[] = "<";
49const char sOpeningBracketAndSlash[] = "</";
50const char sQuote[] = "\"";
51const char sEqualSignAndQuote[] = "=\"";
52const char sSpace[] = " ";
53const char sXmlHeader[] = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n";
54
55namespace sax_fastparser {
56 FastSaxSerializer::FastSaxSerializer( const css::uno::Reference< css::io::XOutputStream >& xOutputStream )
57 : maCachedOutputStream()
58 , maMarkStack()
59 , mbMarkStackEmpty(true)
60 , mpDoubleStr(nullptr)
61 , mnDoubleStrCapacity(RTL_STR_MAX_VALUEOFDOUBLE25)
62 , mbXescape(true)
63 {
64 rtl_string_new_WithLength(&mpDoubleStr, mnDoubleStrCapacity);
65 mxFastTokenHandler = css::xml::sax::FastTokenHandler::create(
66 ::comphelper::getProcessComponentContext());
67 assert(xOutputStream.is())(static_cast <bool> (xOutputStream.is()) ? void (0) : __assert_fail
("xOutputStream.is()", "/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
, 67, __extension__ __PRETTY_FUNCTION__))
; // cannot do anything without that
68 maCachedOutputStream.setOutputStream( xOutputStream );
69 }
70
71 FastSaxSerializer::~FastSaxSerializer()
72 {
73 rtl_string_release(mpDoubleStr);
74 }
75
76 void FastSaxSerializer::startDocument()
77 {
78 writeBytes(sXmlHeader, N_CHARS(sXmlHeader)((sizeof(sal_n_array_size(sXmlHeader))) - 1));
79 }
80
81 void FastSaxSerializer::write( double value )
82 {
83 rtl_math_doubleToString(
84 &mpDoubleStr, &mnDoubleStrCapacity, 0, value, rtl_math_StringFormat_G,
85 RTL_STR_MAX_VALUEOFDOUBLE25 - RTL_CONSTASCII_LENGTH("-x.E-xxx")((sal_Int32)((sizeof(sal_n_array_size("-x.E-xxx")))-1)), '.', nullptr,
86 0, true);
87
88 write(mpDoubleStr->buffer, mpDoubleStr->length);
89 // and "clear" the string
90 mpDoubleStr->length = 0;
91 mnDoubleStrCapacity = RTL_STR_MAX_VALUEOFDOUBLE25;
92 }
93
94 void FastSaxSerializer::write( const OUString& sOutput, bool bEscape )
95 {
96 write( OUStringToOString(sOutput, RTL_TEXTENCODING_UTF8(((rtl_TextEncoding) 76))), bEscape );
97
98 }
99
100 void FastSaxSerializer::write( const OString& sOutput, bool bEscape )
101 {
102 write( sOutput.getStr(), sOutput.getLength(), bEscape );
103 }
104
105 /** Characters not allowed in XML 1.0
106 XML 1.1 would exclude only U+0000
107 */
108 static bool invalidChar( char c )
109 {
110 if (static_cast<unsigned char>(c) >= 0x20)
111 return false;
112
113 switch (c)
114 {
115 case 0x09:
116 case 0x0a:
117 case 0x0d:
118 return false;
119 }
120 return true;
121 }
122
123 static bool isHexDigit( char c )
124 {
125 return ('0' <= c && c <= '9') || ('A' <= c && c <= 'F') || ('a' <= c && c <= 'f');
126 }
127
128 void FastSaxSerializer::write( const char* pStr, sal_Int32 nLen, bool bEscape )
129 {
130 if (nLen == -1)
12
Assuming the condition is false
13
Taking false branch
131 nLen = pStr ? strlen(pStr) : 0;
132
133 if (!bEscape
13.1
'bEscape' is true
)
14
Taking false branch
134 {
135 writeBytes( pStr, nLen );
136 return;
137 }
138
139 bool bGood = true;
140 const sal_Int32 kXescapeLen = 7;
141 char bufXescape[kXescapeLen+1];
142 sal_Int32 nNextXescape = 0;
143 for (sal_Int32 i = 0; i < nLen; ++i)
15
Assuming 'i' is < 'nLen'
16
Loop condition is true. Entering loop body
144 {
145 char c = pStr[ i ];
17
Array access (from variable 'pStr') results in a null pointer dereference
146 switch( c )
147 {
148 case '<': writeBytes( "&lt;", 4 ); break;
149 case '>': writeBytes( "&gt;", 4 ); break;
150 case '&': writeBytes( "&amp;", 5 ); break;
151 case '\'': writeBytes( "&apos;", 6 ); break;
152 case '"': writeBytes( "&quot;", 6 ); break;
153 case '\t':
154#if 0
155 // Seems OOXML prefers the _xHHHH_ escape over the
156 // entity in *some* cases, apparently in attribute
157 // values but not in element data.
158 // Would need to distinguish at a higher level.
159 if (mbXescape)
160 {
161 snprintf( bufXescape, kXescapeLen+1, "_x%04x_",
162 static_cast<unsigned int>(static_cast<unsigned char>(c)));
163 writeBytes( bufXescape, kXescapeLen);
164 }
165 else
166#endif
167 {
168 writeBytes( "&#9;", 4 );
169 }
170 break;
171 case '\n':
172#if 0
173 if (mbXescape)
174 {
175 snprintf( bufXescape, kXescapeLen+1, "_x%04x_",
176 static_cast<unsigned int>(static_cast<unsigned char>(c)));
177 writeBytes( bufXescape, kXescapeLen);
178 }
179 else
180#endif
181 {
182 writeBytes( "&#10;", 5 );
183 }
184 break;
185 case '\r':
186#if 0
187 if (mbXescape)
188 {
189 snprintf( bufXescape, kXescapeLen+1, "_x%04x_",
190 static_cast<unsigned int>(static_cast<unsigned char>(c)));
191 writeBytes( bufXescape, kXescapeLen);
192 }
193 else
194#endif
195 {
196 writeBytes( "&#13;", 5 );
197 }
198 break;
199 default:
200 if (mbXescape)
201 {
202 char c1, c2, c3, c4;
203 // Escape characters not valid in XML 1.0 as
204 // _xHHHH_. A literal "_xHHHH_" has to be
205 // escaped as _x005F_xHHHH_ (effectively
206 // escaping the leading '_').
207 // See ECMA-376-1:2016 page 3736,
208 // 22.4.2.4 bstr (Basic String)
209 // for reference.
210 if (c == '_' && i >= nNextXescape && i <= nLen - kXescapeLen &&
211 pStr[i+6] == '_' &&
212 ((pStr[i+1] | 0x20) == 'x') &&
213 isHexDigit( c1 = pStr[i+2] ) &&
214 isHexDigit( c2 = pStr[i+3] ) &&
215 isHexDigit( c3 = pStr[i+4] ) &&
216 isHexDigit( c4 = pStr[i+5] ))
217 {
218 // OOXML has the odd habit to write some
219 // names using this that when re-saving
220 // should *not* be escaped, specifically
221 // _x0020_ for blanks in w:xpath values.
222 if (!(c1 == '0' && c2 == '0' && c3 == '2' && c4 == '0'))
223 {
224 // When encountering "_x005F_xHHHH_"
225 // assume that is an already escaped
226 // sequence that was not unescaped and
227 // shall be written as is, to not end
228 // up with "_x005F_x005F_xHHHH_" and
229 // repeated...
230 if (c1 == '0' && c2 == '0' && c3 == '5' && (c4 | 0x20) == 'f' &&
231 i + kXescapeLen <= nLen - 6 &&
232 pStr[i+kXescapeLen+5] == '_' &&
233 ((pStr[i+kXescapeLen+0] | 0x20) == 'x') &&
234 isHexDigit( pStr[i+kXescapeLen+1] ) &&
235 isHexDigit( pStr[i+kXescapeLen+2] ) &&
236 isHexDigit( pStr[i+kXescapeLen+3] ) &&
237 isHexDigit( pStr[i+kXescapeLen+4] ))
238 {
239 writeBytes( &c, 1 );
240 // Remember this fake escapement.
241 nNextXescape = i + kXescapeLen + 6;
242 }
243 else
244 {
245 writeBytes( "_x005F_", kXescapeLen);
246 // Remember this escapement so in
247 // _xHHHH_xHHHH_ only the first '_'
248 // is escaped.
249 nNextXescape = i + kXescapeLen;
250 }
251 break;
252 }
253 }
254 if (invalidChar(c))
255 {
256 snprintf( bufXescape, kXescapeLen+1, "_x%04x_",
257 static_cast<unsigned int>(static_cast<unsigned char>(c)));
258 writeBytes( bufXescape, kXescapeLen);
259 break;
260 }
261 /* TODO: also U+FFFE and U+FFFF are not allowed
262 * in XML 1.0, assuming we're writing UTF-8
263 * those should be escaped as well to be
264 * conformant. Likely that would involve
265 * scanning for both encoded sequences and
266 * write as _xHHHH_? */
267 }
268#if OSL_DEBUG_LEVEL1 > 0
269 else
270 {
271 if (bGood && invalidChar(pStr[i]))
272 {
273 bGood = false;
274 // The SAL_WARN() for the single character is
275 // issued in writeBytes(), just gather for the
276 // SAL_WARN_IF() below.
277 }
278 }
279#endif
280 writeBytes( &c, 1 );
281 break;
282 }
283 }
284 SAL_WARN_IF( !bGood && nLen > 1, "sax", "in '" << OString(pStr,std::min<sal_Int32>(nLen,42)) << "'")do { if (true && (!bGood && nLen > 1)) { switch
(sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN, "sax")) {
case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "in '" << OString(pStr,std::min<sal_Int32
>(nLen,42)) << "'") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sax"), ("/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
":" "284" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "in '" << OString(pStr,std::min<
sal_Int32>(nLen,42)) << "'"), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "in '" <<
OString(pStr,std::min<sal_Int32>(nLen,42)) << "'"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sax"),
("/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
":" "284" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "in '" << OString(pStr,std::min<sal_Int32
>(nLen,42)) << "'") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sax"), ("/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
":" "284" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "in '" << OString(pStr,std::min<
sal_Int32>(nLen,42)) << "'"), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "in '" <<
OString(pStr,std::min<sal_Int32>(nLen,42)) << "'"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sax"),
("/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
":" "284" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
285 }
286
287 void FastSaxSerializer::endDocument()
288 {
289 assert(mbMarkStackEmpty && maMarkStack.empty())(static_cast <bool> (mbMarkStackEmpty && maMarkStack
.empty()) ? void (0) : __assert_fail ("mbMarkStackEmpty && maMarkStack.empty()"
, "/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
, 289, __extension__ __PRETTY_FUNCTION__))
;
290 maCachedOutputStream.flush();
291 }
292
293 void FastSaxSerializer::writeId( ::sal_Int32 nElement )
294 {
295 if( HAS_NAMESPACE( nElement )((nElement & 0xffff0000) != 0) ) {
296 auto const Namespace(mxFastTokenHandler->getUTF8Identifier(NAMESPACE(nElement)(nElement >> 16)));
297 assert(Namespace.hasElements())(static_cast <bool> (Namespace.hasElements()) ? void (0
) : __assert_fail ("Namespace.hasElements()", "/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
, 297, __extension__ __PRETTY_FUNCTION__))
;
298 writeBytes(Namespace);
299 writeBytes(sColon, N_CHARS(sColon)((sizeof(sal_n_array_size(sColon))) - 1));
300 auto const Element(mxFastTokenHandler->getUTF8Identifier(TOKEN(nElement)(nElement & 0xffff)));
301 assert(Element.hasElements())(static_cast <bool> (Element.hasElements()) ? void (0) :
__assert_fail ("Element.hasElements()", "/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
, 301, __extension__ __PRETTY_FUNCTION__))
;
302 writeBytes(Element);
303 } else {
304 auto const Element(mxFastTokenHandler->getUTF8Identifier(nElement));
305 assert(Element.hasElements())(static_cast <bool> (Element.hasElements()) ? void (0) :
__assert_fail ("Element.hasElements()", "/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
, 305, __extension__ __PRETTY_FUNCTION__))
;
306 writeBytes(Element);
307 }
308 }
309
310#ifdef DBG_UTIL
311 OString FastSaxSerializer::getId( ::sal_Int32 nElement )
312 {
313 if (HAS_NAMESPACE(nElement)((nElement & 0xffff0000) != 0)) {
314 Sequence<sal_Int8> const ns(
315 mxFastTokenHandler->getUTF8Identifier(NAMESPACE(nElement)(nElement >> 16)));
316 Sequence<sal_Int8> const name(
317 mxFastTokenHandler->getUTF8Identifier(TOKEN(nElement)(nElement & 0xffff)));
318 return OString(reinterpret_cast<char const*>(ns.getConstArray()), ns.getLength())
319 + OString(sColon, N_CHARS(sColon)((sizeof(sal_n_array_size(sColon))) - 1))
320 + OString(reinterpret_cast<char const*>(name.getConstArray()), name.getLength());
321 } else {
322 Sequence<sal_Int8> const name(
323 mxFastTokenHandler->getUTF8Identifier(nElement));
324 return OString(reinterpret_cast<char const*>(name.getConstArray()), name.getLength());
325 }
326 }
327#endif
328
329 void FastSaxSerializer::startFastElement( ::sal_Int32 Element, FastAttributeList const * pAttrList )
330 {
331 if ( !mbMarkStackEmpty )
332 {
333 maCachedOutputStream.flush();
334 maMarkStack.top()->setCurrentElement( Element );
335 }
336
337#ifdef DBG_UTIL
338 if (mbMarkStackEmpty)
339 m_DebugStartedElements.push(Element);
340 else
341 maMarkStack.top()->m_DebugStartedElements.push_back(Element);
342#endif
343
344 writeBytes(sOpeningBracket, N_CHARS(sOpeningBracket)((sizeof(sal_n_array_size(sOpeningBracket))) - 1));
345
346 writeId(Element);
347 if (pAttrList)
348 writeFastAttributeList(*pAttrList);
349 else
350 writeTokenValueList();
351
352 writeBytes(sClosingBracket, N_CHARS(sClosingBracket)((sizeof(sal_n_array_size(sClosingBracket))) - 1));
353 }
354
355 void FastSaxSerializer::endFastElement( ::sal_Int32 Element )
356 {
357#ifdef DBG_UTIL
358 // Well-formedness constraint: Element Type Match
359 if (mbMarkStackEmpty)
360 {
361 assert(!m_DebugStartedElements.empty())(static_cast <bool> (!m_DebugStartedElements.empty()) ?
void (0) : __assert_fail ("!m_DebugStartedElements.empty()",
"/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
, 361, __extension__ __PRETTY_FUNCTION__))
;
362 assert(Element == m_DebugStartedElements.top())(static_cast <bool> (Element == m_DebugStartedElements.
top()) ? void (0) : __assert_fail ("Element == m_DebugStartedElements.top()"
, "/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
, 362, __extension__ __PRETTY_FUNCTION__))
;
363 m_DebugStartedElements.pop();
364 }
365 else
366 {
367 if (dynamic_cast<ForSort*>(maMarkStack.top().get()))
368 {
369 // Sort is always well-formed fragment
370 assert(!maMarkStack.top()->m_DebugStartedElements.empty())(static_cast <bool> (!maMarkStack.top()->m_DebugStartedElements
.empty()) ? void (0) : __assert_fail ("!maMarkStack.top()->m_DebugStartedElements.empty()"
, "/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
, 370, __extension__ __PRETTY_FUNCTION__))
;
371 }
372 if (maMarkStack.top()->m_DebugStartedElements.empty())
373 {
374 maMarkStack.top()->m_DebugEndedElements.push_back(Element);
375 }
376 else
377 {
378 assert(Element == maMarkStack.top()->m_DebugStartedElements.back())(static_cast <bool> (Element == maMarkStack.top()->m_DebugStartedElements
.back()) ? void (0) : __assert_fail ("Element == maMarkStack.top()->m_DebugStartedElements.back()"
, "/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
, 378, __extension__ __PRETTY_FUNCTION__))
;
379 maMarkStack.top()->m_DebugStartedElements.pop_back();
380 }
381 }
382#endif
383
384 writeBytes(sOpeningBracketAndSlash, N_CHARS(sOpeningBracketAndSlash)((sizeof(sal_n_array_size(sOpeningBracketAndSlash))) - 1));
385
386 writeId(Element);
387
388 writeBytes(sClosingBracket, N_CHARS(sClosingBracket)((sizeof(sal_n_array_size(sClosingBracket))) - 1));
389 }
390
391 void FastSaxSerializer::singleFastElement( ::sal_Int32 Element, FastAttributeList const * pAttrList )
392 {
393 if ( !mbMarkStackEmpty )
1
Assuming field 'mbMarkStackEmpty' is true
2
Taking false branch
394 {
395 maCachedOutputStream.flush();
396 maMarkStack.top()->setCurrentElement( Element );
397 }
398
399 writeBytes(sOpeningBracket, N_CHARS(sOpeningBracket)((sizeof(sal_n_array_size(sOpeningBracket))) - 1));
400
401 writeId(Element);
402 if (pAttrList)
3
Assuming 'pAttrList' is non-null
4
Taking true branch
403 writeFastAttributeList(*pAttrList);
5
Calling 'FastSaxSerializer::writeFastAttributeList'
404 else
405 writeTokenValueList();
406
407 writeBytes(sSlashAndClosingBracket, N_CHARS(sSlashAndClosingBracket)((sizeof(sal_n_array_size(sSlashAndClosingBracket))) - 1));
408 }
409
410 css::uno::Reference< css::io::XOutputStream > const & FastSaxSerializer::getOutputStream() const
411 {
412 return maCachedOutputStream.getOutputStream();
413 }
414
415 void FastSaxSerializer::writeTokenValueList()
416 {
417#ifdef DBG_UTIL
418 ::std::set<OString> DebugAttributes;
419#endif
420 for (const TokenValue & rTokenValue : maTokenValues)
421 {
422 writeBytes(sSpace, N_CHARS(sSpace)((sizeof(sal_n_array_size(sSpace))) - 1));
423
424 sal_Int32 nToken = rTokenValue.nToken;
425 writeId(nToken);
426
427#ifdef DBG_UTIL
428 // Well-formedness constraint: Unique Att Spec
429 OString const nameId(getId(nToken));
430 assert(DebugAttributes.find(nameId) == DebugAttributes.end())(static_cast <bool> (DebugAttributes.find(nameId) == DebugAttributes
.end()) ? void (0) : __assert_fail ("DebugAttributes.find(nameId) == DebugAttributes.end()"
, "/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
, 430, __extension__ __PRETTY_FUNCTION__))
;
431 DebugAttributes.insert(nameId);
432#endif
433
434 writeBytes(sEqualSignAndQuote, N_CHARS(sEqualSignAndQuote)((sizeof(sal_n_array_size(sEqualSignAndQuote))) - 1));
435
436 write(rTokenValue.pValue, -1, true);
437
438 writeBytes(sQuote, N_CHARS(sQuote)((sizeof(sal_n_array_size(sQuote))) - 1));
439 }
440 maTokenValues.clear();
441 }
442
443 void FastSaxSerializer::writeFastAttributeList(FastAttributeList const & rAttrList)
444 {
445#ifdef DBG_UTIL
446 ::std::set<OString> DebugAttributes;
447#endif
448 const std::vector< sal_Int32 >& Tokens = rAttrList.getFastAttributeTokens();
449 for (size_t j = 0; j < Tokens.size(); j++)
6
Assuming the condition is true
7
Loop condition is true. Entering loop body
450 {
451 writeBytes(sSpace, N_CHARS(sSpace)((sizeof(sal_n_array_size(sSpace))) - 1));
452
453 sal_Int32 nToken = Tokens[j];
454 writeId(nToken);
455
456#ifdef DBG_UTIL
457 // Well-formedness constraint: Unique Att Spec
458 OString const nameId(getId(nToken));
459 SAL_WARN_IF(DebugAttributes.find(nameId) != DebugAttributes.end(), "sax", "Duplicate attribute: " << nameId )do { if (true && (DebugAttributes.find(nameId) != DebugAttributes
.end())) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sax")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Duplicate attribute: " << nameId) == 1) { ::
sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sax"), ("/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
":" "459" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Duplicate attribute: " << nameId
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Duplicate attribute: " << nameId; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sax"), ("/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
":" "459" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Duplicate attribute: " << nameId) == 1) { ::
sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sax"), ("/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
":" "459" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Duplicate attribute: " << nameId
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Duplicate attribute: " << nameId; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sax"), ("/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
":" "459" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
460 assert(DebugAttributes.find(nameId) == DebugAttributes.end())(static_cast <bool> (DebugAttributes.find(nameId) == DebugAttributes
.end()) ? void (0) : __assert_fail ("DebugAttributes.find(nameId) == DebugAttributes.end()"
, "/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
, 460, __extension__ __PRETTY_FUNCTION__))
;
461 DebugAttributes.insert(nameId);
462#endif
463
464 writeBytes(sEqualSignAndQuote, N_CHARS(sEqualSignAndQuote)((sizeof(sal_n_array_size(sEqualSignAndQuote))) - 1));
465
466 const char* pAttributeValue = rAttrList.getFastAttributeValue(j);
8
'pAttributeValue' initialized here
467
468 // tdf#127274 don't escape the special VML shape type id "#_x0000_t202"
469 bool bEscape = !(pAttributeValue && strcmp(pAttributeValue, "#_x0000_t202") == 0);
9
Assuming 'pAttributeValue' is null
470
471 write(pAttributeValue, rAttrList.AttributeValueLength(j), bEscape);
10
Passing null pointer value via 1st parameter 'pStr'
11
Calling 'FastSaxSerializer::write'
472
473 writeBytes(sQuote, N_CHARS(sQuote)((sizeof(sal_n_array_size(sQuote))) - 1));
474 }
475 }
476
477 void FastSaxSerializer::mark(sal_Int32 const nTag, const Int32Sequence& rOrder)
478 {
479 if (rOrder.hasElements())
480 {
481 auto pSort = std::make_shared<ForSort>(nTag, rOrder);
482 maMarkStack.push( pSort );
483 maCachedOutputStream.setOutput( pSort );
484 }
485 else
486 {
487 auto pMerge = std::make_shared<ForMerge>(nTag);
488 maMarkStack.push( pMerge );
489 maCachedOutputStream.setOutput( pMerge );
490 }
491 mbMarkStackEmpty = false;
492 }
493
494#ifdef DBG_UTIL
495 static void lcl_DebugMergeAppend(
496 std::deque<sal_Int32> & rLeftEndedElements,
497 std::deque<sal_Int32> & rLeftStartedElements,
498 std::deque<sal_Int32> & rRightEndedElements,
499 std::deque<sal_Int32> & rRightStartedElements)
500 {
501 while (!rRightEndedElements.empty())
502 {
503 if (rLeftStartedElements.empty())
504 {
505 rLeftEndedElements.push_back(rRightEndedElements.front());
506 }
507 else
508 {
509 assert(rLeftStartedElements.back() == rRightEndedElements.front())(static_cast <bool> (rLeftStartedElements.back() == rRightEndedElements
.front()) ? void (0) : __assert_fail ("rLeftStartedElements.back() == rRightEndedElements.front()"
, "/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
, 509, __extension__ __PRETTY_FUNCTION__))
;
510 rLeftStartedElements.pop_back();
511 }
512 rRightEndedElements.pop_front();
513 }
514 while (!rRightStartedElements.empty())
515 {
516 rLeftStartedElements.push_back(rRightStartedElements.front());
517 rRightStartedElements.pop_front();
518 }
519 }
520
521 static void lcl_DebugMergePrepend(
522 std::deque<sal_Int32> & rLeftEndedElements,
523 std::deque<sal_Int32> & rLeftStartedElements,
524 std::deque<sal_Int32> & rRightEndedElements,
525 std::deque<sal_Int32> & rRightStartedElements)
526 {
527 while (!rLeftStartedElements.empty())
528 {
529 if (rRightEndedElements.empty())
530 {
531 rRightStartedElements.push_front(rLeftStartedElements.back());
532 }
533 else
534 {
535 assert(rRightEndedElements.front() == rLeftStartedElements.back())(static_cast <bool> (rRightEndedElements.front() == rLeftStartedElements
.back()) ? void (0) : __assert_fail ("rRightEndedElements.front() == rLeftStartedElements.back()"
, "/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
, 535, __extension__ __PRETTY_FUNCTION__))
;
536 rRightEndedElements.pop_front();
537 }
538 rLeftStartedElements.pop_back();
539 }
540 while (!rLeftEndedElements.empty())
541 {
542 rRightEndedElements.push_front(rLeftEndedElements.back());
543 rLeftEndedElements.pop_back();
544 }
545 }
546#endif
547
548 void FastSaxSerializer::mergeTopMarks(
549 sal_Int32 const nTag, sax_fastparser::MergeMarks const eMergeType)
550 {
551 SAL_WARN_IF(mbMarkStackEmpty, "sax", "Empty mark stack - nothing to merge")do { if (true && (mbMarkStackEmpty)) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "sax")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "Empty mark stack - nothing to merge"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sax"
), ("/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
":" "551" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Empty mark stack - nothing to merge")
, 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Empty mark stack - nothing to merge"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sax"), ("/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
":" "551" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Empty mark stack - nothing to merge") == 1) { ::
sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sax"), ("/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
":" "551" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Empty mark stack - nothing to merge")
, 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Empty mark stack - nothing to merge"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sax"), ("/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
":" "551" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
552 assert(!mbMarkStackEmpty)(static_cast <bool> (!mbMarkStackEmpty) ? void (0) : __assert_fail
("!mbMarkStackEmpty", "/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
, 552, __extension__ __PRETTY_FUNCTION__))
; // should never happen
553 if ( mbMarkStackEmpty )
554 return;
555
556 assert(maMarkStack.top()->m_Tag == nTag && "mark/merge tag mismatch!")(static_cast <bool> (maMarkStack.top()->m_Tag == nTag
&& "mark/merge tag mismatch!") ? void (0) : __assert_fail
("maMarkStack.top()->m_Tag == nTag && \"mark/merge tag mismatch!\""
, "/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
, 556, __extension__ __PRETTY_FUNCTION__))
;
557 (void) nTag;
558#ifdef DBG_UTIL
559 if (dynamic_cast<ForSort*>(maMarkStack.top().get()))
560 {
561 // Sort is always well-formed fragment
562 assert(maMarkStack.top()->m_DebugStartedElements.empty())(static_cast <bool> (maMarkStack.top()->m_DebugStartedElements
.empty()) ? void (0) : __assert_fail ("maMarkStack.top()->m_DebugStartedElements.empty()"
, "/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
, 562, __extension__ __PRETTY_FUNCTION__))
;
563 assert(maMarkStack.top()->m_DebugEndedElements.empty())(static_cast <bool> (maMarkStack.top()->m_DebugEndedElements
.empty()) ? void (0) : __assert_fail ("maMarkStack.top()->m_DebugEndedElements.empty()"
, "/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
, 563, __extension__ __PRETTY_FUNCTION__))
;
564 }
565 lcl_DebugMergeAppend(
566 maMarkStack.top()->m_DebugEndedElements,
567 maMarkStack.top()->m_DebugStartedElements,
568 maMarkStack.top()->m_DebugPostponedEndedElements,
569 maMarkStack.top()->m_DebugPostponedStartedElements);
570#endif
571
572 // flush, so that we get everything in getData()
573 maCachedOutputStream.flush();
574
575 if (maMarkStack.size() == 1)
576 {
577#ifdef DBG_UTIL
578 while (!maMarkStack.top()->m_DebugEndedElements.empty())
579 {
580 assert(maMarkStack.top()->m_DebugEndedElements.front() == m_DebugStartedElements.top())(static_cast <bool> (maMarkStack.top()->m_DebugEndedElements
.front() == m_DebugStartedElements.top()) ? void (0) : __assert_fail
("maMarkStack.top()->m_DebugEndedElements.front() == m_DebugStartedElements.top()"
, "/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
, 580, __extension__ __PRETTY_FUNCTION__))
;
581 maMarkStack.top()->m_DebugEndedElements.pop_front();
582 m_DebugStartedElements.pop();
583 }
584 while (!maMarkStack.top()->m_DebugStartedElements.empty())
585 {
586 m_DebugStartedElements.push(maMarkStack.top()->m_DebugStartedElements.front());
587 maMarkStack.top()->m_DebugStartedElements.pop_front();
588 }
589#endif
590 Sequence<sal_Int8> aSeq( maMarkStack.top()->getData() );
591 maMarkStack.pop();
592 mbMarkStackEmpty = true;
593 maCachedOutputStream.resetOutputToStream();
594 maCachedOutputStream.writeBytes( aSeq.getConstArray(), aSeq.getLength() );
595 return;
596 }
597
598#ifdef DBG_UTIL
599 ::std::deque<sal_Int32> topDebugStartedElements(maMarkStack.top()->m_DebugStartedElements);
600 ::std::deque<sal_Int32> topDebugEndedElements(maMarkStack.top()->m_DebugEndedElements);
601#endif
602 const Int8Sequence aMerge( maMarkStack.top()->getData() );
603 maMarkStack.pop();
604#ifdef DBG_UTIL
605 switch (eMergeType)
606 {
607 case MergeMarks::APPEND:
608 lcl_DebugMergeAppend(
609 maMarkStack.top()->m_DebugEndedElements,
610 maMarkStack.top()->m_DebugStartedElements,
611 topDebugEndedElements,
612 topDebugStartedElements);
613 break;
614 case MergeMarks::PREPEND:
615 if (dynamic_cast<ForSort*>(maMarkStack.top().get())) // argh...
616 {
617 lcl_DebugMergeAppend(
618 maMarkStack.top()->m_DebugEndedElements,
619 maMarkStack.top()->m_DebugStartedElements,
620 topDebugEndedElements,
621 topDebugStartedElements);
622 }
623 else
624 {
625 lcl_DebugMergePrepend(
626 topDebugEndedElements,
627 topDebugStartedElements,
628 maMarkStack.top()->m_DebugEndedElements,
629 maMarkStack.top()->m_DebugStartedElements);
630 }
631 break;
632 case MergeMarks::POSTPONE:
633 lcl_DebugMergeAppend(
634 maMarkStack.top()->m_DebugPostponedEndedElements,
635 maMarkStack.top()->m_DebugPostponedStartedElements,
636 topDebugEndedElements,
637 topDebugStartedElements);
638 break;
639 }
640#endif
641 if (maMarkStack.empty())
642 {
643 mbMarkStackEmpty = true;
644 maCachedOutputStream.resetOutputToStream();
645 }
646 else
647 {
648 maCachedOutputStream.setOutput( maMarkStack.top() );
649 }
650
651 switch ( eMergeType )
652 {
653 case MergeMarks::APPEND: maMarkStack.top()->append( aMerge ); break;
654 case MergeMarks::PREPEND: maMarkStack.top()->prepend( aMerge ); break;
655 case MergeMarks::POSTPONE: maMarkStack.top()->postpone( aMerge ); break;
656 }
657 }
658
659 void FastSaxSerializer::writeBytes( const Sequence< sal_Int8 >& rData )
660 {
661 maCachedOutputStream.writeBytes( rData.getConstArray(), rData.getLength() );
662 }
663
664 void FastSaxSerializer::writeBytes( const char* pStr, size_t nLen )
665 {
666#if OSL_DEBUG_LEVEL1 > 0
667 {
668 bool bGood = true;
669 for (size_t i=0; i < nLen; ++i)
670 {
671 if (invalidChar(pStr[i]))
672 {
673 bGood = false;
674 SAL_WARN("sax", "FastSaxSerializer::writeBytes - illegal XML character 0x" <<do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sax")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "FastSaxSerializer::writeBytes - illegal XML character 0x"
<< std::hex << int(static_cast<unsigned char>
(pStr[i]))) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sax"), ("/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
":" "675" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "FastSaxSerializer::writeBytes - illegal XML character 0x"
<< std::hex << int(static_cast<unsigned char>
(pStr[i]))), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "FastSaxSerializer::writeBytes - illegal XML character 0x"
<< std::hex << int(static_cast<unsigned char>
(pStr[i])); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN)
, ("sax"), ("/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
":" "675" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "FastSaxSerializer::writeBytes - illegal XML character 0x"
<< std::hex << int(static_cast<unsigned char>
(pStr[i]))) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sax"), ("/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
":" "675" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "FastSaxSerializer::writeBytes - illegal XML character 0x"
<< std::hex << int(static_cast<unsigned char>
(pStr[i]))), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "FastSaxSerializer::writeBytes - illegal XML character 0x"
<< std::hex << int(static_cast<unsigned char>
(pStr[i])); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN)
, ("sax"), ("/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
":" "675" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
675 std::hex << int(static_cast<unsigned char>(pStr[i])))do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sax")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "FastSaxSerializer::writeBytes - illegal XML character 0x"
<< std::hex << int(static_cast<unsigned char>
(pStr[i]))) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sax"), ("/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
":" "675" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "FastSaxSerializer::writeBytes - illegal XML character 0x"
<< std::hex << int(static_cast<unsigned char>
(pStr[i]))), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "FastSaxSerializer::writeBytes - illegal XML character 0x"
<< std::hex << int(static_cast<unsigned char>
(pStr[i])); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN)
, ("sax"), ("/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
":" "675" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "FastSaxSerializer::writeBytes - illegal XML character 0x"
<< std::hex << int(static_cast<unsigned char>
(pStr[i]))) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sax"), ("/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
":" "675" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "FastSaxSerializer::writeBytes - illegal XML character 0x"
<< std::hex << int(static_cast<unsigned char>
(pStr[i]))), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "FastSaxSerializer::writeBytes - illegal XML character 0x"
<< std::hex << int(static_cast<unsigned char>
(pStr[i])); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN)
, ("sax"), ("/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
":" "675" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
676 }
677 }
678 SAL_WARN_IF( !bGood && nLen > 1, "sax", "in '" << OString(pStr,std::min<sal_Int32>(nLen,42)) << "'")do { if (true && (!bGood && nLen > 1)) { switch
(sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN, "sax")) {
case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "in '" << OString(pStr,std::min<sal_Int32
>(nLen,42)) << "'") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sax"), ("/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
":" "678" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "in '" << OString(pStr,std::min<
sal_Int32>(nLen,42)) << "'"), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "in '" <<
OString(pStr,std::min<sal_Int32>(nLen,42)) << "'"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sax"),
("/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
":" "678" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "in '" << OString(pStr,std::min<sal_Int32
>(nLen,42)) << "'") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sax"), ("/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
":" "678" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "in '" << OString(pStr,std::min<
sal_Int32>(nLen,42)) << "'"), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "in '" <<
OString(pStr,std::min<sal_Int32>(nLen,42)) << "'"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sax"),
("/home/maarten/src/libreoffice/core/sax/source/tools/fastserializer.cxx"
":" "678" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
679 }
680#endif
681 maCachedOutputStream.writeBytes( reinterpret_cast<const sal_Int8*>(pStr), nLen );
682 }
683
684 FastSaxSerializer::Int8Sequence& FastSaxSerializer::ForMerge::getData()
685 {
686 merge( maData, maPostponed, true );
687 maPostponed.realloc( 0 );
688
689 return maData;
690 }
691
692#if OSL_DEBUG_LEVEL1 > 0
693 void FastSaxSerializer::ForMerge::print( )
694 {
695 std::cerr << "Data: ";
696 for ( sal_Int32 i=0, len=maData.getLength(); i < len; i++ )
697 {
698 std::cerr << maData[i];
699 }
700
701 std::cerr << "\nPostponed: ";
702 for ( sal_Int32 i=0, len=maPostponed.getLength(); i < len; i++ )
703 {
704 std::cerr << maPostponed[i];
705 }
706
707 std::cerr << "\n";
708 }
709#endif
710
711 void FastSaxSerializer::ForMerge::prepend( const Int8Sequence &rWhat )
712 {
713 merge( maData, rWhat, false );
714 }
715
716 void FastSaxSerializer::ForMerge::append( const css::uno::Sequence<sal_Int8> &rWhat )
717 {
718 merge( maData, rWhat, true );
719 }
720
721 void FastSaxSerializer::ForMerge::postpone( const Int8Sequence &rWhat )
722 {
723 merge( maPostponed, rWhat, true );
724 }
725
726 void FastSaxSerializer::ForMerge::merge( Int8Sequence &rTop, const Int8Sequence &rMerge, bool bAppend )
727 {
728 sal_Int32 nMergeLen = rMerge.getLength();
729 if ( nMergeLen <= 0 )
730 return;
731
732 sal_Int32 nTopLen = rTop.getLength();
733
734 rTop.realloc( nTopLen + nMergeLen );
735 if ( bAppend )
736 {
737 // append the rMerge to the rTop
738 memcpy( rTop.getArray() + nTopLen, rMerge.getConstArray(), nMergeLen );
739 }
740 else
741 {
742 // prepend the rMerge to the rTop
743 memmove( rTop.getArray() + nMergeLen, rTop.getConstArray(), nTopLen );
744 memcpy( rTop.getArray(), rMerge.getConstArray(), nMergeLen );
745 }
746 }
747
748 void FastSaxSerializer::ForMerge::resetData( )
749 {
750 maData = Int8Sequence();
751 }
752
753 void FastSaxSerializer::ForSort::setCurrentElement( sal_Int32 nElement )
754 {
755 vector< sal_Int32 > aOrder( comphelper::sequenceToContainer<vector<sal_Int32> >(maOrder) );
756 if( std::find( aOrder.begin(), aOrder.end(), nElement ) != aOrder.end() )
757 {
758 mnCurrentElement = nElement;
759 if ( maData.find( nElement ) == maData.end() )
760 maData[ nElement ] = Int8Sequence();
761 }
762 }
763
764 void FastSaxSerializer::ForSort::prepend( const Int8Sequence &rWhat )
765 {
766 append( rWhat );
767 }
768
769 void FastSaxSerializer::ForSort::append( const css::uno::Sequence<sal_Int8> &rWhat )
770 {
771 merge( maData[mnCurrentElement], rWhat, true );
772 }
773
774 void FastSaxSerializer::ForSort::sort()
775 {
776 // Clear the ForMerge data to avoid duplicate items
777 resetData();
778
779 // Sort it all
780 std::map< sal_Int32, Int8Sequence >::iterator iter;
781 for ( const auto nIndex : std::as_const(maOrder) )
782 {
783 iter = maData.find( nIndex );
784 if ( iter != maData.end() )
785 ForMerge::append( iter->second );
786 }
787 }
788
789 FastSaxSerializer::Int8Sequence& FastSaxSerializer::ForSort::getData()
790 {
791 sort( );
792 return ForMerge::getData();
793 }
794
795#if OSL_DEBUG_LEVEL1 > 0
796 void FastSaxSerializer::ForSort::print( )
797 {
798 for ( const auto& [rElement, rData] : maData )
799 {
800 std::cerr << "pair: " << rElement;
801 for ( sal_Int32 i=0, len=rData.getLength(); i < len; ++i )
802 std::cerr << rData[i];
803 std::cerr << "\n";
804 }
805
806 sort( );
807 ForMerge::print();
808 }
809#endif
810
811} // namespace sax_fastparser
812
813/* vim:set shiftwidth=4 softtabstop=4 expandtab: */