From 320571bf701a092d0f2d15fd4589ae271802a03f Mon Sep 17 00:00:00 2001 From: Stephan Bergmann Date: Mon, 25 Feb 2013 15:31:05 +0100 Subject: WIP: Experimental new binary type.rdb format Move unoidl functionality into a module of its own, as a prerequisite to use it in codemaker etc. (This is intended to ultimately remove modules store and registry, modulo backwards compatibility constraints.) Change-Id: If5274cbd3a595951e6cf7a9664bc542f01833f38 --- unoidl/Library_unoidl.mk | 26 + unoidl/Makefile | 14 + unoidl/Module_unoidl.mk | 17 + unoidl/Package_inc.mk | 16 + unoidl/inc/unoidl/detail/dllapi.hxx | 26 + unoidl/inc/unoidl/detail/unoidldllapi.hxx | 26 + unoidl/inc/unoidl/unoidl.hxx | 618 ++++++++++++++ unoidl/inc/unoidl/unoidlprovider.hxx | 57 ++ unoidl/prj/build.lst | 2 + unoidl/prj/d.lst | 0 unoidl/source/unoidl.cxx | 66 ++ unoidl/source/unoidlprovider.cxx | 1313 +++++++++++++++++++++++++++++ 12 files changed, 2181 insertions(+) create mode 100644 unoidl/Library_unoidl.mk create mode 100644 unoidl/Makefile create mode 100644 unoidl/Module_unoidl.mk create mode 100644 unoidl/Package_inc.mk create mode 100644 unoidl/inc/unoidl/detail/dllapi.hxx create mode 100644 unoidl/inc/unoidl/detail/unoidldllapi.hxx create mode 100644 unoidl/inc/unoidl/unoidl.hxx create mode 100644 unoidl/inc/unoidl/unoidlprovider.hxx create mode 100644 unoidl/prj/build.lst create mode 100644 unoidl/prj/d.lst create mode 100644 unoidl/source/unoidl.cxx create mode 100644 unoidl/source/unoidlprovider.cxx (limited to 'unoidl') diff --git a/unoidl/Library_unoidl.mk b/unoidl/Library_unoidl.mk new file mode 100644 index 000000000000..8a7a668299e7 --- /dev/null +++ b/unoidl/Library_unoidl.mk @@ -0,0 +1,26 @@ +# -*- 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_Library_Library,unoidl)) + +$(eval $(call gb_Library_add_defs,unoidl,-DLO_DLLIMPLEMENTATION_UNOIDL)) + +$(eval $(call gb_Library_add_exception_objects,unoidl, \ + unoidl/source/unoidl \ + unoidl/source/unoidlprovider \ +)) + +$(eval $(call gb_Library_use_libraries,unoidl, \ + sal \ + salhelper \ +)) + +$(eval $(call gb_Library_use_package,unoidl,unoidl_inc)) + +# vim: set noet sw=4 ts=4: diff --git a/unoidl/Makefile b/unoidl/Makefile new file mode 100644 index 000000000000..0997e628485b --- /dev/null +++ b/unoidl/Makefile @@ -0,0 +1,14 @@ +# -*- 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/. +# + +module_directory:=$(dir $(realpath $(firstword $(MAKEFILE_LIST)))) + +include $(module_directory)/../solenv/gbuild/partial_build.mk + +# vim: set noet sw=4 ts=4: diff --git a/unoidl/Module_unoidl.mk b/unoidl/Module_unoidl.mk new file mode 100644 index 000000000000..7017b80a897c --- /dev/null +++ b/unoidl/Module_unoidl.mk @@ -0,0 +1,17 @@ +# -*- 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_Module_Module,unoidl)) + +$(eval $(call gb_Module_add_targets,unoidl, \ + Library_unoidl \ + Package_inc \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/unoidl/Package_inc.mk b/unoidl/Package_inc.mk new file mode 100644 index 000000000000..563ae365d07c --- /dev/null +++ b/unoidl/Package_inc.mk @@ -0,0 +1,16 @@ +# -*- 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_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/unoidl.hxx,unoidl.hxx)) +$(eval $(call gb_Package_add_file,unoidl_inc,inc/unoidl/unoidlprovider.hxx,unoidlprovider.hxx)) + +# vim: set noet sw=4 ts=4: diff --git a/unoidl/inc/unoidl/detail/dllapi.hxx b/unoidl/inc/unoidl/detail/dllapi.hxx new file mode 100644 index 000000000000..ad011ad4eb77 --- /dev/null +++ b/unoidl/inc/unoidl/detail/dllapi.hxx @@ -0,0 +1,26 @@ +/* -*- 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_DETAIL_DLLAPI_HXX +#define INCLUDED_UNOIDL_DETAIL_DLLAPI_HXX + +#include "sal/config.h" + +#include "sal/types.h" + +#if defined LO_DLLIMPLEMENTATION_UNOIDL +#define LO_DLLPUBLIC_UNOIDL SAL_DLLPUBLIC_EXPORT +#else +#define LO_DLLPUBLIC_UNOIDL SAL_DLLPUBLIC_IMPORT +#endif + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoidl/inc/unoidl/detail/unoidldllapi.hxx b/unoidl/inc/unoidl/detail/unoidldllapi.hxx new file mode 100644 index 000000000000..cfb1e90fd488 --- /dev/null +++ b/unoidl/inc/unoidl/detail/unoidldllapi.hxx @@ -0,0 +1,26 @@ +/* -*- 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_DETAIL_UNOIDLDLLAPI_HXX +#define INCLUDED_UNOIDL_DETAIL_UNOIDLDLLAPI_HXX + +#include "sal/config.h" + +#include "sal/types.h" + +#if defined LO_DLLIMPLEMENTATION_UNOIDL +#define LO_DLLPUBLIC_UNOIDL SAL_DLLPUBLIC_EXPORT +#else +#define LO_DLLPUBLIC_UNOIDL SAL_DLLPUBLIC_IMPORT +#endif + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoidl/inc/unoidl/unoidl.hxx b/unoidl/inc/unoidl/unoidl.hxx new file mode 100644 index 000000000000..372ed3889ade --- /dev/null +++ b/unoidl/inc/unoidl/unoidl.hxx @@ -0,0 +1,618 @@ +/* -*- 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_UNOIDL_HXX +#define INCLUDED_UNOIDL_UNOIDL_HXX + +#include "sal/config.h" + +#include +#include + +#include "rtl/ref.hxx" +#include "rtl/ustring.hxx" +#include "sal/types.h" +#include "salhelper/simplereferenceobject.hxx" +#include "unoidl/detail/dllapi.hxx" + +namespace unoidl { + +class LO_DLLPUBLIC_UNOIDL NoSuchFileException { +public: + SAL_DLLPRIVATE NoSuchFileException(rtl::OUString const & uri): uri_(uri) {} + + SAL_DLLPRIVATE NoSuchFileException(NoSuchFileException const & other): + uri_(other.uri_) {} + + virtual SAL_DLLPRIVATE ~NoSuchFileException() throw (); + + rtl::OUString getUri() const { return uri_; } + +private: + void operator =(NoSuchFileException) SAL_DELETED_FUNCTION; + + rtl::OUString uri_; +}; + +class LO_DLLPUBLIC_UNOIDL FileFormatException { +public: + SAL_DLLPRIVATE FileFormatException( + rtl::OUString const & uri, rtl::OUString const & detail): + uri_(uri), detail_(detail) + {} + + SAL_DLLPRIVATE FileFormatException(FileFormatException const & other): + uri_(other.uri_), detail_(other.detail_) + {} + + virtual SAL_DLLPRIVATE ~FileFormatException() throw (); + + rtl::OUString getUri() const { return uri_; } + + rtl::OUString getDetail() const { return detail_; } + +private: + void operator =(FileFormatException) SAL_DELETED_FUNCTION; + + rtl::OUString uri_; + rtl::OUString detail_; +}; + +class LO_DLLPUBLIC_UNOIDL Entity: public salhelper::SimpleReferenceObject { +public: + enum Sort { + SORT_MODULE, SORT_ENUM_TYPE, SORT_PLAIN_STRUCT_TYPE, + SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE, SORT_EXCEPTION_TYPE, + SORT_INTERFACE_TYPE, SORT_TYPEDEF, SORT_CONSTANT_GROUP, + SORT_SINGLE_INTERFACE_BASED_SERVICE, SORT_ACCUMULATION_BASED_SERVICE, + SORT_INTERFACE_BASED_SINGLETON, SORT_SERVICE_BASED_SINGLETON + }; + + Sort getSort() const { return sort_; } + +protected: + explicit SAL_DLLPRIVATE Entity(Sort sort): sort_(sort) {} + + virtual SAL_DLLPRIVATE ~Entity() throw (); + +private: + Sort sort_; +}; + +class LO_DLLPUBLIC_UNOIDL MapCursor: public salhelper::SimpleReferenceObject { +public: + // throws FileFormatException: + virtual rtl::Reference< Entity > getNext(rtl::OUString * name) = 0; + +protected: + SAL_DLLPRIVATE MapCursor() {} + + virtual SAL_DLLPRIVATE ~MapCursor() throw(); +}; + +class LO_DLLPUBLIC_UNOIDL ModuleEntity: public Entity { +public: + // throws FileFormatException: + virtual std::vector< rtl::OUString > getMemberNames() const = 0; + + // throws FileFormatException: + virtual rtl::Reference< MapCursor > createCursor() const = 0; + +protected: + SAL_DLLPRIVATE ModuleEntity(): Entity(SORT_MODULE) {} + + virtual SAL_DLLPRIVATE ~ModuleEntity() throw (); +}; + +class LO_DLLPUBLIC_UNOIDL PublishableEntity: public Entity { +public: + bool isPublished() const { return published_; } + +protected: + SAL_DLLPRIVATE PublishableEntity(Sort sort, bool published): + Entity(sort), published_(published) + {} + + virtual SAL_DLLPRIVATE ~PublishableEntity() throw (); + +private: + bool published_; +}; + +class LO_DLLPUBLIC_UNOIDL EnumTypeEntity: public PublishableEntity { +public: + struct Member { + Member(rtl::OUString const & theName, sal_Int32 theValue): + name(theName), value(theValue) + {} + + rtl::OUString name; + + sal_Int32 value; + }; + + SAL_DLLPRIVATE EnumTypeEntity( + bool published, std::vector< Member > const & members): + PublishableEntity(SORT_ENUM_TYPE, published), members_(members) + { assert(!members.empty()); } + + std::vector< Member > const & getMembers() const { return members_; } + +private: + virtual SAL_DLLPRIVATE ~EnumTypeEntity() throw (); + + std::vector< Member > members_; +}; + +class LO_DLLPUBLIC_UNOIDL PlainStructTypeEntity: public PublishableEntity { +public: + struct Member { + Member(rtl::OUString const & theName, rtl::OUString const & theType): + name(theName), type(theType) + {} + + rtl::OUString name; + + rtl::OUString type; + }; + + SAL_DLLPRIVATE PlainStructTypeEntity( + bool published, rtl::OUString const & directBase, + std::vector< Member > const & directMembers): + PublishableEntity(SORT_PLAIN_STRUCT_TYPE, published), + directBase_(directBase), directMembers_(directMembers) + {} + + rtl::OUString getDirectBase() const { return directBase_; } + + std::vector< Member > const & getDirectMembers() const + { return directMembers_; } + +private: + virtual SAL_DLLPRIVATE ~PlainStructTypeEntity() throw (); + + rtl::OUString directBase_; + std::vector< Member > directMembers_; +}; + +class LO_DLLPUBLIC_UNOIDL PolymorphicStructTypeTemplateEntity: + public PublishableEntity +{ +public: + struct Member { + Member( + rtl::OUString const & theName, rtl::OUString const & theType, + bool theParameterized): + name(theName), type(theType), parameterized(theParameterized) + {} + + rtl::OUString name; + + rtl::OUString type; + + bool parameterized; + }; + + SAL_DLLPRIVATE PolymorphicStructTypeTemplateEntity( + bool published, std::vector< rtl::OUString > const & typeParameters, + std::vector< Member > const & members): + PublishableEntity(SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE, published), + typeParameters_(typeParameters), members_(members) + {} + + std::vector< rtl::OUString > const & getTypeParameters() const + { return typeParameters_; } + + std::vector< Member > const & getMembers() const { return members_; } + +private: + virtual SAL_DLLPRIVATE ~PolymorphicStructTypeTemplateEntity() throw (); + + std::vector< rtl::OUString > typeParameters_; + std::vector< Member > members_; +}; + +class LO_DLLPUBLIC_UNOIDL ExceptionTypeEntity: public PublishableEntity { +public: + struct Member { + Member(rtl::OUString const & theName, rtl::OUString const & theType): + name(theName), type(theType) + {} + + rtl::OUString name; + + rtl::OUString type; + }; + + SAL_DLLPRIVATE ExceptionTypeEntity( + bool published, rtl::OUString const & directBase, + std::vector< Member > const & directMembers): + PublishableEntity(SORT_EXCEPTION_TYPE, published), + directBase_(directBase), directMembers_(directMembers) + {} + + rtl::OUString getDirectBase() const { return directBase_; } + + std::vector< Member > const & getDirectMembers() const + { return directMembers_; } + +private: + virtual SAL_DLLPRIVATE ~ExceptionTypeEntity() throw (); + + rtl::OUString directBase_; + std::vector< Member > directMembers_; +}; + +class LO_DLLPUBLIC_UNOIDL InterfaceTypeEntity: public PublishableEntity { +public: + struct Attribute { + Attribute( + rtl::OUString const & theName, rtl::OUString const & theType, + bool theBound, bool theReadOnly, + std::vector< rtl::OUString > const & theGetExceptions, + std::vector< rtl::OUString > const & theSetExceptions): + name(theName), type(theType), bound(theBound), + readOnly(theReadOnly), getExceptions(theGetExceptions), + setExceptions(theSetExceptions) + { assert(!theReadOnly || theSetExceptions.empty()); } + + rtl::OUString name; + + rtl::OUString type; + + bool bound; + + bool readOnly; + + std::vector< rtl::OUString > getExceptions; + + std::vector< rtl::OUString > setExceptions; + }; + + struct Method { + struct Parameter { + enum Direction { DIRECTION_IN, DIRECTION_OUT, DIRECTION_IN_OUT }; + + Parameter( + rtl::OUString const & theName, rtl::OUString const & theType, + Direction theDirection): + name(theName), type(theType), direction(theDirection) + {} + + rtl::OUString name; + + rtl::OUString type; + + Direction direction; + }; + + Method( + rtl::OUString const & theName, rtl::OUString const & theReturnType, + std::vector< Parameter > const & theParameters, + std::vector< rtl::OUString > const & theExceptions): + name(theName), returnType(theReturnType), parameters(theParameters), + exceptions(theExceptions) + {} + + rtl::OUString name; + + rtl::OUString returnType; + + std::vector< Parameter > parameters; + + std::vector< rtl::OUString > exceptions; + }; + + SAL_DLLPRIVATE InterfaceTypeEntity( + bool published, + std::vector< rtl::OUString > const & directMandatoryBases, + std::vector< rtl::OUString > const & directOptionalBases, + std::vector< Attribute > const & directAttributes, + std::vector< Method > const & directMethods): + PublishableEntity(SORT_INTERFACE_TYPE, published), + directMandatoryBases_(directMandatoryBases), + directOptionalBases_(directOptionalBases), + directAttributes_(directAttributes), directMethods_(directMethods) + {} + + std::vector< rtl::OUString > const & getDirectMandatoryBases() const + { return directMandatoryBases_; } + + std::vector< rtl::OUString > const & getDirectOptionalBases() const + { return directOptionalBases_; } + + std::vector< Attribute > const & getDirectAttributes() const + { return directAttributes_; } + + std::vector< Method > const & getDirectMethods() const + { return directMethods_; } + +private: + virtual SAL_DLLPRIVATE ~InterfaceTypeEntity() throw (); + + std::vector< rtl::OUString > directMandatoryBases_; + std::vector< rtl::OUString > directOptionalBases_; + std::vector< Attribute > directAttributes_; + std::vector< Method > directMethods_; +}; + +class LO_DLLPUBLIC_UNOIDL TypedefEntity: public PublishableEntity { +public: + SAL_DLLPRIVATE TypedefEntity(bool published, rtl::OUString const & type): + PublishableEntity(SORT_TYPEDEF, published), type_(type) + {} + + rtl::OUString getType() const { return type_; } + +private: + virtual SAL_DLLPRIVATE ~TypedefEntity() throw (); + + rtl::OUString type_; +}; + +struct LO_DLLPUBLIC_UNOIDL ConstantValue { + enum Type { + TYPE_BOOLEAN, TYPE_BYTE, TYPE_SHORT, TYPE_UNSIGNED_SHORT, TYPE_LONG, + TYPE_UNSIGNED_LONG, TYPE_HYPER, TYPE_UNSIGNED_HYPER, TYPE_FLOAT, + TYPE_DOUBLE }; + + explicit ConstantValue(bool value): type(TYPE_BOOLEAN), booleanValue(value) + {} + + explicit ConstantValue(sal_Int8 value): type(TYPE_BYTE), byteValue(value) {} + + explicit ConstantValue(sal_Int16 value): type(TYPE_SHORT), shortValue(value) + {} + + explicit ConstantValue(sal_uInt16 value): + type(TYPE_UNSIGNED_SHORT), unsignedShortValue(value) + {} + + explicit ConstantValue(sal_Int32 value): type(TYPE_LONG), longValue(value) + {} + + explicit ConstantValue(sal_uInt32 value): + type(TYPE_UNSIGNED_LONG), unsignedLongValue(value) + {} + + explicit ConstantValue(sal_Int64 value): type(TYPE_HYPER), hyperValue(value) + {} + + explicit ConstantValue(sal_uInt64 value): + type(TYPE_UNSIGNED_HYPER), unsignedHyperValue(value) + {} + + explicit ConstantValue(float value): type(TYPE_FLOAT), floatValue(value) {} + + explicit ConstantValue(double value): type(TYPE_DOUBLE), doubleValue(value) + {} + + Type type; + + union { + bool booleanValue; + sal_Int8 byteValue; + sal_Int16 shortValue; + sal_uInt16 unsignedShortValue; + sal_Int32 longValue; + sal_uInt32 unsignedLongValue; + sal_Int64 hyperValue; + sal_uInt64 unsignedHyperValue; + float floatValue; + double doubleValue; + }; +}; + +class LO_DLLPUBLIC_UNOIDL ConstantGroupEntity: public PublishableEntity { +public: + struct Member { + Member(rtl::OUString const & theName, ConstantValue const & theValue): + name(theName), value(theValue) + {} + + rtl::OUString name; + + ConstantValue value; + }; + + SAL_DLLPRIVATE ConstantGroupEntity( + bool published, std::vector< Member > const & members): + PublishableEntity(SORT_CONSTANT_GROUP, published), members_(members) + {} + + std::vector< Member > const & getMembers() const { return members_; } + +private: + virtual SAL_DLLPRIVATE ~ConstantGroupEntity() throw (); + + std::vector< Member > members_; +}; + +class LO_DLLPUBLIC_UNOIDL SingleInterfaceBasedServiceEntity: + public PublishableEntity +{ +public: + struct Constructor { + struct Parameter { + Parameter( + rtl::OUString const & theName, rtl::OUString const & theType, + bool theRest): + name(theName), type(theType), rest(theRest) + {} + + rtl::OUString name; + + rtl::OUString type; + + bool rest; + }; + + Constructor(): defaultConstructor(true) {} + + Constructor( + rtl::OUString const & theName, + std::vector< Parameter > const & theParameters, + std::vector< rtl::OUString > const & theExceptions): + name(theName), parameters(theParameters), exceptions(theExceptions), + defaultConstructor(false) + {} + + rtl::OUString name; + + std::vector< Parameter > parameters; + + std::vector< rtl::OUString > exceptions; + + bool defaultConstructor; + }; + + SAL_DLLPRIVATE SingleInterfaceBasedServiceEntity( + bool published, rtl::OUString const & base, + std::vector< Constructor > const & constructors): + PublishableEntity(SORT_SINGLE_INTERFACE_BASED_SERVICE, published), + base_(base), constructors_(constructors) + {} + + rtl::OUString getBase() const { return base_; } + + std::vector< Constructor > const & getConstructors() const + { return constructors_; } + +private: + virtual SAL_DLLPRIVATE ~SingleInterfaceBasedServiceEntity() throw (); + + rtl::OUString base_; + std::vector< Constructor > constructors_; +}; + +class LO_DLLPUBLIC_UNOIDL AccumulationBasedServiceEntity: + public PublishableEntity +{ +public: + struct Property { + enum Attributes { + ATTRIBUTE_MAYBE_VOID = 0x001, + ATTRIBUTE_BOUND = 0x002, + ATTRIBUTE_CONSTRAINED = 0x004, + ATTRIBUTE_TRANSIENT = 0x008, + ATTRIBUTE_READ_ONLY = 0x010, + ATTRIBUTE_MAYBE_AMBIGUOUS = 0x020, + ATTRIBUTE_MAYBE_DEFAULT = 0x040, + ATTRIBUTE_REMOVABLE = 0x080, + ATTRIBUTE_OPTIONAL = 0x100 + }; + + Property( + rtl::OUString const & theName, rtl::OUString const & theType, + Attributes theAttributes): + name(theName), type(theType), attributes(theAttributes) + {} + + rtl::OUString name; + + rtl::OUString type; + + Attributes attributes; + }; + + SAL_DLLPRIVATE AccumulationBasedServiceEntity( + bool published, + std::vector< rtl::OUString > const & directMandatoryBaseServices, + std::vector< rtl::OUString > const & directOptionalBaseServices, + std::vector< rtl::OUString > const & directMandatoryBaseInterfaces, + std::vector< rtl::OUString > const & directOptionalBaseInterfaces, + std::vector< Property > const & directProperties): + PublishableEntity(SORT_ACCUMULATION_BASED_SERVICE, published), + directMandatoryBaseServices_(directMandatoryBaseServices), + directOptionalBaseServices_(directOptionalBaseServices), + directMandatoryBaseInterfaces_(directMandatoryBaseInterfaces), + directOptionalBaseInterfaces_(directOptionalBaseInterfaces), + directProperties_(directProperties) + {} + + std::vector< rtl::OUString > const & getDirectMandatoryBaseServices() const + { return directMandatoryBaseServices_; } + + std::vector< rtl::OUString > const & getDirectOptionalBaseServices() const + { return directOptionalBaseServices_; } + + std::vector< rtl::OUString > const & getDirectMandatoryBaseInterfaces() + const + { return directMandatoryBaseInterfaces_; } + + std::vector< rtl::OUString > const & getDirectOptionalBaseInterfaces() const + { return directOptionalBaseInterfaces_; } + + std::vector< Property > const & getDirectProperties() const + { return directProperties_; } + +private: + virtual SAL_DLLPRIVATE ~AccumulationBasedServiceEntity() throw (); + + std::vector< rtl::OUString > directMandatoryBaseServices_; + std::vector< rtl::OUString > directOptionalBaseServices_; + std::vector< rtl::OUString > directMandatoryBaseInterfaces_; + std::vector< rtl::OUString > directOptionalBaseInterfaces_; + std::vector< Property > directProperties_; +}; + +class LO_DLLPUBLIC_UNOIDL InterfaceBasedSingletonEntity: + public PublishableEntity +{ +public: + SAL_DLLPRIVATE InterfaceBasedSingletonEntity( + bool published, rtl::OUString const & base): + PublishableEntity(SORT_INTERFACE_BASED_SINGLETON, published), + base_(base) + {} + + rtl::OUString getBase() const { return base_; } + +private: + virtual SAL_DLLPRIVATE ~InterfaceBasedSingletonEntity() throw (); + + rtl::OUString base_; +}; + +class LO_DLLPUBLIC_UNOIDL ServiceBasedSingletonEntity: public PublishableEntity +{ +public: + SAL_DLLPRIVATE ServiceBasedSingletonEntity( + bool published, rtl::OUString const & base): + PublishableEntity(SORT_SERVICE_BASED_SINGLETON, published), base_(base) + {} + + rtl::OUString getBase() const { return base_; } + +private: + virtual SAL_DLLPRIVATE ~ServiceBasedSingletonEntity() throw (); + + rtl::OUString base_; +}; + +class LO_DLLPUBLIC_UNOIDL Provider: public salhelper::SimpleReferenceObject { +public: + // throws FileFormatException: + virtual rtl::Reference< MapCursor > createRootCursor() const = 0; + +protected: + SAL_DLLPRIVATE Provider() {} + + virtual SAL_DLLPRIVATE ~Provider() throw (); +}; + +// throws FileFormatException, NoSuchFileException: +LO_DLLPUBLIC_UNOIDL rtl::Reference< Provider > loadProvider( + rtl::OUString const & uri); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoidl/inc/unoidl/unoidlprovider.hxx b/unoidl/inc/unoidl/unoidlprovider.hxx new file mode 100644 index 000000000000..07388a604034 --- /dev/null +++ b/unoidl/inc/unoidl/unoidlprovider.hxx @@ -0,0 +1,57 @@ +/* -*- 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_UNOIDLPROVIDER_HXX +#define INCLUDED_UNOIDL_UNOIDLPROVIDER_HXX + +#include "sal/config.h" + +#include "rtl/ref.hxx" +#include "sal/types.h" +#include "unoidl/detail/dllapi.hxx" +#include "unoidl/unoidl.hxx" + +namespace rtl { class OUString; } +namespace unoidl { namespace detail { + class MappedFile; + struct MapEntry; +} } + +namespace unoidl { + +class LO_DLLPUBLIC_UNOIDL UnoidlProvider: public Provider { +public: + // throws FileFormatException, NoSuchFileException: + explicit UnoidlProvider(rtl::OUString const & uri); + + // throws FileFormatException: + virtual rtl::Reference< MapCursor > createRootCursor() const; + + // throws FileFormatException: + sal_uInt32 find(rtl::OUString const & name, bool * constant = 0) const; + + // throws FileFormatException: + rtl::Reference< Entity > getEntity(sal_uInt32 offset) const; + + // throws FileFormatException: + ConstantValue getConstant(sal_uInt32 offset) const; + +private: + virtual SAL_DLLPRIVATE ~UnoidlProvider() throw (); + + rtl::Reference< detail::MappedFile > file_; + detail::MapEntry const * mapBegin_; + sal_uInt32 mapSize_; +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoidl/prj/build.lst b/unoidl/prj/build.lst new file mode 100644 index 000000000000..32409d2a0b63 --- /dev/null +++ b/unoidl/prj/build.lst @@ -0,0 +1,2 @@ +un unoidl: sal salhelper NULL +un unoidl\prj nmake - all un_prj NULL diff --git a/unoidl/prj/d.lst b/unoidl/prj/d.lst new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/unoidl/source/unoidl.cxx b/unoidl/source/unoidl.cxx new file mode 100644 index 000000000000..f34eee0ae7a6 --- /dev/null +++ b/unoidl/source/unoidl.cxx @@ -0,0 +1,66 @@ +/* -*- 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 + +#include "rtl/ref.hxx" +#include "rtl/ustring.hxx" +#include "unoidl/unoidl.hxx" +#include "unoidl/unoidlprovider.hxx" + +namespace unoidl { + +NoSuchFileException::~NoSuchFileException() throw () {} + +FileFormatException::~FileFormatException() throw () {} + +Entity::~Entity() throw () {} + +MapCursor::~MapCursor() throw () {} + +ModuleEntity::~ModuleEntity() throw () {} + +PublishableEntity::~PublishableEntity() throw () {} + +EnumTypeEntity::~EnumTypeEntity() throw () {} + +PlainStructTypeEntity::~PlainStructTypeEntity() throw () {} + +PolymorphicStructTypeTemplateEntity::~PolymorphicStructTypeTemplateEntity() + throw () +{} + +ExceptionTypeEntity::~ExceptionTypeEntity() throw () {} + +InterfaceTypeEntity::~InterfaceTypeEntity() throw () {} + +TypedefEntity::~TypedefEntity() throw () {} + +ConstantGroupEntity::~ConstantGroupEntity() throw () {} + +SingleInterfaceBasedServiceEntity::~SingleInterfaceBasedServiceEntity() throw () +{} + +AccumulationBasedServiceEntity::~AccumulationBasedServiceEntity() throw () {} + +InterfaceBasedSingletonEntity::~InterfaceBasedSingletonEntity() throw () {} + +ServiceBasedSingletonEntity::~ServiceBasedSingletonEntity() throw () {} + +Provider::~Provider() throw () {} + +rtl::Reference< Provider > loadProvider(OUString const & uri) { + return new UnoidlProvider(uri); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unoidl/source/unoidlprovider.cxx b/unoidl/source/unoidlprovider.cxx new file mode 100644 index 000000000000..03daf5aac222 --- /dev/null +++ b/unoidl/source/unoidlprovider.cxx @@ -0,0 +1,1313 @@ +/* -*- 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 +#include +#include +#include + +#include "osl/endian.h" +#include "osl/file.h" +#include "rtl/ref.hxx" +#include "rtl/ustring.hxx" +#include "sal/log.hxx" +#include "sal/types.h" +#include "salhelper/simplereferenceobject.hxx" +#include "unoidl/unoidl.hxx" +#include "unoidl/unoidlprovider.hxx" + +// New binary format: +// +// Uses the following definitions: +// +// * UInt16: 2-byte value, LSB first +// * UInt32: 4-byte value, LSB first +// * UInt64: 8-byte value, LSB first +// * Offset: UInt32 value, counting bytes from start of file +// * NUL-Name: zero or more non-NUL US-ASCII bytes followed by a NUL byte +// * Len-Name: UInt32 number of characters, with 0x80000000 bit 1, followed by +// that many (- 0x80000000) US-ASCII bytes +// * Idx-Name: either an Offset (with 0x80000000 bit 0) of a Len-Name, or a +// Len-Name +// * Entry: Offset of NUL-Name followed by Offset of payload +// * Map: zero or more Entries +// +// Layout of per-entry payload in the root or a module Map: +// +// * kind byte: +// ** 0: module +// *** followed by: +// **** UInt32 number N1 of entries of Map +// **** N1 * Entry +// ** otherwise: +// *** 0x80 bit: 1 if published +// *** 0x40 bit: 1 if deprecated +// *** 0x20 bit: flag (may only be 1 for certain kinds, see below) +// *** remaining bits: +// **** 1: enum type +// ***** followed by: +// ****** UInt32 number N1 of members +// ****** N1 * tuple of: +// ******* Offset of Idx-Name +// ******* UInt32 +// **** 2: plain struct type (with base if flag is 1) +// ***** followed by: +// ****** if "with base": Offset of Idx-Name +// ****** UInt32 number N1 of direct members +// ****** N1 * tuple of: +// ******* Offset of Idx-Name name +// ******* Offset of Idx-Name type +// **** 3: polymorphic struct type template +// ***** followed by: +// ****** UInt32 number N1 of type parameters +// ****** N1 * Offset of Idx-Name +// ****** UInt32 number N2 of members +// ****** N2 * tuple of: +// ******* kind byte: 0x01 bit is 1 if parameterized type +// ******* Offset of Idx-Name name +// ******* Offset of Idx-Name type +// **** 4: exception type (with base if flag is 1) +// ***** followed by: +// ****** if "with base": Offset of Idx-Name +// ****** UInt32 number N1 of direct members +// ****** N1 * tuple of: +// ******* Offset of Idx-Name name +// ******* Offset of Idx-Name type +// **** 5: interface type +// ***** followed by: +// ****** UInt32 number N1 of direct mandatory bases +// ****** N1 * Offset of Idx-Name +// ****** UInt32 number N2 of direct optional bases +// ****** N2 * Offset of Idx-Name +// ****** UInt32 number N3 of direct attributes +// ****** N3 * tuple of: +// ******* kind byte: +// ******** 0x02 bit: 1 if read-only +// ******** 0x01 bit: 1 if bound +// ******* Offset of Idx-Name name +// ******* Offset of Idx-Name type +// ******* UInt32 number N4 of get exceptions +// ******* N4 * Offset of Idx-Name +// ******* UInt32 number N5 of set exceptions +// ******* N5 * Offset of Idx-Name +// ****** UInt32 number N6 of direct methods +// ****** N6 * tuple of: +// ******* Offset of Idx-Name name +// ******* Offset of Idx-Name return type +// ******* UInt32 number N7 of parameters +// ******* N7 * tuple of: +// ******** direction byte: 0 for in, 1 for out, 2 for in-out +// ******** Offset of Idx-Name name +// ******** Offset of Idx-Name type +// ******* UInt32 number N8 of exceptions +// ******* N8 * Offset of Idx-Name +// **** 6: typedef +// ***** followed by: +// ****** Offset of Idx-Name +// **** 7: constant group +// ***** followed by: +// ****** UInt32 number N1 of entries of Map +// ****** N1 * Entry +// **** 8: single-interface--based service (with default constructor if flag is +// 1) +// ***** followed by: +// ****** Offset of Idx-Name +// ****** if not "with default constructor": +// ******* UInt32 number N1 of constructors +// ******* N1 * tuple of: +// ******** Offset of Idx-Name +// ******** UInt32 number N2 of parameters +// ******** N2 * tuple of +// ********* kind byte: 0x04 bit is 1 if rest parameter +// ********* Offset of Idx-Name name +// ********* Offset of Idx-Name type +// ******** UInt32 number N3 of exceptions +// ******** N3 * Offset of Idx-Name +// **** 9: accumulation-based service +// ***** followed by: +// ****** UInt32 number N1 of direct mandatory base services +// ****** N1 * Offset of Idx-Name +// ****** UInt32 number N2 of direct optional base services +// ****** N2 * Offset of Idx-Name +// ****** UInt32 number N3 of direct mandatory base interfaces +// ****** N3 * Offset of Idx-Name +// ****** UInt32 number N4 of direct optional base interfaces +// ****** N4 * Offset of Idx-Name +// ****** UInt32 number N5 of direct properties +// ****** N5 * tuple of: +// ******* UInt16 kind: +// ******** 0x0100 bit: 1 if optional +// ******** 0x0080 bit: 1 if removable +// ******** 0x0040 bit: 1 if maybedefault +// ******** 0x0020 bit: 1 if maybeambiguous +// ******** 0x0010 bit: 1 if readonly +// ******** 0x0008 bit: 1 if transient +// ******** 0x0004 bit: 1 if constrained +// ******** 0x0002 bit: 1 if bound +// ******** 0x0001 bit: 1 if maybevoid +// ******* Offset of Idx-Name name +// ******* Offset of Idx-Name type +// **** 10: interface-based singleton +// ***** followed by: +// ****** Offset of Idx-Name +// **** 11: service-based singleton +// ***** followed by: +// ****** Offset of Idx-Name +// +// Layout of per-entry payload in a constant group Map: +// +// * kind byte: +// ** 0x80 bit: 1 if deprecated +// ** remaining bits: +// *** 0: BOOLEAN +// **** followed by value byte, 0 represents false, 1 represents true +// *** 1: BYTE +// **** followed by value byte, representing values with two's complement +// *** 2: SHORT +// **** followed by UInt16 value, representing values with two's complement +// *** 3: UNSIGNED SHORT +// **** followed by UInt16 value +// *** 4: LONG +// **** followed by UInt32 value, representing values with two's complement +// *** 5: UNSIGNED LONG +// **** followed by UInt32 value +// *** 6: HYPER +// **** followed by UInt64 value, representing values with two's complement +// *** 7: UNSIGNED HYPER +// **** followed by UInt64 value +// *** 8: FLOAT +// **** followed by 4-byte value, representing values in ISO 60599 binary32 +// format, LSB first +// *** 9: DOUBLE +// **** followed by 8-byte value, representing values in ISO 60599 binary64 +// format, LSB first +// +// Memory layout: +// +// * 8 byte header "UNOIDL\0\xFF +// * Offset of root Map +// * UInt32 number of entries of root Map +// ... + +namespace { + +// sizeof (Memory16) == 2 +struct Memory16 { + unsigned char byte[2]; + + sal_uInt16 getUnsigned16() const { + return static_cast< sal_uInt16 >(byte[0]) + | (static_cast< sal_uInt16 >(byte[1]) << 8); + } +}; + +// sizeof (Memory32) == 4 +struct Memory32 { + unsigned char byte[4]; + + sal_uInt32 getUnsigned32() const { + return static_cast< sal_uInt32 >(byte[0]) + | (static_cast< sal_uInt32 >(byte[1]) << 8) + | (static_cast< sal_uInt32 >(byte[2]) << 16) + | (static_cast< sal_uInt32 >(byte[3]) << 24); + } + + float getIso60599Binary32() const { + union { + unsigned char buf[4]; + float f; // assuming float is ISO 60599 binary32 + } sa; +#if defined OSL_LITENDIAN + sa.buf[0] = byte[0]; + sa.buf[1] = byte[1]; + sa.buf[2] = byte[2]; + sa.buf[3] = byte[3]; +#else + sa.buf[0] = byte[3]; + sa.buf[1] = byte[2]; + sa.buf[2] = byte[1]; + sa.buf[3] = byte[0]; +#endif + return sa.f; + } +}; + +// sizeof (Memory64) == 8 +struct Memory64 { + unsigned char byte[8]; + + sal_uInt64 getUnsigned64() const { + return static_cast< sal_uInt64 >(byte[0]) + | (static_cast< sal_uInt64 >(byte[1]) << 8) + | (static_cast< sal_uInt64 >(byte[2]) << 16) + | (static_cast< sal_uInt64 >(byte[3]) << 24) + | (static_cast< sal_uInt64 >(byte[4]) << 32) + | (static_cast< sal_uInt64 >(byte[5]) << 40) + | (static_cast< sal_uInt64 >(byte[6]) << 48) + | (static_cast< sal_uInt64 >(byte[7]) << 56); + } + + double getIso60599Binary64() const { + union { + unsigned char buf[8]; + double d; // assuming double is ISO 60599 binary64 + } sa; +#if defined OSL_LITENDIAN + sa.buf[0] = byte[0]; + sa.buf[1] = byte[1]; + sa.buf[2] = byte[2]; + sa.buf[3] = byte[3]; + sa.buf[4] = byte[4]; + sa.buf[5] = byte[5]; + sa.buf[6] = byte[6]; + sa.buf[7] = byte[7]; +#else + sa.buf[0] = byte[7]; + sa.buf[1] = byte[6]; + sa.buf[2] = byte[5]; + sa.buf[3] = byte[4]; + sa.buf[4] = byte[3]; + sa.buf[5] = byte[2]; + sa.buf[6] = byte[1]; + sa.buf[7] = byte[0]; +#endif + return sa.d; + } +}; + +} + +namespace unoidl { + +namespace detail { + +class MappedFile: public salhelper::SimpleReferenceObject { +public: + explicit MappedFile(OUString const & fileUrl); + + sal_uInt8 read8(sal_uInt32 offset) const; + + sal_uInt16 read16(sal_uInt32 offset) const; + + sal_uInt32 read32(sal_uInt32 offset) const; + + sal_uInt64 read64(sal_uInt32 offset) const; + + float readIso60599Binary32(sal_uInt32 offset) const; + + double readIso60599Binary64(sal_uInt32 offset) const; + + OUString readNameNul(sal_uInt32 offset) const; + + OUString readNameLen(sal_uInt32 offset, sal_uInt32 * newOffset = 0) const; + + OUString uri; + oslFileHandle handle; + sal_uInt64 size; + void * address; + +private: + virtual ~MappedFile(); + + sal_uInt8 get8(sal_uInt32 offset) const; + + sal_uInt16 get16(sal_uInt32 offset) const; + + sal_uInt32 get32(sal_uInt32 offset) const; + + sal_uInt64 get64(sal_uInt32 offset) const; + + float getIso60599Binary32(sal_uInt32 offset) const; + + double getIso60599Binary64(sal_uInt32 offset) const; +}; + +MappedFile::MappedFile(OUString const & fileUrl): uri(fileUrl) { + oslFileError e = osl_openFile(uri.pData, &handle, osl_File_OpenFlag_Read); + switch (e) { + case osl_File_E_None: + break; + case osl_File_E_NOENT: + throw NoSuchFileException(uri); + default: + throw FileFormatException(uri, "cannot open: " + OUString::number(e)); + } + e = osl_getFileSize(handle, &size); + if (e == osl_File_E_None) { + e = osl_mapFile( + handle, &address, size, 0, osl_File_MapFlag_RandomAccess); + } + if (e != osl_File_E_None) { + oslFileError e2 = osl_closeFile(handle); + SAL_WARN_IF( + e2 != osl_File_E_None, "unoidl", + "cannot close " << uri << ": " << +e2); + throw FileFormatException(uri, "cannot mmap: " + OUString::number(e)); + } +} + +sal_uInt8 MappedFile::read8(sal_uInt32 offset) const { + assert(size >= 8); + if (offset > size - 1) { + throw FileFormatException( + uri, "UNOIDL format: offset for 8-bit value too large"); + } + return get8(offset); +} + +sal_uInt16 MappedFile::read16(sal_uInt32 offset) const { + assert(size >= 8); + if (offset > size - 2) { + throw FileFormatException( + uri, "UNOIDL format: offset for 16-bit value too large"); + } + return get16(offset); +} + +sal_uInt32 MappedFile::read32(sal_uInt32 offset) const { + assert(size >= 8); + if (offset > size - 4) { + throw FileFormatException( + uri, "UNOIDL format: offset for 32-bit value too large"); + } + return get32(offset); +} + +sal_uInt64 MappedFile::read64(sal_uInt32 offset) const { + assert(size >= 8); + if (offset > size - 8) { + throw FileFormatException( + uri, "UNOIDL format: offset for 64-bit value too large"); + } + return get64(offset); +} + +float MappedFile::readIso60599Binary32(sal_uInt32 offset) const { + assert(size >= 8); + if (offset > size - 4) { + throw FileFormatException( + uri, "UNOIDL format: offset for 32-bit value too large"); + } + return getIso60599Binary32(offset); +} + +double MappedFile::readIso60599Binary64(sal_uInt32 offset) const { + assert(size >= 8); + if (offset > size - 8) { + throw FileFormatException( + uri, "UNOIDL format: offset for 64-bit value too large"); + } + return getIso60599Binary64(offset); +} + +OUString MappedFile::readNameNul(sal_uInt32 offset) const { + if (offset > size) { + throw FileFormatException( + uri, "UNOIDL format: offset for string too large"); + } + sal_uInt64 end = offset; + for (;; ++end) { + if (end == size) { + throw FileFormatException( + uri, "UNOIDL format: string misses trailing NUL"); + } + if (static_cast< char const * >(address)[end] == 0) { + break; + } + } + if (end - offset > SAL_MAX_INT32) { + throw FileFormatException(uri, "UNOIDL format: string too long"); + } + OUString name; + if (!rtl_convertStringToUString( + &name.pData, static_cast< char const * >(address) + offset, + end - offset, RTL_TEXTENCODING_ASCII_US, + (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR + | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR + | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR))) + { + throw FileFormatException(uri, "UNOIDL format: name is not ASCII"); + } + return name; +} + +OUString MappedFile::readNameLen(sal_uInt32 offset, sal_uInt32 * newOffset) + const +{ + sal_uInt32 len = read32(offset); + if ((len & 0x80000000) == 0) { + if (newOffset != 0) { + *newOffset = offset + 4; + } + offset = len; + len = read32(offset); + if ((len & 0x80000000) == 0) { + throw FileFormatException( + uri, "UNOIDL format: name length high bit unset"); + } + len &= ~0x80000000; + } else { + len &= ~0x80000000; + if (newOffset != 0) { + *newOffset = offset + 4 + len; + } + } + if (len > SAL_MAX_INT32 || len > size - offset - 4) { + throw FileFormatException( + uri, "UNOIDL format: size of name is too large"); + } + OUString name; + if (!rtl_convertStringToUString( + &name.pData, static_cast< char const * >(address) + offset + 4, len, + RTL_TEXTENCODING_ASCII_US, + (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR + | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR + | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR))) + { + throw FileFormatException(uri, "UNOIDL format: name is not ASCII"); + } + return name; +} + +MappedFile::~MappedFile() { + oslFileError e = osl_unmapMappedFile(handle, address, size); + SAL_WARN_IF(e != osl_File_E_None, "unoidl", "cannot unmap: " << +e); + e = osl_closeFile(handle); + SAL_WARN_IF(e != osl_File_E_None, "unoidl", "cannot close: " << +e); +} + +sal_uInt8 MappedFile::get8(sal_uInt32 offset) const { + assert(size >= 8); + assert(offset <= size - 1); + return static_cast< char const * >(address)[offset]; +} + +sal_uInt16 MappedFile::get16(sal_uInt32 offset) const { + assert(size >= 8); + assert(offset <= size - 2); + return reinterpret_cast< Memory16 const * >( + static_cast< char const * >(address) + offset)->getUnsigned16(); +} + +sal_uInt32 MappedFile::get32(sal_uInt32 offset) const { + assert(size >= 8); + assert(offset <= size - 4); + return reinterpret_cast< Memory32 const * >( + static_cast< char const * >(address) + offset)->getUnsigned32(); +} + +sal_uInt64 MappedFile::get64(sal_uInt32 offset) const { + assert(size >= 8); + assert(offset <= size - 8); + return reinterpret_cast< Memory64 const * >( + static_cast< char const * >(address) + offset)->getUnsigned64(); +} + +float MappedFile::getIso60599Binary32(sal_uInt32 offset) const { + assert(size >= 8); + assert(offset <= size - 4); + return reinterpret_cast< Memory32 const * >( + static_cast< char const * >(address) + offset)->getIso60599Binary32(); +} + +double MappedFile::getIso60599Binary64(sal_uInt32 offset) const { + assert(size >= 8); + assert(offset <= size - 8); + return reinterpret_cast< Memory64 const * >( + static_cast< char const * >(address) + offset)->getIso60599Binary64(); +} + +// sizeof (MapEntry) == 8 +struct MapEntry { + Memory32 name; + Memory32 data; +}; + +} + +namespace { + +enum Compare { COMPARE_LESS, COMPARE_GREATER, COMPARE_EQUAL }; + +Compare compare( + rtl::Reference< detail::MappedFile > const & file, OUString const & name, + sal_Int32 nameOffset, sal_Int32 nameLength, detail::MapEntry const * entry) +{ + assert(file.is()); + assert(entry != 0); + sal_uInt32 off = entry->name.getUnsigned32(); + if (off > file->size - 1) { // at least a trailing NUL + throw FileFormatException( + file->uri, "UNOIDL format: string offset too large"); + } + assert(nameLength >= 0); + sal_uInt64 min = std::min( + static_cast< sal_uInt64 >(nameLength), file->size - off); + for (sal_uInt64 i = 0; i != min; ++i) { + sal_Unicode c1 = name[nameOffset + i]; + sal_Unicode c2 = static_cast< unsigned char const * >(file->address)[ + off + i]; + if (c1 < c2) { + return COMPARE_LESS; + } else if (c1 > c2 || c2 == 0) { + // ...the "|| c2 == 0" is for the odd case where name erroneously + // contains NUL characters + return COMPARE_GREATER; + } + } + if (static_cast< sal_uInt64 >(nameLength) == min) { + if (file->size - off == min) { + throw FileFormatException( + file->uri, "UNOIDL format: string misses trailing NUL"); + } + return + static_cast< unsigned char const * >(file->address)[off + min] == 0 + ? COMPARE_EQUAL : COMPARE_LESS; + } else { + return COMPARE_GREATER; + } +} + +sal_uInt32 findInMap( + rtl::Reference< detail::MappedFile > const & file, + detail::MapEntry const * mapBegin, sal_uInt32 mapSize, + OUString const & name, sal_Int32 nameOffset, sal_Int32 nameLength) +{ + if (mapSize == 0) { + return 0; + } + sal_uInt32 n = mapSize / 2; + detail::MapEntry const * p = mapBegin + n; + switch (compare(file, name, nameOffset, nameLength, p)) { + case COMPARE_LESS: + return findInMap(file, mapBegin, n, name, nameOffset, nameLength); + case COMPARE_GREATER: + return findInMap( + file, p + 1, mapSize - n - 1, name, nameOffset, nameLength); + default: // COMPARE_EQUAL + break; + } + sal_uInt32 off = mapBegin[n].data.getUnsigned32(); + if (off == 0) { + throw FileFormatException( + file->uri, "UNOIDL format: map entry data offset is null"); + } + return off; +} + +ConstantValue readConstant( + rtl::Reference< detail::MappedFile > const & file, sal_uInt32 offset) +{ + assert(file.is()); + int v = file->read8(offset); + int type = v & 0x7F; + bool deprecated = (v & 0x80) != 0; (void)deprecated;//TODO + switch (type) { + case 0: // BOOLEAN + v = file->read8(offset + 1); + switch (v) { + case 0: + return ConstantValue(false); + case 1: + return ConstantValue(true); + default: + throw FileFormatException( + file->uri, + ("UNOIDL format: bad boolean constant value " + + OUString::number(v))); + } + case 1: // BYTE + return ConstantValue(static_cast< sal_Int8 >(file->read8(offset + 1))); + //TODO: implementation-defined behavior of conversion from sal_uInt8 + // to sal_Int8 relies on two's complement representation + case 2: // SHORT + return ConstantValue( + static_cast< sal_Int16 >(file->read16(offset + 1))); + //TODO: implementation-defined behavior of conversion from + // sal_uInt16 to sal_Int16 relies on two's complement representation + case 3: // UNSIGNED SHORT + return ConstantValue(file->read16(offset + 1)); + case 4: // LONG + return ConstantValue( + static_cast< sal_Int32 >(file->read32(offset + 1))); + //TODO: implementation-defined behavior of conversion from + // sal_uInt32 to sal_Int32 relies on two's complement representation + case 5: // UNSIGNED LONG + return ConstantValue(file->read32(offset + 1)); + case 6: // HYPER + return ConstantValue( + static_cast< sal_Int64 >(file->read64(offset + 1))); + //TODO: implementation-defined behavior of conversion from + // sal_uInt64 to sal_Int64 relies on two's complement representation + case 7: // UNSIGNED HYPER + return ConstantValue(file->read64(offset + 1)); + case 8: // FLOAT + return ConstantValue(file->readIso60599Binary32(offset + 1)); + case 9: // DOUBLE + return ConstantValue(file->readIso60599Binary64(offset + 1)); + default: + throw FileFormatException( + file->uri, + "UNOIDL format: bad constant type byte " + OUString::number(v)); + } +} + +rtl::Reference< Entity > readEntity( + rtl::Reference< detail::MappedFile > const & file, sal_uInt32 offset); + +class UnoidlCursor: public MapCursor { +public: + UnoidlCursor( + rtl::Reference< detail::MappedFile > file, + detail::MapEntry const * mapBegin, sal_uInt32 mapSize): + file_(file), mapIndex_(mapBegin), mapEnd_(mapBegin + mapSize) + {} + +private: + virtual ~UnoidlCursor() throw () {} + + virtual rtl::Reference< Entity > getNext(OUString * name); + + rtl::Reference< detail::MappedFile > file_; + detail::MapEntry const * mapIndex_; + detail::MapEntry const * mapEnd_; +}; + +rtl::Reference< Entity > UnoidlCursor::getNext(OUString * name) { + assert(name != 0); + rtl::Reference< Entity > ent; + if (mapIndex_ != mapEnd_) { + *name = file_->readNameNul(mapIndex_->name.getUnsigned32()); + ent = readEntity(file_, mapIndex_->data.getUnsigned32()); + ++mapIndex_; + } + return ent; +} + +class UnoidlModuleEntity: public ModuleEntity { +public: + UnoidlModuleEntity( + rtl::Reference< detail::MappedFile > const & file, sal_uInt32 mapOffset, + sal_uInt32 mapSize): + file_(file), + mapBegin_( + reinterpret_cast< detail::MapEntry const * >( + static_cast< char const * >(file_->address) + mapOffset)), + mapSize_(mapSize) + { assert(file.is()); } + +private: + virtual ~UnoidlModuleEntity() throw () {} + + virtual std::vector< OUString > getMemberNames() const; + + virtual rtl::Reference< MapCursor > createCursor() const + { return new UnoidlCursor(file_, mapBegin_, mapSize_); } + + rtl::Reference< detail::MappedFile > file_; + detail::MapEntry const * mapBegin_; + sal_uInt32 mapSize_; +}; + +std::vector< OUString > UnoidlModuleEntity::getMemberNames() const { + std::vector< OUString > names; + for (sal_uInt32 i = 0; i != mapSize_; ++i) { + names.push_back(file_->readNameNul(mapBegin_[i].name.getUnsigned32())); + } + return names; +} + +rtl::Reference< Entity > readEntity( + rtl::Reference< detail::MappedFile > const & file, sal_uInt32 offset) +{ + assert(file.is()); + int v = file->read8(offset); + int type = v & 0x3F; + bool published = (v & 0x80) != 0; + bool deprecated = (v & 0x40) != 0; (void)deprecated;//TODO + bool flag = (v & 0x20) != 0; + switch (type) { + case 0: // module + { + if (v != 0) { + throw FileFormatException( + file->uri, + ("UNOIDL format: bad module type byte " + + OUString::number(v))); + } + sal_uInt32 n = file->read32(offset + 1); + if (n > SAL_MAX_INT32) { + throw FileFormatException( + file->uri, "UNOIDL format: too many items in module"); + } + if (offset + 5 + 8 * n > file->size) { //TODO: overflow + throw FileFormatException( + file->uri, + "UNOIDL format: module map offset + size too large"); + } + return new UnoidlModuleEntity(file, offset + 5, n); + } + case 1: // enum type + { + sal_uInt32 n = file->read32(offset + 1); + if (n > SAL_MAX_INT32) { + throw FileFormatException( + file->uri, "UNOIDL format: too many members of enum type"); + } + offset += 5; + std::vector< EnumTypeEntity::Member > mems; + for (sal_uInt32 i = 0; i != n; ++i) { + OUString memName(file->readNameLen(offset, &offset)); + sal_Int32 memValue = static_cast< sal_Int32 >( + file->read32(offset)); + //TODO: implementation-defined behavior of conversion from + // sal_uInt32 to sal_Int32 relies on two's complement + // representation + offset += 4; + mems.push_back(EnumTypeEntity::Member(memName, memValue)); + } + return new EnumTypeEntity(published, mems); + } + case 2: // plain struct type without base + case 2 | 0x20: // plain struct type with base + { + ++offset; + OUString base; + if (flag) { + base = file->readNameLen(offset, &offset); + if (base.isEmpty()) { + throw FileFormatException( + file->uri, + ("UNOIDL format: empty base type name of plain struct" + " type")); + } + } + sal_uInt32 n = file->read32(offset); + if (n > SAL_MAX_INT32) { + throw FileFormatException( + file->uri, + ("UNOIDL format: too many direct members of plain struct" + " type")); + } + offset += 4; + std::vector< PlainStructTypeEntity::Member > mems; + for (sal_uInt32 i = 0; i != n; ++i) { + OUString memName(file->readNameLen(offset, &offset)); + OUString memType(file->readNameLen(offset, &offset)); + mems.push_back(PlainStructTypeEntity::Member(memName, memType)); + } + return new PlainStructTypeEntity(published, base, mems); + } + case 3: // polymorphic struct type template + { + sal_uInt32 n = file->read32(offset + 1); + if (n > SAL_MAX_INT32) { + throw FileFormatException( + file->uri, + ("UNOIDL format: too many type parameters of polymorphic" + " struct type template")); + } + offset += 5; + std::vector< OUString > params; + for (sal_uInt32 i = 0; i != n; ++i) { + params.push_back(file->readNameLen(offset, &offset)); + } + n = file->read32(offset); + if (n > SAL_MAX_INT32) { + throw FileFormatException( + file->uri, + ("UNOIDL format: too many members of polymorphic struct" + " type template")); + } + offset += 4; + std::vector< PolymorphicStructTypeTemplateEntity::Member > mems; + for (sal_uInt32 i = 0; i != n; ++i) { + v = file->read8(offset); + ++offset; + OUString memName(file->readNameLen(offset, &offset)); + OUString memType(file->readNameLen(offset, &offset)); + if (v > 1) { + throw FileFormatException( + file->uri, + ("UNOIDL format: bad flags " + OUString::number(v) + + " for member " + memName + + " of polymorphic struct type template")); + } + mems.push_back( + PolymorphicStructTypeTemplateEntity::Member( + memName, memType, v == 1)); + } + return new PolymorphicStructTypeTemplateEntity( + published, params, mems); + } + case 4: // exception type without base + case 4 | 0x20: // exception type with base + { + ++offset; + OUString base; + if (flag) { + base = file->readNameLen(offset, &offset); + if (base.isEmpty()) { + throw FileFormatException( + file->uri, + ("UNOIDL format: empty base type name of exception" + " type")); + } + } + sal_uInt32 n = file->read32(offset); + if (n > SAL_MAX_INT32) { + throw FileFormatException( + file->uri, + "UNOIDL format: too many direct members of exception type"); + } + offset += 4; + std::vector< ExceptionTypeEntity::Member > mems; + for (sal_uInt32 i = 0; i != n; ++i) { + OUString memName(file->readNameLen(offset, &offset)); + OUString memType(file->readNameLen(offset, &offset)); + mems.push_back(ExceptionTypeEntity::Member(memName, memType)); + } + return new ExceptionTypeEntity(published, base, mems); + } + case 5: // interface type + { + sal_uInt32 n = file->read32(offset + 1); + if (n > SAL_MAX_INT32) { + throw FileFormatException( + file->uri, + ("UNOIDL format: too many direct mandatory bases of" + " interface type")); + } + offset += 5; + std::vector< OUString > mandBases; + for (sal_uInt32 i = 0; i != n; ++i) { + mandBases.push_back(file->readNameLen(offset, &offset)); + } + n = file->read32(offset); + if (n > SAL_MAX_INT32) { + throw FileFormatException( + file->uri, + ("UNOIDL format: too many direct optional bases of" + " interface type")); + } + offset += 4; + std::vector< OUString > optBases; + for (sal_uInt32 i = 0; i != n; ++i) { + optBases.push_back(file->readNameLen(offset, &offset)); + } + sal_uInt32 nAttrs = file->read32(offset); + if (nAttrs > SAL_MAX_INT32) { + throw FileFormatException( + file->uri, + ("UNOIDL format: too many direct attributes of interface" + " type")); + } + offset += 4; + std::vector< InterfaceTypeEntity::Attribute > attrs; + for (sal_uInt32 i = 0; i != nAttrs; ++i) { + v = file->read8(offset); + ++offset; + OUString attrName(file->readNameLen(offset, &offset)); + OUString attrType(file->readNameLen(offset, &offset)); + if (v > 0x03) { + throw FileFormatException( + file->uri, + ("UNOIDL format: bad flags for direct attribute " + + attrName + " of interface type")); + } + std::vector< OUString > getExcs; + sal_uInt32 m = file->read32(offset); + if (m > SAL_MAX_INT32) { + throw FileFormatException( + file->uri, + ("UNOIDL format: too many getter exceptions for direct" + " attribute " + attrName + " of interface type")); + } + offset += 4; + for (sal_uInt32 j = 0; j != m; ++j) { + getExcs.push_back(file->readNameLen(offset, &offset)); + } + std::vector< OUString > setExcs; + if ((v & 0x02) == 0) { + m = file->read32(offset); + if (m > SAL_MAX_INT32) { + throw FileFormatException( + file->uri, + ("UNOIDL format: too many setter exceptions for" + " direct attribute " + attrName + + " of interface type")); + } + offset += 4; + for (sal_uInt32 j = 0; j != m; ++j) { + setExcs.push_back(file->readNameLen(offset, &offset)); + } + } + attrs.push_back( + InterfaceTypeEntity::Attribute( + attrName, attrType, (v & 0x01) != 0, (v & 0x02) != 0, + getExcs, setExcs)); + } + sal_uInt32 nMeths = file->read32(offset); + if (nMeths > SAL_MAX_INT32 - nAttrs) { + throw FileFormatException( + file->uri, + ("UNOIDL format: too many direct attributes and methods of" + " interface type")); + } + offset += 4; + std::vector< InterfaceTypeEntity::Method > meths; + for (sal_uInt32 i = 0; i != nMeths; ++i) { + OUString methName(file->readNameLen(offset, &offset)); + OUString methType(file->readNameLen(offset, &offset)); + sal_uInt32 m = file->read32(offset); + if (m > SAL_MAX_INT32) { + throw FileFormatException( + file->uri, + ("UNOIDL format: too many parameters for method " + + methName + " of interface type")); + } + offset += 4; + std::vector< InterfaceTypeEntity::Method::Parameter > params; + for (sal_uInt32 j = 0; j != m; ++j) { + v = file->read8(offset); + ++offset; + OUString paramName(file->readNameLen(offset, &offset)); + OUString paramType(file->readNameLen(offset, &offset)); + InterfaceTypeEntity::Method::Parameter::Direction dir; + switch (v) { + case 0: + dir = InterfaceTypeEntity::Method::Parameter:: + DIRECTION_IN; + break; + case 1: + dir = InterfaceTypeEntity::Method::Parameter:: + DIRECTION_OUT; + break; + case 2: + dir = InterfaceTypeEntity::Method::Parameter:: + DIRECTION_IN_OUT; + break; + default: + throw FileFormatException( + file->uri, + ("UNOIDL format: bad direction " + + OUString::number(v) + " of parameter " + + paramName + " for method " + methName + + " of interface type")); + } + params.push_back( + InterfaceTypeEntity::Method::Parameter( + paramName, paramType, dir)); + } + std::vector< OUString > excs; + m = file->read32(offset); + if (m > SAL_MAX_INT32) { + throw FileFormatException( + file->uri, + ("UNOIDL format: too many exceptions for method " + + methName + " of interface type")); + } + offset += 4; + for (sal_uInt32 j = 0; j != m; ++j) { + excs.push_back(file->readNameLen(offset, &offset)); + } + meths.push_back( + InterfaceTypeEntity::Method( + methName, methType, params, excs)); + } + return new InterfaceTypeEntity( + published, mandBases, optBases, attrs, meths); + } + case 6: // typedef + return new TypedefEntity(published, file->readNameLen(offset + 1)); + case 7: // constant group + { + sal_uInt32 n = file->read32(offset + 1); + if (n > SAL_MAX_INT32) { + throw FileFormatException( + file->uri, + "UNOIDL format: too many constants in constant group"); + } + if (offset + 5 + 8 * n > file->size) { //TODO: overflow + throw FileFormatException( + file->uri, + ("UNOIDL format: constant group map offset + size too" + " large")); + } + detail::MapEntry const * p + = reinterpret_cast< detail::MapEntry const * >( + static_cast< char const * >(file->address) + offset + 5); + std::vector< ConstantGroupEntity::Member > mems; + for (sal_uInt32 i = 0; i != n; ++i) { + mems.push_back( + ConstantGroupEntity::Member( + file->readNameNul(p[i].name.getUnsigned32()), + readConstant(file, p[i].data.getUnsigned32()))); + } + return new ConstantGroupEntity(published, mems); + } + case 8: // single-interface--based service without default constructor + case 8 | 0x20: // single-interface--based service with default constructor + { + OUString base(file->readNameLen(offset + 1, &offset)); + std::vector< SingleInterfaceBasedServiceEntity::Constructor > ctors; + if (flag) { + ctors.push_back( + SingleInterfaceBasedServiceEntity::Constructor()); + } else { + sal_uInt32 n = file->read32(offset); + if (n > SAL_MAX_INT32) { + throw FileFormatException( + file->uri, + ("UNOIDL format: too many constructors of" + " single-interface--based service")); + } + offset += 4; + for (sal_uInt32 i = 0; i != n; ++i) { + OUString ctorName(file->readNameLen(offset, &offset)); + sal_uInt32 m = file->read32(offset); + if (m > SAL_MAX_INT32) { + throw FileFormatException( + file->uri, + ("UNOIDL format: too many parameters for" + " constructor " + ctorName + + " of single-interface--based service")); + } + offset += 4; + std::vector< + SingleInterfaceBasedServiceEntity::Constructor:: + Parameter > params; + for (sal_uInt32 j = 0; j != m; ++j) { + v = file->read8(offset); + ++offset; + OUString paramName(file->readNameLen(offset, &offset)); + OUString paramType(file->readNameLen(offset, &offset)); + bool rest; + switch (v) { + case 0: + rest = false; + break; + case 0x04: + rest = true; + break; + default: + throw FileFormatException( + file->uri, + ("UNOIDL format: bad mode " + + OUString::number(v) + " of parameter " + + paramName + " for constructor " + ctorName + + " of single-interface--based service")); + } + params.push_back( + SingleInterfaceBasedServiceEntity::Constructor:: + Parameter( + paramName, paramType, rest)); + } + std::vector< OUString > excs; + m = file->read32(offset); + if (m > SAL_MAX_INT32) { + throw FileFormatException( + file->uri, + ("UNOIDL format: too many exceptions for" + " constructor " + ctorName + + " of single-interface--based service")); + } + offset += 4; + for (sal_uInt32 j = 0; j != m; ++j) { + excs.push_back(file->readNameLen(offset, &offset)); + } + ctors.push_back( + SingleInterfaceBasedServiceEntity::Constructor( + ctorName, params, excs)); + } + } + return new SingleInterfaceBasedServiceEntity( + published, base, ctors); + } + case 9: // accumulation-based service + { + sal_uInt32 n = file->read32(offset + 1); + if (n > SAL_MAX_INT32) { + throw FileFormatException( + file->uri, + ("UNOIDL format: too many direct mandatory service bases of" + " accumulation-based service")); + } + offset += 5; + std::vector< OUString > mandServs; + for (sal_uInt32 i = 0; i != n; ++i) { + mandServs.push_back(file->readNameLen(offset, &offset)); + } + n = file->read32(offset); + if (n > SAL_MAX_INT32) { + throw FileFormatException( + file->uri, + ("UNOIDL format: too many direct optional service bases of" + " accumulation-based service")); + } + offset += 4; + std::vector< OUString > optServs; + for (sal_uInt32 i = 0; i != n; ++i) { + optServs.push_back(file->readNameLen(offset, &offset)); + } + n = file->read32(offset); + if (n > SAL_MAX_INT32) { + throw FileFormatException( + file->uri, + ("UNOIDL format: too many direct mandatory interface bases" + " of accumulation-based service")); + } + offset += 4; + std::vector< OUString > mandIfcs; + for (sal_uInt32 i = 0; i != n; ++i) { + mandIfcs.push_back(file->readNameLen(offset, &offset)); + } + n = file->read32(offset); + if (n > SAL_MAX_INT32) { + throw FileFormatException( + file->uri, + ("UNOIDL format: too many direct optional interface bases" + " of accumulation-based service")); + } + offset += 4; + std::vector< OUString > optIfcs; + for (sal_uInt32 i = 0; i != n; ++i) { + optIfcs.push_back(file->readNameLen(offset, &offset)); + } + n = file->read32(offset); + if (n > SAL_MAX_INT32) { + throw FileFormatException( + file->uri, + ("UNOIDL format: too many direct properties of" + " accumulation-based service")); + } + offset += 4; + std::vector< AccumulationBasedServiceEntity::Property > props; + for (sal_uInt32 i = 0; i != n; ++i) { + sal_uInt16 attrs = file->read16(offset); + offset += 2; + OUString propName(file->readNameLen(offset, &offset)); + OUString propType(file->readNameLen(offset, &offset)); + if (attrs > 0x01FF) { // see css.beans.PropertyAttribute + throw FileFormatException( + file->uri, + ("UNOIDL format: bad mode " + OUString::number(v) + + " of property " + propName + + " for accumulation-based servcie")); + } + props.push_back( + AccumulationBasedServiceEntity::Property( + propName, propType, + static_cast< + AccumulationBasedServiceEntity::Property:: + Attributes >( + attrs))); + } + return new AccumulationBasedServiceEntity( + published, mandServs, optServs, mandIfcs, optIfcs, props); + } + case 10: // interface-based singleton + return new InterfaceBasedSingletonEntity( + published, file->readNameLen(offset + 1)); + case 11: // service-based singleton + return new ServiceBasedSingletonEntity( + published, file->readNameLen(offset + 1)); + default: + throw FileFormatException( + file->uri, "UNOIDL format: bad type byte " + OUString::number(v)); + } +} + +} + +UnoidlProvider::UnoidlProvider(OUString const & uri): + file_(new detail::MappedFile(uri)) +{ + if (file_->size < 8 || std::memcmp(file_->address, "UNOIDL\0\xFF", 8) != 0) + { + throw FileFormatException( + file_->uri, + "UNOIDL format: does not begin with magic UNOIDL\\0\\xFF"); + } + sal_uInt32 off = file_->read32(8); + mapSize_ = file_->read32(12); + if (off + 8 * mapSize_ > file_->size) { //TODO: overflow + throw FileFormatException( + file_->uri, "UNOIDL format: root map offset + size too large"); + } + mapBegin_ = reinterpret_cast< detail::MapEntry const * >( + static_cast< char const * >(file_->address) + off); +} + +rtl::Reference< MapCursor > UnoidlProvider::createRootCursor() const { + return new UnoidlCursor(file_, mapBegin_, mapSize_); +} + +sal_uInt32 UnoidlProvider::find(OUString const & name, bool * constant) const { + detail::MapEntry const * mapBegin = mapBegin_; + sal_uInt32 mapSize = mapSize_; + bool cgroup = false; + for (sal_Int32 i = 0;;) { + sal_Int32 j = name.indexOf('.', i); + if (j == -1) { + j = name.getLength(); + } + sal_Int32 off = findInMap(file_, mapBegin, mapSize, name, i, j - i); + if (off == 0) { + return 0; + } + if (j == name.getLength()) { + if (constant != 0) { + *constant = cgroup; + } + return off; + } + if (cgroup) { + return 0; + //TODO: throw an exception instead here, where the segments of a + // constant's name are a prefix of the requested name's + // segments? + } + int v = file_->read8(off); + if (v != 0) { // module + if ((v & 0x3F) == 7) { // constant group + cgroup = true; + } else { + return 0; + //TODO: throw an exception instead here, where the segments + // of a non-module, non-constant-group entity's name are a + // prefix of the requested name's segments? + } + } + mapSize = file_->read32(off + 1); + if (8 * mapSize > file_->size - off - 5) { //TODO: overflow + throw FileFormatException( + file_->uri, "UNOIDL format: map offset + size too large"); + } + mapBegin = reinterpret_cast< detail::MapEntry const * >( + static_cast< char const * >(file_->address) + off + 5); + i = j + 1; + } +} + +rtl::Reference< Entity > UnoidlProvider::getEntity(sal_uInt32 offset) const { + return readEntity(file_, offset); +} + +ConstantValue UnoidlProvider::getConstant(sal_uInt32 offset) const { + return readConstant(file_, offset); +} + +UnoidlProvider::~UnoidlProvider() throw () {} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit