Coverage Report

Created: 2025-12-31 10:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/unoidl/source/unoidl.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 <sal/config.h>
11
#include <sal/log.hxx>
12
13
#include <set>
14
#include <utility>
15
#include <vector>
16
17
#include <config_fuzzers.h>
18
19
#include <osl/file.h>
20
#include <osl/file.hxx>
21
#include <osl/mutex.hxx>
22
#include <rtl/ref.hxx>
23
#include <rtl/ustring.hxx>
24
#include <unoidl/unoidl.hxx>
25
26
#if !ENABLE_FUZZERS
27
#include "legacyprovider.hxx"
28
#endif
29
#include "sourcefileprovider.hxx"
30
#include "sourcetreeprovider.hxx"
31
#include "unoidlprovider.hxx"
32
33
namespace unoidl {
34
35
namespace {
36
37
class AggregatingModule: public ModuleEntity {
38
public:
39
    AggregatingModule(
40
        std::vector< rtl::Reference< Provider > >&& providers,
41
        OUString name):
42
0
        providers_(std::move(providers)), name_(std::move(name))
43
0
    {}
44
45
private:
46
0
    virtual ~AggregatingModule() noexcept override {}
47
48
    virtual std::vector< OUString > getMemberNames() const override;
49
50
    virtual rtl::Reference< MapCursor > createCursor() const override;
51
52
    std::vector< rtl::Reference< Provider > > providers_;
53
    OUString name_;
54
};
55
56
0
std::vector< OUString > AggregatingModule::getMemberNames() const {
57
0
    std::set< OUString > names;
58
0
    for (auto & i: providers_) {
59
0
        rtl::Reference< Entity > ent(i->findEntity(name_));
60
0
        if (ent.is() && ent->getSort() == Entity::SORT_MODULE) {
61
0
            std::vector< OUString > ns(
62
0
                static_cast< ModuleEntity * >(ent.get())->getMemberNames());
63
0
            names.insert(ns.begin(), ns.end());
64
0
        }
65
0
    }
66
0
    return std::vector< OUString >(names.begin(), names.end());
67
0
}
68
69
class AggregatingCursor: public MapCursor {
70
public:
71
    AggregatingCursor(
72
        std::vector< rtl::Reference< Provider > >&& providers,
73
        OUString name):
74
0
        providers_(std::move(providers)), name_(std::move(name)), iterator_(providers_.begin())
75
0
    { findCursor(); }
76
77
private:
78
0
    virtual ~AggregatingCursor() noexcept override {}
79
80
    virtual rtl::Reference< Entity > getNext(OUString * name) override;
81
82
    void findCursor();
83
84
    std::vector< rtl::Reference< Provider > > providers_;
85
    OUString name_;
86
    std::vector< rtl::Reference< Provider > >::iterator iterator_;
87
    rtl::Reference< MapCursor > cursor_;
88
    std::set< OUString > seen_;
89
};
90
91
0
rtl::Reference< Entity > AggregatingCursor::getNext(OUString * name) {
92
0
    while (cursor_.is()) {
93
0
        OUString n;
94
0
        rtl::Reference< Entity > ent(cursor_->getNext(&n));
95
0
        if (ent.is()) {
96
0
            if (seen_.insert(n).second) {
97
0
                if (name != nullptr) {
98
0
                    *name = n;
99
0
                }
100
0
                return ent->getSort() == Entity::SORT_MODULE
101
0
                    ? new AggregatingModule(
102
0
                        std::vector(providers_), (name_.isEmpty() ? name_ : name_ + ".") + n)
103
0
                    : ent;
104
0
            }
105
0
        } else {
106
0
            cursor_.clear();
107
0
            findCursor();
108
0
        }
109
0
    }
110
0
    return rtl::Reference< Entity >();
111
0
}
112
113
0
void AggregatingCursor::findCursor() {
114
0
    for (; !cursor_.is() && iterator_ != providers_.end(); ++iterator_) {
115
0
        if (name_.isEmpty()) {
116
0
            cursor_ = (*iterator_)->createRootCursor();
117
0
        } else {
118
0
            rtl::Reference< Entity > ent((*iterator_)->findEntity(name_));
119
0
            if (ent.is() && ent->getSort() == Entity::SORT_MODULE) {
120
0
                cursor_ = static_cast< ModuleEntity * >(ent.get())->
121
0
                    createCursor();
122
0
            }
123
0
        }
124
0
    }
125
0
}
126
127
0
rtl::Reference< MapCursor > AggregatingModule::createCursor() const {
128
0
    return new AggregatingCursor(std::vector(providers_), name_);
129
0
}
130
131
}
132
133
0
NoSuchFileException::~NoSuchFileException() noexcept {}
134
135
0
FileFormatException::~FileFormatException() noexcept {}
136
137
15.2k
Entity::~Entity() noexcept {}
138
139
0
MapCursor::~MapCursor() noexcept {}
140
141
ModuleEntity::~ModuleEntity() noexcept {}
142
143
15.2k
PublishableEntity::~PublishableEntity() noexcept {}
144
145
199
EnumTypeEntity::~EnumTypeEntity() noexcept {}
146
147
851
PlainStructTypeEntity::~PlainStructTypeEntity() noexcept {}
148
149
PolymorphicStructTypeTemplateEntity::~PolymorphicStructTypeTemplateEntity()
150
    noexcept
151
0
{}
152
153
222
ExceptionTypeEntity::~ExceptionTypeEntity() noexcept {}
154
155
13.7k
InterfaceTypeEntity::~InterfaceTypeEntity() noexcept {}
156
157
190
TypedefEntity::~TypedefEntity() noexcept {}
158
159
0
ConstantGroupEntity::~ConstantGroupEntity() noexcept {}
160
161
SingleInterfaceBasedServiceEntity::~SingleInterfaceBasedServiceEntity() noexcept
162
0
{}
163
164
0
AccumulationBasedServiceEntity::~AccumulationBasedServiceEntity() noexcept {}
165
166
0
InterfaceBasedSingletonEntity::~InterfaceBasedSingletonEntity() noexcept {}
167
168
0
ServiceBasedSingletonEntity::~ServiceBasedSingletonEntity() noexcept {}
169
170
0
Provider::~Provider() noexcept {}
171
172
216
rtl::Reference< Provider > Manager::addProvider(OUString const & uri) {
173
216
    rtl::Reference< Provider > p(loadProvider(uri));
174
216
    assert(p.is());
175
216
    {
176
216
        osl::MutexGuard g(mutex_);
177
216
        providers_.push_back(p);
178
216
    }
179
216
    return p;
180
216
}
181
182
15.2k
rtl::Reference< Entity > Manager::findEntity(OUString const & name) const {
183
    //TODO: caching? (here or in cppuhelper::TypeManager?)
184
15.2k
    osl::MutexGuard g(mutex_);
185
20.8k
    for (auto & i: providers_) {
186
20.8k
        rtl::Reference< Entity > ent(i->findEntity(name));
187
20.8k
        if (ent.is()) {
188
15.2k
            return ent;
189
15.2k
        }
190
20.8k
    }
191
0
    return rtl::Reference< Entity >();
192
15.2k
}
193
194
rtl::Reference< MapCursor > Manager::createCursor(OUString const & name)
195
    const
196
0
{
197
0
    return new AggregatingCursor(std::vector(providers_), name);
198
0
}
199
200
0
Manager::~Manager() noexcept {}
201
202
216
rtl::Reference< Provider > Manager::loadProvider(OUString const & uri) {
203
216
    osl::DirectoryItem item;
204
216
    if (osl::DirectoryItem::get(uri, item) == osl::FileBase::E_None) {
205
216
        osl::FileStatus status(osl_FileStatus_Mask_Type);
206
216
        if (item.getFileStatus(status) == osl::FileBase::E_None
207
216
            && status.getFileType() == osl::FileStatus::Directory)
208
0
        {
209
0
            return new detail::SourceTreeProvider(*this, uri);
210
0
        }
211
216
    }
212
216
    if (uri.endsWith(".idl")) {
213
0
        return new detail::SourceFileProvider(this, uri);
214
0
    }
215
216
    try {
216
216
        return new detail::UnoidlProvider(uri);
217
216
    } catch (FileFormatException & e) {
218
#if !ENABLE_FUZZERS
219
        SAL_INFO(
220
            "unoidl",
221
            "FileFormatException \"" << e.getDetail() << "\", retrying <" << uri
222
                << "> as legacy format");
223
        return new detail::LegacyProvider(*this, uri);
224
#else
225
0
        (void)e;
226
0
        return nullptr;
227
0
#endif
228
0
    }
229
216
}
230
231
}
232
233
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */