diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2013-03-01 23:23:50 +0100 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2013-03-01 23:23:50 +0100 |
commit | 12353c73868d26690aa4ac008ef5e9f2db8bc12c (patch) | |
tree | 5dc83b1d377e9b51c5af215e94b2ed9777cf762a /unoidl | |
parent | 866ebf66b3a50b2d601825e4533898949d5b86c8 (diff) |
WIP: Experimental new binary type.rdb format
Add LegacyProvider to read the old format (requires a provider Manager, to
resolve singletons' bases, to decide whether they are interface- or service-
based).
Replace registry-based reg2bin with provider-based reg2unoidl.
Change-Id: I5865e62308cc2d9c5439211ac803d84e93aab656
Diffstat (limited to 'unoidl')
-rw-r--r-- | unoidl/Executable_reg2unoidl.mk | 22 | ||||
-rw-r--r-- | unoidl/Library_unoidl.mk | 2 | ||||
-rw-r--r-- | unoidl/Module_unoidl.mk | 1 | ||||
-rw-r--r-- | unoidl/Package_inc.mk | 1 | ||||
-rw-r--r-- | unoidl/inc/unoidl/legacyprovider.hxx | 49 | ||||
-rw-r--r-- | unoidl/inc/unoidl/unoidl.hxx | 21 | ||||
-rw-r--r-- | unoidl/inc/unoidl/unoidlprovider.hxx | 4 | ||||
-rw-r--r-- | unoidl/prj/build.lst | 2 | ||||
-rw-r--r-- | unoidl/source/legacyprovider.cxx | 778 | ||||
-rw-r--r-- | unoidl/source/reg2unoidl.cxx | 786 | ||||
-rw-r--r-- | unoidl/source/unoidl.cxx | 36 | ||||
-rw-r--r-- | unoidl/source/unoidlprovider.cxx | 7 |
12 files changed, 1705 insertions, 4 deletions
diff --git a/unoidl/Executable_reg2unoidl.mk b/unoidl/Executable_reg2unoidl.mk new file mode 100644 index 000000000000..7f21a08454cb --- /dev/null +++ b/unoidl/Executable_reg2unoidl.mk @@ -0,0 +1,22 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# 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/. +# + +$(eval $(call gb_Executable_Executable,reg2unoidl)) + +$(eval $(call gb_Executable_add_exception_objects,reg2unoidl, \ + unoidl/source/reg2unoidl \ +)) + +$(eval $(call gb_Executable_use_libraries,reg2unoidl, \ + sal \ + salhelper \ + unoidl \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/unoidl/Library_unoidl.mk b/unoidl/Library_unoidl.mk index 8a7a668299e7..5de3cf163ac0 100644 --- a/unoidl/Library_unoidl.mk +++ b/unoidl/Library_unoidl.mk @@ -12,11 +12,13 @@ $(eval $(call gb_Library_Library,unoidl)) $(eval $(call gb_Library_add_defs,unoidl,-DLO_DLLIMPLEMENTATION_UNOIDL)) $(eval $(call gb_Library_add_exception_objects,unoidl, \ + unoidl/source/legacyprovider \ unoidl/source/unoidl \ unoidl/source/unoidlprovider \ )) $(eval $(call gb_Library_use_libraries,unoidl, \ + reg \ sal \ salhelper \ )) diff --git a/unoidl/Module_unoidl.mk b/unoidl/Module_unoidl.mk index 7017b80a897c..e612d9d051d8 100644 --- a/unoidl/Module_unoidl.mk +++ b/unoidl/Module_unoidl.mk @@ -10,6 +10,7 @@ $(eval $(call gb_Module_Module,unoidl)) $(eval $(call gb_Module_add_targets,unoidl, \ + Executable_reg2unoidl \ Library_unoidl \ Package_inc \ )) diff --git a/unoidl/Package_inc.mk b/unoidl/Package_inc.mk index 563ae365d07c..84a11a311e8b 100644 --- a/unoidl/Package_inc.mk +++ b/unoidl/Package_inc.mk @@ -10,6 +10,7 @@ $(eval $(call gb_Package_Package,unoidl_inc,$(SRCDIR)/unoidl/inc/unoidl)) $(eval $(call gb_Package_add_file,unoidl_inc,inc/unoidl/detail/dllapi.hxx,detail/dllapi.hxx)) +$(eval $(call gb_Package_add_file,unoidl_inc,inc/unoidl/legacyprovider.hxx,legacyprovider.hxx)) $(eval $(call gb_Package_add_file,unoidl_inc,inc/unoidl/unoidl.hxx,unoidl.hxx)) $(eval $(call gb_Package_add_file,unoidl_inc,inc/unoidl/unoidlprovider.hxx,unoidlprovider.hxx)) diff --git a/unoidl/inc/unoidl/legacyprovider.hxx b/unoidl/inc/unoidl/legacyprovider.hxx new file mode 100644 index 000000000000..68db79c933c2 --- /dev/null +++ b/unoidl/inc/unoidl/legacyprovider.hxx @@ -0,0 +1,49 @@ +/* -*- 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/. + */ + +#ifndef INCLUDED_UNOIDL_LEGACYPROVIDER_HXX +#define INCLUDED_UNOIDL_LEGACYPROVIDER_HXX + +#include "sal/config.h" + +#include "registry/registry.hxx" +#include "rtl/ref.hxx" +#include "sal/types.h" +#include "unoidl/detail/dllapi.hxx" +#include "unoidl/unoidl.hxx" + +namespace rtl { class OUString; } + +namespace unoidl { + +class LO_DLLPUBLIC_UNOIDL LegacyProvider: public Provider { +public: + // throws FileFormatException, NoSuchFileException: + LegacyProvider( + rtl::Reference< Manager > const & manager, rtl::OUString const & uri); + + // throws FileFormatException: + virtual rtl::Reference< MapCursor > createRootCursor() const; + + // throws FileFormatException: + virtual rtl::Reference< Entity > findEntity(rtl::OUString const & name) + const; + +private: + virtual SAL_DLLPRIVATE ~LegacyProvider() throw (); + + rtl::Reference< Manager > manager_; + mutable RegistryKey ucr_; +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoidl/inc/unoidl/unoidl.hxx b/unoidl/inc/unoidl/unoidl.hxx index 372ed3889ade..5597227c16e0 100644 --- a/unoidl/inc/unoidl/unoidl.hxx +++ b/unoidl/inc/unoidl/unoidl.hxx @@ -601,15 +601,34 @@ public: // throws FileFormatException: virtual rtl::Reference< MapCursor > createRootCursor() const = 0; + // throws FileFormatException: + virtual rtl::Reference< Entity > findEntity(rtl::OUString const & name) + const = 0; + protected: SAL_DLLPRIVATE Provider() {} virtual SAL_DLLPRIVATE ~Provider() throw (); }; +class LO_DLLPUBLIC_UNOIDL Manager: public salhelper::SimpleReferenceObject { +public: + Manager() {} + + void addProvider(rtl::Reference< Provider > const & provider); + + // throws FileFormatException: + rtl::Reference< Entity > findEntity(rtl::OUString const & name) const; + +private: + virtual SAL_DLLPRIVATE ~Manager() throw (); + + std::vector< rtl::Reference< Provider > > providers_; +}; + // throws FileFormatException, NoSuchFileException: LO_DLLPUBLIC_UNOIDL rtl::Reference< Provider > loadProvider( - rtl::OUString const & uri); + rtl::Reference< Manager > const & manager, rtl::OUString const & uri); } diff --git a/unoidl/inc/unoidl/unoidlprovider.hxx b/unoidl/inc/unoidl/unoidlprovider.hxx index 07388a604034..b72a629990ef 100644 --- a/unoidl/inc/unoidl/unoidlprovider.hxx +++ b/unoidl/inc/unoidl/unoidlprovider.hxx @@ -34,6 +34,10 @@ public: virtual rtl::Reference< MapCursor > createRootCursor() const; // throws FileFormatException: + virtual rtl::Reference< Entity > findEntity(rtl::OUString const & name) + const; + + // throws FileFormatException: sal_uInt32 find(rtl::OUString const & name, bool * constant = 0) const; // throws FileFormatException: diff --git a/unoidl/prj/build.lst b/unoidl/prj/build.lst index 32409d2a0b63..c6b2abf3cafc 100644 --- a/unoidl/prj/build.lst +++ b/unoidl/prj/build.lst @@ -1,2 +1,2 @@ -un unoidl: sal salhelper NULL +un unoidl: registry sal salhelper NULL un unoidl\prj nmake - all un_prj NULL diff --git a/unoidl/source/legacyprovider.cxx b/unoidl/source/legacyprovider.cxx new file mode 100644 index 000000000000..0f620bc51fd0 --- /dev/null +++ b/unoidl/source/legacyprovider.cxx @@ -0,0 +1,778 @@ +/* -*- 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 <cstring> +#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/legacyprovider.hxx" +#include "unoidl/unoidl.hxx" + +namespace unoidl { + +namespace { + +ConstantValue translateConstantValue( + RegistryKey & key, RTConstValue const & value) +{ + switch (value.m_type) { + case RT_TYPE_BOOL: + return ConstantValue(static_cast< bool >(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 > const & manager, RegistryKey const & ucr, + RegistryKey const & key); + +private: + virtual ~Cursor() throw () {} + + virtual rtl::Reference< Entity > getNext(OUString * name); + + rtl::Reference< Manager > manager_; + RegistryKey ucr_; + RegistryKey key_; + OUString prefix_; + RegistryKeyNames names_; + sal_uInt32 index_; +}; + +Cursor::Cursor( + rtl::Reference< Manager > const & manager, RegistryKey const & ucr, + RegistryKey const & key): + manager_(manager), ucr_(ucr), key_(key), index_(0) +{ + prefix_ = key_.getName(); + if (!prefix_.endsWith("/")) { + prefix_ += "/"; + } + RegError e = key_.getKeyNames("", names_); + if (e != REG_NO_ERROR) { + throw FileFormatException( + key_.getRegistryName(), + ("legacy format: cannot get sub-key names of " + key_.getName() + + ": " + OUString::number(e))); + } +} + +rtl::Reference< Entity > Cursor::getNext(OUString * name) { + assert(name != 0); + 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 > const & manager, RegistryKey const & ucr, + RegistryKey const & key): + manager_(manager), ucr_(ucr), key_(key) + {} + +private: + virtual ~Module() throw () {} + + virtual std::vector< OUString > getMemberNames() const; + + virtual rtl::Reference< MapCursor > createCursor() const + { 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 != REG_NO_ERROR) { + throw FileFormatException( + key_.getRegistryName(), + ("legacy format: cannot get sub-key names of " + key_.getName() + + ": " + OUString::number(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 != 0); + RegValueType type; + sal_uInt32 size; + RegError e = key.getValueInfo("", &type, &size); + if (e != REG_NO_ERROR) { + throw FileFormatException( + key.getRegistryName(), + ("legacy format: cannot get value info about key " + key.getName() + + ": " + OUString::number(e))); + } + if (type != RG_VALUETYPE_BINARY) { + throw FileFormatException( + key.getRegistryName(), + ("legacy format: unexpected value type " + OUString::number(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)[0]); + if (e != REG_NO_ERROR) { + throw FileFormatException( + key.getRegistryName(), + ("legacy format: cannot get binary value of key " + key.getName() + + ": " + OUString::number(e))); + } + typereg::Reader reader(&(*buffer)[0], size, false, TYPEREG_VERSION_1); + 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 REG_NO_ERROR: + break; + case REG_KEY_NOT_EXISTS: + if (probe) { + return rtl::Reference< Entity >(); + } + // fall through + default: + throw FileFormatException( + key.getRegistryName(), + ("legacy format: cannot open sub-key " + path + " of " + + key.getName() + ": " + OUString::number(e))); + } + std::vector< char > buf; + typereg::Reader reader(getReader(sub, &buf)); + switch (reader.getTypeClass()) { + case RT_TYPE_INTERFACE: + { + std::vector< OUString > mandBases; + sal_uInt16 n = reader.getSuperTypeCount(); + for (sal_uInt16 j = 0; j != n; ++j) { + mandBases.push_back( + reader.getSuperTypeName(j).replace('/', '.')); + } + std::vector< OUString > optBases; + n = reader.getReferenceCount(); + for (sal_uInt16 j = 0; j != n; ++j) { + optBases.push_back( + reader.getReferenceTypeName(j).replace('/', '.')); + } + 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 RT_MODE_ATTRIBUTE_GET: + { + sal_uInt16 m + = reader.getMethodExceptionCount(k); + for (sal_uInt16 l = 0; l != m; ++l) { + getExcs.push_back( + reader.getMethodExceptionTypeName(k, l). + replace('/', '.')); + } + break; + } + case RT_MODE_ATTRIBUTE_SET: + { + sal_uInt16 m + = reader.getMethodExceptionCount(k); + 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.push_back( + InterfaceTypeEntity::Attribute( + attrName, reader.getFieldTypeName(j).replace('/', '.'), + (flags & RT_ACCESS_BOUND) != 0, + (flags & RT_ACCESS_READONLY) != 0, getExcs, setExcs)); + } + std::vector< InterfaceTypeEntity::Method > meths; + for (sal_uInt16 j = 0; j != methodCount; ++j) { + RTMethodMode flags = reader.getMethodFlags(j); + if (flags != RT_MODE_ATTRIBUTE_GET + && flags != RT_MODE_ATTRIBUTE_SET) + { + std::vector< InterfaceTypeEntity::Method::Parameter > + params; + sal_uInt16 m = reader.getMethodParameterCount(j); + 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::DIRECTION_IN; + break; + case RT_PARAM_OUT: + dir = InterfaceTypeEntity::Method::Parameter:: + Direction::DIRECTION_OUT; + break; + case RT_PARAM_INOUT: + dir = InterfaceTypeEntity::Method::Parameter:: + Direction::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.push_back( + InterfaceTypeEntity::Method::Parameter( + reader.getMethodParameterName(j, k), + (reader.getMethodParameterTypeName(j, k). + replace('/', '.')), + dir)); + } + std::vector< OUString > excs; + m = reader.getMethodExceptionCount(j); + for (sal_uInt16 k = 0; k != m; ++k) { + excs.push_back( + reader.getMethodExceptionTypeName(j, k).replace( + '/', '.')); + } + meths.push_back( + InterfaceTypeEntity::Method( + reader.getMethodName(j), + reader.getMethodReturnTypeName(j).replace('/', '.'), + params, excs)); + } + } + return new InterfaceTypeEntity( + reader.isPublished(), mandBases, optBases, attrs, meths); + } + case RT_TYPE_MODULE: + return new Module(manager, ucr, sub); + case RT_TYPE_STRUCT: + { + sal_uInt32 n = reader.getReferenceCount(); + if (n == 0) { + OUString base; + switch (reader.getSuperTypeCount()) { + case 0: + break; + case 1: + base = reader.getSuperTypeName(0).replace('/', '.'); + break; + default: + 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.push_back( + PlainStructTypeEntity::Member( + reader.getFieldName(j), + reader.getFieldTypeName(j).replace('/', '.'))); + } + return new PlainStructTypeEntity( + reader.isPublished(), base, mems); + } else { + if (reader.getSuperTypeCount() != 0) { + 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.push_back( + PolymorphicStructTypeTemplateEntity::Member( + reader.getFieldName(j), + reader.getFieldTypeName(j).replace('/', '.'), + ((reader.getFieldFlags(j) + & RT_ACCESS_PARAMETERIZED_TYPE) + != 0))); + } + return new PolymorphicStructTypeTemplateEntity( + reader.isPublished(), params, mems); + } + } + 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) { + 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.push_back( + EnumTypeEntity::Member( + reader.getFieldName(j), v.m_value.aLong)); + } + return new EnumTypeEntity(reader.isPublished(), mems); + } + 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.push_back( + ExceptionTypeEntity::Member( + reader.getFieldName(j), + reader.getFieldTypeName(j).replace('/', '.'))); + } + return new ExceptionTypeEntity(reader.isPublished(), base, mems); + } + 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('/', '.')); + case RT_TYPE_SERVICE: + switch (reader.getSuperTypeCount()) { + case 0: + { + std::vector< OUString > mandServs; + std::vector< OUString > optServs; + std::vector< OUString > mandIfcs; + std::vector< OUString > optIfcs; + sal_uInt16 n = reader.getReferenceCount(); + for (sal_uInt16 j = 0; j != n; ++j) { + OUString refName( + reader.getReferenceTypeName(j).replace('/', '.')); + switch (reader.getReferenceSort(j)) { + case RT_REF_EXPORTS: + if ((reader.getReferenceFlags(j) & RT_ACCESS_OPTIONAL) + == 0) + { + mandServs.push_back(refName); + } else { + optServs.push_back(refName); + } + break; + case RT_REF_SUPPORTS: + if ((reader.getReferenceFlags(j) & RT_ACCESS_OPTIONAL) + == 0) + { + mandIfcs.push_back(refName); + } else { + optIfcs.push_back(refName); + } + break; + default: + throw FileFormatException( + key.getRegistryName(), + ("legacy format: unexpected mode " + + OUString::number(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 & RT_ACCESS_READONLY) != 0) { + attrs |= AccumulationBasedServiceEntity::Property:: + ATTRIBUTE_READ_ONLY; + } + if ((acc & RT_ACCESS_OPTIONAL) != 0) { + attrs |= AccumulationBasedServiceEntity::Property:: + ATTRIBUTE_OPTIONAL; + } + if ((acc & RT_ACCESS_MAYBEVOID) != 0) { + attrs |= AccumulationBasedServiceEntity::Property:: + ATTRIBUTE_MAYBE_VOID; + } + if ((acc & RT_ACCESS_BOUND) != 0) { + attrs |= AccumulationBasedServiceEntity::Property:: + ATTRIBUTE_BOUND; + } + if ((acc & RT_ACCESS_CONSTRAINED) != 0) { + attrs |= AccumulationBasedServiceEntity::Property:: + ATTRIBUTE_CONSTRAINED; + } + if ((acc & RT_ACCESS_TRANSIENT) != 0) { + attrs |= AccumulationBasedServiceEntity::Property:: + ATTRIBUTE_TRANSIENT; + } + if ((acc & RT_ACCESS_MAYBEAMBIGUOUS) != 0) { + attrs |= AccumulationBasedServiceEntity::Property:: + ATTRIBUTE_MAYBE_AMBIGUOUS; + } + if ((acc & RT_ACCESS_MAYBEDEFAULT) != 0) { + attrs |= AccumulationBasedServiceEntity::Property:: + ATTRIBUTE_MAYBE_DEFAULT; + } + if ((acc & RT_ACCESS_REMOVEABLE) != 0) { + attrs |= AccumulationBasedServiceEntity::Property:: + ATTRIBUTE_REMOVABLE; + } + props.push_back( + AccumulationBasedServiceEntity::Property( + reader.getFieldName(j), + reader.getFieldTypeName(j).replace('/', '.'), + static_cast< + AccumulationBasedServiceEntity::Property:: + Attributes >(attrs))); + } + return new AccumulationBasedServiceEntity( + reader.isPublished(), mandServs, optServs, mandIfcs, + optIfcs, props); + } + case 1: + { + std::vector< SingleInterfaceBasedServiceEntity::Constructor > + ctors; + sal_uInt16 n = reader.getMethodCount(); + if (n == 1 && reader.getMethodFlags(0) == 0 + && 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) != RT_MODE_TWOWAY) { + throw FileFormatException( + key.getRegistryName(), + ("legacy format: unexpected mode " + + OUString::number(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); + 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, 1)) + == "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.push_back( + SingleInterfaceBasedServiceEntity::Constructor:: + Parameter( + reader.getMethodParameterName(j, k), + (reader.getMethodParameterTypeName(j, k). + replace('/', '.')), + (mode & RT_PARAM_REST) != 0)); + } + std::vector< OUString > excs; + m = reader.getMethodExceptionCount(j); + for (sal_uInt16 k = 0; k != m; ++k) { + excs.push_back( + reader.getMethodExceptionTypeName(j, k). + replace('/', '.')); + } + ctors.push_back( + SingleInterfaceBasedServiceEntity::Constructor( + reader.getMethodName(j), params, excs)); + } + } + return new SingleInterfaceBasedServiceEntity( + reader.isPublished(), + reader.getSuperTypeName(0).replace('/', '.'), ctors); + } + 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 REG_NO_ERROR: + break; + case REG_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(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)) + : rtl::Reference< Entity >( + new ServiceBasedSingletonEntity( + reader.isPublished(), baseName)); + } + case RT_TYPE_CONSTANTS: + { + std::vector< ConstantGroupEntity::Member > mems; + sal_uInt16 n = reader.getFieldCount(); + for (sal_uInt16 j = 0; j != n; ++j) { + mems.push_back( + ConstantGroupEntity::Member( + reader.getFieldName(j), + translateConstantValue(sub, reader.getFieldValue(j)))); + } + return new ConstantGroupEntity(reader.isPublished(), mems); + } + default: + throw FileFormatException( + key.getRegistryName(), + ("legacy format: unexpected type class " + + OUString::number(reader.getTypeClass()) + " of key " + + sub.getName())); + } +} + +} + +LegacyProvider::LegacyProvider( + rtl::Reference< Manager > const & manager, OUString const & uri): + manager_(manager) +{ + Registry reg; + RegError e = reg.open(uri, REG_READONLY); + switch (e) { + case REG_NO_ERROR: + break; + case REG_REGISTRY_NOT_EXISTS: + throw NoSuchFileException(uri); + default: + throw FileFormatException( + uri, "cannot open legacy file: " + OUString::number(e)); + } + RegistryKey root; + e = reg.openRootKey(root); + if (e != REG_NO_ERROR) { + throw FileFormatException( + uri, "legacy format: cannot open root key: " + OUString::number(e)); + } + e = root.openKey("UCR", ucr_); + if (e != REG_NO_ERROR) { + throw FileFormatException( + uri, "legacy format: cannot open UCR key: " + OUString::number(e)); + } +} + +rtl::Reference< MapCursor > LegacyProvider::createRootCursor() const { + return new Cursor(manager_, ucr_, ucr_); +} + +rtl::Reference< Entity > LegacyProvider::findEntity(rtl::OUString const & name) + const +{ + return readEntity(manager_, ucr_, ucr_, name.replace('.', '/'), true); +} + +LegacyProvider::~LegacyProvider() throw () {} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoidl/source/reg2unoidl.cxx b/unoidl/source/reg2unoidl.cxx new file mode 100644 index 000000000000..b0a013d68a5f --- /dev/null +++ b/unoidl/source/reg2unoidl.cxx @@ -0,0 +1,786 @@ +/* -*- 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 <cstddef> +#include <cstdlib> +#include <iostream> +#include <map> +#include <utility> +#include <vector> + +#include "osl/endian.h" +#include "osl/file.h" +#include "osl/file.hxx" +#include "osl/process.h" +#include "rtl/process.h" +#include "rtl/string.hxx" +#include "rtl/textenc.h" +#include "rtl/textcvt.h" +#include "rtl/ustring.hxx" +#include "sal/macros.h" +#include "sal/main.h" +#include "unoidl/unoidl.hxx" + +namespace { + +OUString getArgumentUri(sal_uInt32 argument) { + OUString arg; + rtl_getAppCommandArg(argument, &arg.pData); + OUString url; + osl::FileBase::RC e1 = osl::FileBase::getFileURLFromSystemPath(arg, url); + if (e1 != osl::FileBase::E_None) { + std::cerr + << "Cannot convert \"" << arg << "\" to file URL, error code " + << +e1 << std::endl; + std::exit(EXIT_FAILURE); + } + OUString cwd; + oslProcessError e2 = osl_getProcessWorkingDir(&cwd.pData); + if (e2 != osl_Process_E_None) { + std::cerr + << "Cannot obtain working directory, error code " << +e2 + << std::endl; + std::exit(EXIT_FAILURE); + } + OUString abs; + e1 = osl::FileBase::getAbsoluteFileURL(cwd, url, abs); + if (e1 != osl::FileBase::E_None) { + std::cerr + << "Cannot make \"" << url + << "\" into an absolute file URL, error code " << +e1 << std::endl; + std::exit(EXIT_FAILURE); + } + return abs; +} + +rtl::Reference< unoidl::Provider > load( + rtl::Reference< unoidl::Manager > const & manager, OUString const & uri) +{ + try { + return unoidl::loadProvider(manager, uri); + } catch (unoidl::NoSuchFileException &) { + std::cerr << "Input <" << uri << "> does not exist" << std::endl; + std::exit(EXIT_FAILURE); + } catch (unoidl::FileFormatException & e) { + std::cerr + << "Cannot read input <" << uri << ">: " << e.getDetail() + << std::endl; + std::exit(EXIT_FAILURE); + } +} + +sal_uInt64 getOffset(osl::File & file) { + sal_uInt64 off; + osl::FileBase::RC e = file.getPos(off); + if (e != osl::FileBase::E_None) { + std::cerr + << "Cannot determine current position in <" << file.getURL() + << ">, error code " << +e << std::endl; + std::exit(EXIT_FAILURE); + } + return off; +} + +void write(osl::File & file, void const * buffer, sal_uInt64 size) { + sal_uInt64 n; + osl::FileBase::RC e = file.write(buffer, size, n); + if (e != osl::FileBase::E_None) { + std::cerr + << "Cannot write to <" << file.getURL() << ">, error code " << +e + << std::endl; + std::exit(EXIT_FAILURE); + } + if (n != size) { + std::cerr + << "Bad write of " << n << " instead of " << size << " bytes to <" + << file.getURL() << '>' << std::endl; + std::exit(EXIT_FAILURE); + } +} + +void write8(osl::File & file, sal_uInt64 value) { + if (value > 0xFF) { + std::cerr + << "Cannot write value >= 2^8; input is too large" << std::endl; + std::exit(EXIT_FAILURE); + } + unsigned char buf[1]; + buf[0] = value & 0xFF; + write(file, buf, SAL_N_ELEMENTS(buf)); +} + +void write16(osl::File & file, sal_uInt64 value) { + if (value > 0xFFFF) { + std::cerr + << "Cannot write value >= 2^16; input is too large" << std::endl; + std::exit(EXIT_FAILURE); + } + unsigned char buf[2]; + buf[0] = value & 0xFF; + buf[1] = (value >> 8) & 0xFF; + write(file, buf, SAL_N_ELEMENTS(buf)); +} + +void write32(osl::File & file, sal_uInt64 value) { + if (value > 0xFFFFFFFF) { + std::cerr + << "Cannot write value >= 2^32; input is too large" << std::endl; + std::exit(EXIT_FAILURE); + } + unsigned char buf[4]; + buf[0] = value & 0xFF; + buf[1] = (value >> 8) & 0xFF; + buf[2] = (value >> 16) & 0xFF; + buf[3] = (value >> 24) & 0xFF; + write(file, buf, SAL_N_ELEMENTS(buf)); +} + +void write64(osl::File & file, sal_uInt64 value) { + unsigned char buf[8]; + buf[0] = value & 0xFF; + buf[1] = (value >> 8) & 0xFF; + buf[2] = (value >> 16) & 0xFF; + buf[3] = (value >> 24) & 0xFF; + buf[3] = (value >> 32) & 0xFF; + buf[3] = (value >> 40) & 0xFF; + buf[3] = (value >> 48) & 0xFF; + buf[3] = (value >> 56) & 0xFF; + write(file, buf, SAL_N_ELEMENTS(buf)); +} + +void writeIso60599Binary32(osl::File & file, float value) { + union { + unsigned char buf[4]; + float f; // assuming float is ISO 60599 binary32 + } sa; + sa.f = value; +#if defined OSL_BIGENDIAN + std::swap(sa.buf[0], sa.buf[3]); + std::swap(sa.buf[1], sa.buf[2]); +#endif + write(file, sa.buf, SAL_N_ELEMENTS(sa.buf)); +} + +void writeIso60599Binary64(osl::File & file, double value) { + union { + unsigned char buf[8]; + float d; // assuming double is ISO 60599 binary64 + } sa; + sa.d = value; +#if defined OSL_BIGENDIAN + std::swap(sa.buf[0], sa.buf[7]); + std::swap(sa.buf[1], sa.buf[6]); + std::swap(sa.buf[2], sa.buf[5]); + std::swap(sa.buf[3], sa.buf[4]); +#endif + write(file, sa.buf, SAL_N_ELEMENTS(sa.buf)); +} + +OString toAscii(OUString const & name) { + OString ascii; + if (!name.convertToString( + &ascii, RTL_TEXTENCODING_ASCII_US, + (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR + | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR))) + { + std::cerr + << "Cannot convert \"" << name << "\" to US ASCII" << std::endl; + std::exit(EXIT_FAILURE); + } + return ascii; +} + +sal_uInt64 writeNameNul(osl::File & file, OUString const & name) { + OString ascii(toAscii(name)); + if (ascii.indexOf('\0') != -1) { + std::cerr + << "Name \"" << ascii << "\" contains NUL characters" << std::endl; + std::exit(EXIT_FAILURE); + } + sal_uInt64 off = getOffset(file); + write(file, ascii.getStr(), ascii.getLength() + 1); + return off; +} + +void writeNameLen(osl::File & file, OUString const & name) { + static std::map< OUString, sal_uInt64 > reuse; + std::map< OUString, sal_uInt64 >::iterator i(reuse.find(name)); + if (i == reuse.end()) { + reuse.insert(std::make_pair(name, getOffset(file))); + OString ascii(toAscii(name)); + assert( + (static_cast< sal_uInt64 >(ascii.getLength()) & 0x80000000) == 0); + write32( + file, static_cast< sal_uInt64 >(ascii.getLength()) | 0x80000000); + write(file, ascii.getStr(), ascii.getLength()); + } else { + write32(file, i->second); + } +} + +void writeKind( + osl::File & file, + rtl::Reference< unoidl::PublishableEntity > const & entity, + bool flag = false) +{ + assert(entity.is()); + sal_uInt64 v = entity->getSort(); + if (entity->isPublished()) { + v |= 0x80; + } + if (false /*TODO: deprecated */) { + v |= 0x40; + } + if (flag) { + v |= 0x20; + } + write8(file, v); +} + +sal_uInt64 writeMap( + osl::File & file, rtl::Reference< unoidl::MapCursor > const & cursor, + std::size_t * rootSize) +{ + assert(cursor.is()); + struct Item { + explicit Item(rtl::Reference< unoidl::Entity > const & theEntity): + entity(theEntity) + {} + rtl::Reference< unoidl::Entity > entity; + sal_uInt64 nameOffset; + sal_uInt64 dataOffset; + }; + std::map< OUString, Item > map; + for (;;) { + OUString name; + rtl::Reference< unoidl::Entity > ent(cursor->getNext(&name)); + if (!ent.is()) { + break; + } + if (!map.insert(std::make_pair(name, Item(ent))).second) { + std::cout << "Duplicate name \"" << name << '"' << std::endl; + std::exit(EXIT_FAILURE); + } + } + for (std::map< OUString, Item >::iterator i(map.begin()); i != map.end(); + ++i) + { + switch (i->second.entity->getSort()) { + case unoidl::Entity::SORT_MODULE: + { + rtl::Reference< unoidl::ModuleEntity > ent2( + static_cast< unoidl::ModuleEntity * >( + i->second.entity.get())); + i->second.dataOffset = writeMap(file, ent2->createCursor(), 0); + break; + } + case unoidl::Entity::SORT_ENUM_TYPE: + { + rtl::Reference< unoidl::EnumTypeEntity > ent2( + static_cast< unoidl::EnumTypeEntity * >( + i->second.entity.get())); + i->second.dataOffset = getOffset(file); + writeKind(file, ent2.get()); + write32(file, ent2->getMembers().size()); + for (std::vector< unoidl::EnumTypeEntity::Member >:: + const_iterator j(ent2->getMembers().begin()); + j != ent2->getMembers().end(); ++j) + { + writeNameLen(file, j->name); + write32(file, static_cast< sal_uInt32 >(j->value)); + } + break; + } + case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE: + { + rtl::Reference< unoidl::PlainStructTypeEntity > ent2( + static_cast< unoidl::PlainStructTypeEntity * >( + i->second.entity.get())); + i->second.dataOffset = getOffset(file); + writeKind(file, ent2.get(), !ent2->getDirectBase().isEmpty()); + if (!ent2->getDirectBase().isEmpty()) { + writeNameLen(file, ent2->getDirectBase()); + } + write32(file, ent2->getDirectMembers().size()); + for (std::vector< unoidl::PlainStructTypeEntity::Member >:: + const_iterator j(ent2->getDirectMembers().begin()); + j != ent2->getDirectMembers().end(); ++j) + { + writeNameLen(file, j->name); + writeNameLen(file, j->type); + } + break; + } + case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE: + { + rtl::Reference< unoidl::PolymorphicStructTypeTemplateEntity > + ent2( + static_cast< + unoidl::PolymorphicStructTypeTemplateEntity * >( + i->second.entity.get())); + i->second.dataOffset = getOffset(file); + writeKind(file, ent2.get()); + write32(file, ent2->getTypeParameters().size()); + for (std::vector< OUString >::const_iterator j( + ent2->getTypeParameters().begin()); + j != ent2->getTypeParameters().end(); ++j) + { + writeNameLen(file, *j); + } + write32(file, ent2->getMembers().size()); + for (std::vector< + unoidl::PolymorphicStructTypeTemplateEntity::Member >:: + const_iterator j( + ent2->getMembers().begin()); + j != ent2->getMembers().end(); ++j) + { + sal_uInt64 f = 0; + if (j->parameterized) { + f |= 0x01; + } + write8(file, f); + writeNameLen(file, j->name); + writeNameLen(file, j->type); + } + break; + } + case unoidl::Entity::SORT_EXCEPTION_TYPE: + { + rtl::Reference< unoidl::ExceptionTypeEntity > ent2( + static_cast< unoidl::ExceptionTypeEntity * >( + i->second.entity.get())); + i->second.dataOffset = getOffset(file); + writeKind(file, ent2.get(), !ent2->getDirectBase().isEmpty()); + if (!ent2->getDirectBase().isEmpty()) { + writeNameLen(file, ent2->getDirectBase()); + } + write32(file, ent2->getDirectMembers().size()); + for (std::vector< unoidl::ExceptionTypeEntity::Member >:: + const_iterator j(ent2->getDirectMembers().begin()); + j != ent2->getDirectMembers().end(); ++j) + { + writeNameLen(file, j->name); + writeNameLen(file, j->type); + } + break; + } + case unoidl::Entity::SORT_INTERFACE_TYPE: + { + rtl::Reference< unoidl::InterfaceTypeEntity > ent2( + static_cast< unoidl::InterfaceTypeEntity * >( + i->second.entity.get())); + i->second.dataOffset = getOffset(file); + writeKind(file, ent2.get()); + write32(file, ent2->getDirectMandatoryBases().size()); + for (std::vector< OUString >::const_iterator j( + ent2->getDirectMandatoryBases().begin()); + j != ent2->getDirectMandatoryBases().end(); ++j) + { + writeNameLen(file, *j); + } + write32(file, ent2->getDirectOptionalBases().size()); + for (std::vector< OUString >::const_iterator j( + ent2->getDirectOptionalBases().begin()); + j != ent2->getDirectOptionalBases().end(); ++j) + { + writeNameLen(file, *j); + } + write32(file, ent2->getDirectAttributes().size()); + for (std::vector< unoidl::InterfaceTypeEntity::Attribute >:: + const_iterator j(ent2->getDirectAttributes().begin()); + j != ent2->getDirectAttributes().end(); ++j) + { + sal_uInt64 f = 0; + if (j->bound) { + f |= 0x01; + } + if (j->readOnly) { + f |= 0x02; + } + write8(file, f); + writeNameLen(file, j->name); + writeNameLen(file, j->type); + write32(file, j->getExceptions.size()); + for (std::vector< OUString >::const_iterator k( + j->getExceptions.begin()); + k != j->getExceptions.end(); ++k) + { + writeNameLen(file, *k); + } + if (!j->readOnly) { + write32(file, j->setExceptions.size()); + for (std::vector< OUString >::const_iterator k( + j->setExceptions.begin()); + k != j->setExceptions.end(); ++k) + { + writeNameLen(file, *k); + } + } + } + write32(file, ent2->getDirectMethods().size()); + for (std::vector< unoidl::InterfaceTypeEntity::Method >:: + const_iterator j(ent2->getDirectMethods().begin()); + j != ent2->getDirectMethods().end(); ++j) + { + writeNameLen(file, j->name); + writeNameLen(file, j->returnType); + write32(file, j->parameters.size()); + for (std::vector< + unoidl::InterfaceTypeEntity::Method::Parameter >:: + const_iterator k(j->parameters.begin()); + k != j->parameters.end(); ++k) + { + write8(file, k->direction); + writeNameLen(file, k->name); + writeNameLen(file, k->type); + } + write32(file, j->exceptions.size()); + for (std::vector< OUString >::const_iterator k( + j->exceptions.begin()); + k != j->exceptions.end(); ++k) + { + writeNameLen(file, *k); + } + } + break; + } + case unoidl::Entity::SORT_TYPEDEF: + { + rtl::Reference< unoidl::TypedefEntity > ent2( + static_cast< unoidl::TypedefEntity * >( + i->second.entity.get())); + i->second.dataOffset = getOffset(file); + writeKind(file, ent2.get()); + writeNameLen(file, ent2->getType()); + break; + } + case unoidl::Entity::SORT_CONSTANT_GROUP: + { + rtl::Reference< unoidl::ConstantGroupEntity > ent2( + static_cast< unoidl::ConstantGroupEntity * >( + i->second.entity.get())); + struct ConstItem { + explicit ConstItem( + unoidl::ConstantValue const & theConstant): + constant(theConstant) + {} + unoidl::ConstantValue constant; + sal_uInt64 nameOffset; + sal_uInt64 dataOffset; + }; + std::map< OUString, ConstItem > cmap; + for (std::vector< unoidl::ConstantGroupEntity::Member >:: + const_iterator j(ent2->getMembers().begin()); + j != ent2->getMembers().end(); ++j) + { + if (!cmap.insert( + std::make_pair(j->name, ConstItem(j->value))). + second) + { + std::cout + << "Duplicate constant group member name \"" + << j->name << '"' << std::endl; + std::exit(EXIT_FAILURE); + } + } + for (std::map< OUString, ConstItem >::iterator j(cmap.begin()); + j != cmap.end(); ++j) + { + j->second.dataOffset = getOffset(file); + sal_uInt64 v = j->second.constant.type; + if (false /*TODO: deprecated */) { + v |= 0x80; + } + write8(file, v); + switch (j->second.constant.type) { + case unoidl::ConstantValue::TYPE_BOOLEAN: + write8(file, j->second.constant.booleanValue ? 1 : 0); + break; + case unoidl::ConstantValue::TYPE_BYTE: + write8( + file, + static_cast< sal_uInt8 >( + j->second.constant.byteValue)); + break; + case unoidl::ConstantValue::TYPE_SHORT: + write16( + file, + static_cast< sal_uInt16 >( + j->second.constant.shortValue)); + break; + case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT: + write16(file, j->second.constant.unsignedShortValue); + break; + case unoidl::ConstantValue::TYPE_LONG: + write32( + file, + static_cast< sal_uInt32 >( + j->second.constant.longValue)); + break; + case unoidl::ConstantValue::TYPE_UNSIGNED_LONG: + write32(file, j->second.constant.unsignedLongValue); + break; + case unoidl::ConstantValue::TYPE_HYPER: + write64( + file, + static_cast< sal_uInt64 >( + j->second.constant.hyperValue)); + break; + case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER: + write64(file, j->second.constant.unsignedHyperValue); + break; + case unoidl::ConstantValue::TYPE_FLOAT: + writeIso60599Binary32( + file, j->second.constant.floatValue); + break; + case unoidl::ConstantValue::TYPE_DOUBLE: + writeIso60599Binary64( + file, j->second.constant.doubleValue); + break; + default: + for (;;) { std::abort(); } // this cannot happen + } + } + for (std::map< OUString, ConstItem >::iterator j( + cmap.begin()); + j != cmap.end(); ++j) + { + j->second.nameOffset = writeNameNul(file, j->first); + } + i->second.dataOffset = getOffset(file); + writeKind(file, ent2.get()); + write32(file, cmap.size()); + // overflow from std::map::size_type -> sal_uInt64 is + // unrealistic + for (std::map< OUString, ConstItem >::iterator j( + cmap.begin()); + j != cmap.end(); ++j) + { + write32(file, j->second.nameOffset); + write32(file, j->second.dataOffset); + } + break; + } + case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE: + { + rtl::Reference< unoidl::SingleInterfaceBasedServiceEntity > + ent2( + static_cast< + unoidl::SingleInterfaceBasedServiceEntity * >( + i->second.entity.get())); + i->second.dataOffset = getOffset(file); + bool dfltCtor = ent2->getConstructors().size() == 1 + && ent2->getConstructors()[0].defaultConstructor; + writeKind(file, ent2.get(), dfltCtor); + writeNameLen(file, ent2->getBase()); + if (!dfltCtor) { + write32(file, ent2->getConstructors().size()); + for (std::vector< + unoidl::SingleInterfaceBasedServiceEntity:: + Constructor >::const_iterator j( + ent2->getConstructors().begin()); + j != ent2->getConstructors().end(); ++j) + { + if (j->defaultConstructor) { + std::cout + << "Unexpected default constructor \"" + << j->name << '"' << std::endl; + std::exit(EXIT_FAILURE); + } + writeNameLen(file, j->name); + write32(file, j->parameters.size()); + for (std::vector< + unoidl::SingleInterfaceBasedServiceEntity:: + Constructor::Parameter >::const_iterator k( + j->parameters.begin()); + k != j->parameters.end(); ++k) + { + sal_uInt64 f = 0; + if (k->rest) { + f |= 0x04; + } + write8(file, f); + writeNameLen(file, k->name); + writeNameLen(file, k->type); + } + write32(file, j->exceptions.size()); + for (std::vector< OUString >::const_iterator k( + j->exceptions.begin()); + k != j->exceptions.end(); ++k) + { + writeNameLen(file, *k); + } + } + } + break; + } + case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE: + { + rtl::Reference< unoidl::AccumulationBasedServiceEntity > ent2( + static_cast< unoidl::AccumulationBasedServiceEntity * >( + i->second.entity.get())); + i->second.dataOffset = getOffset(file); + writeKind(file, ent2.get()); + write32(file, ent2->getDirectMandatoryBaseServices().size()); + for (std::vector< OUString >::const_iterator j( + ent2->getDirectMandatoryBaseServices().begin()); + j != ent2->getDirectMandatoryBaseServices().end(); ++j) + { + writeNameLen(file, *j); + } + write32(file, ent2->getDirectOptionalBaseServices().size()); + for (std::vector< OUString >::const_iterator j( + ent2->getDirectOptionalBaseServices().begin()); + j != ent2->getDirectOptionalBaseServices().end(); ++j) + { + writeNameLen(file, *j); + } + write32(file, ent2->getDirectMandatoryBaseInterfaces().size()); + for (std::vector< OUString >::const_iterator j( + ent2->getDirectMandatoryBaseInterfaces().begin()); + j != ent2->getDirectMandatoryBaseInterfaces().end(); ++j) + { + writeNameLen(file, *j); + } + write32(file, ent2->getDirectOptionalBaseInterfaces().size()); + for (std::vector< OUString >::const_iterator j( + ent2->getDirectOptionalBaseInterfaces().begin()); + j != ent2->getDirectOptionalBaseInterfaces().end(); ++j) + { + writeNameLen(file, *j); + } + write32(file, ent2->getDirectProperties().size()); + for (std::vector< + unoidl::AccumulationBasedServiceEntity::Property >:: + const_iterator j( + ent2->getDirectProperties().begin()); + j != ent2->getDirectProperties().end(); ++j) + { + write16(file, static_cast< sal_uInt16 >(j->attributes)); + writeNameLen(file, j->name); + writeNameLen(file, j->type); + } + break; + } + case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON: + { + rtl::Reference< unoidl::InterfaceBasedSingletonEntity > ent2( + static_cast< unoidl::InterfaceBasedSingletonEntity * >( + i->second.entity.get())); + i->second.dataOffset = getOffset(file); + writeKind(file, ent2.get()); + writeNameLen(file, ent2->getBase()); + break; + } + case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON: + { + rtl::Reference< unoidl::ServiceBasedSingletonEntity > ent2( + static_cast< unoidl::ServiceBasedSingletonEntity * >( + i->second.entity.get())); + i->second.dataOffset = getOffset(file); + writeKind(file, ent2.get()); + writeNameLen(file, ent2->getBase()); + break; + } + } + } + for (std::map< OUString, Item >::iterator i(map.begin()); i != map.end(); + ++i) + { + i->second.nameOffset = writeNameNul(file, i->first); + } + sal_uInt64 off = getOffset(file); + if (rootSize == 0) { + write8(file, 0); // SORT_MODULE + write32(file, map.size()); + // overflow from std::map::size_type -> sal_uInt64 is unrealistic + } else { + *rootSize = map.size(); + // overflow from std::map::size_type -> std::size_t is unrealistic + } + for (std::map< OUString, Item >::iterator i(map.begin()); i != map.end(); + ++i) + { + write32(file, i->second.nameOffset); + write32(file, i->second.dataOffset); + } + return off; +} + +} + +SAL_IMPLEMENT_MAIN() { + sal_uInt32 args = rtl_getAppCommandArgCount(); + if (args < 2) { + std::cerr + << "Usage: reg2unoidl <extra .rdb files> <.rdb file> <unoidl file>" + << std::endl; + std::exit(EXIT_FAILURE); + } + rtl::Reference< unoidl::Manager > mgr(new unoidl::Manager); + for (sal_uInt32 i = 0; i != args - 2; ++i) { + mgr->addProvider(load(mgr, getArgumentUri(i))); + } + rtl::Reference< unoidl::Provider > prov( + load(mgr, getArgumentUri(args - 2))); + osl::File f(getArgumentUri(args - 1)); + osl::FileBase::RC e = f.open(osl_File_OpenFlag_Write); + if (e == osl::FileBase::E_NOENT) { + e = f.open(osl_File_OpenFlag_Write | osl_File_OpenFlag_Create); + } + if (e != osl::FileBase::E_None) { + std::cerr + << "Cannot open <" << f.getURL() << "> for writing, error code " + << +e << std::endl; + std::exit(EXIT_FAILURE); + } + write(f, "UNOIDL\0\xFF", 8); + write32(f, 0); // root map offset + write32(f, 0); // root map size + sal_uInt64 off; + std::size_t size; + try { + off = writeMap(f, prov->createRootCursor(), &size); + } catch (unoidl::FileFormatException & e) { + std::cerr + << "Bad input <" << e.getUri() << ">: " << e.getDetail() + << std::endl; + std::exit(EXIT_FAILURE); + } + e = f.setSize(getOffset(f)); // truncate in case it already existed + if (e != osl::FileBase::E_None) { + std::cerr + << "Cannot set size of <" << f.getURL() << ">, error code " << +e + << std::endl; + std::exit(EXIT_FAILURE); + } + e = f.setPos(osl_Pos_Absolut, 8); + if (e != osl::FileBase::E_None) { + std::cerr + << "Cannot rewind current position in <" << f.getURL() + << ">, error code " << +e << std::endl; + std::exit(EXIT_FAILURE); + } + write32(f, off); + write32(f, size); + // overflow from std::map::size_type -> sal_uInt64 is unrealistic + e = f.close(); + if (e != osl::FileBase::E_None) { + std::cerr + << "Cannot close <" << f.getURL() << "> after writing, error code " + << +e << std::endl; + std::exit(EXIT_FAILURE); + } + return EXIT_SUCCESS; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoidl/source/unoidl.cxx b/unoidl/source/unoidl.cxx index f34eee0ae7a6..0ffeb6bdd014 100644 --- a/unoidl/source/unoidl.cxx +++ b/unoidl/source/unoidl.cxx @@ -13,6 +13,7 @@ #include "rtl/ref.hxx" #include "rtl/ustring.hxx" +#include "unoidl/legacyprovider.hxx" #include "unoidl/unoidl.hxx" #include "unoidl/unoidlprovider.hxx" @@ -57,10 +58,41 @@ ServiceBasedSingletonEntity::~ServiceBasedSingletonEntity() throw () {} Provider::~Provider() throw () {} -rtl::Reference< Provider > loadProvider(OUString const & uri) { - return new UnoidlProvider(uri); +rtl::Reference< Provider > loadProvider( + rtl::Reference< Manager > const & manager, OUString const & uri) +{ + try { + return new UnoidlProvider(uri); + } catch (FileFormatException & e) { + SAL_INFO( + "unoidl", + "FileFormatException \"" << e.getDetail() << "\", retrying <" << uri + << "> as legacy format"); + return new LegacyProvider(manager, uri); + } } +void Manager::addProvider(rtl::Reference< Provider > const & provider) { + assert(provider.is()); + providers_.push_back(provider); +} + +rtl::Reference< Entity > Manager::findEntity(rtl::OUString const & name) const { + //TODO: add caching + for (std::vector< rtl::Reference< Provider > >::const_iterator i( + providers_.begin()); + i != providers_.end(); ++i) + { + rtl::Reference< Entity > ent((*i)->findEntity(name)); + if (ent.is()) { + return ent; + } + } + return rtl::Reference< Entity >(); +} + +Manager::~Manager() throw () {} + } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoidl/source/unoidlprovider.cxx b/unoidl/source/unoidlprovider.cxx index 03daf5aac222..da3a147113d7 100644 --- a/unoidl/source/unoidlprovider.cxx +++ b/unoidl/source/unoidlprovider.cxx @@ -1251,6 +1251,13 @@ rtl::Reference< MapCursor > UnoidlProvider::createRootCursor() const { return new UnoidlCursor(file_, mapBegin_, mapSize_); } +rtl::Reference< Entity > UnoidlProvider::findEntity(OUString const & name) const +{ + bool cnst; + sal_uInt32 off = find(name, &cnst); + return off == 0 || cnst ? rtl::Reference< Entity >() : getEntity(off); +} + sal_uInt32 UnoidlProvider::find(OUString const & name, bool * constant) const { detail::MapEntry const * mapBegin = mapBegin_; sal_uInt32 mapSize = mapSize_; |