summaryrefslogtreecommitdiff
path: root/unoidl
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2013-02-25 15:31:05 +0100
committerStephan Bergmann <sbergman@redhat.com>2013-02-25 16:24:44 +0100
commit320571bf701a092d0f2d15fd4589ae271802a03f (patch)
tree6b6fa9fd7d5c259037d4b9a976adb023e5ea6332 /unoidl
parentb324cbefb0b92dc7a4813dca88dc8dbd9641cc0b (diff)
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
Diffstat (limited to 'unoidl')
-rw-r--r--unoidl/Library_unoidl.mk26
-rw-r--r--unoidl/Makefile14
-rw-r--r--unoidl/Module_unoidl.mk17
-rw-r--r--unoidl/Package_inc.mk16
-rw-r--r--unoidl/inc/unoidl/detail/dllapi.hxx26
-rw-r--r--unoidl/inc/unoidl/detail/unoidldllapi.hxx26
-rw-r--r--unoidl/inc/unoidl/unoidl.hxx618
-rw-r--r--unoidl/inc/unoidl/unoidlprovider.hxx57
-rw-r--r--unoidl/prj/build.lst2
-rw-r--r--unoidl/prj/d.lst0
-rw-r--r--unoidl/source/unoidl.cxx66
-rw-r--r--unoidl/source/unoidlprovider.cxx1313
12 files changed, 2181 insertions, 0 deletions
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 <cassert>
+#include <vector>
+
+#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
--- /dev/null
+++ b/unoidl/prj/d.lst
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 <vector>
+
+#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 <algorithm>
+#include <cassert>
+#include <cstring>
+#include <vector>
+
+#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: */