18#include <osl/file.hxx>
19#include <rtl/character.hxx>
21#include <rtl/ustrbuf.hxx>
22#include <rtl/ustring.hxx>
30#include <osl/thread.h>
40OUString getFileName(OUString
const & uri, osl::FileStatus
const & status) {
42 sal_Int32
i = uri.lastIndexOf(
'/') + 1;
44 if (osl::FileBase::getSystemPathFromFileURL(uri.copy(0, i), path)
45 != osl::FileBase::E_None)
49 "cannot getSystemPathFromFileURL(" << uri.copy(0, i) <<
")");
50 return status.getFileName();
54 DIR *
d = opendir(dir.getStr());
56 SAL_WARN(
"unoidl",
"cannot opendir(" << dir <<
")");
57 return status.getFileName();
62 int e = readdir_r(d, &ent, &p);
64 SAL_WARN(
"unoidl",
"cannot readdir_r");
66 return status.getFileName();
70 "unoidl",
"cannot find " << name <<
" via readdir of " << dir);
72 return status.getFileName();
74 if (
name.equalsIgnoreAsciiCase(
p->d_name)) {
77 p->d_name, std::strlen(
p->d_name), osl_getThreadTextEncoding());
82 return status.getFileName();
86bool exists(OUString
const & uri,
bool directory) {
87 osl::DirectoryItem item;
88 osl::FileStatus status(
89 osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileName);
90 return osl::DirectoryItem::get(uri, item) == osl::FileBase::E_None
91 && item.getFileStatus(status) == osl::FileBase::E_None
92 && (status.getFileType() == osl::FileStatus::Directory) == directory
93 && getFileName(uri, status) == uri.subView(uri.lastIndexOf(
'/') + 1);
96class Cursor:
public MapCursor {
101 rc != osl::FileBase::E_None,
"unoidl",
"open(" << uri <<
") failed with " << +rc);
105 virtual ~Cursor() noexcept
override {}
113class SourceModuleEntity:
public ModuleEntity {
118 virtual ~SourceModuleEntity() noexcept
override {}
120 virtual std::vector<OUString> getMemberNames()
const override
121 {
return std::vector<OUString>(); }
130bool isValidFileName(std::u16string_view name,
bool directory) {
131 for (
size_t i = 0;; ++
i) {
132 if (
i ==
name.size()) {
138 auto const c =
name[
i];
140 if (
i == 0 ||
name[
i - 1] ==
'_') {
143 return !directory &&
name.substr(
i + 1) ==
u"idl";
144 }
else if (c ==
'_') {
146 if (
i == 0 ||
name[
i - 1] ==
'_') {
149 }
else if (rtl::isAsciiDigit(c)) {
153 }
else if (!rtl::isAsciiAlpha(c)) {
162 assert(name !=
nullptr);
164 osl::DirectoryItem
i;
167 case osl::FileBase::E_None:
169 osl::FileStatus stat(
170 osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileName |
171 osl_FileStatus_Mask_FileURL);
172 rc =
i.getFileStatus(stat);
173 if (rc != osl::FileBase::E_None) {
176 "getFileSatus in <" <<
directory_.getURL() <<
"> failed with " << +rc);
179 auto const dir = stat.getFileType() == osl::FileStatus::Directory;
180 if (!isValidFileName(stat.getFileName(), dir)) {
188 *
name = stat.getFileName();
189 return new SourceModuleEntity(
manager_, stat.getFileURL());
191 SourceProviderScannerData data(&
manager_);
192 if (!
parse(stat.getFileURL(), &data)) {
193 SAL_WARN(
"unoidl",
"cannot parse <" << stat.getFileURL() <<
">");
196 auto ent = data.entities.end();
197 for (
auto j = data.entities.begin(); j != data.entities.end(); ++j) {
203 if (ent != data.entities.end()) {
204 throw FileFormatException(
205 stat.getFileURL(),
"source file defines more than one entity");
209 if (ent == data.entities.end()) {
210 throw FileFormatException(
211 stat.getFileURL(),
"source file defines no entity");
214 *
name = ent->first.copy(ent->first.lastIndexOf(
'.') + 1);
215 return ent->second.entity;
219 SAL_WARN(
"unoidl",
"getNext from <" <<
directory_.getURL() <<
"> failed with " << +rc);
221 case osl::FileBase::E_NOENT:
238 std::map< OUString, rtl::Reference<Entity> >::iterator ci(
252 OUStringBuffer buf(
name);
255 for (;
i !=
name.getLength(); ++
i) {
261 "",
"Illegal UNOIDL identifier \"" +
name +
"\"");
265 }
else if (c ==
'_') {
271 "",
"Illegal UNOIDL identifier \"" +
name +
"\"");
273 }
else if (rtl::isAsciiDigit(c)) {
276 "",
"Illegal UNOIDL identifier \"" +
name +
"\"");
278 }
else if (!rtl::isAsciiAlpha(c)) {
280 "",
"Illegal UNOIDL identifier \"" +
name +
"\"");
285 "",
"Illegal UNOIDL identifier \"" +
name +
"\"");
287 OUString uri(
uri_ + buf);
291 if (exists(uri,
true) && !exists(uri +
".idl",
false)) {
292 ent =
new SourceModuleEntity(
manager_, uri);
296 if (
parse(uri, &data)) {
297 std::map<OUString, SourceProviderEntity>::const_iterator j(
300 ent = j->second.entity;
304 "<" << uri <<
"> does not define entity " <<
name);
virtual rtl::Reference< Entity > findEntity(OUString const &name) const override
virtual rtl::Reference< MapCursor > createRootCursor() const override
virtual ~SourceTreeProvider() noexcept override
std::map< OUString, rtl::Reference< Entity > > cache_
SourceTreeProvider(Manager &manager, OUString const &uri)
rtl::Reference< ParseManager > manager
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
bool parse(OUString const &uri, SourceProviderScannerData *data)
osl::Directory directory_
std::map< OUString, SourceProviderEntity > entities