summaryrefslogtreecommitdiffstats
path: root/unoidl/source/legacyprovider.cxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
commit267c6f2ac71f92999e969232431ba04678e7437e (patch)
tree358c9467650e1d0a1d7227a21dac2e3d08b622b2 /unoidl/source/legacyprovider.cxx
parentInitial commit. (diff)
downloadlibreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz
libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'unoidl/source/legacyprovider.cxx')
-rw-r--r--unoidl/source/legacyprovider.cxx829
1 files changed, 829 insertions, 0 deletions
diff --git a/unoidl/source/legacyprovider.cxx b/unoidl/source/legacyprovider.cxx
new file mode 100644
index 0000000000..9299ae7ce0
--- /dev/null
+++ b/unoidl/source/legacyprovider.cxx
@@ -0,0 +1,829 @@
+/* -*- 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 <cassert>
+#include <utility>
+#include <vector>
+
+#include <registry/reader.hxx>
+#include <registry/registry.hxx>
+#include <registry/regtype.h>
+#include <rtl/ref.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/types.h>
+#include <unoidl/unoidl.hxx>
+
+#include "legacyprovider.hxx"
+
+namespace unoidl::detail {
+
+namespace {
+
+std::vector< OUString > translateAnnotations(std::u16string_view documentation) {
+ std::vector< OUString > ans;
+ if (documentation.find(u"@deprecated") != std::u16string_view::npos) {
+ //TODO: this check is somewhat crude
+ ans.push_back("deprecated");
+ }
+ return ans;
+}
+
+ConstantValue translateConstantValue(
+ RegistryKey & key, RTConstValue const & value)
+{
+ switch (value.m_type) {
+ case RT_TYPE_BOOL:
+ return ConstantValue(value.m_value.aBool);
+ case RT_TYPE_BYTE:
+ return ConstantValue(value.m_value.aByte);
+ case RT_TYPE_INT16:
+ return ConstantValue(value.m_value.aShort);
+ case RT_TYPE_UINT16:
+ return ConstantValue(value.m_value.aUShort);
+ case RT_TYPE_INT32:
+ return ConstantValue(value.m_value.aLong);
+ case RT_TYPE_UINT32:
+ return ConstantValue(value.m_value.aULong);
+ case RT_TYPE_INT64:
+ return ConstantValue(value.m_value.aHyper);
+ case RT_TYPE_UINT64:
+ return ConstantValue(value.m_value.aUHyper);
+ case RT_TYPE_FLOAT:
+ return ConstantValue(value.m_value.aFloat);
+ case RT_TYPE_DOUBLE:
+ return ConstantValue(value.m_value.aDouble);
+ default:
+ throw FileFormatException(
+ key.getRegistryName(),
+ ("legacy format: unexpected type " + OUString::number(value.m_type)
+ + " of value of a field of constant group with key "
+ + key.getName()));
+ }
+}
+
+rtl::Reference< Entity > readEntity(
+ rtl::Reference< Manager > const & manager, RegistryKey & ucr,
+ RegistryKey & key, OUString const & path, bool probe);
+
+class Cursor: public MapCursor {
+public:
+ Cursor(
+ rtl::Reference< Manager > manager, RegistryKey const & ucr,
+ RegistryKey const & key);
+
+private:
+ virtual ~Cursor() noexcept override {}
+
+ virtual rtl::Reference< Entity > getNext(OUString * name) override;
+
+ rtl::Reference< Manager > manager_;
+ RegistryKey ucr_;
+ RegistryKey key_;
+ OUString prefix_;
+ RegistryKeyNames names_;
+ sal_uInt32 index_;
+};
+
+Cursor::Cursor(
+ rtl::Reference< Manager > manager, RegistryKey const & ucr,
+ RegistryKey const & key):
+ manager_(std::move(manager)), ucr_(ucr), key_(key), index_(0)
+{
+ if (!ucr_.isValid())
+ return;
+
+ prefix_ = key_.getName();
+ if (!prefix_.endsWith("/")) {
+ prefix_ += "/";
+ }
+ RegError e = key_.getKeyNames("", names_);
+ if (e != RegError::NO_ERROR) {
+ throw FileFormatException(
+ key_.getRegistryName(),
+ ("legacy format: cannot get sub-key names of " + key_.getName()
+ + ": " + OUString::number(static_cast<int>(e))));
+ }
+}
+
+rtl::Reference< Entity > Cursor::getNext(OUString * name) {
+ assert(name != nullptr);
+ rtl::Reference< Entity > ent;
+ if (index_ != names_.getLength()) {
+ OUString path(names_.getElement(index_));
+ assert(path.match(prefix_));
+ *name = path.copy(prefix_.getLength());
+ ent = readEntity(manager_, ucr_, key_, *name, false);
+ assert(ent.is());
+ ++index_;
+ }
+ return ent;
+}
+
+class Module: public ModuleEntity {
+public:
+ Module(
+ rtl::Reference< Manager > manager, RegistryKey const & ucr,
+ RegistryKey const & key):
+ manager_(std::move(manager)), ucr_(ucr), key_(key)
+ {}
+
+private:
+ virtual ~Module() noexcept override {}
+
+ virtual std::vector< OUString > getMemberNames() const override;
+
+ virtual rtl::Reference< MapCursor > createCursor() const override
+ { return new Cursor(manager_, ucr_, key_); }
+
+ rtl::Reference< Manager > manager_;
+ RegistryKey ucr_;
+ mutable RegistryKey key_;
+};
+
+std::vector< OUString > Module::getMemberNames() const {
+ RegistryKeyNames names;
+ RegError e = key_.getKeyNames("", names);
+ if (e != RegError::NO_ERROR) {
+ throw FileFormatException(
+ key_.getRegistryName(),
+ ("legacy format: cannot get sub-key names of " + key_.getName()
+ + ": " + OUString::number(static_cast<int>(e))));
+ }
+ std::vector< OUString > ns;
+ for (sal_uInt32 i = 0; i != names.getLength(); ++i) {
+ ns.push_back(names.getElement(i));
+ }
+ return ns;
+}
+
+typereg::Reader getReader(RegistryKey & key, std::vector< char > * buffer) {
+ assert(buffer != nullptr);
+ RegValueType type;
+ sal_uInt32 size;
+ RegError e = key.getValueInfo("", &type, &size);
+ if (e != RegError::NO_ERROR) {
+ throw FileFormatException(
+ key.getRegistryName(),
+ ("legacy format: cannot get value info about key " + key.getName()
+ + ": " + OUString::number(static_cast<int>(e))));
+ }
+ if (type != RegValueType::BINARY) {
+ throw FileFormatException(
+ key.getRegistryName(),
+ ("legacy format: unexpected value type " + OUString::number(static_cast<int>(type))
+ + " of key " + key.getName()));
+ }
+ if (size == 0
+ /*TODO: || size > std::numeric_limits< std::vector< char >::size_type >::max() */)
+ {
+ throw FileFormatException(
+ key.getRegistryName(),
+ ("legacy format: bad binary value size " + OUString::number(size)
+ + " of key " + key.getName()));
+ }
+ buffer->resize(static_cast< std::vector< char >::size_type >(size));
+ e = key.getValue("", buffer->data());
+ if (e != RegError::NO_ERROR) {
+ throw FileFormatException(
+ key.getRegistryName(),
+ ("legacy format: cannot get binary value of key " + key.getName()
+ + ": " + OUString::number(static_cast<int>(e))));
+ }
+ typereg::Reader reader(buffer->data(), size);
+ if (!reader.isValid()) {
+ throw FileFormatException(
+ key.getRegistryName(),
+ "legacy format: malformed binary value of key " + key.getName());
+ }
+ return reader;
+}
+
+rtl::Reference< Entity > readEntity(
+ rtl::Reference< Manager > const & manager, RegistryKey & ucr,
+ RegistryKey & key, OUString const & path, bool probe)
+{
+ assert(manager.is());
+ RegistryKey sub;
+ RegError e = key.openKey(path, sub);
+ switch (e) {
+ case RegError::NO_ERROR:
+ break;
+ case RegError::KEY_NOT_EXISTS:
+ if (probe) {
+ return rtl::Reference< Entity >();
+ }
+ [[fallthrough]];
+ default:
+ throw FileFormatException(
+ key.getRegistryName(),
+ ("legacy format: cannot open sub-key " + path + " of "
+ + key.getName() + ": " + OUString::number(static_cast<int>(e))));
+ }
+ std::vector< char > buf;
+ typereg::Reader reader(getReader(sub, &buf));
+ switch (reader.getTypeClass()) {
+ case RT_TYPE_INTERFACE:
+ {
+ std::vector< AnnotatedReference > mandBases;
+ sal_uInt16 n = reader.getSuperTypeCount();
+ for (sal_uInt16 j = 0; j != n; ++j) {
+ mandBases.emplace_back(
+ reader.getSuperTypeName(j).replace('/', '.'),
+ std::vector< OUString >());
+ }
+ std::vector< AnnotatedReference > optBases;
+ n = reader.getReferenceCount();
+ for (sal_uInt16 j = 0; j != n; ++j) {
+ optBases.emplace_back(
+ reader.getReferenceTypeName(j).replace('/', '.'),
+ translateAnnotations(reader.getReferenceDocumentation(j)));
+ }
+ sal_uInt16 methodCount = reader.getMethodCount();
+ std::vector< InterfaceTypeEntity::Attribute > attrs;
+ n = reader.getFieldCount(); // attributes
+ for (sal_uInt16 j = 0; j != n; ++j) {
+ OUString attrName(reader.getFieldName(j));
+ std::vector< OUString > getExcs;
+ std::vector< OUString > setExcs;
+ for (sal_uInt16 k = 0; k != methodCount; ++k) {
+ if (reader.getMethodName(k) == attrName) {
+ switch (reader.getMethodFlags(k)) {
+ case RTMethodMode::ATTRIBUTE_GET:
+ {
+ sal_uInt16 m
+ = reader.getMethodExceptionCount(k);
+ // cid#1213376 unhelpfully warns about an
+ // untrusted loop bound here:
+ // coverity[tainted_data] - trusted data source
+ for (sal_uInt16 l = 0; l != m; ++l) {
+ getExcs.push_back(
+ reader.getMethodExceptionTypeName(k, l).
+ replace('/', '.'));
+ }
+ break;
+ }
+ case RTMethodMode::ATTRIBUTE_SET:
+ {
+ sal_uInt16 m
+ = reader.getMethodExceptionCount(k);
+ // cid#1213376 unhelpfully warns about an
+ // untrusted loop bound here:
+ // coverity[tainted_data] - trusted data source
+ for (sal_uInt16 l = 0; l != m; ++l) {
+ setExcs.push_back(
+ reader.getMethodExceptionTypeName(k, l).
+ replace('/', '.'));
+ }
+ break;
+ }
+ default:
+ throw FileFormatException(
+ key.getRegistryName(),
+ ("legacy format: method and attribute with same"
+ " name " + attrName
+ + " in interface type with key "
+ + sub.getName()));
+ }
+ }
+ }
+ RTFieldAccess flags = reader.getFieldFlags(j);
+ attrs.emplace_back(
+ attrName, reader.getFieldTypeName(j).replace('/', '.'),
+ bool(flags & RTFieldAccess::BOUND),
+ bool(flags & RTFieldAccess::READONLY), std::move(getExcs), std::move(setExcs),
+ translateAnnotations(reader.getFieldDocumentation(j)));
+ }
+ std::vector< InterfaceTypeEntity::Method > meths;
+ meths.reserve(methodCount);
+ for (sal_uInt16 j = 0; j != methodCount; ++j) {
+ RTMethodMode flags = reader.getMethodFlags(j);
+ if (flags != RTMethodMode::ATTRIBUTE_GET
+ && flags != RTMethodMode::ATTRIBUTE_SET)
+ {
+ std::vector< InterfaceTypeEntity::Method::Parameter >
+ params;
+ sal_uInt16 m = reader.getMethodParameterCount(j);
+ // cid#1213376 unhelpfully warns about an untrusted loop
+ // bound here:
+ // coverity[tainted_data] - trusted data source
+ for (sal_uInt16 k = 0; k != m; ++k) {
+ RTParamMode mode = reader.getMethodParameterFlags(j, k);
+ InterfaceTypeEntity::Method::Parameter::Direction dir;
+ switch (mode) {
+ case RT_PARAM_IN:
+ dir = InterfaceTypeEntity::Method::Parameter::DIRECTION_IN;
+ break;
+ case RT_PARAM_OUT:
+ dir = InterfaceTypeEntity::Method::Parameter::DIRECTION_OUT;
+ break;
+ case RT_PARAM_INOUT:
+ dir = InterfaceTypeEntity::Method::Parameter::DIRECTION_IN_OUT;
+ break;
+ default:
+ throw FileFormatException(
+ key.getRegistryName(),
+ ("legacy format: unexpected mode "
+ + OUString::number(mode) + " of parameter "
+ + reader.getMethodParameterName(j, k)
+ + " of method " + reader.getMethodName(j)
+ + " in interface type with key "
+ + sub.getName()));
+ }
+ params.emplace_back(
+ reader.getMethodParameterName(j, k),
+ (reader.getMethodParameterTypeName(j, k).
+ replace('/', '.')),
+ dir);
+ }
+ std::vector< OUString > excs;
+ m = reader.getMethodExceptionCount(j);
+ // cid#1213376 unhelpfully warns about an untrusted loop
+ // bound here:
+ // coverity[tainted_data] - trusted data source
+ for (sal_uInt16 k = 0; k != m; ++k) {
+ excs.push_back(
+ reader.getMethodExceptionTypeName(j, k).replace(
+ '/', '.'));
+ }
+ meths.emplace_back(
+ reader.getMethodName(j),
+ reader.getMethodReturnTypeName(j).replace('/', '.'),
+ std::move(params), std::move(excs),
+ translateAnnotations(
+ reader.getMethodDocumentation(j)));
+ }
+ }
+ return new InterfaceTypeEntity(
+ reader.isPublished(), std::move(mandBases), std::move(optBases), std::move(attrs), std::move(meths),
+ translateAnnotations(reader.getDocumentation()));
+ }
+ case RT_TYPE_MODULE:
+ return new Module(manager, ucr, sub);
+ case RT_TYPE_STRUCT:
+ {
+ sal_uInt16 n = reader.getReferenceCount();
+ if (n == 0) {
+ OUString base;
+ switch (reader.getSuperTypeCount()) {
+ case 0:
+ break;
+ case 1:
+ base = reader.getSuperTypeName(0).replace('/', '.');
+ break;
+ default:
+ throw FileFormatException(
+ key.getRegistryName(),
+ ("legacy format: unexpected number "
+ + OUString::number(reader.getSuperTypeCount())
+ + " of super-types of plain struct type with key "
+ + sub.getName()));
+ }
+ std::vector< PlainStructTypeEntity::Member > mems;
+ n = reader.getFieldCount();
+ for (sal_uInt16 j = 0; j != n; ++j) {
+ mems.emplace_back(
+ reader.getFieldName(j),
+ reader.getFieldTypeName(j).replace('/', '.'),
+ translateAnnotations(reader.getFieldDocumentation(j)));
+ }
+ return new PlainStructTypeEntity(
+ reader.isPublished(), base, std::move(mems),
+ translateAnnotations(reader.getDocumentation()));
+ } else {
+ if (reader.getSuperTypeCount() != 0) {
+ throw FileFormatException(
+ key.getRegistryName(),
+ ("legacy format: unexpected number "
+ + OUString::number(reader.getSuperTypeCount())
+ + " of super-types of polymorphic struct type template"
+ " with key " + sub.getName()));
+ }
+ std::vector< OUString > params;
+ for (sal_uInt16 j = 0; j != n; ++j) {
+ params.push_back(
+ reader.getReferenceTypeName(j).replace('/', '.'));
+ }
+ std::vector< PolymorphicStructTypeTemplateEntity::Member > mems;
+ n = reader.getFieldCount();
+ for (sal_uInt16 j = 0; j != n; ++j) {
+ mems.emplace_back(
+ reader.getFieldName(j),
+ reader.getFieldTypeName(j).replace('/', '.'),
+ bool(
+ reader.getFieldFlags(j)
+ & RTFieldAccess::PARAMETERIZED_TYPE),
+ translateAnnotations(reader.getFieldDocumentation(j)));
+ }
+ return new PolymorphicStructTypeTemplateEntity(
+ reader.isPublished(), std::move(params), std::move(mems),
+ translateAnnotations(reader.getDocumentation()));
+ }
+ }
+ case RT_TYPE_ENUM:
+ {
+ std::vector< EnumTypeEntity::Member > mems;
+ sal_uInt16 n = reader.getFieldCount();
+ for (sal_uInt16 j = 0; j != n; ++j) {
+ RTConstValue v(reader.getFieldValue(j));
+ if (v.m_type != RT_TYPE_INT32) {
+ throw FileFormatException(
+ key.getRegistryName(),
+ ("legacy format: unexpected type "
+ + OUString::number(v.m_type) + " of value of field "
+ + reader.getFieldName(j) + " of enum type with key "
+ + sub.getName()));
+ }
+ mems.emplace_back(
+ reader.getFieldName(j), v.m_value.aLong,
+ translateAnnotations(reader.getFieldDocumentation(j)));
+
+ }
+ return new EnumTypeEntity(
+ reader.isPublished(), std::move(mems),
+ translateAnnotations(reader.getDocumentation()));
+ }
+ case RT_TYPE_EXCEPTION:
+ {
+ OUString base;
+ switch (reader.getSuperTypeCount()) {
+ case 0:
+ break;
+ case 1:
+ base = reader.getSuperTypeName(0).replace('/', '.');
+ break;
+ default:
+ throw FileFormatException(
+ key.getRegistryName(),
+ ("legacy format: unexpected number "
+ + OUString::number(reader.getSuperTypeCount())
+ + " of super-types of exception type with key "
+ + sub.getName()));
+ }
+ std::vector< ExceptionTypeEntity::Member > mems;
+ sal_uInt16 n = reader.getFieldCount();
+ for (sal_uInt16 j = 0; j != n; ++j) {
+ mems.emplace_back(
+ reader.getFieldName(j),
+ reader.getFieldTypeName(j).replace('/', '.'),
+ translateAnnotations(reader.getFieldDocumentation(j)));
+ }
+ return new ExceptionTypeEntity(
+ reader.isPublished(), base, std::move(mems),
+ translateAnnotations(reader.getDocumentation()));
+ }
+ case RT_TYPE_TYPEDEF:
+ if (reader.getSuperTypeCount() != 1) {
+ throw FileFormatException(
+ key.getRegistryName(),
+ ("legacy format: unexpected number "
+ + OUString::number(reader.getSuperTypeCount())
+ + " of super-types of typedef with key " + sub.getName()));
+ }
+ return new TypedefEntity(
+ reader.isPublished(), reader.getSuperTypeName(0).replace('/', '.'),
+ translateAnnotations(reader.getDocumentation()));
+ case RT_TYPE_SERVICE:
+ switch (reader.getSuperTypeCount()) {
+ case 0:
+ {
+ std::vector< AnnotatedReference > mandServs;
+ std::vector< AnnotatedReference > optServs;
+ std::vector< AnnotatedReference > mandIfcs;
+ std::vector< AnnotatedReference > optIfcs;
+ sal_uInt16 n = reader.getReferenceCount();
+ for (sal_uInt16 j = 0; j != n; ++j) {
+ AnnotatedReference base{
+ reader.getReferenceTypeName(j).replace('/', '.'),
+ translateAnnotations(
+ reader.getReferenceDocumentation(j))};
+ switch (reader.getReferenceSort(j)) {
+ case RTReferenceType::EXPORTS:
+ if (!(reader.getReferenceFlags(j) & RTFieldAccess::OPTIONAL))
+ {
+ mandServs.push_back(base);
+ } else {
+ optServs.push_back(base);
+ }
+ break;
+ case RTReferenceType::SUPPORTS:
+ if (!(reader.getReferenceFlags(j) & RTFieldAccess::OPTIONAL))
+ {
+ mandIfcs.push_back(base);
+ } else {
+ optIfcs.push_back(base);
+ }
+ break;
+ default:
+ throw FileFormatException(
+ key.getRegistryName(),
+ ("legacy format: unexpected mode "
+ + OUString::number(static_cast<int>(reader.getReferenceSort(j)))
+ + " of reference " + reader.getReferenceTypeName(j)
+ + " in service with key " + sub.getName()));
+ }
+ }
+ std::vector< AccumulationBasedServiceEntity::Property > props;
+ n = reader.getFieldCount();
+ for (sal_uInt16 j = 0; j != n; ++j) {
+ RTFieldAccess acc = reader.getFieldFlags(j);
+ int attrs = 0;
+ if (acc & RTFieldAccess::READONLY) {
+ attrs |= AccumulationBasedServiceEntity::Property::
+ ATTRIBUTE_READ_ONLY;
+ }
+ if (acc & RTFieldAccess::OPTIONAL) {
+ attrs |= AccumulationBasedServiceEntity::Property::
+ ATTRIBUTE_OPTIONAL;
+ }
+ if (acc & RTFieldAccess::MAYBEVOID) {
+ attrs |= AccumulationBasedServiceEntity::Property::
+ ATTRIBUTE_MAYBE_VOID;
+ }
+ if (acc & RTFieldAccess::BOUND) {
+ attrs |= AccumulationBasedServiceEntity::Property::
+ ATTRIBUTE_BOUND;
+ }
+ if (acc & RTFieldAccess::CONSTRAINED) {
+ attrs |= AccumulationBasedServiceEntity::Property::
+ ATTRIBUTE_CONSTRAINED;
+ }
+ if (acc & RTFieldAccess::TRANSIENT) {
+ attrs |= AccumulationBasedServiceEntity::Property::
+ ATTRIBUTE_TRANSIENT;
+ }
+ if (acc & RTFieldAccess::MAYBEAMBIGUOUS) {
+ attrs |= AccumulationBasedServiceEntity::Property::
+ ATTRIBUTE_MAYBE_AMBIGUOUS;
+ }
+ if (acc & RTFieldAccess::MAYBEDEFAULT) {
+ attrs |= AccumulationBasedServiceEntity::Property::
+ ATTRIBUTE_MAYBE_DEFAULT;
+ }
+ if (acc & RTFieldAccess::REMOVABLE) {
+ attrs |= AccumulationBasedServiceEntity::Property::
+ ATTRIBUTE_REMOVABLE;
+ }
+ props.emplace_back(
+ reader.getFieldName(j),
+ reader.getFieldTypeName(j).replace('/', '.'),
+ static_cast<
+ AccumulationBasedServiceEntity::Property::
+ Attributes >(attrs),
+ translateAnnotations(reader.getFieldDocumentation(j)));
+ }
+ return new AccumulationBasedServiceEntity(
+ reader.isPublished(), std::move(mandServs), std::move(optServs), std::move(mandIfcs),
+ std::move(optIfcs), std::move(props),
+ translateAnnotations(reader.getDocumentation()));
+ }
+ case 1:
+ {
+ std::vector< SingleInterfaceBasedServiceEntity::Constructor >
+ ctors;
+ sal_uInt16 n = reader.getMethodCount();
+ if (n == 1 && reader.getMethodFlags(0) == RTMethodMode::TWOWAY
+ && reader.getMethodName(0).isEmpty()
+ && reader.getMethodReturnTypeName(0) == "void"
+ && reader.getMethodParameterCount(0) == 0
+ && reader.getMethodExceptionCount(0) == 0)
+ {
+ ctors.push_back(
+ SingleInterfaceBasedServiceEntity::Constructor());
+ } else {
+ for (sal_uInt16 j = 0; j != n; ++j) {
+ if (reader.getMethodFlags(j) != RTMethodMode::TWOWAY) {
+ throw FileFormatException(
+ key.getRegistryName(),
+ ("legacy format: unexpected mode "
+ + OUString::number(static_cast<int>(reader.getMethodFlags(j)))
+ + " of constructor " + reader.getMethodName(j)
+ + " in service with key " + sub.getName()));
+ }
+ std::vector<
+ SingleInterfaceBasedServiceEntity::Constructor::
+ Parameter > params;
+ sal_uInt16 m = reader.getMethodParameterCount(j);
+ // cid#1213376 unhelpfully warns about an untrusted
+ // loop bound here:
+ // coverity[tainted_data] - trusted data source
+ for (sal_uInt16 k = 0; k != m; ++k) {
+ RTParamMode mode
+ = reader.getMethodParameterFlags(j, k);
+ if ((mode & ~RT_PARAM_REST) != RT_PARAM_IN) {
+ throw FileFormatException(
+ key.getRegistryName(),
+ ("legacy format: unexpected mode "
+ + OUString::number(mode)
+ + " of parameter "
+ + reader.getMethodParameterName(j, k)
+ + " of constructor "
+ + reader.getMethodName(j)
+ + " in service with key "
+ + sub.getName()));
+ }
+ if ((mode & RT_PARAM_REST) != 0
+ && (m != 1
+ || ((reader.getMethodParameterTypeName(
+ j, 0))
+ != "any")))
+ {
+ throw FileFormatException(
+ key.getRegistryName(),
+ ("legacy format: bad rest parameter "
+ + reader.getMethodParameterName(j, k)
+ + " of constructor "
+ + reader.getMethodName(j)
+ + " in service with key "
+ + sub.getName()));
+ }
+ params.emplace_back(
+ reader.getMethodParameterName(j, k),
+ (reader.getMethodParameterTypeName(j, k).
+ replace('/', '.')),
+ (mode & RT_PARAM_REST) != 0);
+ }
+ std::vector< OUString > excs;
+ m = reader.getMethodExceptionCount(j);
+ // cid#1213376 unhelpfully warns about an untrusted
+ // loop bound here:
+ // coverity[tainted_data] - trusted data source
+ for (sal_uInt16 k = 0; k != m; ++k) {
+ excs.push_back(
+ reader.getMethodExceptionTypeName(j, k).replace(
+ '/', '.'));
+ }
+ ctors.push_back(
+ SingleInterfaceBasedServiceEntity::Constructor(
+ reader.getMethodName(j), std::move(params), std::move(excs),
+ translateAnnotations(
+ reader.getMethodDocumentation(j))));
+ }
+ }
+ return new SingleInterfaceBasedServiceEntity(
+ reader.isPublished(),
+ reader.getSuperTypeName(0).replace('/', '.'), std::move(ctors),
+ translateAnnotations(reader.getDocumentation()));
+ }
+ default:
+ throw FileFormatException(
+ key.getRegistryName(),
+ ("legacy format: unexpected number "
+ + OUString::number(reader.getSuperTypeCount())
+ + " of super-types of service with key " + sub.getName()));
+ }
+ case RT_TYPE_SINGLETON:
+ {
+ if (reader.getSuperTypeCount() != 1) {
+ throw FileFormatException(
+ key.getRegistryName(),
+ ("legacy format: unexpected number "
+ + OUString::number(reader.getSuperTypeCount())
+ + " of super-types of singleton with key "
+ + sub.getName()));
+ }
+ OUString basePath(reader.getSuperTypeName(0));
+ OUString baseName(basePath.replace('/', '.'));
+ bool newStyle;
+ rtl::Reference< Entity > base(manager->findEntity(baseName));
+ if (base.is()) {
+ switch (base->getSort()) {
+ case Entity::SORT_INTERFACE_TYPE:
+ newStyle = true;
+ break;
+ case Entity::SORT_ACCUMULATION_BASED_SERVICE:
+ newStyle = false;
+ break;
+ default:
+ throw FileFormatException(
+ key.getRegistryName(),
+ ("legacy format: unexpected sort "
+ + OUString::number(base->getSort()) + " of base "
+ + baseName + " of singleton with key "
+ + sub.getName()));
+ }
+ } else {
+ RegistryKey key2;
+ e = ucr.openKey(basePath, key2);
+ switch (e) {
+ case RegError::NO_ERROR:
+ break;
+ case RegError::KEY_NOT_EXISTS:
+ throw FileFormatException(
+ key.getRegistryName(),
+ ("legacy format: unknown super-type " + basePath
+ + " of super-type with key " + sub.getName()));
+ default:
+ throw FileFormatException(
+ key.getRegistryName(),
+ ("legacy format: cannot open ucr sub-key " + basePath
+ + ": " + OUString::number(static_cast<int>(e))));
+ }
+ std::vector< char > buf2;
+ typereg::Reader reader2(getReader(key2, &buf2));
+ switch (reader2.getTypeClass()) {
+ case RT_TYPE_INTERFACE:
+ newStyle = true;
+ break;
+ case RT_TYPE_SERVICE:
+ newStyle = false;
+ break;
+ default:
+ throw FileFormatException(
+ key.getRegistryName(),
+ ("legacy format: unexpected type class "
+ + OUString::number(reader2.getTypeClass())
+ + " of super-type with key " + key2.getName()
+ + " of singleton with key " + sub.getName()));
+ }
+ }
+ return newStyle
+ ? rtl::Reference< Entity >(
+ new InterfaceBasedSingletonEntity(
+ reader.isPublished(), baseName,
+ translateAnnotations(reader.getDocumentation())))
+ : rtl::Reference< Entity >(
+ new ServiceBasedSingletonEntity(
+ reader.isPublished(), baseName,
+ translateAnnotations(reader.getDocumentation())));
+ }
+ case RT_TYPE_CONSTANTS:
+ {
+ std::vector< ConstantGroupEntity::Member > mems;
+ sal_uInt16 n = reader.getFieldCount();
+ for (sal_uInt16 j = 0; j != n; ++j) {
+ mems.emplace_back(
+ reader.getFieldName(j),
+ translateConstantValue(sub, reader.getFieldValue(j)),
+ translateAnnotations(reader.getFieldDocumentation(j)));
+ }
+ return new ConstantGroupEntity(
+ reader.isPublished(), std::move(mems),
+ translateAnnotations(reader.getDocumentation()));
+ }
+ default:
+ throw FileFormatException(
+ key.getRegistryName(),
+ ("legacy format: unexpected type class "
+ + OUString::number(reader.getTypeClass()) + " of key "
+ + sub.getName()));
+ }
+}
+
+}
+
+LegacyProvider::LegacyProvider(Manager & manager, OUString const & uri):
+ manager_(manager)
+{
+ Registry reg;
+ RegError e = reg.open(uri, RegAccessMode::READONLY);
+ switch (e) {
+ case RegError::NO_ERROR:
+ break;
+ case RegError::REGISTRY_NOT_EXISTS:
+ throw NoSuchFileException(uri);
+ default:
+ throw FileFormatException(
+ uri, "cannot open legacy file: " + OUString::number(static_cast<int>(e)));
+ }
+ RegistryKey root;
+ e = reg.openRootKey(root);
+ if (e != RegError::NO_ERROR) {
+ throw FileFormatException(
+ uri, "legacy format: cannot open root key: " + OUString::number(static_cast<int>(e)));
+ }
+ e = root.openKey("UCR", ucr_);
+ switch (e) {
+ case RegError::NO_ERROR:
+ case RegError::KEY_NOT_EXISTS: // such effectively empty files exist in the wild
+ break;
+ default:
+ throw FileFormatException(
+ uri, "legacy format: cannot open UCR key: " + OUString::number(static_cast<int>(e)));
+ }
+}
+
+rtl::Reference< MapCursor > LegacyProvider::createRootCursor() const {
+ return new Cursor(&manager_, ucr_, ucr_);
+}
+
+rtl::Reference< Entity > LegacyProvider::findEntity(OUString const & name)
+ const
+{
+ return ucr_.isValid()
+ ? readEntity(&manager_, ucr_, ucr_, name.replace('.', '/'), true)
+ : rtl::Reference< Entity >();
+}
+
+LegacyProvider::~LegacyProvider() noexcept {}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */