Kaydet (Commit) 12353c73 authored tarafından Stephan Bergmann's avatar Stephan Bergmann

WIP: Experimental new binary type.rdb format

Add LegacyProvider to read the old format (requires a provider Manager, to
resolve singletons' bases, to decide whether they are interface- or service-
based).

Replace registry-based reg2bin with provider-based reg2unoidl.

Change-Id: I5865e62308cc2d9c5439211ac803d84e93aab656
üst 866ebf66
......@@ -52,7 +52,7 @@ $(eval $(call gb_Helper_register_executables,NONE, \
pdf2xml \
pdfunzip \
propex \
reg2bin \
reg2unoidl \
regsvrex \
rsc \
rscdep \
......
......@@ -35,7 +35,6 @@ ifneq (,$(filter DESKTOP,$(BUILD_TYPE)))
$(eval $(call gb_Module_add_targets,registry,\
StaticLibrary_registry_helper \
Executable_reg2bin \
Executable_regmerge \
Executable_regview \
Executable_regcompare \
......
/* -*- 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 <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <utility>
#include <vector>
#include "osl/endian.h"
#include "osl/file.h"
#include "osl/file.hxx"
#include "osl/process.h"
#include "registry/reader.hxx"
#include "registry/refltype.hxx"
#include "registry/registry.hxx"
#include "registry/regtype.h"
#include "registry/types.h"
#include "registry/version.h"
#include "rtl/process.h"
#include "rtl/string.hxx"
#include "rtl/textenc.h"
#include "rtl/textcvt.h"
#include "rtl/ustring.hxx"
#include "sal/macros.h"
#include "sal/main.h"
namespace {
rtl::OUString getArgumentUrl(sal_uInt32 argument) {
rtl::OUString arg;
rtl_getAppCommandArg(argument, &arg.pData);
rtl::OUString url;
osl::FileBase::RC e1 = osl::FileBase::getFileURLFromSystemPath(arg, url);
if (e1 != osl::FileBase::E_None) {
std::cerr
<< "Cannot convert \"" << arg << "\" to file URL, error code "
<< +e1 << "\n";
std::exit(EXIT_FAILURE);
}
rtl::OUString cwd;
oslProcessError e2 = osl_getProcessWorkingDir(&cwd.pData);
if (e2 != osl_Process_E_None) {
std::cerr
<< "Cannot obtain working directory, error code " << +e2 << "\n";
std::exit(EXIT_FAILURE);
}
rtl::OUString abs;
e1 = osl::FileBase::getAbsoluteFileURL(cwd, url, abs);
if (e1 != osl::FileBase::E_None) {
std::cerr
<< "Cannot make \"" << url
<< "\" into an absolute file URL, error code " << +e1 << "\n";
std::exit(EXIT_FAILURE);
}
return abs;
}
enum Type {
TYPE_MODULE,
TYPE_ENUM,
TYPE_STRUCT,
TYPE_POLYSTRUCT,
TYPE_EXCEPTION,
TYPE_INTERFACE,
TYPE_TYPEDEF,
TYPE_CONSTANTS,
TYPE_NEWSERVICE,
TYPE_OLDSERVICE,
TYPE_NEWSINGLETON,
TYPE_OLDSINGLETON
};
struct Field {
Field(rtl::OUString const & theName, sal_Int32 theValue):
name(theName), value(theValue) {}
Field(rtl::OUString const & theName, rtl::OUString const & theType):
name(theName), type(theType) {}
Field(
rtl::OUString const & theName, rtl::OUString const & theType,
bool parameterized):
name(theName), type(theType), bound(parameterized) {}
Field(
rtl::OUString const & theName, rtl::OUString const & theType,
bool theBound, bool theReadOnly,
std::vector< rtl::OUString > theGetExceptions,
std::vector< rtl::OUString > theSetExceptions):
name(theName), type(theType), bound(theBound), readOnly(theReadOnly),
getExceptions(theGetExceptions), setExceptions(theSetExceptions) {}
Field(
rtl::OUString const & theName, rtl::OUString const & theType,
sal_Int32 flags):
name(theName), type(theType), value(flags) {}
rtl::OUString name;
rtl::OUString type;
sal_Int32 value;
bool bound; // aka polymorphic struct type template of parameterized type
bool readOnly;
std::vector< rtl::OUString > getExceptions;
std::vector< rtl::OUString > setExceptions;
};
struct Parameter {
Parameter(
rtl::OUString const & theName, rtl::OUString const & theType,
RTParamMode theMode):
name(theName), type(theType), mode(theMode) {}
rtl::OUString name;
rtl::OUString type;
RTParamMode mode;
};
struct Method {
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) {}
Method(
rtl::OUString const & theName,
std::vector< Parameter > const & theParameters,
std::vector< rtl::OUString > const & theExceptions):
name(theName), parameters(theParameters), exceptions(theExceptions) {}
rtl::OUString name;
rtl::OUString returnType;
std::vector< Parameter > parameters;
std::vector< rtl::OUString > exceptions;
};
enum ConstantType {
CONSTANT_TYPE_BOOLEAN,
CONSTANT_TYPE_BYTE,
CONSTANT_TYPE_SHORT,
CONSTANT_TYPE_UNSIGNED_SHORT,
CONSTANT_TYPE_LONG,
CONSTANT_TYPE_UNSIGNED_LONG,
CONSTANT_TYPE_HYPER,
CONSTANT_TYPE_UNSIGNED_HYPER,
CONSTANT_TYPE_FLOAT,
CONSTANT_TYPE_DOUBLE
};
struct Item {
Type type;
std::map< rtl::OUString, Item > elements;
bool published;
bool deprecated;
std::vector< rtl::OUString > supertypes;
std::vector< rtl::OUString > optionalSupertypes;
std::vector< Field > fields;
std::vector< Method > methods;
std::vector< rtl::OUString > references;
std::vector< rtl::OUString > optionalReferences;
ConstantType constantType;
union {
bool bo;
sal_Int8 by;
sal_Int16 s;
sal_uInt16 us;
sal_Int32 l;
sal_uInt32 ul;
sal_Int64 h;
sal_uInt64 uh;
float f;
double d;
} constantValue;
bool defaultConstructor;
sal_uInt64 nameOffset;
sal_uInt64 dataOffset;
};
void insert(
rtl::OUString const & name, Item const & item,
std::map< rtl::OUString, Item > * map)
{
assert(map != 0);
if(!map->insert(std::make_pair(name, item)).second)
{
assert(false);
}
}
typereg::Reader getReader(RegistryKey & key, std::vector< char > * buffer) {
assert(buffer != 0);
RegValueType type;
sal_uInt32 size;
RegError e = key.getValueInfo("", &type, &size);
if (e != REG_NO_ERROR) {
std::cerr
<< "Cannot get value info about key \"" << key.getName()
<< "\" in registry \"" << key.getRegistryName() << "\", error code "
<< +e << "\n";
std::exit(EXIT_FAILURE);
}
if (type != RG_VALUETYPE_BINARY) {
std::cerr
<< "Unexpected value type " << +type << " of key \""
<< key.getName() << "\" in registry \"" << key.getRegistryName()
<< "\"\n";
std::exit(EXIT_FAILURE);
}
if (size == 0
/* || size > std::numeric_limits< std::vector< char >::size_type >::max() */)
{
std::cerr
<< "Bad binary value size " << size << " of key \"" << key.getName()
<< "\" in registry \"" << key.getRegistryName() << "\"\n";
std::exit(EXIT_FAILURE);
}
buffer->resize(static_cast< std::vector< char >::size_type >(size));
e = key.getValue("", &(*buffer)[0]);
if (e != REG_NO_ERROR) {
std::cerr
<< "Cannot get binary value of key \"" << key.getName()
<< "\" in registry \"" << key.getRegistryName() << "\", error code "
<< +e << "\n";
std::exit(EXIT_FAILURE);
}
typereg::Reader reader(&(*buffer)[0], size, false, TYPEREG_VERSION_1);
if (!reader.isValid()) {
std::cerr
<< "Malformed binary value of key \"" << key.getName()
<< "\" in registry \"" << key.getRegistryName() << "\"\n";
std::exit(EXIT_FAILURE);
}
return reader;
}
void setDeprecated(rtl::OUString const & documentation, Item * item) {
assert(item != 0);
item->deprecated = documentation.indexOf("@deprecated") != -1;
//TODO: this check is somewhat crude
}
void setFlags(typereg::Reader const & reader, Item * item) {
assert(item != 0);
item->published = reader.isPublished();
setDeprecated(reader.getDocumentation(), item);
}
void readModule(
std::vector< RegistryKey > & roots, RegistryKey & key,
std::map< rtl::OUString, Item > * map)
{
RegistryKeyNames names;
RegError e = key.getKeyNames("", names);
if (e != REG_NO_ERROR) {
std::cerr
<< "Cannot get sub-key names of \"" << key.getName()
<< "\" in registry \"" << roots[0].getRegistryName()
<< "\", error code " << +e << "\n";
std::exit(EXIT_FAILURE);
}
for (sal_uInt32 i = 0; i != names.getLength(); ++i) {
RegistryKey sub;
e = roots[0].openKey(names.getElement(i), sub);
if (e != REG_NO_ERROR) {
std::cerr
<< "Cannot get key \"" << names.getElement(i)
<< "\" in registry \"" << roots[0].getRegistryName()
<< "\", error code " << +e << "\n";
std::exit(EXIT_FAILURE);
}
std::vector< char > buf;
typereg::Reader reader(getReader(sub, &buf));
assert(sub.getName().match(key.getName() + "/"));
rtl::OUString name(
sub.getName().copy(key.getName().getLength() + std::strlen("/")));
switch (reader.getTypeClass()) {
case RT_TYPE_INTERFACE:
{
Item item;
item.type = TYPE_INTERFACE;
setFlags(reader, &item);
sal_uInt16 n = reader.getSuperTypeCount();
for (sal_uInt16 j = 0; j != n; ++j) {
item.supertypes.push_back(
reader.getSuperTypeName(j).replace('/', '.'));
}
n = reader.getReferenceCount(); // optional base types
for (sal_uInt16 j = 0; j != n; ++j) {
item.optionalSupertypes.push_back(
reader.getReferenceTypeName(j).replace('/', '.'));
}
sal_uInt16 methodCount = reader.getMethodCount();
n = reader.getFieldCount(); // attributes
for (sal_uInt16 j = 0; j != n; ++j) {
rtl::OUString attrName(reader.getFieldName(j));
std::vector< rtl::OUString > getExcs;
std::vector< rtl::OUString > setExcs;
for (sal_uInt16 k = 0; k != methodCount; ++k) {
if (reader.getMethodName(k) == attrName) {
switch (reader.getMethodFlags(k)) {
case RT_MODE_ATTRIBUTE_GET:
{
sal_uInt16 m
= reader.getMethodExceptionCount(k);
for (sal_uInt16 l = 0; l != m; ++l) {
getExcs.push_back(
reader.
getMethodExceptionTypeName(k, l).
replace('/', '.'));
}
break;
}
case RT_MODE_ATTRIBUTE_SET:
{
sal_uInt16 m
= reader.getMethodExceptionCount(k);
for (sal_uInt16 l = 0; l != m; ++l) {
setExcs.push_back(
reader.
getMethodExceptionTypeName(k, l).
replace('/', '.'));
}
break;
}
default:
std::cerr
<< "Method and attribute with same name \""
<< attrName
<< "\" in interface type with key \""
<< sub.getName() << "\" in registry \""
<< roots[0].getRegistryName() << "\"\n";
std::exit(EXIT_FAILURE);
}
}
}
RTFieldAccess flags = reader.getFieldFlags(j);
item.fields.push_back(
Field(
attrName,
reader.getFieldTypeName(j).replace('/', '.'),
(flags & RT_ACCESS_BOUND) != 0,
(flags & RT_ACCESS_READONLY) != 0, getExcs,
setExcs));
}
for (sal_uInt16 j = 0; j != methodCount; ++j) {
RTMethodMode flags = reader.getMethodFlags(j);
if (flags != RT_MODE_ATTRIBUTE_GET
&& flags != RT_MODE_ATTRIBUTE_SET)
{
std::vector< Parameter > params;
sal_uInt16 m = reader.getMethodParameterCount(j);
for (sal_uInt16 k = 0; k != m; ++k) {
RTParamMode mode = reader.getMethodParameterFlags(
j, k);
switch (mode) {
case RT_PARAM_IN:
case RT_PARAM_OUT:
case RT_PARAM_INOUT:
break;
default:
std::cerr
<< "Unexpected mode " << +mode
<< " of parameter \""
<< reader.getMethodParameterName(j, k)
<< "\" of method \""
<< reader.getMethodName(j)
<< "\" in interface type with key \""
<< sub.getName() << "\" in registry \""
<< roots[0].getRegistryName() << "\"\n";
std::exit(EXIT_FAILURE);
}
params.push_back(
Parameter(
reader.getMethodParameterName(j, k),
(reader.getMethodParameterTypeName(j, k).
replace('/', '.')),
mode));
}
std::vector< rtl::OUString > excs;
m = reader.getMethodExceptionCount(j);
for (sal_uInt16 k = 0; k != m; ++k) {
excs.push_back(
reader.getMethodExceptionTypeName(j, k).replace(
'/', '.'));
}
item.methods.push_back(
Method(
reader.getMethodName(j),
reader.getMethodReturnTypeName(j).replace(
'/', '.'),
params, excs));
}
}
insert(name, item, map);
break;
}
case RT_TYPE_MODULE:
{
Item item;
item.type = TYPE_MODULE;
readModule(roots, sub, &item.elements);
insert(name, item, map);
break;
}
case RT_TYPE_STRUCT:
{
Item item;
sal_uInt32 n = reader.getReferenceCount();
if (n == 0) {
item.type = TYPE_STRUCT;
setFlags(reader, &item);
switch (reader.getSuperTypeCount()) {
case 0:
break;
case 1:
item.supertypes.push_back(
reader.getSuperTypeName(0).replace('/', '.'));
break;
default:
std::cerr
<< "Unexpected number "
<< reader.getSuperTypeCount()
<< (" of super-types of plain struct type with key"
" \"")
<< sub.getName() << "\" in registry \""
<< roots[0].getRegistryName() << "\"\n";
std::exit(EXIT_FAILURE);
}
n = reader.getFieldCount();
for (sal_uInt16 j = 0; j != n; ++j) {
item.fields.push_back(
Field(
reader.getFieldName(j),
reader.getFieldTypeName(j).replace('/', '.')));
}
} else {
item.type = TYPE_POLYSTRUCT;
setFlags(reader, &item);
if (reader.getSuperTypeCount() != 0) {
std::cerr
<< "Unexpected number "
<< reader.getSuperTypeCount()
<< (" of super-types of polymorphic struct type"
" template with key \"")
<< sub.getName() << "\" in registry \""
<< roots[0].getRegistryName() << "\"\n";
std::exit(EXIT_FAILURE);
}
for (sal_uInt16 j = 0; j != n; ++j) {
item.references.push_back(
reader.getReferenceTypeName(j).replace('/', '.'));
}
n = reader.getFieldCount();
for (sal_uInt16 j = 0; j != n; ++j) {
item.fields.push_back(
Field(
reader.getFieldName(j),
reader.getFieldTypeName(j).replace('/', '.'),
((reader.getFieldFlags(j)
& RT_ACCESS_PARAMETERIZED_TYPE)
!= 0)));
}
}
insert(name, item, map);
break;
}
case RT_TYPE_ENUM:
{
Item item;
item.type = TYPE_ENUM;
setFlags(reader, &item);
sal_uInt16 n = reader.getFieldCount();
for (sal_uInt16 j = 0; j != n; ++j) {
RTConstValue v(reader.getFieldValue(j));
if (v.m_type != RT_TYPE_INT32) {
std::cerr
<< "Unexpected type " << +v.m_type
<< " of value of field \"" << reader.getFieldName(j)
<< "\" of enum type with key \"" << sub.getName()
<< "\" in registry \"" << roots[0].getRegistryName()
<< "\"\n";
std::exit(EXIT_FAILURE);
}
item.fields.push_back(
Field(reader.getFieldName(j), v.m_value.aLong));
}
insert(name, item, map);
break;
}
case RT_TYPE_EXCEPTION:
{
Item item;
item.type = TYPE_EXCEPTION;
setFlags(reader, &item);
switch (reader.getSuperTypeCount()) {
case 0:
break;
case 1:
item.supertypes.push_back(
reader.getSuperTypeName(0).replace('/', '.'));
break;
default:
std::cerr
<< "Unexpected number " << reader.getSuperTypeCount()
<< " of super-types of exception type with key \""
<< sub.getName() << "\" in registry \""
<< roots[0].getRegistryName() << "\"\n";
std::exit(EXIT_FAILURE);
}
sal_uInt16 n = reader.getFieldCount();
for (sal_uInt16 j = 0; j != n; ++j) {
item.fields.push_back(
Field(
reader.getFieldName(j),
reader.getFieldTypeName(j).replace('/', '.')));
}
insert(name, item, map);
break;
}
case RT_TYPE_TYPEDEF:
{
Item item;
item.type = TYPE_TYPEDEF;
setFlags(reader, &item);
if (reader.getSuperTypeCount() != 1) {
std::cerr
<< "Unexpected number " << reader.getSuperTypeCount()
<< " of super-types of typedef with key \""
<< sub.getName() << "\" in registry \""
<< roots[0].getRegistryName() << "\"\n";
std::exit(EXIT_FAILURE);
}
item.supertypes.push_back(
reader.getSuperTypeName(0).replace('/', '.'));
insert(name, item, map);
break;
}
case RT_TYPE_SERVICE:
{
Item item;
switch (reader.getSuperTypeCount()) {
case 0:
{
item.type = TYPE_OLDSERVICE;
setFlags(reader, &item);
sal_uInt16 n = reader.getReferenceCount();
for (sal_uInt16 j = 0; j != n; ++j) {
rtl::OUString refName(
reader.getReferenceTypeName(j).replace(
'/', '.'));
switch (reader.getReferenceSort(j)) {
case RT_REF_SUPPORTS:
if ((reader.getReferenceFlags(j)
& RT_ACCESS_OPTIONAL)
!= 0)
{
item.optionalSupertypes.push_back(refName);
} else {
item.supertypes.push_back(refName);
}
break;
case RT_REF_EXPORTS:
if ((reader.getReferenceFlags(j)
& RT_ACCESS_OPTIONAL)
!= 0)
{
item.optionalReferences.push_back(refName);
} else {
item.references.push_back(refName);
}
break;
default:
std::cerr
<< "Unexpected mode "
<< +reader.getReferenceSort(j)
<< " of reference \""
<< reader.getReferenceTypeName(j)
<< "\" in service with key \""
<< sub.getName() << "\" in registry \""
<< roots[0].getRegistryName() << "\"\n";
std::exit(EXIT_FAILURE);
}
}
n = reader.getFieldCount();
for (sal_uInt16 j = 0; j != n; ++j) {
RTFieldAccess acc = reader.getFieldFlags(j);
sal_Int32 v = 0;
if ((acc & RT_ACCESS_READONLY) != 0) {
v |= 0x0010;
}
if ((acc & RT_ACCESS_OPTIONAL) != 0) {
v |= 0x0100;
}
if ((acc & RT_ACCESS_MAYBEVOID) != 0) {
v |= 0x0001;
}
if ((acc & RT_ACCESS_BOUND) != 0) {
v |= 0x0002;
}
if ((acc & RT_ACCESS_CONSTRAINED) != 0) {
v |= 0x0004;
}
if ((acc & RT_ACCESS_TRANSIENT) != 0) {
v |= 0x0008;
}
if ((acc & RT_ACCESS_MAYBEAMBIGUOUS) != 0) {
v |= 0x0020;
}
if ((acc & RT_ACCESS_MAYBEDEFAULT) != 0) {
v |= 0x0040;
}
if ((acc & RT_ACCESS_REMOVEABLE) != 0) {
v |= 0x0080;
}
item.fields.push_back(
Field(
reader.getFieldName(j),
reader.getFieldTypeName(j).replace(
'/', '.'),
v));
}
break;
}
case 1:
{
item.type = TYPE_NEWSERVICE;
setFlags(reader, &item);
item.supertypes.push_back(
reader.getSuperTypeName(0).replace('/', '.'));
sal_uInt16 n = reader.getMethodCount();
if (n == 1 && reader.getMethodFlags(0) == 0
&& reader.getMethodName(0).isEmpty()
&& reader.getMethodReturnTypeName(0) == "void"
&& reader.getMethodParameterCount(0) == 0
&& reader.getMethodExceptionCount(0) == 0)
{
item.defaultConstructor = true;
} else {
item.defaultConstructor = false;
for (sal_uInt16 j = 0; j != n; ++j) {
if (reader.getMethodFlags(j) != RT_MODE_TWOWAY)
{
std::cerr
<< "Unexpected mode "
<< +reader.getMethodFlags(j)
<< " of constructor \""
<< reader.getMethodName(j)
<< "\" in service with key \""
<< sub.getName() << "\" in registry \""
<< roots[0].getRegistryName() << "\"\n";
std::exit(EXIT_FAILURE);
}
std::vector< Parameter > params;
sal_uInt16 m = reader.getMethodParameterCount(
j);
for (sal_uInt16 k = 0; k != m; ++k) {
RTParamMode mode
= reader.getMethodParameterFlags(j, k);
if ((mode & ~RT_PARAM_REST) != RT_PARAM_IN)
{
std::cerr
<< "Unexpected mode " << +mode
<< " of parameter \""
<< reader.getMethodParameterName(
j, k)
<< "\" of constructor \""
<< reader.getMethodName(j)
<< "\" in service with key \""
<< sub.getName()
<< "\" in registry \""
<< roots[0].getRegistryName()
<< "\"\n";
std::exit(EXIT_FAILURE);
}
if ((mode & RT_PARAM_REST) != 0
&& !(m == 1
&& ((reader.
getMethodParameterTypeName(
j, 1))
== "any")))
{
std::cerr
<< "Bad rest parameter \""
<< reader.getMethodParameterName(
j, k)
<< "\" of constructor \""
<< reader.getMethodName(j)
<< "\" in service with key \""
<< sub.getName()
<< "\" in registry \""
<< roots[0].getRegistryName()
<< "\"\n";
std::exit(EXIT_FAILURE);
}
params.push_back(
Parameter(
reader.getMethodParameterName(j, k),
(reader.
getMethodParameterTypeName(j, k).
replace('/', '.')),
mode));
}
std::vector< rtl::OUString > excs;
m = reader.getMethodExceptionCount(j);
for (sal_uInt16 k = 0; k != m; ++k) {
excs.push_back(
reader.getMethodExceptionTypeName(j, k).
replace('/', '.'));
}
item.methods.push_back(
Method(
reader.getMethodName(j), params, excs));
}
}
break;
}
default:
std::cerr
<< "Unexpected number " << reader.getSuperTypeCount()
<< " of super-types of service with key \""
<< sub.getName() << "\" in registry \""
<< roots[0].getRegistryName() << "\"\n";
std::exit(EXIT_FAILURE);
}
insert(name, item, map);
break;
}
case RT_TYPE_SINGLETON:
{
Item item;
if (reader.getSuperTypeCount() != 1) {
std::cerr
<< "Unexpected number " << reader.getSuperTypeCount()
<< " of super-types of singleton with key \""
<< sub.getName() << "\" in registry \""
<< roots[0].getRegistryName() << "\"\n";
std::exit(EXIT_FAILURE);
}
rtl::OUString path("/UCR/" + reader.getSuperTypeName(0));
RegistryKey key2;
for (std::vector< RegistryKey >::iterator j(roots.begin());
j != roots.end(); ++j)
{
e = j->openKey(path, key2);
switch (e) {
case REG_NO_ERROR:
{
std::vector< char > buf2;
typereg::Reader reader2(getReader(key2, &buf2));
switch (reader2.getTypeClass()) {
case RT_TYPE_INTERFACE:
item.type = TYPE_NEWSINGLETON;
goto done;
case RT_TYPE_SERVICE:
item.type = TYPE_OLDSINGLETON;
goto done;
default:
std::cerr
<< "Unexpected type class "
<< +reader2.getTypeClass()
<< " of super-type with key \""
<< key2.getName() << "\" in registry \""
<< j->getRegistryName()
<< "\" of singleton with key \""
<< sub.getName() << "\" in registry \""
<< roots[0].getRegistryName() << "\"\n";
std::exit(EXIT_FAILURE);
}
break;
}
case REG_KEY_NOT_EXISTS:
break;
default:
std::cerr
<< "Cannot get key \"" << path
<< "\" in registry \"" << j->getRegistryName()
<< "\", error code " << +e << "\n";
std::exit(EXIT_FAILURE);
}
}
std::cerr
<< "Unknown super-type with key \"" << path
<< "\" of singleton with key \"" << sub.getName()
<< "\" in registry \"" << roots[0].getRegistryName()
<< "\"\n";
std::exit(EXIT_FAILURE);
done:
setFlags(reader, &item);
item.supertypes.push_back(
reader.getSuperTypeName(0).replace('/', '.'));
insert(name, item, map);
break;
}
case RT_TYPE_CONSTANTS:
{
Item item;
item.type = TYPE_CONSTANTS;
setFlags(reader, &item);
sal_uInt16 n = reader.getFieldCount();
for (sal_uInt16 j = 0; j != n; ++j) {
Item item2;
setDeprecated(reader.getFieldDocumentation(j), &item2);
RTConstValue v(reader.getFieldValue(j));
switch (v.m_type) {
case RT_TYPE_BOOL:
item2.constantType = CONSTANT_TYPE_BOOLEAN;
item2.constantValue.bo = v.m_value.aBool;
break;
case RT_TYPE_BYTE:
item2.constantType = CONSTANT_TYPE_BYTE;
item2.constantValue.by = v.m_value.aByte;
break;
case RT_TYPE_INT16:
item2.constantType = CONSTANT_TYPE_SHORT;
item2.constantValue.s = v.m_value.aShort;
break;
case RT_TYPE_UINT16:
item2.constantType = CONSTANT_TYPE_UNSIGNED_SHORT;
item2.constantValue.us = v.m_value.aUShort;
break;
case RT_TYPE_INT32:
item2.constantType = CONSTANT_TYPE_LONG;
item2.constantValue.l = v.m_value.aLong;
break;
case RT_TYPE_UINT32:
item2.constantType = CONSTANT_TYPE_UNSIGNED_LONG;
item2.constantValue.ul = v.m_value.aULong;
break;
case RT_TYPE_INT64:
item2.constantType = CONSTANT_TYPE_HYPER;
item2.constantValue.h = v.m_value.aHyper;
break;
case RT_TYPE_UINT64:
item2.constantType = CONSTANT_TYPE_UNSIGNED_HYPER;
item2.constantValue.uh = v.m_value.aUHyper;
break;
case RT_TYPE_FLOAT:
item2.constantType = CONSTANT_TYPE_FLOAT;
item2.constantValue.f = v.m_value.aFloat;
break;
case RT_TYPE_DOUBLE:
item2.constantType = CONSTANT_TYPE_DOUBLE;
item2.constantValue.d = v.m_value.aDouble;
break;
default:
std::cerr
<< "Unexpected type " << +v.m_type
<< " of value of field \"" << reader.getFieldName(j)
<< "\" of constant group with key \""
<< sub.getName() << "\" in registry \""
<< roots[0].getRegistryName() << "\"\n";
std::exit(EXIT_FAILURE);
}
insert(reader.getFieldName(j), item2, &item.elements);
}
insert(name, item, map);
break;
}
default:
std::cerr
<< "Unexpected type class " << +reader.getTypeClass()
<< " of key \"" << sub.getName() << "\" in registry \""
<< roots[0].getRegistryName() << "\"\n";
std::exit(EXIT_FAILURE);
}
}
}
sal_uInt64 getOffset(osl::File & file) {
sal_uInt64 off;
osl::FileBase::RC e = file.getPos(off);
if (e != osl::FileBase::E_None) {
std::cerr
<< "Cannot determine current position in \"" << file.getURL()
<< "\", error code " << +e << "\n";
std::exit(EXIT_FAILURE);
}
return off;
}
void write(osl::File & file, void const * buffer, sal_uInt64 size) {
sal_uInt64 n;
osl::FileBase::RC e = file.write(buffer, size, n);
if (e != osl::FileBase::E_None) {
std::cerr
<< "Cannot write to \"" << file.getURL() << "\", error code " << +e
<< "\n";
std::exit(EXIT_FAILURE);
}
if (n != size) {
std::cerr
<< "Bad write of " << n << " instead of " << size << " bytes to \""
<< file.getURL() << "\"\n";
std::exit(EXIT_FAILURE);
}
}
void write8(osl::File & file, sal_uInt64 value) {
if (value > 0xFF) {
std::cerr << "Cannot write value >= 2^8; input is too large\n";
std::exit(EXIT_FAILURE);
}
unsigned char buf[1];
buf[0] = value & 0xFF;
write(file, buf, SAL_N_ELEMENTS(buf));
}
void write16(osl::File & file, sal_uInt64 value) {
if (value > 0xFFFF) {
std::cerr << "Cannot write value >= 2^16; input is too large\n";
std::exit(EXIT_FAILURE);
}
unsigned char buf[2];
buf[0] = value & 0xFF;
buf[1] = (value >> 8) & 0xFF;
write(file, buf, SAL_N_ELEMENTS(buf));
}
void write32(osl::File & file, sal_uInt64 value) {
if (value > 0xFFFFFFFF) {
std::cerr << "Cannot write value >= 2^32; input is too large\n";
std::exit(EXIT_FAILURE);
}
unsigned char buf[4];
buf[0] = value & 0xFF;
buf[1] = (value >> 8) & 0xFF;
buf[2] = (value >> 16) & 0xFF;
buf[3] = (value >> 24) & 0xFF;
write(file, buf, SAL_N_ELEMENTS(buf));
}
void write64(osl::File & file, sal_uInt64 value) {
unsigned char buf[8];
buf[0] = value & 0xFF;
buf[1] = (value >> 8) & 0xFF;
buf[2] = (value >> 16) & 0xFF;
buf[3] = (value >> 24) & 0xFF;
buf[3] = (value >> 32) & 0xFF;
buf[3] = (value >> 40) & 0xFF;
buf[3] = (value >> 48) & 0xFF;
buf[3] = (value >> 56) & 0xFF;
write(file, buf, SAL_N_ELEMENTS(buf));
}
void writeIso60599Binary32(osl::File & file, float value) {
union {
unsigned char buf[4];
float f; // assuming float is ISO 60599 binary32
} sa;
sa.f = value;
#if defined OSL_BIGENDIAN
std::swap(sa.buf[0], sa.buf[3]);
std::swap(sa.buf[1], sa.buf[2]);
#endif
write(file, sa.buf, SAL_N_ELEMENTS(sa.buf));
}
void writeIso60599Binary64(osl::File & file, double value) {
union {
unsigned char buf[8];
float d; // assuming double is ISO 60599 binary64
} sa;
sa.d = value;
#if defined OSL_BIGENDIAN
std::swap(sa.buf[0], sa.buf[7]);
std::swap(sa.buf[1], sa.buf[6]);
std::swap(sa.buf[2], sa.buf[5]);
std::swap(sa.buf[3], sa.buf[4]);
#endif
write(file, sa.buf, SAL_N_ELEMENTS(sa.buf));
}
rtl::OString toAscii(rtl::OUString const & name) {
rtl::OString ascii;
if (!name.convertToString(
&ascii, RTL_TEXTENCODING_ASCII_US,
(RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
| RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
{
std::cerr << "Cannot convert \"" << name << "\" to US ASCII\n";
std::exit(EXIT_FAILURE);
}
return ascii;
}
sal_uInt64 writeNameNul(osl::File & file, rtl::OUString const & name) {
rtl::OString ascii(toAscii(name));
if (ascii.indexOf('\0') != -1) {
std::cerr << "Name \"" << ascii << "\" contains NUL characters\n";
std::exit(EXIT_FAILURE);
}
sal_uInt64 off = getOffset(file);
write(file, ascii.getStr(), ascii.getLength() + 1);
return off;
}
void writeNameLen(osl::File & file, rtl::OUString const & name) {
static std::map< rtl::OUString, sal_uInt64 > reuse;
std::map< rtl::OUString, sal_uInt64 >::iterator i(reuse.find(name));
if (i == reuse.end()) {
reuse.insert(std::make_pair(name, getOffset(file)));
rtl::OString ascii(toAscii(name));
assert(
(static_cast< sal_uInt64 >(ascii.getLength()) & 0x80000000) == 0);
write32(
file, static_cast< sal_uInt64 >(ascii.getLength()) | 0x80000000);
write(file, ascii.getStr(), ascii.getLength());
} else {
write32(file, i->second);
}
}
void writeType(osl::File & file, Item const & item, bool flag = false) {
assert(item.type != TYPE_MODULE);
sal_uInt64 v = item.type;
if (item.published) {
v |= 0x80;
}
if (item.deprecated) {
v |= 0x40;
}
if (flag) {
v |= 0x20;
}
write8(file, v);
}
sal_uInt64 writeMap(
osl::File & file, std::map< rtl::OUString, Item > & map, bool root)
{
for (std::map< rtl::OUString, Item >::iterator i(map.begin());
i != map.end(); ++i)
{
switch (i->second.type) {
case TYPE_MODULE:
i->second.dataOffset = writeMap(file, i->second.elements, false);
break;
case TYPE_ENUM:
i->second.dataOffset = getOffset(file);
writeType(file, i->second);
write32(file, i->second.fields.size());
for (std::vector< Field >::const_iterator j(
i->second.fields.begin());
j != i->second.fields.end(); ++j)
{
writeNameLen(file, j->name);
write32(file, static_cast< sal_uInt32 >(j->value));
}
break;
case TYPE_STRUCT:
case TYPE_EXCEPTION:
i->second.dataOffset = getOffset(file);
writeType(file, i->second, !i->second.supertypes.empty());
if (!i->second.supertypes.empty()) {
writeNameLen(file, i->second.supertypes[0]);
}
write32(file, i->second.fields.size());
for (std::vector< Field >::const_iterator j(
i->second.fields.begin());
j != i->second.fields.end(); ++j)
{
writeNameLen(file, j->name);
writeNameLen(file, j->type);
}
break;
case TYPE_POLYSTRUCT:
i->second.dataOffset = getOffset(file);
writeType(file, i->second);
write32(file, i->second.references.size());
for (std::vector< rtl::OUString >::const_iterator j(
i->second.references.begin());
j != i->second.references.end(); ++j)
{
writeNameLen(file, *j);
}
write32(file, i->second.fields.size());
for (std::vector< Field >::const_iterator j(
i->second.fields.begin());
j != i->second.fields.end(); ++j)
{
sal_uInt64 f = 0;
if (j->bound) {
f |= 0x01;
}
write8(file, f);
writeNameLen(file, j->name);
writeNameLen(file, j->type);
}
break;
case TYPE_INTERFACE:
i->second.dataOffset = getOffset(file);
writeType(file, i->second);
write32(file, i->second.supertypes.size());
for (std::vector< rtl::OUString >::const_iterator j(
i->second.supertypes.begin());
j != i->second.supertypes.end(); ++j)
{
writeNameLen(file, *j);
}
write32(file, i->second.optionalSupertypes.size());
for (std::vector< rtl::OUString >::const_iterator j(
i->second.optionalSupertypes.begin());
j != i->second.optionalSupertypes.end(); ++j)
{
writeNameLen(file, *j);
}
write32(file, i->second.fields.size());
for (std::vector< Field >::const_iterator j(
i->second.fields.begin());
j != i->second.fields.end(); ++j)
{
sal_uInt64 f = 0;
if (j->bound) {
f |= 0x01;
}
if (j->readOnly) {
f |= 0x02;
}
write8(file, f);
writeNameLen(file, j->name);
writeNameLen(file, j->type);
write32(file, j->getExceptions.size());
for (std::vector< rtl::OUString >::const_iterator k(
j->getExceptions.begin());
k != j->getExceptions.end(); ++k)
{
writeNameLen(file, *k);
}
if (!j->readOnly) {
write32(file, j->setExceptions.size());
for (std::vector< rtl::OUString >::const_iterator k(
j->setExceptions.begin());
k != j->setExceptions.end(); ++k)
{
writeNameLen(file, *k);
}
}
}
write32(file, i->second.methods.size());
for (std::vector< Method >::const_iterator j(
i->second.methods.begin());
j != i->second.methods.end(); ++j)
{
writeNameLen(file, j->name);
writeNameLen(file, j->returnType);
write32(file, j->parameters.size());
for (std::vector< Parameter >::const_iterator k(
j->parameters.begin());
k != j->parameters.end(); ++k)
{
sal_uInt64 f = sal_uInt64();
switch (k->mode) {
case RT_PARAM_IN:
f = 0;
break;
case RT_PARAM_OUT:
f = 1;
break;
case RT_PARAM_INOUT:
f = 2;
break;
default:
std::abort(); // this cannot happen
}
write8(file, f);
writeNameLen(file, k->name);
writeNameLen(file, k->type);
}
write32(file, j->exceptions.size());
for (std::vector< rtl::OUString >::const_iterator k(
j->exceptions.begin());
k != j->exceptions.end(); ++k)
{
writeNameLen(file, *k);
}
}
break;
case TYPE_TYPEDEF:
i->second.dataOffset = getOffset(file);
writeType(file, i->second);
assert(i->second.supertypes.size() == 1);
writeNameLen(file, i->second.supertypes[0]);
break;
case TYPE_CONSTANTS:
for (std::map< rtl::OUString, Item >::iterator j(
i->second.elements.begin());
j != i->second.elements.end(); ++j)
{
j->second.dataOffset = getOffset(file);
sal_uInt64 v = j->second.constantType;
if (j->second.deprecated) {
v |= 0x80;
}
write8(file, v);
switch (j->second.constantType) {
case CONSTANT_TYPE_BOOLEAN:
write8(file, j->second.constantValue.bo ? 1 : 0);
break;
case CONSTANT_TYPE_BYTE:
write8(
file,
static_cast< sal_uInt8 >(j->second.constantValue.by));
break;
case CONSTANT_TYPE_SHORT:
write16(
file,
static_cast< sal_uInt16 >(j->second.constantValue.s));
break;
case CONSTANT_TYPE_UNSIGNED_SHORT:
write16(file, j->second.constantValue.us);
break;
case CONSTANT_TYPE_LONG:
write32(
file,
static_cast< sal_uInt32 >(j->second.constantValue.l));
break;
case CONSTANT_TYPE_UNSIGNED_LONG:
write32(file, j->second.constantValue.ul);
break;
case CONSTANT_TYPE_HYPER:
write64(
file,
static_cast< sal_uInt64 >(j->second.constantValue.h));
break;
case CONSTANT_TYPE_UNSIGNED_HYPER:
write64(file, j->second.constantValue.uh);
break;
case CONSTANT_TYPE_FLOAT:
writeIso60599Binary32(file, j->second.constantValue.f);
break;
case CONSTANT_TYPE_DOUBLE:
writeIso60599Binary64(file, j->second.constantValue.d);
break;
default:
std::abort(); // this cannot happen
}
}
for (std::map< rtl::OUString, Item >::iterator j(
i->second.elements.begin());
j != i->second.elements.end(); ++j)
{
j->second.nameOffset = writeNameNul(file, j->first);
}
i->second.dataOffset = getOffset(file);
writeType(file, i->second);
write32(file, i->second.elements.size());
// overflow from std::map::size_type -> sal_uInt64 is
// unrealistic
for (std::map< rtl::OUString, Item >::iterator j(
i->second.elements.begin());
j != i->second.elements.end(); ++j)
{
write32(file, j->second.nameOffset);
write32(file, j->second.dataOffset);
}
break;
case TYPE_NEWSERVICE:
i->second.dataOffset = getOffset(file);
writeType(file, i->second, i->second.defaultConstructor);
assert(i->second.supertypes.size() == 1);
writeNameLen(file, i->second.supertypes[0]);
if (!i->second.defaultConstructor) {
write32(file, i->second.methods.size());
for (std::vector< Method >::const_iterator j(
i->second.methods.begin());
j != i->second.methods.end(); ++j)
{
writeNameLen(file, j->name);
write32(file, j->parameters.size());
for (std::vector< Parameter >::const_iterator k(
j->parameters.begin());
k != j->parameters.end(); ++k)
{
sal_uInt64 f = 0;
if ((k->mode & RT_PARAM_REST) != 0) {
f |= 0x04;
}
write8(file, f);
writeNameLen(file, k->name);
writeNameLen(file, k->type);
}
write32(file, j->exceptions.size());
for (std::vector< rtl::OUString >::const_iterator k(
j->exceptions.begin());
k != j->exceptions.end(); ++k)
{
writeNameLen(file, *k);
}
}
}
break;
case TYPE_OLDSERVICE:
i->second.dataOffset = getOffset(file);
writeType(file, i->second);
write32(file, i->second.references.size());
for (std::vector< rtl::OUString >::const_iterator j(
i->second.references.begin());
j != i->second.references.end(); ++j)
{
writeNameLen(file, *j);
}
write32(file, i->second.optionalReferences.size());
for (std::vector< rtl::OUString >::const_iterator j(
i->second.optionalReferences.begin());
j != i->second.optionalReferences.end(); ++j)
{
writeNameLen(file, *j);
}
write32(file, i->second.supertypes.size());
for (std::vector< rtl::OUString >::const_iterator j(
i->second.supertypes.begin());
j != i->second.supertypes.end(); ++j)
{
writeNameLen(file, *j);
}
write32(file, i->second.optionalSupertypes.size());
for (std::vector< rtl::OUString >::const_iterator j(
i->second.optionalSupertypes.begin());
j != i->second.optionalSupertypes.end(); ++j)
{
writeNameLen(file, *j);
}
write32(file, i->second.fields.size());
for (std::vector< Field >::const_iterator j(
i->second.fields.begin());
j != i->second.fields.end(); ++j)
{
write16(file, static_cast< sal_uInt16 >(j->value));
writeNameLen(file, j->name);
writeNameLen(file, j->type);
}
break;
case TYPE_NEWSINGLETON:
i->second.dataOffset = getOffset(file);
writeType(file, i->second);
assert(i->second.supertypes.size() == 1);
writeNameLen(file, i->second.supertypes[0]);
break;
case TYPE_OLDSINGLETON:
i->second.dataOffset = getOffset(file);
writeType(file, i->second);
assert(i->second.supertypes.size() == 1);
writeNameLen(file, i->second.supertypes[0]);
break;
}
}
for (std::map< rtl::OUString, Item >::iterator i(map.begin());
i != map.end(); ++i)
{
i->second.nameOffset = writeNameNul(file, i->first);
}
sal_uInt64 off = getOffset(file);
if (!root) {
write8(file, 0); // TYPE_MODULE
write32(file, map.size());
// overflow from std::map::size_type -> sal_uInt64 is unrealistic
}
for (std::map< rtl::OUString, Item >::iterator i(map.begin());
i != map.end(); ++i)
{
write32(file, i->second.nameOffset);
write32(file, i->second.dataOffset);
}
return off;
}
}
SAL_IMPLEMENT_MAIN() {
sal_uInt32 args = rtl_getAppCommandArgCount();
if (args < 2) {
std::cerr
<< ("Usage: reg2bin <.bin file> <.rdb file> <additional .rdb files>"
"\n");
std::exit(EXIT_FAILURE);
}
std::vector< RegistryKey > roots;
for (sal_uInt32 i = 1; i != args; ++i) {
rtl::OUString url(getArgumentUrl(i));
Registry reg;
RegError e = reg.open(url, REG_READONLY);
if (e != REG_NO_ERROR) {
std::cerr
<< "Cannot open registry \"" << url << "\", error code " << +e
<< "\n";
std::exit(EXIT_FAILURE);
}
RegistryKey root;
e = reg.openRootKey(root);
if (e != REG_NO_ERROR) {
std::cerr
<< "Cannot get root key of registry \"" << url
<< "\", error code " << +e << "\n";
std::exit(EXIT_FAILURE);
}
roots.push_back(root);
}
RegistryKey ucr;
RegError e1 = roots[0].openKey("UCR", ucr);
if (e1 != REG_NO_ERROR) {
std::cerr
<< "Cannot get /UCR key of registry \""
<< roots[0].getRegistryName() << "\", error code " << +e1 << "\n";
std::exit(EXIT_FAILURE);
}
std::map< rtl::OUString, Item > map;
readModule(roots, ucr, &map);
osl::File f(getArgumentUrl(0));
osl::FileBase::RC e2 = f.open(osl_File_OpenFlag_Write);
if (e2 == osl::FileBase::E_NOENT) {
e2 = f.open(osl_File_OpenFlag_Write | osl_File_OpenFlag_Create);
}
if (e2 != osl::FileBase::E_None) {
std::cerr
<< "Cannot open \"" << f.getURL() << "\" for writing, error code "
<< +e2 << "\n";
std::exit(EXIT_FAILURE);
}
write(f, "UNOIDL\0\xFF", 8);
write32(f, 0); // root map offset
write32(f, 0); // root map size
sal_uInt64 off = writeMap(f, map, true);
e2 = f.setSize(getOffset(f)); // truncate in case it already existed
if (e2 != osl::FileBase::E_None) {
std::cerr
<< "Cannot set size of \"" << f.getURL() << "\", error code "
<< +e2 << "\n";
std::exit(EXIT_FAILURE);
}
e2 = f.setPos(osl_Pos_Absolut, 8);
if (e2 != osl::FileBase::E_None) {
std::cerr
<< "Cannot rewind current position in \"" << f.getURL()
<< "\", error code " << +e2 << "\n";
std::exit(EXIT_FAILURE);
}
write32(f, off);
write32(f, map.size());
// overflow from std::map::size_type -> sal_uInt64 is unrealistic
e2 = f.close();
if (e2 != osl::FileBase::E_None) {
std::cerr
<< "Cannot close \"" << f.getURL()
<< "\" after writing, error code " << +e2 << "\n";
std::exit(EXIT_FAILURE);
}
return EXIT_SUCCESS;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
......@@ -7,15 +7,16 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
$(eval $(call gb_Executable_Executable,reg2bin))
$(eval $(call gb_Executable_Executable,reg2unoidl))
$(eval $(call gb_Executable_add_exception_objects,reg2bin, \
registry/tools/reg2bin \
$(eval $(call gb_Executable_add_exception_objects,reg2unoidl, \
unoidl/source/reg2unoidl \
))
$(eval $(call gb_Executable_use_libraries,reg2bin, \
reg \
$(eval $(call gb_Executable_use_libraries,reg2unoidl, \
sal \
salhelper \
unoidl \
))
# vim: set noet sw=4 ts=4:
......@@ -12,11 +12,13 @@ $(eval $(call gb_Library_Library,unoidl))
$(eval $(call gb_Library_add_defs,unoidl,-DLO_DLLIMPLEMENTATION_UNOIDL))
$(eval $(call gb_Library_add_exception_objects,unoidl, \
unoidl/source/legacyprovider \
unoidl/source/unoidl \
unoidl/source/unoidlprovider \
))
$(eval $(call gb_Library_use_libraries,unoidl, \
reg \
sal \
salhelper \
))
......
......@@ -10,6 +10,7 @@
$(eval $(call gb_Module_Module,unoidl))
$(eval $(call gb_Module_add_targets,unoidl, \
Executable_reg2unoidl \
Library_unoidl \
Package_inc \
))
......
......@@ -10,6 +10,7 @@
$(eval $(call gb_Package_Package,unoidl_inc,$(SRCDIR)/unoidl/inc/unoidl))
$(eval $(call gb_Package_add_file,unoidl_inc,inc/unoidl/detail/dllapi.hxx,detail/dllapi.hxx))
$(eval $(call gb_Package_add_file,unoidl_inc,inc/unoidl/legacyprovider.hxx,legacyprovider.hxx))
$(eval $(call gb_Package_add_file,unoidl_inc,inc/unoidl/unoidl.hxx,unoidl.hxx))
$(eval $(call gb_Package_add_file,unoidl_inc,inc/unoidl/unoidlprovider.hxx,unoidlprovider.hxx))
......
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef INCLUDED_UNOIDL_LEGACYPROVIDER_HXX
#define INCLUDED_UNOIDL_LEGACYPROVIDER_HXX
#include "sal/config.h"
#include "registry/registry.hxx"
#include "rtl/ref.hxx"
#include "sal/types.h"
#include "unoidl/detail/dllapi.hxx"
#include "unoidl/unoidl.hxx"
namespace rtl { class OUString; }
namespace unoidl {
class LO_DLLPUBLIC_UNOIDL LegacyProvider: public Provider {
public:
// throws FileFormatException, NoSuchFileException:
LegacyProvider(
rtl::Reference< Manager > const & manager, rtl::OUString const & uri);
// throws FileFormatException:
virtual rtl::Reference< MapCursor > createRootCursor() const;
// throws FileFormatException:
virtual rtl::Reference< Entity > findEntity(rtl::OUString const & name)
const;
private:
virtual SAL_DLLPRIVATE ~LegacyProvider() throw ();
rtl::Reference< Manager > manager_;
mutable RegistryKey ucr_;
};
}
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
......@@ -601,15 +601,34 @@ public:
// throws FileFormatException:
virtual rtl::Reference< MapCursor > createRootCursor() const = 0;
// throws FileFormatException:
virtual rtl::Reference< Entity > findEntity(rtl::OUString const & name)
const = 0;
protected:
SAL_DLLPRIVATE Provider() {}
virtual SAL_DLLPRIVATE ~Provider() throw ();
};
class LO_DLLPUBLIC_UNOIDL Manager: public salhelper::SimpleReferenceObject {
public:
Manager() {}
void addProvider(rtl::Reference< Provider > const & provider);
// throws FileFormatException:
rtl::Reference< Entity > findEntity(rtl::OUString const & name) const;
private:
virtual SAL_DLLPRIVATE ~Manager() throw ();
std::vector< rtl::Reference< Provider > > providers_;
};
// throws FileFormatException, NoSuchFileException:
LO_DLLPUBLIC_UNOIDL rtl::Reference< Provider > loadProvider(
rtl::OUString const & uri);
rtl::Reference< Manager > const & manager, rtl::OUString const & uri);
}
......
......@@ -33,6 +33,10 @@ public:
// throws FileFormatException:
virtual rtl::Reference< MapCursor > createRootCursor() const;
// throws FileFormatException:
virtual rtl::Reference< Entity > findEntity(rtl::OUString const & name)
const;
// throws FileFormatException:
sal_uInt32 find(rtl::OUString const & name, bool * constant = 0) const;
......
un unoidl: sal salhelper NULL
un unoidl: registry sal salhelper NULL
un unoidl\prj nmake - all un_prj NULL
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "sal/config.h"
#include <cassert>
#include <cstring>
#include <vector>
#include "registry/reader.hxx"
#include "registry/registry.hxx"
#include "registry/regtype.h"
#include "rtl/ref.hxx"
#include "rtl/ustring.hxx"
#include "sal/types.h"
#include "unoidl/legacyprovider.hxx"
#include "unoidl/unoidl.hxx"
namespace unoidl {
namespace {
ConstantValue translateConstantValue(
RegistryKey & key, RTConstValue const & value)
{
switch (value.m_type) {
case RT_TYPE_BOOL:
return ConstantValue(static_cast< bool >(value.m_value.aBool));
case RT_TYPE_BYTE:
return ConstantValue(value.m_value.aByte);
case RT_TYPE_INT16:
return ConstantValue(value.m_value.aShort);
case RT_TYPE_UINT16:
return ConstantValue(value.m_value.aUShort);
case RT_TYPE_INT32:
return ConstantValue(value.m_value.aLong);
case RT_TYPE_UINT32:
return ConstantValue(value.m_value.aULong);
case RT_TYPE_INT64:
return ConstantValue(value.m_value.aHyper);
case RT_TYPE_UINT64:
return ConstantValue(value.m_value.aUHyper);
case RT_TYPE_FLOAT:
return ConstantValue(value.m_value.aFloat);
case RT_TYPE_DOUBLE:
return ConstantValue(value.m_value.aDouble);
default:
throw FileFormatException(
key.getRegistryName(),
("legacy format: unexpected type " + OUString::number(value.m_type)
+ " of value of a field of constant group with key "
+ key.getName()));
}
}
rtl::Reference< Entity > readEntity(
rtl::Reference< Manager > const & manager, RegistryKey & ucr,
RegistryKey & key, OUString const & path, bool probe);
class Cursor: public MapCursor {
public:
Cursor(
rtl::Reference< Manager > const & manager, RegistryKey const & ucr,
RegistryKey const & key);
private:
virtual ~Cursor() throw () {}
virtual rtl::Reference< Entity > getNext(OUString * name);
rtl::Reference< Manager > manager_;
RegistryKey ucr_;
RegistryKey key_;
OUString prefix_;
RegistryKeyNames names_;
sal_uInt32 index_;
};
Cursor::Cursor(
rtl::Reference< Manager > const & manager, RegistryKey const & ucr,
RegistryKey const & key):
manager_(manager), ucr_(ucr), key_(key), index_(0)
{
prefix_ = key_.getName();
if (!prefix_.endsWith("/")) {
prefix_ += "/";
}
RegError e = key_.getKeyNames("", names_);
if (e != REG_NO_ERROR) {
throw FileFormatException(
key_.getRegistryName(),
("legacy format: cannot get sub-key names of " + key_.getName()
+ ": " + OUString::number(e)));
}
}
rtl::Reference< Entity > Cursor::getNext(OUString * name) {
assert(name != 0);
rtl::Reference< Entity > ent;
if (index_ != names_.getLength()) {
OUString path(names_.getElement(index_));
assert(path.match(prefix_));
*name = path.copy(prefix_.getLength());
ent = readEntity(manager_, ucr_, key_, *name, false);
assert(ent.is());
++index_;
}
return ent;
}
class Module: public ModuleEntity {
public:
Module(
rtl::Reference< Manager > const & manager, RegistryKey const & ucr,
RegistryKey const & key):
manager_(manager), ucr_(ucr), key_(key)
{}
private:
virtual ~Module() throw () {}
virtual std::vector< OUString > getMemberNames() const;
virtual rtl::Reference< MapCursor > createCursor() const
{ return new Cursor(manager_, ucr_, key_); }
rtl::Reference< Manager > manager_;
RegistryKey ucr_;
mutable RegistryKey key_;
};
std::vector< OUString > Module::getMemberNames() const {
RegistryKeyNames names;
RegError e = key_.getKeyNames("", names);
if (e != REG_NO_ERROR) {
throw FileFormatException(
key_.getRegistryName(),
("legacy format: cannot get sub-key names of " + key_.getName()
+ ": " + OUString::number(e)));
}
std::vector< OUString > ns;
for (sal_uInt32 i = 0; i != names.getLength(); ++i) {
ns.push_back(names.getElement(i));
}
return ns;
}
typereg::Reader getReader(RegistryKey & key, std::vector< char > * buffer) {
assert(buffer != 0);
RegValueType type;
sal_uInt32 size;
RegError e = key.getValueInfo("", &type, &size);
if (e != REG_NO_ERROR) {
throw FileFormatException(
key.getRegistryName(),
("legacy format: cannot get value info about key " + key.getName()
+ ": " + OUString::number(e)));
}
if (type != RG_VALUETYPE_BINARY) {
throw FileFormatException(
key.getRegistryName(),
("legacy format: unexpected value type " + OUString::number(type)
+ " of key " + key.getName()));
}
if (size == 0
/*TODO: || size > std::numeric_limits< std::vector< char >::size_type >::max() */)
{
throw FileFormatException(
key.getRegistryName(),
("legacy format: bad binary value size " + OUString::number(size)
+ " of key " + key.getName()));
}
buffer->resize(static_cast< std::vector< char >::size_type >(size));
e = key.getValue("", &(*buffer)[0]);
if (e != REG_NO_ERROR) {
throw FileFormatException(
key.getRegistryName(),
("legacy format: cannot get binary value of key " + key.getName()
+ ": " + OUString::number(e)));
}
typereg::Reader reader(&(*buffer)[0], size, false, TYPEREG_VERSION_1);
if (!reader.isValid()) {
throw FileFormatException(
key.getRegistryName(),
"legacy format: malformed binary value of key " + key.getName());
}
return reader;
}
rtl::Reference< Entity > readEntity(
rtl::Reference< Manager > const & manager, RegistryKey & ucr,
RegistryKey & key, OUString const & path, bool probe)
{
assert(manager.is());
RegistryKey sub;
RegError e = key.openKey(path, sub);
switch (e) {
case REG_NO_ERROR:
break;
case REG_KEY_NOT_EXISTS:
if (probe) {
return rtl::Reference< Entity >();
}
// fall through
default:
throw FileFormatException(
key.getRegistryName(),
("legacy format: cannot open sub-key " + path + " of "
+ key.getName() + ": " + OUString::number(e)));
}
std::vector< char > buf;
typereg::Reader reader(getReader(sub, &buf));
switch (reader.getTypeClass()) {
case RT_TYPE_INTERFACE:
{
std::vector< OUString > mandBases;
sal_uInt16 n = reader.getSuperTypeCount();
for (sal_uInt16 j = 0; j != n; ++j) {
mandBases.push_back(
reader.getSuperTypeName(j).replace('/', '.'));
}
std::vector< OUString > optBases;
n = reader.getReferenceCount();
for (sal_uInt16 j = 0; j != n; ++j) {
optBases.push_back(
reader.getReferenceTypeName(j).replace('/', '.'));
}
sal_uInt16 methodCount = reader.getMethodCount();
std::vector< InterfaceTypeEntity::Attribute > attrs;
n = reader.getFieldCount(); // attributes
for (sal_uInt16 j = 0; j != n; ++j) {
OUString attrName(reader.getFieldName(j));
std::vector< OUString > getExcs;
std::vector< OUString > setExcs;
for (sal_uInt16 k = 0; k != methodCount; ++k) {
if (reader.getMethodName(k) == attrName) {
switch (reader.getMethodFlags(k)) {
case RT_MODE_ATTRIBUTE_GET:
{
sal_uInt16 m
= reader.getMethodExceptionCount(k);
for (sal_uInt16 l = 0; l != m; ++l) {
getExcs.push_back(
reader.getMethodExceptionTypeName(k, l).
replace('/', '.'));
}
break;
}
case RT_MODE_ATTRIBUTE_SET:
{
sal_uInt16 m
= reader.getMethodExceptionCount(k);
for (sal_uInt16 l = 0; l != m; ++l) {
setExcs.push_back(
reader.getMethodExceptionTypeName(k, l).
replace('/', '.'));
}
break;
}
default:
throw FileFormatException(
key.getRegistryName(),
("legacy format: method and attribute with same"
" name " + attrName
+ " in interface type with key "
+ sub.getName()));
}
}
}
RTFieldAccess flags = reader.getFieldFlags(j);
attrs.push_back(
InterfaceTypeEntity::Attribute(
attrName, reader.getFieldTypeName(j).replace('/', '.'),
(flags & RT_ACCESS_BOUND) != 0,
(flags & RT_ACCESS_READONLY) != 0, getExcs, setExcs));
}
std::vector< InterfaceTypeEntity::Method > meths;
for (sal_uInt16 j = 0; j != methodCount; ++j) {
RTMethodMode flags = reader.getMethodFlags(j);
if (flags != RT_MODE_ATTRIBUTE_GET
&& flags != RT_MODE_ATTRIBUTE_SET)
{
std::vector< InterfaceTypeEntity::Method::Parameter >
params;
sal_uInt16 m = reader.getMethodParameterCount(j);
for (sal_uInt16 k = 0; k != m; ++k) {
RTParamMode mode = reader.getMethodParameterFlags(j, k);
InterfaceTypeEntity::Method::Parameter::Direction dir;
switch (mode) {
case RT_PARAM_IN:
dir = InterfaceTypeEntity::Method::Parameter::
Direction::DIRECTION_IN;
break;
case RT_PARAM_OUT:
dir = InterfaceTypeEntity::Method::Parameter::
Direction::DIRECTION_OUT;
break;
case RT_PARAM_INOUT:
dir = InterfaceTypeEntity::Method::Parameter::
Direction::DIRECTION_IN_OUT;
break;
default:
throw FileFormatException(
key.getRegistryName(),
("legacy format: unexpected mode "
+ OUString::number(mode) + " of parameter "
+ reader.getMethodParameterName(j, k)
+ " of method " + reader.getMethodName(j)
+ " in interface type with key "
+ sub.getName()));
}
params.push_back(
InterfaceTypeEntity::Method::Parameter(
reader.getMethodParameterName(j, k),
(reader.getMethodParameterTypeName(j, k).
replace('/', '.')),
dir));
}
std::vector< OUString > excs;
m = reader.getMethodExceptionCount(j);
for (sal_uInt16 k = 0; k != m; ++k) {
excs.push_back(
reader.getMethodExceptionTypeName(j, k).replace(
'/', '.'));
}
meths.push_back(
InterfaceTypeEntity::Method(
reader.getMethodName(j),
reader.getMethodReturnTypeName(j).replace('/', '.'),
params, excs));
}
}
return new InterfaceTypeEntity(
reader.isPublished(), mandBases, optBases, attrs, meths);
}
case RT_TYPE_MODULE:
return new Module(manager, ucr, sub);
case RT_TYPE_STRUCT:
{
sal_uInt32 n = reader.getReferenceCount();
if (n == 0) {
OUString base;
switch (reader.getSuperTypeCount()) {
case 0:
break;
case 1:
base = reader.getSuperTypeName(0).replace('/', '.');
break;
default:
FileFormatException(
key.getRegistryName(),
("legacy format: unexpected number "
+ OUString::number(reader.getSuperTypeCount())
+ " of super-types of plain struct type with key "
+ sub.getName()));
}
std::vector< PlainStructTypeEntity::Member > mems;
n = reader.getFieldCount();
for (sal_uInt16 j = 0; j != n; ++j) {
mems.push_back(
PlainStructTypeEntity::Member(
reader.getFieldName(j),
reader.getFieldTypeName(j).replace('/', '.')));
}
return new PlainStructTypeEntity(
reader.isPublished(), base, mems);
} else {
if (reader.getSuperTypeCount() != 0) {
FileFormatException(
key.getRegistryName(),
("legacy format: unexpected number "
+ OUString::number(reader.getSuperTypeCount())
+ " of super-types of polymorphic struct type template"
" with key " + sub.getName()));
}
std::vector< OUString > params;
for (sal_uInt16 j = 0; j != n; ++j) {
params.push_back(
reader.getReferenceTypeName(j).replace('/', '.'));
}
std::vector< PolymorphicStructTypeTemplateEntity::Member > mems;
n = reader.getFieldCount();
for (sal_uInt16 j = 0; j != n; ++j) {
mems.push_back(
PolymorphicStructTypeTemplateEntity::Member(
reader.getFieldName(j),
reader.getFieldTypeName(j).replace('/', '.'),
((reader.getFieldFlags(j)
& RT_ACCESS_PARAMETERIZED_TYPE)
!= 0)));
}
return new PolymorphicStructTypeTemplateEntity(
reader.isPublished(), params, mems);
}
}
case RT_TYPE_ENUM:
{
std::vector< EnumTypeEntity::Member > mems;
sal_uInt16 n = reader.getFieldCount();
for (sal_uInt16 j = 0; j != n; ++j) {
RTConstValue v(reader.getFieldValue(j));
if (v.m_type != RT_TYPE_INT32) {
FileFormatException(
key.getRegistryName(),
("legacy format: unexpected type "
+ OUString::number(v.m_type) + " of value of field "
+ reader.getFieldName(j) + " of enum type with key "
+ sub.getName()));
}
mems.push_back(
EnumTypeEntity::Member(
reader.getFieldName(j), v.m_value.aLong));
}
return new EnumTypeEntity(reader.isPublished(), mems);
}
case RT_TYPE_EXCEPTION:
{
OUString base;
switch (reader.getSuperTypeCount()) {
case 0:
break;
case 1:
base = reader.getSuperTypeName(0).replace('/', '.');
break;
default:
throw FileFormatException(
key.getRegistryName(),
("legacy format: unexpected number "
+ OUString::number(reader.getSuperTypeCount())
+ " of super-types of exception type with key "
+ sub.getName()));
}
std::vector< ExceptionTypeEntity::Member > mems;
sal_uInt16 n = reader.getFieldCount();
for (sal_uInt16 j = 0; j != n; ++j) {
mems.push_back(
ExceptionTypeEntity::Member(
reader.getFieldName(j),
reader.getFieldTypeName(j).replace('/', '.')));
}
return new ExceptionTypeEntity(reader.isPublished(), base, mems);
}
case RT_TYPE_TYPEDEF:
if (reader.getSuperTypeCount() != 1) {
throw FileFormatException(
key.getRegistryName(),
("legacy format: unexpected number "
+ OUString::number(reader.getSuperTypeCount())
+ " of super-types of typedef with key " + sub.getName()));
}
return new TypedefEntity(
reader.isPublished(), reader.getSuperTypeName(0).replace('/', '.'));
case RT_TYPE_SERVICE:
switch (reader.getSuperTypeCount()) {
case 0:
{
std::vector< OUString > mandServs;
std::vector< OUString > optServs;
std::vector< OUString > mandIfcs;
std::vector< OUString > optIfcs;
sal_uInt16 n = reader.getReferenceCount();
for (sal_uInt16 j = 0; j != n; ++j) {
OUString refName(
reader.getReferenceTypeName(j).replace('/', '.'));
switch (reader.getReferenceSort(j)) {
case RT_REF_EXPORTS:
if ((reader.getReferenceFlags(j) & RT_ACCESS_OPTIONAL)
== 0)
{
mandServs.push_back(refName);
} else {
optServs.push_back(refName);
}
break;
case RT_REF_SUPPORTS:
if ((reader.getReferenceFlags(j) & RT_ACCESS_OPTIONAL)
== 0)
{
mandIfcs.push_back(refName);
} else {
optIfcs.push_back(refName);
}
break;
default:
throw FileFormatException(
key.getRegistryName(),
("legacy format: unexpected mode "
+ OUString::number(reader.getReferenceSort(j))
+ " of reference " + reader.getReferenceTypeName(j)
+ " in service with key " + sub.getName()));
}
}
std::vector< AccumulationBasedServiceEntity::Property > props;
n = reader.getFieldCount();
for (sal_uInt16 j = 0; j != n; ++j) {
RTFieldAccess acc = reader.getFieldFlags(j);
int attrs = 0;
if ((acc & RT_ACCESS_READONLY) != 0) {
attrs |= AccumulationBasedServiceEntity::Property::
ATTRIBUTE_READ_ONLY;
}
if ((acc & RT_ACCESS_OPTIONAL) != 0) {
attrs |= AccumulationBasedServiceEntity::Property::
ATTRIBUTE_OPTIONAL;
}
if ((acc & RT_ACCESS_MAYBEVOID) != 0) {
attrs |= AccumulationBasedServiceEntity::Property::
ATTRIBUTE_MAYBE_VOID;
}
if ((acc & RT_ACCESS_BOUND) != 0) {
attrs |= AccumulationBasedServiceEntity::Property::
ATTRIBUTE_BOUND;
}
if ((acc & RT_ACCESS_CONSTRAINED) != 0) {
attrs |= AccumulationBasedServiceEntity::Property::
ATTRIBUTE_CONSTRAINED;
}
if ((acc & RT_ACCESS_TRANSIENT) != 0) {
attrs |= AccumulationBasedServiceEntity::Property::
ATTRIBUTE_TRANSIENT;
}
if ((acc & RT_ACCESS_MAYBEAMBIGUOUS) != 0) {
attrs |= AccumulationBasedServiceEntity::Property::
ATTRIBUTE_MAYBE_AMBIGUOUS;
}
if ((acc & RT_ACCESS_MAYBEDEFAULT) != 0) {
attrs |= AccumulationBasedServiceEntity::Property::
ATTRIBUTE_MAYBE_DEFAULT;
}
if ((acc & RT_ACCESS_REMOVEABLE) != 0) {
attrs |= AccumulationBasedServiceEntity::Property::
ATTRIBUTE_REMOVABLE;
}
props.push_back(
AccumulationBasedServiceEntity::Property(
reader.getFieldName(j),
reader.getFieldTypeName(j).replace('/', '.'),
static_cast<
AccumulationBasedServiceEntity::Property::
Attributes >(attrs)));
}
return new AccumulationBasedServiceEntity(
reader.isPublished(), mandServs, optServs, mandIfcs,
optIfcs, props);
}
case 1:
{
std::vector< SingleInterfaceBasedServiceEntity::Constructor >
ctors;
sal_uInt16 n = reader.getMethodCount();
if (n == 1 && reader.getMethodFlags(0) == 0
&& reader.getMethodName(0).isEmpty()
&& reader.getMethodReturnTypeName(0) == "void"
&& reader.getMethodParameterCount(0) == 0
&& reader.getMethodExceptionCount(0) == 0)
{
ctors.push_back(
SingleInterfaceBasedServiceEntity::Constructor());
} else {
for (sal_uInt16 j = 0; j != n; ++j) {
if (reader.getMethodFlags(j) != RT_MODE_TWOWAY) {
throw FileFormatException(
key.getRegistryName(),
("legacy format: unexpected mode "
+ OUString::number(reader.getMethodFlags(j))
+ " of constructor " + reader.getMethodName(j)
+ " in service with key " + sub.getName()));
}
std::vector<
SingleInterfaceBasedServiceEntity::Constructor::
Parameter > params;
sal_uInt16 m = reader.getMethodParameterCount(j);
for (sal_uInt16 k = 0; k != m; ++k) {
RTParamMode mode
= reader.getMethodParameterFlags(j, k);
if ((mode & ~RT_PARAM_REST) != RT_PARAM_IN) {
throw FileFormatException(
key.getRegistryName(),
("legacy format: unexpected mode "
+ OUString::number(mode)
+ " of parameter "
+ reader.getMethodParameterName(j, k)
+ " of constructor "
+ reader.getMethodName(j)
+ " in service with key "
+ sub.getName()));
}
if ((mode & RT_PARAM_REST) != 0
&& !(m == 1
&& ((reader.getMethodParameterTypeName(
j, 1))
== "any")))
{
throw FileFormatException(
key.getRegistryName(),
("legacy format: bad rest parameter "
+ reader.getMethodParameterName(j, k)
+ " of constructor "
+ reader.getMethodName(j)
+ " in service with key "
+ sub.getName()));
}
params.push_back(
SingleInterfaceBasedServiceEntity::Constructor::
Parameter(
reader.getMethodParameterName(j, k),
(reader.getMethodParameterTypeName(j, k).
replace('/', '.')),
(mode & RT_PARAM_REST) != 0));
}
std::vector< OUString > excs;
m = reader.getMethodExceptionCount(j);
for (sal_uInt16 k = 0; k != m; ++k) {
excs.push_back(
reader.getMethodExceptionTypeName(j, k).
replace('/', '.'));
}
ctors.push_back(
SingleInterfaceBasedServiceEntity::Constructor(
reader.getMethodName(j), params, excs));
}
}
return new SingleInterfaceBasedServiceEntity(
reader.isPublished(),
reader.getSuperTypeName(0).replace('/', '.'), ctors);
}
default:
throw FileFormatException(
key.getRegistryName(),
("legacy format: unexpected number "
+ OUString::number(reader.getSuperTypeCount())
+ " of super-types of service with key " + sub.getName()));
}
case RT_TYPE_SINGLETON:
{
if (reader.getSuperTypeCount() != 1) {
throw FileFormatException(
key.getRegistryName(),
("legacy format: unexpected number "
+ OUString::number(reader.getSuperTypeCount())
+ " of super-types of singleton with key "
+ sub.getName()));
}
OUString basePath(reader.getSuperTypeName(0));
OUString baseName(basePath.replace('/', '.'));
bool newStyle;
rtl::Reference< Entity > base(manager->findEntity(baseName));
if (base.is()) {
switch (base->getSort()) {
case Entity::SORT_INTERFACE_TYPE:
newStyle = true;
break;
case Entity::SORT_ACCUMULATION_BASED_SERVICE:
newStyle = false;
break;
default:
throw FileFormatException(
key.getRegistryName(),
("legacy format: unexpected sort "
+ OUString::number(base->getSort()) + " of base "
+ baseName + " of singleton with key "
+ sub.getName()));
}
} else {
RegistryKey key2;
e = ucr.openKey(basePath, key2);
switch (e) {
case REG_NO_ERROR:
break;
case REG_KEY_NOT_EXISTS:
throw FileFormatException(
key.getRegistryName(),
("legacy format: unknown super-type " + basePath
+ " of super-type with key " + sub.getName()));
default:
throw FileFormatException(
key.getRegistryName(),
("legacy format: cannot open ucr sub-key " + basePath
+ ": " + OUString::number(e)));
}
std::vector< char > buf2;
typereg::Reader reader2(getReader(key2, &buf2));
switch (reader2.getTypeClass()) {
case RT_TYPE_INTERFACE:
newStyle = true;
break;
case RT_TYPE_SERVICE:
newStyle = false;
break;
default:
throw FileFormatException(
key.getRegistryName(),
("legacy format: unexpected type class "
+ OUString::number(reader2.getTypeClass())
+ " of super-type with key " + key2.getName()
+ " of singleton with key " + sub.getName()));
}
}
return newStyle
? rtl::Reference< Entity >(
new InterfaceBasedSingletonEntity(
reader.isPublished(), baseName))
: rtl::Reference< Entity >(
new ServiceBasedSingletonEntity(
reader.isPublished(), baseName));
}
case RT_TYPE_CONSTANTS:
{
std::vector< ConstantGroupEntity::Member > mems;
sal_uInt16 n = reader.getFieldCount();
for (sal_uInt16 j = 0; j != n; ++j) {
mems.push_back(
ConstantGroupEntity::Member(
reader.getFieldName(j),
translateConstantValue(sub, reader.getFieldValue(j))));
}
return new ConstantGroupEntity(reader.isPublished(), mems);
}
default:
throw FileFormatException(
key.getRegistryName(),
("legacy format: unexpected type class "
+ OUString::number(reader.getTypeClass()) + " of key "
+ sub.getName()));
}
}
}
LegacyProvider::LegacyProvider(
rtl::Reference< Manager > const & manager, OUString const & uri):
manager_(manager)
{
Registry reg;
RegError e = reg.open(uri, REG_READONLY);
switch (e) {
case REG_NO_ERROR:
break;
case REG_REGISTRY_NOT_EXISTS:
throw NoSuchFileException(uri);
default:
throw FileFormatException(
uri, "cannot open legacy file: " + OUString::number(e));
}
RegistryKey root;
e = reg.openRootKey(root);
if (e != REG_NO_ERROR) {
throw FileFormatException(
uri, "legacy format: cannot open root key: " + OUString::number(e));
}
e = root.openKey("UCR", ucr_);
if (e != REG_NO_ERROR) {
throw FileFormatException(
uri, "legacy format: cannot open UCR key: " + OUString::number(e));
}
}
rtl::Reference< MapCursor > LegacyProvider::createRootCursor() const {
return new Cursor(manager_, ucr_, ucr_);
}
rtl::Reference< Entity > LegacyProvider::findEntity(rtl::OUString const & name)
const
{
return readEntity(manager_, ucr_, ucr_, name.replace('.', '/'), true);
}
LegacyProvider::~LegacyProvider() throw () {}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "sal/config.h"
#include <cassert>
#include <cstddef>
#include <cstdlib>
#include <iostream>
#include <map>
#include <utility>
#include <vector>
#include "osl/endian.h"
#include "osl/file.h"
#include "osl/file.hxx"
#include "osl/process.h"
#include "rtl/process.h"
#include "rtl/string.hxx"
#include "rtl/textenc.h"
#include "rtl/textcvt.h"
#include "rtl/ustring.hxx"
#include "sal/macros.h"
#include "sal/main.h"
#include "unoidl/unoidl.hxx"
namespace {
OUString getArgumentUri(sal_uInt32 argument) {
OUString arg;
rtl_getAppCommandArg(argument, &arg.pData);
OUString url;
osl::FileBase::RC e1 = osl::FileBase::getFileURLFromSystemPath(arg, url);
if (e1 != osl::FileBase::E_None) {
std::cerr
<< "Cannot convert \"" << arg << "\" to file URL, error code "
<< +e1 << std::endl;
std::exit(EXIT_FAILURE);
}
OUString cwd;
oslProcessError e2 = osl_getProcessWorkingDir(&cwd.pData);
if (e2 != osl_Process_E_None) {
std::cerr
<< "Cannot obtain working directory, error code " << +e2
<< std::endl;
std::exit(EXIT_FAILURE);
}
OUString abs;
e1 = osl::FileBase::getAbsoluteFileURL(cwd, url, abs);
if (e1 != osl::FileBase::E_None) {
std::cerr
<< "Cannot make \"" << url
<< "\" into an absolute file URL, error code " << +e1 << std::endl;
std::exit(EXIT_FAILURE);
}
return abs;
}
rtl::Reference< unoidl::Provider > load(
rtl::Reference< unoidl::Manager > const & manager, OUString const & uri)
{
try {
return unoidl::loadProvider(manager, uri);
} catch (unoidl::NoSuchFileException &) {
std::cerr << "Input <" << uri << "> does not exist" << std::endl;
std::exit(EXIT_FAILURE);
} catch (unoidl::FileFormatException & e) {
std::cerr
<< "Cannot read input <" << uri << ">: " << e.getDetail()
<< std::endl;
std::exit(EXIT_FAILURE);
}
}
sal_uInt64 getOffset(osl::File & file) {
sal_uInt64 off;
osl::FileBase::RC e = file.getPos(off);
if (e != osl::FileBase::E_None) {
std::cerr
<< "Cannot determine current position in <" << file.getURL()
<< ">, error code " << +e << std::endl;
std::exit(EXIT_FAILURE);
}
return off;
}
void write(osl::File & file, void const * buffer, sal_uInt64 size) {
sal_uInt64 n;
osl::FileBase::RC e = file.write(buffer, size, n);
if (e != osl::FileBase::E_None) {
std::cerr
<< "Cannot write to <" << file.getURL() << ">, error code " << +e
<< std::endl;
std::exit(EXIT_FAILURE);
}
if (n != size) {
std::cerr
<< "Bad write of " << n << " instead of " << size << " bytes to <"
<< file.getURL() << '>' << std::endl;
std::exit(EXIT_FAILURE);
}
}
void write8(osl::File & file, sal_uInt64 value) {
if (value > 0xFF) {
std::cerr
<< "Cannot write value >= 2^8; input is too large" << std::endl;
std::exit(EXIT_FAILURE);
}
unsigned char buf[1];
buf[0] = value & 0xFF;
write(file, buf, SAL_N_ELEMENTS(buf));
}
void write16(osl::File & file, sal_uInt64 value) {
if (value > 0xFFFF) {
std::cerr
<< "Cannot write value >= 2^16; input is too large" << std::endl;
std::exit(EXIT_FAILURE);
}
unsigned char buf[2];
buf[0] = value & 0xFF;
buf[1] = (value >> 8) & 0xFF;
write(file, buf, SAL_N_ELEMENTS(buf));
}
void write32(osl::File & file, sal_uInt64 value) {
if (value > 0xFFFFFFFF) {
std::cerr
<< "Cannot write value >= 2^32; input is too large" << std::endl;
std::exit(EXIT_FAILURE);
}
unsigned char buf[4];
buf[0] = value & 0xFF;
buf[1] = (value >> 8) & 0xFF;
buf[2] = (value >> 16) & 0xFF;
buf[3] = (value >> 24) & 0xFF;
write(file, buf, SAL_N_ELEMENTS(buf));
}
void write64(osl::File & file, sal_uInt64 value) {
unsigned char buf[8];
buf[0] = value & 0xFF;
buf[1] = (value >> 8) & 0xFF;
buf[2] = (value >> 16) & 0xFF;
buf[3] = (value >> 24) & 0xFF;
buf[3] = (value >> 32) & 0xFF;
buf[3] = (value >> 40) & 0xFF;
buf[3] = (value >> 48) & 0xFF;
buf[3] = (value >> 56) & 0xFF;
write(file, buf, SAL_N_ELEMENTS(buf));
}
void writeIso60599Binary32(osl::File & file, float value) {
union {
unsigned char buf[4];
float f; // assuming float is ISO 60599 binary32
} sa;
sa.f = value;
#if defined OSL_BIGENDIAN
std::swap(sa.buf[0], sa.buf[3]);
std::swap(sa.buf[1], sa.buf[2]);
#endif
write(file, sa.buf, SAL_N_ELEMENTS(sa.buf));
}
void writeIso60599Binary64(osl::File & file, double value) {
union {
unsigned char buf[8];
float d; // assuming double is ISO 60599 binary64
} sa;
sa.d = value;
#if defined OSL_BIGENDIAN
std::swap(sa.buf[0], sa.buf[7]);
std::swap(sa.buf[1], sa.buf[6]);
std::swap(sa.buf[2], sa.buf[5]);
std::swap(sa.buf[3], sa.buf[4]);
#endif
write(file, sa.buf, SAL_N_ELEMENTS(sa.buf));
}
OString toAscii(OUString const & name) {
OString ascii;
if (!name.convertToString(
&ascii, RTL_TEXTENCODING_ASCII_US,
(RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
| RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
{
std::cerr
<< "Cannot convert \"" << name << "\" to US ASCII" << std::endl;
std::exit(EXIT_FAILURE);
}
return ascii;
}
sal_uInt64 writeNameNul(osl::File & file, OUString const & name) {
OString ascii(toAscii(name));
if (ascii.indexOf('\0') != -1) {
std::cerr
<< "Name \"" << ascii << "\" contains NUL characters" << std::endl;
std::exit(EXIT_FAILURE);
}
sal_uInt64 off = getOffset(file);
write(file, ascii.getStr(), ascii.getLength() + 1);
return off;
}
void writeNameLen(osl::File & file, OUString const & name) {
static std::map< OUString, sal_uInt64 > reuse;
std::map< OUString, sal_uInt64 >::iterator i(reuse.find(name));
if (i == reuse.end()) {
reuse.insert(std::make_pair(name, getOffset(file)));
OString ascii(toAscii(name));
assert(
(static_cast< sal_uInt64 >(ascii.getLength()) & 0x80000000) == 0);
write32(
file, static_cast< sal_uInt64 >(ascii.getLength()) | 0x80000000);
write(file, ascii.getStr(), ascii.getLength());
} else {
write32(file, i->second);
}
}
void writeKind(
osl::File & file,
rtl::Reference< unoidl::PublishableEntity > const & entity,
bool flag = false)
{
assert(entity.is());
sal_uInt64 v = entity->getSort();
if (entity->isPublished()) {
v |= 0x80;
}
if (false /*TODO: deprecated */) {
v |= 0x40;
}
if (flag) {
v |= 0x20;
}
write8(file, v);
}
sal_uInt64 writeMap(
osl::File & file, rtl::Reference< unoidl::MapCursor > const & cursor,
std::size_t * rootSize)
{
assert(cursor.is());
struct Item {
explicit Item(rtl::Reference< unoidl::Entity > const & theEntity):
entity(theEntity)
{}
rtl::Reference< unoidl::Entity > entity;
sal_uInt64 nameOffset;
sal_uInt64 dataOffset;
};
std::map< OUString, Item > map;
for (;;) {
OUString name;
rtl::Reference< unoidl::Entity > ent(cursor->getNext(&name));
if (!ent.is()) {
break;
}
if (!map.insert(std::make_pair(name, Item(ent))).second) {
std::cout << "Duplicate name \"" << name << '"' << std::endl;
std::exit(EXIT_FAILURE);
}
}
for (std::map< OUString, Item >::iterator i(map.begin()); i != map.end();
++i)
{
switch (i->second.entity->getSort()) {
case unoidl::Entity::SORT_MODULE:
{
rtl::Reference< unoidl::ModuleEntity > ent2(
static_cast< unoidl::ModuleEntity * >(
i->second.entity.get()));
i->second.dataOffset = writeMap(file, ent2->createCursor(), 0);
break;
}
case unoidl::Entity::SORT_ENUM_TYPE:
{
rtl::Reference< unoidl::EnumTypeEntity > ent2(
static_cast< unoidl::EnumTypeEntity * >(
i->second.entity.get()));
i->second.dataOffset = getOffset(file);
writeKind(file, ent2.get());
write32(file, ent2->getMembers().size());
for (std::vector< unoidl::EnumTypeEntity::Member >::
const_iterator j(ent2->getMembers().begin());
j != ent2->getMembers().end(); ++j)
{
writeNameLen(file, j->name);
write32(file, static_cast< sal_uInt32 >(j->value));
}
break;
}
case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE:
{
rtl::Reference< unoidl::PlainStructTypeEntity > ent2(
static_cast< unoidl::PlainStructTypeEntity * >(
i->second.entity.get()));
i->second.dataOffset = getOffset(file);
writeKind(file, ent2.get(), !ent2->getDirectBase().isEmpty());
if (!ent2->getDirectBase().isEmpty()) {
writeNameLen(file, ent2->getDirectBase());
}
write32(file, ent2->getDirectMembers().size());
for (std::vector< unoidl::PlainStructTypeEntity::Member >::
const_iterator j(ent2->getDirectMembers().begin());
j != ent2->getDirectMembers().end(); ++j)
{
writeNameLen(file, j->name);
writeNameLen(file, j->type);
}
break;
}
case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE:
{
rtl::Reference< unoidl::PolymorphicStructTypeTemplateEntity >
ent2(
static_cast<
unoidl::PolymorphicStructTypeTemplateEntity * >(
i->second.entity.get()));
i->second.dataOffset = getOffset(file);
writeKind(file, ent2.get());
write32(file, ent2->getTypeParameters().size());
for (std::vector< OUString >::const_iterator j(
ent2->getTypeParameters().begin());
j != ent2->getTypeParameters().end(); ++j)
{
writeNameLen(file, *j);
}
write32(file, ent2->getMembers().size());
for (std::vector<
unoidl::PolymorphicStructTypeTemplateEntity::Member >::
const_iterator j(
ent2->getMembers().begin());
j != ent2->getMembers().end(); ++j)
{
sal_uInt64 f = 0;
if (j->parameterized) {
f |= 0x01;
}
write8(file, f);
writeNameLen(file, j->name);
writeNameLen(file, j->type);
}
break;
}
case unoidl::Entity::SORT_EXCEPTION_TYPE:
{
rtl::Reference< unoidl::ExceptionTypeEntity > ent2(
static_cast< unoidl::ExceptionTypeEntity * >(
i->second.entity.get()));
i->second.dataOffset = getOffset(file);
writeKind(file, ent2.get(), !ent2->getDirectBase().isEmpty());
if (!ent2->getDirectBase().isEmpty()) {
writeNameLen(file, ent2->getDirectBase());
}
write32(file, ent2->getDirectMembers().size());
for (std::vector< unoidl::ExceptionTypeEntity::Member >::
const_iterator j(ent2->getDirectMembers().begin());
j != ent2->getDirectMembers().end(); ++j)
{
writeNameLen(file, j->name);
writeNameLen(file, j->type);
}
break;
}
case unoidl::Entity::SORT_INTERFACE_TYPE:
{
rtl::Reference< unoidl::InterfaceTypeEntity > ent2(
static_cast< unoidl::InterfaceTypeEntity * >(
i->second.entity.get()));
i->second.dataOffset = getOffset(file);
writeKind(file, ent2.get());
write32(file, ent2->getDirectMandatoryBases().size());
for (std::vector< OUString >::const_iterator j(
ent2->getDirectMandatoryBases().begin());
j != ent2->getDirectMandatoryBases().end(); ++j)
{
writeNameLen(file, *j);
}
write32(file, ent2->getDirectOptionalBases().size());
for (std::vector< OUString >::const_iterator j(
ent2->getDirectOptionalBases().begin());
j != ent2->getDirectOptionalBases().end(); ++j)
{
writeNameLen(file, *j);
}
write32(file, ent2->getDirectAttributes().size());
for (std::vector< unoidl::InterfaceTypeEntity::Attribute >::
const_iterator j(ent2->getDirectAttributes().begin());
j != ent2->getDirectAttributes().end(); ++j)
{
sal_uInt64 f = 0;
if (j->bound) {
f |= 0x01;
}
if (j->readOnly) {
f |= 0x02;
}
write8(file, f);
writeNameLen(file, j->name);
writeNameLen(file, j->type);
write32(file, j->getExceptions.size());
for (std::vector< OUString >::const_iterator k(
j->getExceptions.begin());
k != j->getExceptions.end(); ++k)
{
writeNameLen(file, *k);
}
if (!j->readOnly) {
write32(file, j->setExceptions.size());
for (std::vector< OUString >::const_iterator k(
j->setExceptions.begin());
k != j->setExceptions.end(); ++k)
{
writeNameLen(file, *k);
}
}
}
write32(file, ent2->getDirectMethods().size());
for (std::vector< unoidl::InterfaceTypeEntity::Method >::
const_iterator j(ent2->getDirectMethods().begin());
j != ent2->getDirectMethods().end(); ++j)
{
writeNameLen(file, j->name);
writeNameLen(file, j->returnType);
write32(file, j->parameters.size());
for (std::vector<
unoidl::InterfaceTypeEntity::Method::Parameter >::
const_iterator k(j->parameters.begin());
k != j->parameters.end(); ++k)
{
write8(file, k->direction);
writeNameLen(file, k->name);
writeNameLen(file, k->type);
}
write32(file, j->exceptions.size());
for (std::vector< OUString >::const_iterator k(
j->exceptions.begin());
k != j->exceptions.end(); ++k)
{
writeNameLen(file, *k);
}
}
break;
}
case unoidl::Entity::SORT_TYPEDEF:
{
rtl::Reference< unoidl::TypedefEntity > ent2(
static_cast< unoidl::TypedefEntity * >(
i->second.entity.get()));
i->second.dataOffset = getOffset(file);
writeKind(file, ent2.get());
writeNameLen(file, ent2->getType());
break;
}
case unoidl::Entity::SORT_CONSTANT_GROUP:
{
rtl::Reference< unoidl::ConstantGroupEntity > ent2(
static_cast< unoidl::ConstantGroupEntity * >(
i->second.entity.get()));
struct ConstItem {
explicit ConstItem(
unoidl::ConstantValue const & theConstant):
constant(theConstant)
{}
unoidl::ConstantValue constant;
sal_uInt64 nameOffset;
sal_uInt64 dataOffset;
};
std::map< OUString, ConstItem > cmap;
for (std::vector< unoidl::ConstantGroupEntity::Member >::
const_iterator j(ent2->getMembers().begin());
j != ent2->getMembers().end(); ++j)
{
if (!cmap.insert(
std::make_pair(j->name, ConstItem(j->value))).
second)
{
std::cout
<< "Duplicate constant group member name \""
<< j->name << '"' << std::endl;
std::exit(EXIT_FAILURE);
}
}
for (std::map< OUString, ConstItem >::iterator j(cmap.begin());
j != cmap.end(); ++j)
{
j->second.dataOffset = getOffset(file);
sal_uInt64 v = j->second.constant.type;
if (false /*TODO: deprecated */) {
v |= 0x80;
}
write8(file, v);
switch (j->second.constant.type) {
case unoidl::ConstantValue::TYPE_BOOLEAN:
write8(file, j->second.constant.booleanValue ? 1 : 0);
break;
case unoidl::ConstantValue::TYPE_BYTE:
write8(
file,
static_cast< sal_uInt8 >(
j->second.constant.byteValue));
break;
case unoidl::ConstantValue::TYPE_SHORT:
write16(
file,
static_cast< sal_uInt16 >(
j->second.constant.shortValue));
break;
case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT:
write16(file, j->second.constant.unsignedShortValue);
break;
case unoidl::ConstantValue::TYPE_LONG:
write32(
file,
static_cast< sal_uInt32 >(
j->second.constant.longValue));
break;
case unoidl::ConstantValue::TYPE_UNSIGNED_LONG:
write32(file, j->second.constant.unsignedLongValue);
break;
case unoidl::ConstantValue::TYPE_HYPER:
write64(
file,
static_cast< sal_uInt64 >(
j->second.constant.hyperValue));
break;
case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER:
write64(file, j->second.constant.unsignedHyperValue);
break;
case unoidl::ConstantValue::TYPE_FLOAT:
writeIso60599Binary32(
file, j->second.constant.floatValue);
break;
case unoidl::ConstantValue::TYPE_DOUBLE:
writeIso60599Binary64(
file, j->second.constant.doubleValue);
break;
default:
for (;;) { std::abort(); } // this cannot happen
}
}
for (std::map< OUString, ConstItem >::iterator j(
cmap.begin());
j != cmap.end(); ++j)
{
j->second.nameOffset = writeNameNul(file, j->first);
}
i->second.dataOffset = getOffset(file);
writeKind(file, ent2.get());
write32(file, cmap.size());
// overflow from std::map::size_type -> sal_uInt64 is
// unrealistic
for (std::map< OUString, ConstItem >::iterator j(
cmap.begin());
j != cmap.end(); ++j)
{
write32(file, j->second.nameOffset);
write32(file, j->second.dataOffset);
}
break;
}
case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE:
{
rtl::Reference< unoidl::SingleInterfaceBasedServiceEntity >
ent2(
static_cast<
unoidl::SingleInterfaceBasedServiceEntity * >(
i->second.entity.get()));
i->second.dataOffset = getOffset(file);
bool dfltCtor = ent2->getConstructors().size() == 1
&& ent2->getConstructors()[0].defaultConstructor;
writeKind(file, ent2.get(), dfltCtor);
writeNameLen(file, ent2->getBase());
if (!dfltCtor) {
write32(file, ent2->getConstructors().size());
for (std::vector<
unoidl::SingleInterfaceBasedServiceEntity::
Constructor >::const_iterator j(
ent2->getConstructors().begin());
j != ent2->getConstructors().end(); ++j)
{
if (j->defaultConstructor) {
std::cout
<< "Unexpected default constructor \""
<< j->name << '"' << std::endl;
std::exit(EXIT_FAILURE);
}
writeNameLen(file, j->name);
write32(file, j->parameters.size());
for (std::vector<
unoidl::SingleInterfaceBasedServiceEntity::
Constructor::Parameter >::const_iterator k(
j->parameters.begin());
k != j->parameters.end(); ++k)
{
sal_uInt64 f = 0;
if (k->rest) {
f |= 0x04;
}
write8(file, f);
writeNameLen(file, k->name);
writeNameLen(file, k->type);
}
write32(file, j->exceptions.size());
for (std::vector< OUString >::const_iterator k(
j->exceptions.begin());
k != j->exceptions.end(); ++k)
{
writeNameLen(file, *k);
}
}
}
break;
}
case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE:
{
rtl::Reference< unoidl::AccumulationBasedServiceEntity > ent2(
static_cast< unoidl::AccumulationBasedServiceEntity * >(
i->second.entity.get()));
i->second.dataOffset = getOffset(file);
writeKind(file, ent2.get());
write32(file, ent2->getDirectMandatoryBaseServices().size());
for (std::vector< OUString >::const_iterator j(
ent2->getDirectMandatoryBaseServices().begin());
j != ent2->getDirectMandatoryBaseServices().end(); ++j)
{
writeNameLen(file, *j);
}
write32(file, ent2->getDirectOptionalBaseServices().size());
for (std::vector< OUString >::const_iterator j(
ent2->getDirectOptionalBaseServices().begin());
j != ent2->getDirectOptionalBaseServices().end(); ++j)
{
writeNameLen(file, *j);
}
write32(file, ent2->getDirectMandatoryBaseInterfaces().size());
for (std::vector< OUString >::const_iterator j(
ent2->getDirectMandatoryBaseInterfaces().begin());
j != ent2->getDirectMandatoryBaseInterfaces().end(); ++j)
{
writeNameLen(file, *j);
}
write32(file, ent2->getDirectOptionalBaseInterfaces().size());
for (std::vector< OUString >::const_iterator j(
ent2->getDirectOptionalBaseInterfaces().begin());
j != ent2->getDirectOptionalBaseInterfaces().end(); ++j)
{
writeNameLen(file, *j);
}
write32(file, ent2->getDirectProperties().size());
for (std::vector<
unoidl::AccumulationBasedServiceEntity::Property >::
const_iterator j(
ent2->getDirectProperties().begin());
j != ent2->getDirectProperties().end(); ++j)
{
write16(file, static_cast< sal_uInt16 >(j->attributes));
writeNameLen(file, j->name);
writeNameLen(file, j->type);
}
break;
}
case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON:
{
rtl::Reference< unoidl::InterfaceBasedSingletonEntity > ent2(
static_cast< unoidl::InterfaceBasedSingletonEntity * >(
i->second.entity.get()));
i->second.dataOffset = getOffset(file);
writeKind(file, ent2.get());
writeNameLen(file, ent2->getBase());
break;
}
case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON:
{
rtl::Reference< unoidl::ServiceBasedSingletonEntity > ent2(
static_cast< unoidl::ServiceBasedSingletonEntity * >(
i->second.entity.get()));
i->second.dataOffset = getOffset(file);
writeKind(file, ent2.get());
writeNameLen(file, ent2->getBase());
break;
}
}
}
for (std::map< OUString, Item >::iterator i(map.begin()); i != map.end();
++i)
{
i->second.nameOffset = writeNameNul(file, i->first);
}
sal_uInt64 off = getOffset(file);
if (rootSize == 0) {
write8(file, 0); // SORT_MODULE
write32(file, map.size());
// overflow from std::map::size_type -> sal_uInt64 is unrealistic
} else {
*rootSize = map.size();
// overflow from std::map::size_type -> std::size_t is unrealistic
}
for (std::map< OUString, Item >::iterator i(map.begin()); i != map.end();
++i)
{
write32(file, i->second.nameOffset);
write32(file, i->second.dataOffset);
}
return off;
}
}
SAL_IMPLEMENT_MAIN() {
sal_uInt32 args = rtl_getAppCommandArgCount();
if (args < 2) {
std::cerr
<< "Usage: reg2unoidl <extra .rdb files> <.rdb file> <unoidl file>"
<< std::endl;
std::exit(EXIT_FAILURE);
}
rtl::Reference< unoidl::Manager > mgr(new unoidl::Manager);
for (sal_uInt32 i = 0; i != args - 2; ++i) {
mgr->addProvider(load(mgr, getArgumentUri(i)));
}
rtl::Reference< unoidl::Provider > prov(
load(mgr, getArgumentUri(args - 2)));
osl::File f(getArgumentUri(args - 1));
osl::FileBase::RC e = f.open(osl_File_OpenFlag_Write);
if (e == osl::FileBase::E_NOENT) {
e = f.open(osl_File_OpenFlag_Write | osl_File_OpenFlag_Create);
}
if (e != osl::FileBase::E_None) {
std::cerr
<< "Cannot open <" << f.getURL() << "> for writing, error code "
<< +e << std::endl;
std::exit(EXIT_FAILURE);
}
write(f, "UNOIDL\0\xFF", 8);
write32(f, 0); // root map offset
write32(f, 0); // root map size
sal_uInt64 off;
std::size_t size;
try {
off = writeMap(f, prov->createRootCursor(), &size);
} catch (unoidl::FileFormatException & e) {
std::cerr
<< "Bad input <" << e.getUri() << ">: " << e.getDetail()
<< std::endl;
std::exit(EXIT_FAILURE);
}
e = f.setSize(getOffset(f)); // truncate in case it already existed
if (e != osl::FileBase::E_None) {
std::cerr
<< "Cannot set size of <" << f.getURL() << ">, error code " << +e
<< std::endl;
std::exit(EXIT_FAILURE);
}
e = f.setPos(osl_Pos_Absolut, 8);
if (e != osl::FileBase::E_None) {
std::cerr
<< "Cannot rewind current position in <" << f.getURL()
<< ">, error code " << +e << std::endl;
std::exit(EXIT_FAILURE);
}
write32(f, off);
write32(f, size);
// overflow from std::map::size_type -> sal_uInt64 is unrealistic
e = f.close();
if (e != osl::FileBase::E_None) {
std::cerr
<< "Cannot close <" << f.getURL() << "> after writing, error code "
<< +e << std::endl;
std::exit(EXIT_FAILURE);
}
return EXIT_SUCCESS;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
......@@ -13,6 +13,7 @@
#include "rtl/ref.hxx"
#include "rtl/ustring.hxx"
#include "unoidl/legacyprovider.hxx"
#include "unoidl/unoidl.hxx"
#include "unoidl/unoidlprovider.hxx"
......@@ -57,10 +58,41 @@ ServiceBasedSingletonEntity::~ServiceBasedSingletonEntity() throw () {}
Provider::~Provider() throw () {}
rtl::Reference< Provider > loadProvider(OUString const & uri) {
return new UnoidlProvider(uri);
rtl::Reference< Provider > loadProvider(
rtl::Reference< Manager > const & manager, OUString const & uri)
{
try {
return new UnoidlProvider(uri);
} catch (FileFormatException & e) {
SAL_INFO(
"unoidl",
"FileFormatException \"" << e.getDetail() << "\", retrying <" << uri
<< "> as legacy format");
return new LegacyProvider(manager, uri);
}
}
void Manager::addProvider(rtl::Reference< Provider > const & provider) {
assert(provider.is());
providers_.push_back(provider);
}
rtl::Reference< Entity > Manager::findEntity(rtl::OUString const & name) const {
//TODO: add caching
for (std::vector< rtl::Reference< Provider > >::const_iterator i(
providers_.begin());
i != providers_.end(); ++i)
{
rtl::Reference< Entity > ent((*i)->findEntity(name));
if (ent.is()) {
return ent;
}
}
return rtl::Reference< Entity >();
}
Manager::~Manager() throw () {}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
......@@ -1251,6 +1251,13 @@ rtl::Reference< MapCursor > UnoidlProvider::createRootCursor() const {
return new UnoidlCursor(file_, mapBegin_, mapSize_);
}
rtl::Reference< Entity > UnoidlProvider::findEntity(OUString const & name) const
{
bool cnst;
sal_uInt32 off = find(name, &cnst);
return off == 0 || cnst ? rtl::Reference< Entity >() : getEntity(off);
}
sal_uInt32 UnoidlProvider::find(OUString const & name, bool * constant) const {
detail::MapEntry const * mapBegin = mapBegin_;
sal_uInt32 mapSize = mapSize_;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment