Coverage Report

Created: 2025-07-07 10:01

/src/libreoffice/tools/source/xml/XmlWriter.cxx
Line
Count
Source (jump to first uncovered line)
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
8.47k
{
21
8.47k
    SvStream* pStream = static_cast<SvStream*>(pContext);
22
8.47k
    return static_cast<int>(pStream->WriteBytes(sBuffer, nLen));
23
8.47k
}
24
25
int funcCloseCallback(void* pContext)
26
8.47k
{
27
8.47k
    SvStream* pStream = static_cast<SvStream*>(pContext);
28
8.47k
    pStream->Flush();
29
8.47k
    return 0; // 0 or -1 in case of error
30
8.47k
}
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
    XmlWriterImpl(SvStream* pStream)
46
8.47k
        : mpStream(pStream)
47
8.47k
        , mpWriter(nullptr)
48
8.47k
        , mbWriteXmlHeader(true)
49
8.47k
    {
50
8.47k
    }
51
52
    SvStream* mpStream;
53
    xmlTextWriterPtr mpWriter;
54
    bool mbWriteXmlHeader;
55
};
56
57
XmlWriter::XmlWriter(SvStream* pStream)
58
8.47k
    : mpImpl(std::make_unique<XmlWriterImpl>(pStream))
59
8.47k
{
60
8.47k
}
61
62
XmlWriter::~XmlWriter()
63
8.47k
{
64
8.47k
    if (mpImpl && mpImpl->mpWriter != nullptr)
65
0
        endDocument();
66
8.47k
}
67
68
bool XmlWriter::startDocument(sal_Int32 nIndent, bool bWriteXmlHeader)
69
8.47k
{
70
8.47k
    mpImpl->mbWriteXmlHeader = bWriteXmlHeader;
71
8.47k
    xmlCharEncodingHandlerPtr pEncodingHandler = xmlGetCharEncodingHandler(XML_CHAR_ENCODING_UTF8);
72
8.47k
    xmlOutputBufferPtr xmlOutBuffer = xmlOutputBufferCreateIO(funcWriteCallback, funcCloseCallback,
73
8.47k
                                                              mpImpl->mpStream, pEncodingHandler);
74
8.47k
    mpImpl->mpWriter = xmlNewTextWriter(xmlOutBuffer);
75
8.47k
    if (mpImpl->mpWriter == nullptr)
76
0
        return false;
77
8.47k
    xmlTextWriterSetIndent(mpImpl->mpWriter, nIndent);
78
8.47k
    if (mpImpl->mbWriteXmlHeader)
79
0
        (void)xmlTextWriterStartDocument(mpImpl->mpWriter, nullptr, "UTF-8", nullptr);
80
8.47k
    return true;
81
8.47k
}
82
83
void XmlWriter::endDocument()
84
8.47k
{
85
8.47k
    if (mpImpl->mbWriteXmlHeader)
86
0
        (void)xmlTextWriterEndDocument(mpImpl->mpWriter);
87
8.47k
    xmlFreeTextWriter(mpImpl->mpWriter);
88
8.47k
    mpImpl->mpWriter = nullptr;
89
8.47k
}
90
91
void XmlWriter::startElement(const OString& sPrefix, const OString& sName,
92
                             const OString& sNamespaceUri)
93
16.9k
{
94
16.9k
    xmlChar* xmlName = BAD_CAST(sName.getStr());
95
16.9k
    xmlChar* xmlPrefix = nullptr;
96
16.9k
    xmlChar* xmlNamespaceUri = nullptr;
97
16.9k
    if (!sPrefix.isEmpty())
98
16.9k
        xmlPrefix = BAD_CAST(sPrefix.getStr());
99
16.9k
    if (!sNamespaceUri.isEmpty())
100
16.9k
        xmlNamespaceUri = BAD_CAST(sNamespaceUri.getStr());
101
102
16.9k
    (void)xmlTextWriterStartElementNS(mpImpl->mpWriter, xmlPrefix, xmlName, xmlNamespaceUri);
103
16.9k
}
104
105
void XmlWriter::startElement(const char* pName)
106
71.0k
{
107
71.0k
    xmlChar* xmlName = BAD_CAST(pName);
108
71.0k
    (void)xmlTextWriterStartElement(mpImpl->mpWriter, xmlName);
109
71.0k
}
110
111
88.0k
void XmlWriter::endElement() { (void)xmlTextWriterEndElement(mpImpl->mpWriter); }
112
113
void XmlWriter::attributeBase64(const char* pName, std::vector<sal_uInt8> const& rValueInBytes)
114
0
{
115
0
    attributeBase64_impl(mpImpl->mpWriter, pName, rValueInBytes.data(), rValueInBytes.size());
116
0
}
117
118
void XmlWriter::attributeBase64(const char* pName, std::vector<char> const& rValueInBytes)
119
0
{
120
0
    attributeBase64_impl(mpImpl->mpWriter, pName, rValueInBytes.data(), rValueInBytes.size());
121
0
}
122
123
void XmlWriter::attribute(const char* name, const OString& value)
124
37.6k
{
125
37.6k
    xmlChar* xmlName = BAD_CAST(name);
126
37.6k
    xmlChar* xmlValue = BAD_CAST(value.getStr());
127
37.6k
    (void)xmlTextWriterWriteAttribute(mpImpl->mpWriter, xmlName, xmlValue);
128
37.6k
}
129
130
void XmlWriter::attribute(const char* name, std::u16string_view value)
131
0
{
132
0
    attribute(name, OUStringToOString(value, RTL_TEXTENCODING_UTF8));
133
0
}
134
135
void XmlWriter::attribute(const char* name, const sal_Int64 aNumber)
136
0
{
137
0
    attribute(name, OString::number(aNumber));
138
0
}
139
140
void XmlWriter::attributeDouble(const char* name, const double aNumber)
141
0
{
142
0
    attribute(name, OString::number(aNumber));
143
0
}
144
145
void XmlWriter::content(const OString& sValue)
146
47.4k
{
147
47.4k
    xmlChar* xmlValue = BAD_CAST(sValue.getStr());
148
47.4k
    (void)xmlTextWriterWriteString(mpImpl->mpWriter, xmlValue);
149
47.4k
}
150
151
void XmlWriter::content(std::u16string_view sValue)
152
0
{
153
0
    content(OUStringToOString(sValue, RTL_TEXTENCODING_UTF8));
154
0
}
155
156
void XmlWriter::element(const char* sName)
157
0
{
158
0
    startElement(sName);
159
0
    endElement();
160
0
}
161
162
} // end tools namespace
163
164
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */