WIP: additional unoidl::Provider that directly reads from .idl files

Change-Id: I30fa6400724f4ca6f0e1986c741500f05710b840
This commit is contained in:
Stephan Bergmann 2013-09-12 17:39:48 +02:00
parent 3ea6e49f58
commit 5c2ba4aad6
7 changed files with 4535 additions and 0 deletions

View file

@ -0,0 +1,48 @@
/* -*- 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_SOURCEPROVIDER_HXX
#define INCLUDED_UNOIDL_SOURCEPROVIDER_HXX
#include "sal/config.h"
#include <map>
#include "rtl/ref.hxx"
#include "sal/types.h"
#include "unoidl/detail/dllapi.hxx"
#include "unoidl/unoidl.hxx"
namespace unoidl {
class LO_DLLPUBLIC_UNOIDL SourceProvider: public Provider {
public:
// throws FileFormatException, NoSuchFileException:
SourceProvider(
rtl::Reference<Manager> const & manager, OUString const & uri);
// throws FileFormatException:
virtual rtl::Reference<MapCursor> createRootCursor() const;
// throws FileFormatException:
virtual rtl::Reference<Entity> findEntity(OUString const & name) const;
private:
virtual SAL_DLLPRIVATE ~SourceProvider() throw ();
rtl::Reference<Manager> manager_;
OUString uri_;
mutable std::map< OUString, rtl::Reference<Entity> > cache_; //TODO: at manager
};
}
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View file

@ -13,10 +13,24 @@ $(eval $(call gb_Library_add_defs,unoidl,-DLO_DLLIMPLEMENTATION_UNOIDL))
$(eval $(call gb_Library_add_exception_objects,unoidl, \
unoidl/source/legacyprovider \
unoidl/source/sourceprovider \
unoidl/source/unoidl \
unoidl/source/unoidlprovider \
))
$(eval $(call gb_Library_add_grammars,unoidl, \
unoidl/source/sourceprovider-parser \
))
$(eval $(call gb_Library_add_scanners,unoidl, \
unoidl/source/sourceprovider-scanner \
))
$(eval $(call gb_Library_set_include,unoidl, \
$$(INCLUDE) \
-I$(SRCDIR)/unoidl/source \
))
$(eval $(call gb_Library_use_libraries,unoidl, \
reg \
sal \

View file

@ -0,0 +1,136 @@
/* -*- 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_SOURCE_SOURCEPROVIDER_PARSER_REQUIRES_HXX
#define INCLUDED_UNOIDL_SOURCE_SOURCEPROVIDER_PARSER_REQUIRES_HXX
#include "sal/config.h"
#include <vector>
#include "rtl/string.hxx"
#include "rtl/ustring.hxx"
#include "sal/types.h"
#include "unoidl/unoidl.hxx"
#define YYLTYPE int
typedef void * yyscan_t;
int yyparse(yyscan_t yyscanner);
namespace unoidl { namespace detail {
struct SourceProviderEntity;
enum SourceProviderAccessDecls { ACCESS_DECL_GET = 0x1, ACCESS_DECL_SET = 0x2 };
enum SourceProviderFlags {
FLAG_ATTRIBUTE = 0x001, FLAG_BOUND = 0x002, FLAG_CONSTRAINED = 0x004,
FLAG_MAYBEAMBIGUOUS = 0x008, FLAG_MAYBEDEFAULT = 0x010,
FLAG_MAYBEVOID = 0x020, FLAG_OPTIONAL = 0x040, FLAG_PROPERTY = 0x080,
FLAG_READONLY = 0x100, FLAG_REMOVABLE = 0x200, FLAG_TRANSIENT = 0x400
};
struct SourceProviderExpr {
static SourceProviderExpr Bool(bool v) {
SourceProviderExpr e;
e.type = TYPE_BOOL;
e.bval = v;
return e;
}
static SourceProviderExpr Int(sal_Int64 v) {
SourceProviderExpr e;
e.type = TYPE_INT;
e.ival = v;
return e;
}
static SourceProviderExpr Uint(sal_uInt64 v) {
SourceProviderExpr e;
e.type = TYPE_UINT;
e.uval = v;
return e;
}
static SourceProviderExpr Float(double v) {
SourceProviderExpr e;
e.type = TYPE_FLOAT;
e.fval = v;
return e;
}
enum Type { TYPE_BOOL, TYPE_INT, TYPE_UINT, TYPE_FLOAT };
Type type;
union {
bool bval;
sal_Int64 ival;
sal_uInt64 uval;
double fval;
};
};
struct SourceProviderType {
enum Type {
TYPE_VOID, TYPE_BOOLEAN, TYPE_BYTE, TYPE_SHORT, TYPE_UNSIGNED_SHORT,
TYPE_LONG, TYPE_UNSIGNED_LONG, TYPE_HYPER, TYPE_UNSIGNED_HYPER,
TYPE_FLOAT, TYPE_DOUBLE, TYPE_CHAR, TYPE_STRING, TYPE_TYPE, TYPE_ANY,
TYPE_SEQUENCE, TYPE_ENUM, TYPE_PLAIN_STRUCT, TYPE_EXCEPTION,
TYPE_INTERFACE, TYPE_INSTANTIATED_POLYMORPHIC_STRUCT, TYPE_PARAMETER
};
SourceProviderType() {}
explicit SourceProviderType(Type theType): type(theType)
{ assert(theType <= TYPE_ANY); }
explicit SourceProviderType(SourceProviderType const * componentType):
type(TYPE_SEQUENCE)
{ assert(componentType != 0); subtypes.push_back(*componentType); }
SourceProviderType(
Type theType, OUString const & theName,
SourceProviderEntity const * theEntity):
type(theType), name(theName), entity(theEntity)
{
assert(theType >= TYPE_ENUM && theType <= TYPE_INTERFACE);
assert(theEntity != 0);
}
SourceProviderType(
OUString const & polymorphicStructTypeTemplateName,
SourceProviderEntity const * theEntity,
std::vector<SourceProviderType> const & typeArguments):
type(TYPE_INSTANTIATED_POLYMORPHIC_STRUCT),
name(polymorphicStructTypeTemplateName), entity(theEntity),
subtypes(typeArguments)
{ assert(theEntity != 0); }
explicit SourceProviderType(OUString const & identifier):
type(TYPE_PARAMETER), name(identifier)
{}
OUString getName() const;
Type type;
OUString name; // TYPE_ENUM ... TYPE_PARAMETER
SourceProviderEntity const * entity;
// TYPE_ENUM ... TYPE_INSTANTIATED_POLYMOPRHIC_STRUCT
std::vector<SourceProviderType> subtypes;
// TYPE_SEQUENCE, TYPE_INSTANTIATED_POLYMOPRHIC_STRUCT
OUString typedefName;
};
} }
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,247 @@
/* -*- 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_SOURCE_SOURCEPROVIDER_SCANNER_HXX
#define INCLUDED_UNOIDL_SOURCE_SOURCEPROVIDER_SCANNER_HXX
#include "sal/config.h"
#include <cassert>
#include <map>
#include <vector>
#include "rtl/ref.hxx"
#include "rtl/ustring.hxx"
#include "sal/types.h"
#include "salhelper/simplereferenceobject.hxx"
#include "unoidl/unoidl.hxx"
#include "sourceprovider-parser-requires.hxx"
#include "sourceprovider-parser.hxx"
namespace unoidl { namespace detail {
class SourceProviderEntityPad: public salhelper::SimpleReferenceObject {
public:
bool isPublished() const { return published_; }
protected:
explicit SourceProviderEntityPad(bool published): published_(published) {}
virtual ~SourceProviderEntityPad() {}
private:
bool const published_;
};
class SourceProviderEnumTypeEntityPad: public SourceProviderEntityPad {
public:
explicit SourceProviderEnumTypeEntityPad(bool published):
SourceProviderEntityPad(published)
{}
std::vector<unoidl::EnumTypeEntity::Member> members;
private:
virtual ~SourceProviderEnumTypeEntityPad() throw () {}
};
class SourceProviderPlainStructTypeEntityPad: public SourceProviderEntityPad {
public:
SourceProviderPlainStructTypeEntityPad(
bool published, OUString theBaseName,
rtl::Reference<unoidl::PlainStructTypeEntity> const & theBaseEntity):
SourceProviderEntityPad(published), baseName(theBaseName),
baseEntity(theBaseEntity)
{ assert(theBaseName.isEmpty() != theBaseEntity.is()); }
OUString const baseName;
rtl::Reference<unoidl::PlainStructTypeEntity> const baseEntity;
std::vector<unoidl::PlainStructTypeEntity::Member> members;
private:
virtual ~SourceProviderPlainStructTypeEntityPad() throw () {}
};
class SourceProviderPolymorphicStructTypeTemplateEntityPad:
public SourceProviderEntityPad
{
public:
SourceProviderPolymorphicStructTypeTemplateEntityPad(bool published):
SourceProviderEntityPad(published)
{}
std::vector<OUString> typeParameters;
std::vector<unoidl::PolymorphicStructTypeTemplateEntity::Member> members;
private:
virtual ~SourceProviderPolymorphicStructTypeTemplateEntityPad() throw () {}
};
class SourceProviderExceptionTypeEntityPad: public SourceProviderEntityPad {
public:
SourceProviderExceptionTypeEntityPad(
bool published, OUString theBaseName,
rtl::Reference<unoidl::ExceptionTypeEntity> const & theBaseEntity):
SourceProviderEntityPad(published), baseName(theBaseName),
baseEntity(theBaseEntity)
{ assert(theBaseName.isEmpty() != theBaseEntity.is()); }
OUString const baseName;
rtl::Reference<unoidl::ExceptionTypeEntity> const baseEntity;
std::vector<unoidl::ExceptionTypeEntity::Member> members;
private:
virtual ~SourceProviderExceptionTypeEntityPad() throw () {}
};
class SourceProviderInterfaceTypeEntityPad: public SourceProviderEntityPad {
public:
struct Base {
Base(
OUString const & theName,
rtl::Reference<unoidl::InterfaceTypeEntity> const & theEntity,
std::vector<OUString> const & theAnnotations):
name(theName), entity(theEntity), annotations(theAnnotations)
{}
OUString name;
rtl::Reference<unoidl::InterfaceTypeEntity> entity;
std::vector<OUString> annotations;
};
SourceProviderInterfaceTypeEntityPad(
bool published, OUString singleBaseName,
rtl::Reference<unoidl::InterfaceTypeEntity> const & singleBaseEntity):
SourceProviderEntityPad(published),
singleBase(!singleBaseName.isEmpty())
{
assert(singleBaseName.isEmpty() != singleBaseEntity.is());
if (singleBase) {
mandatoryBases.push_back(
Base(
singleBaseName, singleBaseEntity, std::vector<OUString>()));
}
}
bool singleBase;
std::vector<Base> mandatoryBases;
std::vector<Base> optionalBases;
std::vector<unoidl::InterfaceTypeEntity::Attribute> attributes;
std::vector<unoidl::InterfaceTypeEntity::Method> methods;
private:
virtual ~SourceProviderInterfaceTypeEntityPad() throw () {}
};
class SourceProviderConstantGroupEntityPad: public SourceProviderEntityPad {
public:
explicit SourceProviderConstantGroupEntityPad(bool published):
SourceProviderEntityPad(published)
{}
std::vector<unoidl::ConstantGroupEntity::Member> members;
private:
virtual ~SourceProviderConstantGroupEntityPad() throw () {}
};
class SourceProviderSingleInterfaceBasedServiceEntityPad:
public SourceProviderEntityPad
{
public:
explicit SourceProviderSingleInterfaceBasedServiceEntityPad(
bool published, OUString const & theBase):
SourceProviderEntityPad(published), base(theBase)
{}
OUString const base;
std::vector<unoidl::SingleInterfaceBasedServiceEntity::Constructor>
constructors;
private:
virtual ~SourceProviderSingleInterfaceBasedServiceEntityPad() throw () {}
};
class SourceProviderAccumulationBasedServiceEntityPad:
public SourceProviderEntityPad
{
public:
explicit SourceProviderAccumulationBasedServiceEntityPad(bool published):
SourceProviderEntityPad(published)
{}
std::vector<unoidl::AnnotatedReference> directMandatoryBaseServices;
std::vector<unoidl::AnnotatedReference> directOptionalBaseServices;
std::vector<unoidl::AnnotatedReference> directMandatoryBaseInterfaces;
std::vector<unoidl::AnnotatedReference> directOptionalBaseInterfaces;
std::vector<unoidl::AccumulationBasedServiceEntity::Property>
directProperties;
private:
virtual ~SourceProviderAccumulationBasedServiceEntityPad() throw () {}
};
struct SourceProviderEntity {
enum Kind { KIND_EXTERNAL, KIND_LOCAL, KIND_INTERFACE_DECL };
explicit SourceProviderEntity(
Kind theKind, rtl::Reference<unoidl::Entity> const & externalEntity):
kind(theKind), entity(externalEntity)
{ assert(theKind != KIND_INTERFACE_DECL); assert(externalEntity.is()); }
explicit SourceProviderEntity(
rtl::Reference<SourceProviderEntityPad> const & localPad):
kind(KIND_LOCAL), pad(localPad)
{ assert(localPad.is()); }
SourceProviderEntity(): kind(KIND_INTERFACE_DECL) {}
Kind kind;
rtl::Reference<unoidl::Entity> entity;
rtl::Reference<SourceProviderEntityPad> pad;
};
struct SourceProviderScannerData {
SourceProviderScannerData(
rtl::Reference<unoidl::Manager> const & theManager,
void const * sourceAddress, sal_uInt64 sourceSize):
manager(theManager),
sourcePosition(static_cast<char const *>(sourceAddress)),
sourceEnd(sourcePosition + sourceSize), errorLine(0)
{ assert(manager.is()); }
rtl::Reference<unoidl::Manager> manager;
char const * sourcePosition;
char const * const sourceEnd;
YYLTYPE errorLine;
OString parserError;
OUString errorMessage;
std::map<OUString, SourceProviderEntity> entities;
std::vector<OUString> modules;
OUString currentName;
};
} }
int yylex_init_extra(
unoidl::detail::SourceProviderScannerData * user_defined,
yyscan_t * yyscanner);
int yylex_destroy(yyscan_t yyscanner);
int yylex(YYSTYPE * yylval_param, YYLTYPE * yylloc_param, yyscan_t yyscanner);
unoidl::detail::SourceProviderScannerData * yyget_extra(yyscan_t yyscanner);
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View file

@ -0,0 +1,253 @@
/* -*- 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/.
*/
%option bison-bridge
%option bison-locations
%option extra-type="unoidl::detail::SourceProviderScannerData *"
%option never-interactive
%option nounistd
%option noyywrap
%option reentrant
%option warn
%option yylineno
%top {
#include "sal/config.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstring>
}
%{
#include "rtl/math.h"
#include "rtl/string.hxx"
#include "rtl/ustring.hxx"
#include "rtl/textenc.h"
#include "sal/types.h"
#include "sourceprovider-parser-requires.hxx"
#include "sourceprovider-parser.hxx"
#include "sourceprovider-scanner.hxx"
namespace unoidl { namespace detail {
static std::size_t sourceProviderScannerInput(
SourceProviderScannerData * data, char * buffer, std::size_t size)
{
assert(data != 0);
if (data->sourcePosition == data->sourceEnd) {
return YY_NULL;
}
assert(data->sourcePosition < data->sourceEnd);
size = std::min<std::size_t>(size, data->sourceEnd - data->sourcePosition);
std::memcpy(buffer, data->sourcePosition, size);
data->sourcePosition += size;
return size;
}
} }
#define YY_INPUT(buf, result, max_size) ((result) = \
::unoidl::detail::sourceProviderScannerInput(yyextra, (buf), (max_size)))
namespace {
int nonZeroIntegerLiteral(
char const * text, std::size_t length, sal_Int16 radix, sal_uInt64 * value,
unoidl::detail::SourceProviderScannerData * data)
{
assert(text != 0);
assert(length != 0);
assert(value != 0);
assert(data != 0);
std::size_t n = length;
switch (text[length - 1]) {
case 'L':
case 'U':
case 'l':
case 'u':
--n;
break;
default:
break;
}
*value = OString(text, n).toUInt64(radix);
if (*value == 0) {
data->errorMessage = "out-of-range integer literal "
+ OUString(text, length, RTL_TEXTENCODING_ASCII_US);
return TOK_ERROR;
}
return TOK_INTEGER;
}
}
%}
%x comment1 comment2 doc docdepr
DIGIT [0-9]
UPPER [A-Z]
LOWER [a-z]
ALPHA {UPPER}|{LOWER}
ALNUM {DIGIT}|{ALPHA}
%%
[ \t\r]
\n *yylloc = yylineno;
"//" BEGIN comment1;
"#" BEGIN comment1; //TODO: only at start of line
<comment1>.
<comment1>\n *yylloc = yylineno; BEGIN INITIAL;
"/*" BEGIN comment2;
"/**" BEGIN doc;
"/***" BEGIN comment2;
<comment2,doc>"*/" BEGIN INITIAL;
<docdepr>"*/" BEGIN INITIAL; return TOK_DEPRECATED;
<comment2,docdepr>.
<comment2,doc,docdepr>\n *yylloc = yylineno;
<comment2,doc,docdepr><<EOF>> {
yyextra->errorMessage = "unterminated comment";
return TOK_ERROR;
}
<doc>[ \t\r]
<doc>"@deprecated" BEGIN docdepr;
<doc>"*"
<doc>[^ \t\r\n*]+
[%&()*+,\-/:;<=>[\]^{|}~] return yytext[0];
"..." return TOK_ELLIPSIS;
"::" return TOK_COLONS;
"<<" return TOK_LEFTSHIFT;
">>" return TOK_RIGHTSHIFT;
"FALSE" return TOK_FALSE;
"False" return TOK_FALSE;
"TRUE" return TOK_TRUE;
"True" return TOK_TRUE;
"any" return TOK_ANY;
"attribute" return TOK_ATTRIBUTE;
"boolean" return TOK_BOOLEAN;
"bound" return TOK_BOUND;
"byte" return TOK_BYTE;
"char" return TOK_CHAR;
"const" return TOK_CONST;
"constants" return TOK_CONSTANTS;
"constrained" return TOK_CONSTRAINED;
"double" return TOK_DOUBLE;
"enum" return TOK_ENUM;
"exception" return TOK_EXCEPTION;
"float" return TOK_FLOAT;
"get" return TOK_GET;
"hyper" return TOK_HYPER;
"in" return TOK_IN;
"inout" return TOK_INOUT;
"interface" return TOK_INTERFACE;
"long" return TOK_LONG;
"maybeambiguous" return TOK_MAYBEAMBIGUOUS;
"maybedefault" return TOK_MAYBEDEFAULT;
"maybevoid" return TOK_MAYBEVOID;
"module" return TOK_MODULE;
"optional" return TOK_OPTIONAL;
"out" return TOK_OUT;
"property" return TOK_PROPERTY;
"published" return TOK_PUBLISHED;
"raises" return TOK_RAISES;
"readonly" return TOK_READONLY;
"removable" return TOK_REMOVABLE;
"sequence" return TOK_SEQUENCE;
"service" return TOK_SERVICE;
"set" return TOK_SET;
"short" return TOK_SHORT;
"singleton" return TOK_SINGLETON;
"string" return TOK_STRING;
"struct" return TOK_STRUCT;
"transient" return TOK_TRANSIENT;
"type" return TOK_TYPE;
"typedef" return TOK_TYPEDEF;
"unsigned" return TOK_UNSIGNED;
"void" return TOK_VOID;
{UPPER}("_"?{ALNUM})*|{LOWER}{ALNUM}* {
yylval->sval = new OString(yytext);
return TOK_IDENTIFIER;
}
({ALPHA}|"_")({ALNUM}|"_")* {
#if 1 //TODO
yylval->sval=new OString(yytext);return TOK_IDENTIFIER;
#else
yyextra->errorMessage = "illegal identifier "
+ OUString(yytext, yyleng, RTL_TEXTENCODING_ASCII_US);
return TOK_ERROR;
#endif
}
0+[LUlu]? |
0[Xx]0+[LUlu]? {
yylval->ival = 0;
return TOK_INTEGER;
}
0[0-7]+[LUlu]? {
return nonZeroIntegerLiteral(yytext, yyleng, 8, &yylval->ival, yyextra);
}
[1-9]{DIGIT}*[LUlu]? {
return nonZeroIntegerLiteral(yytext, yyleng, 10, &yylval->ival, yyextra);
}
0[Xx][0-9A-Fa-f]+[LUlu]? {
return nonZeroIntegerLiteral(
yytext + 2, yyleng - 2, 16, &yylval->ival, yyextra);
}
{DIGIT}+[Ee][+\-]?{DIGIT}+[Ff]? |
{DIGIT}*"."{DIGIT}+([Ee][+\-]?{DIGIT}+)?[Ff]? {
rtl_math_ConversionStatus s;
yylval->fval = rtl_math_stringToDouble(
yytext, yytext + yyleng, '.', 0, &s, 0);
if (s == rtl_math_ConversionStatus_OutOfRange) {
yyextra->errorMessage = "out-of-range floating-point literal "
+ OUString(yytext, yyleng, RTL_TEXTENCODING_ASCII_US);
return TOK_ERROR;
}
return TOK_FLOATING;
}
{DIGIT}({ALNUM}|"_")* {
yyextra->errorMessage = "illegal numeric literal "
+ OUString(yytext, yyleng, RTL_TEXTENCODING_ASCII_US);
return TOK_ERROR;
}
. {
unsigned char c = yytext[0];
yyextra->errorMessage = c >= ' ' && c <= '~'
? OUString("invalid character \"" + OUString(sal_Unicode(c)) + "\"")
: OUString(
"invalid byte x" + OUString::number(c, 16).toAsciiUpperCase());
return TOK_ERROR;
}
%%
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

206
unoidl/source/sourceprovider.cxx Executable file
View file

@ -0,0 +1,206 @@
/* -*- 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 <cerrno>
#include <map>
#include <new>
#include "osl/file.h"
#include "osl/thread.h"
#include "rtl/character.hxx"
#include "rtl/ref.hxx"
#include "rtl/ustrbuf.hxx"
#include "rtl/ustring.hxx"
#include "unoidl/sourceprovider.hxx"
#include "unoidl/unoidl.hxx"
#include "sourceprovider-parser-requires.hxx"
#include "sourceprovider-parser.hxx"
#include "sourceprovider-scanner.hxx"
namespace unoidl {
namespace {
rtl::Reference<Entity> parse(
rtl::Reference<Manager> const & manager, OUString const & name,
OUString const & uri, void const * address, sal_uInt64 size)
{
detail::SourceProviderScannerData data(manager, address, size);
yyscan_t yyscanner;
if (yylex_init_extra(&data, &yyscanner) != 0) {
// Checking errno for the specific EINVAL, ENOMEM documented for
// yylex_init_extra would not work as those values are not defined by
// the C++ Standard:
int e = errno;
throw FileFormatException(
uri, "yylex_init_extra failed with errno " + OUString::number(e));
}
int e = yyparse(yyscanner);
yylex_destroy(yyscanner);
switch (e) {
case 0:
{
std::map<OUString, detail::SourceProviderEntity>::const_iterator i(
data.entities.find(name));
return i == data.entities.end()
? rtl::Reference<Entity>() : i->second.entity;
}
default:
assert(false);
// fall through
case 1:
throw FileFormatException(
uri,
("cannot parse"
+ (data.errorLine == 0
? OUString() : " line " + OUString::number(data.errorLine))
+ (data.parserError.isEmpty()
? OUString()
: (", "
+ OStringToOUString(
data.parserError, osl_getThreadTextEncoding())))
+ (data.errorMessage.isEmpty()
? OUString() : ": \"" + data.errorMessage + "\"")));
case 2:
throw std::bad_alloc();
}
}
class Cursor: public MapCursor {
public:
Cursor() {}
private:
virtual ~Cursor() throw () {}
virtual rtl::Reference<Entity> getNext(OUString *)
{ return rtl::Reference<Entity>(); } //TODO
};
}
SourceProvider::SourceProvider(
rtl::Reference<Manager> const & manager, OUString const & uri):
manager_(manager), uri_(uri.endsWith("/") ? uri : uri + "/")
{}
rtl::Reference<MapCursor> SourceProvider::createRootCursor() const {
return new Cursor;
}
rtl::Reference<Entity> SourceProvider::findEntity(OUString const & name) const {
std::map< OUString, rtl::Reference<Entity> >::iterator ci(
cache_.find(name));
if (ci != cache_.end()) {
return ci->second;
}
// Match name against
// name ::= identifier ("." identifier)*
// identifier ::= upper-blocks | lower-block
// upper-blocks ::= upper ("_"? alnum)*
// lower-block :== lower alnum*
// alnum ::= digit | upper | lower
// digit ::= "0"--"9"
// upper ::= "A"--"Z"
// lower ::= "a"--"z"
OUStringBuffer buf(name);
sal_Int32 start = 0;
sal_Int32 i = 0;
for (; i != name.getLength(); ++i) {
sal_Unicode c = name[i];
if (c == '.') {
assert(i == start || i != 0);
if (i == start || name[i - 1] == '_') {
throw FileFormatException( //TODO
"", "Illegal UNOIDL identifier \"" + name + "\"");
}
buf[i] = '/';
start = i + 1;
} else if (c == '_') {
assert(i == start || i != 0);
if (i == start || name[i - 1] == '_'
|| !rtl::isAsciiUpperCase(name[start]))
{
throw FileFormatException( //TODO
"", "Illegal UNOIDL identifier \"" + name + "\"");
}
} else if (rtl::isAsciiDigit(c)) {
if (i == start) {
throw FileFormatException( //TODO
"", "Illegal UNOIDL identifier \"" + name + "\"");
}
} else if (!rtl::isAsciiAlpha(c)) {
throw FileFormatException( //TODO
"", "Illegal UNOIDL identifier \"" + name + "\"");
}
}
if (i == start) {
throw FileFormatException( //TODO
"", "Illegal UNOIDL identifier \"" + name + "\"");
}
OUString uri(uri_ + buf.makeStringAndClear() + ".idl");
oslFileHandle handle;
oslFileError e = osl_openFile(uri.pData, &handle, osl_File_OpenFlag_Read);
switch (e) {
case osl_File_E_None:
break;
case osl_File_E_NOENT:
cache_.insert(
std::map< OUString, rtl::Reference<Entity> >::value_type(
name, rtl::Reference<Entity>()));
return rtl::Reference<Entity>();
default:
throw FileFormatException(uri, "cannot open: " + OUString::number(e));
}
sal_uInt64 size;
e = osl_getFileSize(handle, &size);
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 get size: " + OUString::number(e));
}
void * address;
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));
}
rtl::Reference<Entity> ent;
try {
ent = parse(manager_, name, uri, address, size);
} catch (...) {
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);
throw;
}
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);
cache_.insert(
std::map< OUString, rtl::Reference<Entity> >::value_type(name, ent));
return ent;
}
SourceProvider::~SourceProvider() throw () {}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */