Coverage Report

Created: 2026-07-10 11:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/tools/source/xml/XmlWriter.cxx
Line
Count
Source
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
10
#include <tools/stream.hxx>
11
#include <tools/XmlWriter.hxx>
12
13
#include <libxml/xmlwriter.h>
14
15
namespace tools
16
{
17
namespace
18
{
19
int funcWriteCallback(void* pContext, const char* sBuffer, int nLen)
20
4.16k
{
21
4.16k
    SvStream* pStream = static_cast<SvStream*>(pContext);
22
4.16k
    return static_cast<int>(pStream->WriteBytes(sBuffer, nLen));
23
4.16k
}
24
25
int funcCloseCallback(void* pContext)
26
4.16k
{
27
4.16k
    SvStream* pStream = static_cast<SvStream*>(pContext);
28
4.16k
    pStream->Flush();
29
4.16k
    return 0; // 0 or -1 in case of error
30
4.16k
}
31
32
template <typename T>
33
requires(sizeof(T) == sizeof(char)) void attributeBase64_impl(xmlTextWriterPtr writer,
34
                                                              const char* name, const T* value,
35
                                                              int size)
36
0
{
37
0
    (void)xmlTextWriterStartAttribute(writer, BAD_CAST(name));
38
0
    (void)xmlTextWriterWriteBase64(writer, reinterpret_cast<const char*>(value), 0, size);
39
0
    (void)xmlTextWriterEndAttribute(writer);
40
0
}
Unexecuted instantiation: XmlWriter.cxx:_ZN5tools12_GLOBAL__N_120attributeBase64_implIhQeqstT_Lm1EEEvP14_xmlTextWriterPKcPKS2_i
Unexecuted instantiation: XmlWriter.cxx:_ZN5tools12_GLOBAL__N_120attributeBase64_implIcQeqstT_Lm1EEEvP14_xmlTextWriterPKcPKS2_i
41
} // end anonymous namespace
42
43
struct XmlWriterImpl
44
{
45
    SvStream* mpStream = nullptr;
46
    xmlTextWriterPtr mpWriter = nullptr;
47
    bool mbWriteXmlHeader = true;
48
    bool mbExternalXmlWriter = false;
49
50
    XmlWriterImpl(SvStream* pStream)
51
4.16k
        : mpStream(pStream)
52
4.16k
    {
53
4.16k
    }
54
55
    XmlWriterImpl(xmlTextWriterPtr pWriter)
56
0
        : mpWriter(pWriter)
57
0
        , mbWriteXmlHeader(false)
58
0
        , mbExternalXmlWriter(true)
59
0
    {
60
0
    }
61
};
62
63
XmlWriter::XmlWriter(SvStream* pStream)
64
4.16k
    : mpImpl(std::make_unique<XmlWriterImpl>(pStream))
65
4.16k
{
66
4.16k
}
67
68
XmlWriter::XmlWriter(xmlTextWriterPtr pWriter)
69
0
    : mpImpl(std::make_unique<XmlWriterImpl>(pWriter))
70
0
{
71
0
}
72
73
XmlWriter::~XmlWriter()
74
4.16k
{
75
4.16k
    if (mpImpl)
76
4.16k
        endDocument();
77
4.16k
}
78
79
bool XmlWriter::startDocument(sal_Int32 nIndent, bool bWriteXmlHeader)
80
4.16k
{
81
4.16k
    if (mpImpl->mpWriter)
82
0
        return false;
83
84
4.16k
    mpImpl->mbWriteXmlHeader = bWriteXmlHeader;
85
4.16k
    xmlCharEncodingHandlerPtr pEncodingHandler = xmlGetCharEncodingHandler(XML_CHAR_ENCODING_UTF8);
86
4.16k
    xmlOutputBufferPtr xmlOutBuffer = xmlOutputBufferCreateIO(funcWriteCallback, funcCloseCallback,
87
4.16k
                                                              mpImpl->mpStream, pEncodingHandler);
88
4.16k
    mpImpl->mpWriter = xmlNewTextWriter(xmlOutBuffer);
89
4.16k
    if (!mpImpl->mpWriter)
90
0
        return false;
91
4.16k
    xmlTextWriterSetIndent(mpImpl->mpWriter, nIndent);
92
4.16k
    if (mpImpl->mbWriteXmlHeader)
93
0
        (void)xmlTextWriterStartDocument(mpImpl->mpWriter, nullptr, "UTF-8", nullptr);
94
95
4.16k
    return true;
96
4.16k
}
97
98
void XmlWriter::endDocument()
99
8.32k
{
100
8.32k
    if (!mpImpl->mpWriter || mpImpl->mbExternalXmlWriter)
101
4.16k
        return;
102
103
4.16k
    if (mpImpl->mbWriteXmlHeader)
104
0
        (void)xmlTextWriterEndDocument(mpImpl->mpWriter);
105
4.16k
    xmlFreeTextWriter(mpImpl->mpWriter);
106
4.16k
    mpImpl->mpWriter = nullptr;
107
4.16k
}
108
109
void XmlWriter::startElement(const OString& sPrefix, const OString& sName,
110
                             const OString& sNamespaceUri)
111
8.32k
{
112
8.32k
    xmlChar* xmlName = BAD_CAST(sName.getStr());
113
8.32k
    xmlChar* xmlPrefix = nullptr;
114
8.32k
    xmlChar* xmlNamespaceUri = nullptr;
115
8.32k
    if (!sPrefix.isEmpty())
116
8.32k
        xmlPrefix = BAD_CAST(sPrefix.getStr());
117
8.32k
    if (!sNamespaceUri.isEmpty())
118
8.32k
        xmlNamespaceUri = BAD_CAST(sNamespaceUri.getStr());
119
120
8.32k
    (void)xmlTextWriterStartElementNS(mpImpl->mpWriter, xmlPrefix, xmlName, xmlNamespaceUri);
121
8.32k
}
122
123
void XmlWriter::startElement(const char* pName)
124
35.6k
{
125
35.6k
    xmlChar* xmlName = BAD_CAST(pName);
126
35.6k
    (void)xmlTextWriterStartElement(mpImpl->mpWriter, xmlName);
127
35.6k
}
128
129
43.9k
void XmlWriter::endElement() { (void)xmlTextWriterEndElement(mpImpl->mpWriter); }
130
131
void XmlWriter::attributeBase64(const char* pName, std::vector<sal_uInt8> const& rValueInBytes)
132
0
{
133
0
    attributeBase64_impl(mpImpl->mpWriter, pName, rValueInBytes.data(), rValueInBytes.size());
134
0
}
135
136
void XmlWriter::attributeBase64(const char* pName, std::vector<char> const& rValueInBytes)
137
0
{
138
0
    attributeBase64_impl(mpImpl->mpWriter, pName, rValueInBytes.data(), rValueInBytes.size());
139
0
}
140
141
void XmlWriter::attribute(const char* name, std::string_view value)
142
18.6k
{
143
18.6k
    xmlChar* xmlName = BAD_CAST(name);
144
18.6k
    (void)xmlTextWriterWriteFormatAttribute(mpImpl->mpWriter, xmlName, "%.*s", int(value.size()),
145
18.6k
                                            value.data());
146
18.6k
}
147
148
void XmlWriter::attribute(const char* name, std::u16string_view value)
149
0
{
150
0
    attribute(name, OUStringToOString(value, RTL_TEXTENCODING_UTF8));
151
0
}
152
153
void XmlWriter::attribute(const char* name, const sal_Int64 aNumber)
154
0
{
155
0
    attribute(name, OString::number(aNumber));
156
0
}
157
158
void XmlWriter::attribute(const char* name, const double aNumber)
159
0
{
160
0
    attribute(name, OString::number(aNumber));
161
0
}
162
163
void XmlWriter::content(std::string_view value)
164
23.3k
{
165
23.3k
    (void)xmlTextWriterWriteFormatString(mpImpl->mpWriter, "%.*s", int(value.size()), value.data());
166
23.3k
}
167
168
void XmlWriter::content(std::u16string_view sValue)
169
0
{
170
0
    content(OUStringToOString(sValue, RTL_TEXTENCODING_UTF8));
171
0
}
172
173
void XmlWriter::element(const char* sName)
174
0
{
175
0
    startElement(sName);
176
0
    endElement();
177
0
}
178
179
} // end tools namespace
180
181
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */