summaryrefslogtreecommitdiffstats
path: root/unoidl/source/unoidl.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'unoidl/source/unoidl.cxx')
-rw-r--r--unoidl/source/unoidl.cxx224
1 files changed, 224 insertions, 0 deletions
diff --git a/unoidl/source/unoidl.cxx b/unoidl/source/unoidl.cxx
new file mode 100644
index 000000000..2022bcd05
--- /dev/null
+++ b/unoidl/source/unoidl.cxx
@@ -0,0 +1,224 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+#include <sal/log.hxx>
+
+#include <set>
+#include <utility>
+#include <vector>
+
+#include <osl/file.h>
+#include <osl/file.hxx>
+#include <osl/mutex.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/ustring.hxx>
+#include <unoidl/unoidl.hxx>
+
+#include "legacyprovider.hxx"
+#include "sourcefileprovider.hxx"
+#include "sourcetreeprovider.hxx"
+#include "unoidlprovider.hxx"
+
+namespace unoidl {
+
+namespace {
+
+class AggregatingModule: public ModuleEntity {
+public:
+ AggregatingModule(
+ std::vector< rtl::Reference< Provider > >&& providers,
+ OUString name):
+ providers_(std::move(providers)), name_(std::move(name))
+ {}
+
+private:
+ virtual ~AggregatingModule() noexcept override {}
+
+ virtual std::vector< OUString > getMemberNames() const override;
+
+ virtual rtl::Reference< MapCursor > createCursor() const override;
+
+ std::vector< rtl::Reference< Provider > > providers_;
+ OUString name_;
+};
+
+std::vector< OUString > AggregatingModule::getMemberNames() const {
+ std::set< OUString > names;
+ for (auto & i: providers_) {
+ rtl::Reference< Entity > ent(i->findEntity(name_));
+ if (ent.is() && ent->getSort() == Entity::SORT_MODULE) {
+ std::vector< OUString > ns(
+ static_cast< ModuleEntity * >(ent.get())->getMemberNames());
+ names.insert(ns.begin(), ns.end());
+ }
+ }
+ return std::vector< OUString >(names.begin(), names.end());
+}
+
+class AggregatingCursor: public MapCursor {
+public:
+ AggregatingCursor(
+ std::vector< rtl::Reference< Provider > >&& providers,
+ OUString name):
+ providers_(std::move(providers)), name_(std::move(name)), iterator_(providers_.begin())
+ { findCursor(); }
+
+private:
+ virtual ~AggregatingCursor() noexcept override {}
+
+ virtual rtl::Reference< Entity > getNext(OUString * name) override;
+
+ void findCursor();
+
+ std::vector< rtl::Reference< Provider > > providers_;
+ OUString name_;
+ std::vector< rtl::Reference< Provider > >::iterator iterator_;
+ rtl::Reference< MapCursor > cursor_;
+ std::set< OUString > seen_;
+};
+
+rtl::Reference< Entity > AggregatingCursor::getNext(OUString * name) {
+ while (cursor_.is()) {
+ OUString n;
+ rtl::Reference< Entity > ent(cursor_->getNext(&n));
+ if (ent.is()) {
+ if (seen_.insert(n).second) {
+ if (name != nullptr) {
+ *name = n;
+ }
+ return ent->getSort() == Entity::SORT_MODULE
+ ? new AggregatingModule(
+ std::vector(providers_), (name_.isEmpty() ? name_ : name_ + ".") + n)
+ : ent;
+ }
+ } else {
+ cursor_.clear();
+ findCursor();
+ }
+ }
+ return rtl::Reference< Entity >();
+}
+
+void AggregatingCursor::findCursor() {
+ for (; !cursor_.is() && iterator_ != providers_.end(); ++iterator_) {
+ if (name_.isEmpty()) {
+ cursor_ = (*iterator_)->createRootCursor();
+ } else {
+ rtl::Reference< Entity > ent((*iterator_)->findEntity(name_));
+ if (ent.is() && ent->getSort() == Entity::SORT_MODULE) {
+ cursor_ = static_cast< ModuleEntity * >(ent.get())->
+ createCursor();
+ }
+ }
+ }
+}
+
+rtl::Reference< MapCursor > AggregatingModule::createCursor() const {
+ return new AggregatingCursor(std::vector(providers_), name_);
+}
+
+}
+
+NoSuchFileException::~NoSuchFileException() noexcept {}
+
+FileFormatException::~FileFormatException() noexcept {}
+
+Entity::~Entity() noexcept {}
+
+MapCursor::~MapCursor() noexcept {}
+
+ModuleEntity::~ModuleEntity() noexcept {}
+
+PublishableEntity::~PublishableEntity() noexcept {}
+
+EnumTypeEntity::~EnumTypeEntity() noexcept {}
+
+PlainStructTypeEntity::~PlainStructTypeEntity() noexcept {}
+
+PolymorphicStructTypeTemplateEntity::~PolymorphicStructTypeTemplateEntity()
+ noexcept
+{}
+
+ExceptionTypeEntity::~ExceptionTypeEntity() noexcept {}
+
+InterfaceTypeEntity::~InterfaceTypeEntity() noexcept {}
+
+TypedefEntity::~TypedefEntity() noexcept {}
+
+ConstantGroupEntity::~ConstantGroupEntity() noexcept {}
+
+SingleInterfaceBasedServiceEntity::~SingleInterfaceBasedServiceEntity() noexcept
+{}
+
+AccumulationBasedServiceEntity::~AccumulationBasedServiceEntity() noexcept {}
+
+InterfaceBasedSingletonEntity::~InterfaceBasedSingletonEntity() noexcept {}
+
+ServiceBasedSingletonEntity::~ServiceBasedSingletonEntity() noexcept {}
+
+Provider::~Provider() noexcept {}
+
+rtl::Reference< Provider > Manager::addProvider(OUString const & uri) {
+ rtl::Reference< Provider > p(loadProvider(uri));
+ assert(p.is());
+ {
+ osl::MutexGuard g(mutex_);
+ providers_.push_back(p);
+ }
+ return p;
+}
+
+rtl::Reference< Entity > Manager::findEntity(OUString const & name) const {
+ //TODO: caching? (here or in cppuhelper::TypeManager?)
+ osl::MutexGuard g(mutex_);
+ for (auto & i: providers_) {
+ rtl::Reference< Entity > ent(i->findEntity(name));
+ if (ent.is()) {
+ return ent;
+ }
+ }
+ return rtl::Reference< Entity >();
+}
+
+rtl::Reference< MapCursor > Manager::createCursor(OUString const & name)
+ const
+{
+ return new AggregatingCursor(std::vector(providers_), name);
+}
+
+Manager::~Manager() noexcept {}
+
+rtl::Reference< Provider > Manager::loadProvider(OUString const & uri) {
+ osl::DirectoryItem item;
+ if (osl::DirectoryItem::get(uri, item) == osl::FileBase::E_None) {
+ osl::FileStatus status(osl_FileStatus_Mask_Type);
+ if (item.getFileStatus(status) == osl::FileBase::E_None
+ && status.getFileType() == osl::FileStatus::Directory)
+ {
+ return new detail::SourceTreeProvider(*this, uri);
+ }
+ }
+ if (uri.endsWith(".idl")) {
+ return new detail::SourceFileProvider(this, uri);
+ }
+ try {
+ return new detail::UnoidlProvider(uri);
+ } catch (FileFormatException & e) {
+ SAL_INFO(
+ "unoidl",
+ "FileFormatException \"" << e.getDetail() << "\", retrying <" << uri
+ << "> as legacy format");
+ return new detail::LegacyProvider(*this, uri);
+ }
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */