1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include "sal/config.h"
17 #include "osl/file.hxx"
18 #include "rtl/character.hxx"
19 #include "rtl/ref.hxx"
20 #include "rtl/ustrbuf.hxx"
21 #include "rtl/ustring.hxx"
22 #include "unoidl/unoidl.hxx"
24 #include "sourceprovider-parser-requires.hxx"
25 #include "sourceprovider-parser.hxx"
26 #include "sourceprovider-scanner.hxx"
27 #include "sourcetreeprovider.hxx"
31 #include "osl/thread.h"
34 namespace unoidl
{ namespace detail
{
38 //TODO: Bad hack to work around osl::FileStatus::getFileName not determining the
39 // original spelling of a file name (not even with
40 // osl_FileStatus_Mask_Validate):
41 OUString
getFileName(OUString
const & uri
, osl::FileStatus
& status
) {
43 sal_Int32 i
= uri
.lastIndexOf('/') + 1;
45 if (osl::FileBase::getSystemPathFromFileURL(uri
.copy(0, i
), path
)
46 != osl::FileBase::E_None
)
50 "cannot getSystemPathFromFileURL(" << uri
.copy(0, i
) << ")");
51 return status
.getFileName();
53 OString
dir(OUStringToOString(path
, osl_getThreadTextEncoding()));
54 OString
name(OUStringToOString(uri
.copy(i
), osl_getThreadTextEncoding()));
55 DIR * d
= opendir(dir
.getStr());
57 SAL_WARN("unoidl", "cannot opendir(" << dir
<< ")");
58 return status
.getFileName();
63 int e
= readdir_r(d
, &ent
, &p
);
65 SAL_WARN("unoidl", "cannot readdir_r");
67 return status
.getFileName();
71 "unoidl", "cannot find " << name
<< " via readdir of " << dir
);
73 return status
.getFileName();
75 if (name
.equalsIgnoreAsciiCase(p
->d_name
)) {
78 p
->d_name
, std::strlen(p
->d_name
), osl_getThreadTextEncoding());
83 return status
.getFileName();
87 bool exists(OUString
const & uri
, bool directory
) {
88 osl::DirectoryItem item
;
89 osl::FileStatus
status(
90 osl_FileStatus_Mask_Type
| osl_FileStatus_Mask_FileName
);
91 return osl::DirectoryItem::get(uri
, item
) == osl::FileBase::E_None
92 && item
.getFileStatus(status
) == osl::FileBase::E_None
93 && (status
.getFileType() == osl::FileStatus::Directory
) == directory
94 && getFileName(uri
, status
) == uri
.copy(uri
.lastIndexOf('/') + 1);
97 class Cursor
: public MapCursor
{
102 virtual ~Cursor() throw () {}
104 virtual rtl::Reference
<Entity
> getNext(OUString
*) SAL_OVERRIDE
105 { return rtl::Reference
<Entity
>(); } //TODO
108 class SourceModuleEntity
: public ModuleEntity
{
110 SourceModuleEntity() {}
113 virtual ~SourceModuleEntity() throw () {}
115 virtual std::vector
<OUString
> getMemberNames() const SAL_OVERRIDE
116 { return std::vector
<OUString
>(); } //TODO
118 virtual rtl::Reference
< MapCursor
> createCursor() const SAL_OVERRIDE
119 { return new Cursor
; }
124 SourceTreeProvider::SourceTreeProvider(Manager
& manager
, OUString
const & uri
):
125 manager_(manager
), uri_(uri
.endsWith("/") ? uri
: uri
+ "/")
128 rtl::Reference
<MapCursor
> SourceTreeProvider::createRootCursor() const {
132 rtl::Reference
<Entity
> SourceTreeProvider::findEntity(OUString
const & name
)
135 std::map
< OUString
, rtl::Reference
<Entity
> >::iterator
ci(
137 if (ci
!= cache_
.end()) {
140 // Match name against
141 // name ::= identifier ("." identifier)*
142 // identifier ::= upper-blocks | lower-block
143 // upper-blocks ::= upper ("_"? alnum)*
144 // lower-block :== lower alnum*
145 // alnum ::= digit | upper | lower
146 // digit ::= "0"--"9"
147 // upper ::= "A"--"Z"
148 // lower ::= "a"--"z"
149 OUStringBuffer
buf(name
);
152 for (; i
!= name
.getLength(); ++i
) {
153 sal_Unicode c
= name
[i
];
155 assert(i
== start
|| i
!= 0);
156 if (i
== start
|| name
[i
- 1] == '_') {
157 throw FileFormatException( //TODO
158 "", "Illegal UNOIDL identifier \"" + name
+ "\"");
162 } else if (c
== '_') {
163 assert(i
== start
|| i
!= 0);
164 if (i
== start
|| name
[i
- 1] == '_'
165 || !rtl::isAsciiUpperCase(name
[start
]))
167 throw FileFormatException( //TODO
168 "", "Illegal UNOIDL identifier \"" + name
+ "\"");
170 } else if (rtl::isAsciiDigit(c
)) {
172 throw FileFormatException( //TODO
173 "", "Illegal UNOIDL identifier \"" + name
+ "\"");
175 } else if (!rtl::isAsciiAlpha(c
)) {
176 throw FileFormatException( //TODO
177 "", "Illegal UNOIDL identifier \"" + name
+ "\"");
181 throw FileFormatException( //TODO
182 "", "Illegal UNOIDL identifier \"" + name
+ "\"");
184 OUString
uri(uri_
+ buf
.makeStringAndClear());
185 rtl::Reference
<Entity
> ent
;
186 // Prevent conflicts between foo/ and Foo.idl on case-preserving file
188 if (exists(uri
, true) && !exists(uri
+ ".idl", false)) {
189 ent
= new SourceModuleEntity
;
192 SourceProviderScannerData
data(&manager_
);
193 if (parse(uri
, &data
)) {
194 std::map
<OUString
, SourceProviderEntity
>::const_iterator
j(
195 data
.entities
.find(name
));
196 if (j
!= data
.entities
.end()) {
197 ent
= j
->second
.entity
;
201 "<" << uri
<< "> does not define entity " << name
);
205 std::map
< OUString
, rtl::Reference
<Entity
> >::value_type(name
, ent
));
209 SourceTreeProvider::~SourceTreeProvider() throw () {}
213 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */