Coverage Report

Created: 2026-06-30 11:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/unoxml/source/dom/characterdata.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
 * 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 "characterdata.hxx"
21
#include "document.hxx"
22
#include <eventdispatcher.hxx>
23
24
#include <string.h>
25
26
#include <memory>
27
28
#include <osl/diagnose.h>
29
30
#include <com/sun/star/xml/dom/DOMException.hpp>
31
#include <com/sun/star/xml/dom/events/XDocumentEvent.hpp>
32
#include <com/sun/star/xml/dom/events/XMutationEvent.hpp>
33
34
using namespace css::uno;
35
using namespace css::xml::dom;
36
using namespace css::xml::dom::events;
37
38
namespace DOM
39
{
40
41
    CCharacterData::CCharacterData(
42
            CDocument const& rDocument, ::osl::Mutex const& rMutex,
43
            NodeType const& reNodeType, xmlNodePtr const& rpNode)
44
1.13M
        : CCharacterData_Base(rDocument, rMutex, reNodeType, rpNode)
45
1.13M
    {
46
1.13M
    }
47
48
    void CCharacterData::dispatchEvent_Impl(::osl::ClearableMutexGuard& guard,
49
            OUString const& prevValue, OUString const& newValue)
50
8.98k
    {
51
8.98k
        CDocument& rDocument(GetOwnerDocument());
52
8.98k
        if (!rDocument.GetEventDispatcher().hasListeners())
53
8.98k
            return;
54
55
0
        guard.clear(); // release mutex before calling event handlers
56
57
0
        Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
58
0
        Reference< XMutationEvent > event(docevent->createEvent(
59
0
            u"DOMCharacterDataModified"_ustr), UNO_QUERY);
60
0
        event->initMutationEvent(
61
0
                u"DOMCharacterDataModified"_ustr,
62
0
                true, false, Reference< XNode >(),
63
0
                prevValue, newValue, OUString(), AttrChangeType(0) );
64
0
        dispatchEvent(event);
65
0
        dispatchSubtreeModified();
66
0
    }
67
68
    /**
69
    Append the string to the end of the character data of the node.
70
    */
71
    void SAL_CALL CCharacterData::appendData(const OUString& arg)
72
0
    {
73
0
        ::osl::ClearableMutexGuard guard(m_rMutex);
74
75
0
        if (m_aNodePtr != nullptr)
76
0
        {
77
0
            OUString oldValue(reinterpret_cast<char*>(m_aNodePtr->content), strlen(reinterpret_cast<char*>(m_aNodePtr->content)), RTL_TEXTENCODING_UTF8);
78
0
            xmlNodeAddContent(m_aNodePtr, reinterpret_cast<const xmlChar*>(OUStringToOString(arg, RTL_TEXTENCODING_UTF8).getStr()));
79
0
            OUString newValue(reinterpret_cast<char*>(m_aNodePtr->content), strlen(reinterpret_cast<char*>(m_aNodePtr->content)), RTL_TEXTENCODING_UTF8);
80
0
            dispatchEvent_Impl(guard, oldValue, newValue);
81
0
        }
82
0
    }
83
84
    /**
85
    Remove a range of 16-bit units from the node.
86
    */
87
    void SAL_CALL CCharacterData::deleteData(sal_Int32 offset, sal_Int32 count)
88
0
    {
89
0
        ::osl::ClearableMutexGuard guard(m_rMutex);
90
91
0
        if (m_aNodePtr == nullptr)
92
0
            return;
93
94
        // get current data
95
0
        std::shared_ptr<xmlChar const> const pContent(
96
0
            xmlNodeGetContent(m_aNodePtr), xmlFree);
97
0
        std::string_view aData(reinterpret_cast<char const*>(pContent.get()));
98
0
        OUString tmp(OStringToOUString(aData, RTL_TEXTENCODING_UTF8));
99
0
        if (offset > tmp.getLength() || offset < 0 || count < 0) {
100
0
            DOMException e;
101
0
            e.Code = DOMExceptionType_INDEX_SIZE_ERR;
102
0
            throw e;
103
0
        }
104
0
        if ((offset+count) > tmp.getLength())
105
0
            count = tmp.getLength() - offset;
106
107
0
        OUString tmp2 = OUString::Concat(tmp.subView(0, offset)) + tmp.subView(offset+count);
108
0
        OUString oldValue(reinterpret_cast<char*>(m_aNodePtr->content), strlen(reinterpret_cast<char*>(m_aNodePtr->content)), RTL_TEXTENCODING_UTF8);
109
0
        xmlNodeSetContent(m_aNodePtr, reinterpret_cast<const xmlChar*>(OUStringToOString(tmp2, RTL_TEXTENCODING_UTF8).getStr()));
110
0
        OUString newValue(reinterpret_cast<char*>(m_aNodePtr->content), strlen(reinterpret_cast<char*>(m_aNodePtr->content)), RTL_TEXTENCODING_UTF8);
111
112
0
        dispatchEvent_Impl(guard, oldValue, newValue);
113
114
0
    }
115
116
117
    /**
118
    Return the character data of the node that implements this interface.
119
    */
120
    OUString SAL_CALL CCharacterData::getData()
121
339k
    {
122
339k
        ::osl::MutexGuard const g(m_rMutex);
123
124
339k
        OUString aData;
125
339k
        if (m_aNodePtr != nullptr)
126
339k
        {
127
339k
            OSL_ENSURE(m_aNodePtr->content, "character data node with NULL content, please inform lars.oppermann@sun.com!");
128
339k
            if (m_aNodePtr->content != nullptr)
129
339k
            {
130
339k
                aData = OUString(reinterpret_cast<char*>(m_aNodePtr->content), strlen(reinterpret_cast<char*>(m_aNodePtr->content)),  RTL_TEXTENCODING_UTF8);
131
339k
            }
132
339k
        }
133
339k
        return aData;
134
339k
    }
135
136
    /**
137
    The number of 16-bit units that are available through data and the
138
    substringData method below.
139
    */
140
    sal_Int32 SAL_CALL CCharacterData::getLength()
141
0
    {
142
0
        ::osl::MutexGuard const g(m_rMutex);
143
144
0
        sal_Int32 length = 0;
145
0
        if (m_aNodePtr != nullptr)
146
0
        {
147
0
             OUString aData(reinterpret_cast<char*>(m_aNodePtr->content), strlen(reinterpret_cast<char*>(m_aNodePtr->content)),  RTL_TEXTENCODING_UTF8);
148
0
             length = aData.getLength();
149
0
        }
150
0
        return length;
151
0
    }
152
153
    /**
154
    Insert a string at the specified 16-bit unit offset.
155
    */
156
    void SAL_CALL CCharacterData::insertData(sal_Int32 offset, const OUString& arg)
157
0
    {
158
0
        ::osl::ClearableMutexGuard guard(m_rMutex);
159
160
0
        if (m_aNodePtr == nullptr)
161
0
            return;
162
163
        // get current data
164
0
        std::shared_ptr<xmlChar const> const pContent(
165
0
            xmlNodeGetContent(m_aNodePtr), xmlFree);
166
0
        std::string_view aData(reinterpret_cast<char const*>(pContent.get()));
167
0
        OUString tmp(OStringToOUString(aData, RTL_TEXTENCODING_UTF8));
168
0
        if (offset > tmp.getLength() || offset < 0) {
169
0
            DOMException e;
170
0
            e.Code = DOMExceptionType_INDEX_SIZE_ERR;
171
0
            throw e;
172
0
        }
173
174
0
        OUString tmp2 = tmp.subView(0, offset) +
175
0
            arg +
176
0
            tmp.subView(offset);
177
0
        OUString oldValue(reinterpret_cast<char*>(m_aNodePtr->content), strlen(reinterpret_cast<char*>(m_aNodePtr->content)), RTL_TEXTENCODING_UTF8);
178
0
        xmlNodeSetContent(m_aNodePtr, reinterpret_cast<const xmlChar*>(OUStringToOString(tmp2, RTL_TEXTENCODING_UTF8).getStr()));
179
0
        OUString newValue(reinterpret_cast<char*>(m_aNodePtr->content), strlen(reinterpret_cast<char*>(m_aNodePtr->content)), RTL_TEXTENCODING_UTF8);
180
181
0
        dispatchEvent_Impl(guard, oldValue, newValue);
182
183
0
    }
184
185
186
    /**
187
    Replace the characters starting at the specified 16-bit unit offset
188
    with the specified string.
189
    */
190
    void SAL_CALL CCharacterData::replaceData(sal_Int32 offset, sal_Int32 count, const OUString& arg)
191
0
    {
192
0
        ::osl::ClearableMutexGuard guard(m_rMutex);
193
194
0
        if (m_aNodePtr == nullptr)
195
0
            return;
196
197
        // get current data
198
0
        std::shared_ptr<xmlChar const> const pContent(
199
0
            xmlNodeGetContent(m_aNodePtr), xmlFree);
200
0
        std::string_view aData(reinterpret_cast<char const*>(pContent.get()));
201
0
        OUString tmp(OStringToOUString(aData, RTL_TEXTENCODING_UTF8));
202
0
        if (offset > tmp.getLength() || offset < 0 || count < 0){
203
0
            DOMException e;
204
0
            e.Code = DOMExceptionType_INDEX_SIZE_ERR;
205
0
            throw e;
206
0
        }
207
0
        if ((offset+count) > tmp.getLength())
208
0
            count = tmp.getLength() - offset;
209
210
0
        OUString tmp2 = tmp.subView(0, offset) +
211
0
            arg +
212
0
            tmp.subView(offset+count);
213
0
        OUString oldValue(reinterpret_cast<char*>(m_aNodePtr->content), strlen(reinterpret_cast<char*>(m_aNodePtr->content)), RTL_TEXTENCODING_UTF8);
214
0
        xmlNodeSetContent(m_aNodePtr, reinterpret_cast<const xmlChar*>(OUStringToOString(tmp2, RTL_TEXTENCODING_UTF8).getStr()));
215
0
        OUString newValue(reinterpret_cast<char*>(m_aNodePtr->content), strlen(reinterpret_cast<char*>(m_aNodePtr->content)), RTL_TEXTENCODING_UTF8);
216
217
0
        dispatchEvent_Impl(guard, oldValue, newValue);
218
219
0
    }
220
221
    /**
222
    Set the character data of the node that implements this interface.
223
    */
224
    void SAL_CALL CCharacterData::setData(const OUString& data)
225
8.98k
    {
226
8.98k
        ::osl::ClearableMutexGuard guard(m_rMutex);
227
228
8.98k
        if (m_aNodePtr != nullptr)
229
8.98k
        {
230
8.98k
            OUString oldValue(reinterpret_cast<char*>(m_aNodePtr->content), strlen(reinterpret_cast<char*>(m_aNodePtr->content)), RTL_TEXTENCODING_UTF8);
231
8.98k
            xmlNodeSetContent(m_aNodePtr, reinterpret_cast<const xmlChar*>(OUStringToOString(data, RTL_TEXTENCODING_UTF8).getStr()));
232
8.98k
            OUString newValue(reinterpret_cast<char*>(m_aNodePtr->content), strlen(reinterpret_cast<char*>(m_aNodePtr->content)), RTL_TEXTENCODING_UTF8);
233
234
8.98k
            dispatchEvent_Impl(guard, oldValue, newValue);
235
8.98k
        }
236
8.98k
    }
237
238
    /**
239
    Extracts a range of data from the node.
240
    */
241
    OUString SAL_CALL CCharacterData::subStringData(sal_Int32 offset, sal_Int32 count)
242
0
    {
243
0
        ::osl::MutexGuard const g(m_rMutex);
244
245
0
        OUString aStr;
246
0
        if (m_aNodePtr != nullptr)
247
0
        {
248
            // get current data
249
0
            std::shared_ptr<xmlChar const> const pContent(
250
0
                xmlNodeGetContent(m_aNodePtr), xmlFree);
251
0
            std::string_view aData(reinterpret_cast<char const*>(pContent.get()));
252
0
            OUString tmp(OStringToOUString(aData, RTL_TEXTENCODING_UTF8));
253
0
            if (offset > tmp.getLength() || offset < 0 || count < 0) {
254
0
                DOMException e;
255
0
                e.Code = DOMExceptionType_INDEX_SIZE_ERR;
256
0
                throw e;
257
0
            }
258
0
            aStr = tmp.copy(offset, count);
259
0
        }
260
0
        return aStr;
261
0
    }
262
263
264
} // namespace DOM
265
266
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */