Use COMReference to handle COM pointers in CreateShortcut
[LibreOffice.git] / unoidl / source / unoidl.cxx
blobacf984613420b86c7a87609fdf204aee9d67c051
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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 */
10 #include <sal/config.h>
11 #include <sal/log.hxx>
13 #include <set>
14 #include <utility>
15 #include <vector>
17 #include <config_fuzzers.h>
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>
26 #if !ENABLE_FUZZERS
27 #include "legacyprovider.hxx"
28 #endif
29 #include "sourcefileprovider.hxx"
30 #include "sourcetreeprovider.hxx"
31 #include "unoidlprovider.hxx"
33 namespace unoidl {
35 namespace {
37 class AggregatingModule: public ModuleEntity {
38 public:
39 AggregatingModule(
40 std::vector< rtl::Reference< Provider > >&& providers,
41 OUString name):
42 providers_(std::move(providers)), name_(std::move(name))
45 private:
46 virtual ~AggregatingModule() noexcept override {}
48 virtual std::vector< OUString > getMemberNames() const override;
50 virtual rtl::Reference< MapCursor > createCursor() const override;
52 std::vector< rtl::Reference< Provider > > providers_;
53 OUString name_;
56 std::vector< OUString > AggregatingModule::getMemberNames() const {
57 std::set< OUString > names;
58 for (auto & i: providers_) {
59 rtl::Reference< Entity > ent(i->findEntity(name_));
60 if (ent.is() && ent->getSort() == Entity::SORT_MODULE) {
61 std::vector< OUString > ns(
62 static_cast< ModuleEntity * >(ent.get())->getMemberNames());
63 names.insert(ns.begin(), ns.end());
66 return std::vector< OUString >(names.begin(), names.end());
69 class AggregatingCursor: public MapCursor {
70 public:
71 AggregatingCursor(
72 std::vector< rtl::Reference< Provider > >&& providers,
73 OUString name):
74 providers_(std::move(providers)), name_(std::move(name)), iterator_(providers_.begin())
75 { findCursor(); }
77 private:
78 virtual ~AggregatingCursor() noexcept override {}
80 virtual rtl::Reference< Entity > getNext(OUString * name) override;
82 void findCursor();
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_;
91 rtl::Reference< Entity > AggregatingCursor::getNext(OUString * name) {
92 while (cursor_.is()) {
93 OUString n;
94 rtl::Reference< Entity > ent(cursor_->getNext(&n));
95 if (ent.is()) {
96 if (seen_.insert(n).second) {
97 if (name != nullptr) {
98 *name = n;
100 return ent->getSort() == Entity::SORT_MODULE
101 ? new AggregatingModule(
102 std::vector(providers_), (name_.isEmpty() ? name_ : name_ + ".") + n)
103 : ent;
105 } else {
106 cursor_.clear();
107 findCursor();
110 return rtl::Reference< Entity >();
113 void AggregatingCursor::findCursor() {
114 for (; !cursor_.is() && iterator_ != providers_.end(); ++iterator_) {
115 if (name_.isEmpty()) {
116 cursor_ = (*iterator_)->createRootCursor();
117 } else {
118 rtl::Reference< Entity > ent((*iterator_)->findEntity(name_));
119 if (ent.is() && ent->getSort() == Entity::SORT_MODULE) {
120 cursor_ = static_cast< ModuleEntity * >(ent.get())->
121 createCursor();
127 rtl::Reference< MapCursor > AggregatingModule::createCursor() const {
128 return new AggregatingCursor(std::vector(providers_), name_);
133 NoSuchFileException::~NoSuchFileException() noexcept {}
135 FileFormatException::~FileFormatException() noexcept {}
137 Entity::~Entity() noexcept {}
139 MapCursor::~MapCursor() noexcept {}
141 ModuleEntity::~ModuleEntity() noexcept {}
143 PublishableEntity::~PublishableEntity() noexcept {}
145 EnumTypeEntity::~EnumTypeEntity() noexcept {}
147 PlainStructTypeEntity::~PlainStructTypeEntity() noexcept {}
149 PolymorphicStructTypeTemplateEntity::~PolymorphicStructTypeTemplateEntity()
150 noexcept
153 ExceptionTypeEntity::~ExceptionTypeEntity() noexcept {}
155 InterfaceTypeEntity::~InterfaceTypeEntity() noexcept {}
157 TypedefEntity::~TypedefEntity() noexcept {}
159 ConstantGroupEntity::~ConstantGroupEntity() noexcept {}
161 SingleInterfaceBasedServiceEntity::~SingleInterfaceBasedServiceEntity() noexcept
164 AccumulationBasedServiceEntity::~AccumulationBasedServiceEntity() noexcept {}
166 InterfaceBasedSingletonEntity::~InterfaceBasedSingletonEntity() noexcept {}
168 ServiceBasedSingletonEntity::~ServiceBasedSingletonEntity() noexcept {}
170 Provider::~Provider() noexcept {}
172 rtl::Reference< Provider > Manager::addProvider(OUString const & uri) {
173 rtl::Reference< Provider > p(loadProvider(uri));
174 assert(p.is());
176 osl::MutexGuard g(mutex_);
177 providers_.push_back(p);
179 return p;
182 rtl::Reference< Entity > Manager::findEntity(OUString const & name) const {
183 //TODO: caching? (here or in cppuhelper::TypeManager?)
184 osl::MutexGuard g(mutex_);
185 for (auto & i: providers_) {
186 rtl::Reference< Entity > ent(i->findEntity(name));
187 if (ent.is()) {
188 return ent;
191 return rtl::Reference< Entity >();
194 rtl::Reference< MapCursor > Manager::createCursor(OUString const & name)
195 const
197 return new AggregatingCursor(std::vector(providers_), name);
200 Manager::~Manager() noexcept {}
202 rtl::Reference< Provider > Manager::loadProvider(OUString const & uri) {
203 osl::DirectoryItem item;
204 if (osl::DirectoryItem::get(uri, item) == osl::FileBase::E_None) {
205 osl::FileStatus status(osl_FileStatus_Mask_Type);
206 if (item.getFileStatus(status) == osl::FileBase::E_None
207 && status.getFileType() == osl::FileStatus::Directory)
209 return new detail::SourceTreeProvider(*this, uri);
212 if (uri.endsWith(".idl")) {
213 return new detail::SourceFileProvider(this, uri);
215 try {
216 return new detail::UnoidlProvider(uri);
217 } 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 (void)e;
226 return nullptr;
227 #endif
233 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */