[Libreoffice-commits] core.git: unoidl/source

Stephan Bergmann (via logerrit) logerrit at kemper.freedesktop.org
Tue Sep 21 05:50:01 UTC 2021


 unoidl/source/sourcetreeprovider.cxx |  118 ++++++++++++++++++++++++++++++++---
 1 file changed, 111 insertions(+), 7 deletions(-)

New commits:
commit 7b10f119040144ff7db1da4c0a2bbdd488dcdf0f
Author:     Stephan Bergmann <sbergman at redhat.com>
AuthorDate: Tue Sep 14 17:11:12 2021 +0200
Commit:     Stephan Bergmann <sbergman at redhat.com>
CommitDate: Tue Sep 21 07:49:27 2021 +0200

    Implement the SourceTreeProvider Cursor
    
    Change-Id: Ibf54bd1e852ea23fb37c7222625895d240452424
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122361
    Tested-by: Jenkins
    Reviewed-by: Stephan Bergmann <sbergman at redhat.com>

diff --git a/unoidl/source/sourcetreeprovider.cxx b/unoidl/source/sourcetreeprovider.cxx
index 9531d057c979..404938c376cc 100644
--- a/unoidl/source/sourcetreeprovider.cxx
+++ b/unoidl/source/sourcetreeprovider.cxx
@@ -94,18 +94,24 @@ bool exists(OUString const & uri, bool directory) {
 
 class Cursor: public MapCursor {
 public:
-    Cursor() {}
+    Cursor(Manager& manager, OUString const & uri): manager_(manager), directory_(uri) {
+        auto const rc = directory_.open();
+        SAL_WARN_IF(
+            rc != osl::FileBase::E_None, "unoidl", "open(" << uri << ") failed with " << +rc);
+    }
 
 private:
     virtual ~Cursor() noexcept override {}
 
-    virtual rtl::Reference<Entity> getNext(OUString *) override
-    { return rtl::Reference<Entity>(); } //TODO
+    virtual rtl::Reference<Entity> getNext(OUString *) override;
+
+    Manager& manager_;
+    osl::Directory directory_;
 };
 
 class SourceModuleEntity: public ModuleEntity {
 public:
-    SourceModuleEntity() {}
+    SourceModuleEntity(Manager& manager, OUString const & uri): manager_(manager), uri_(uri) {}
 
 private:
     virtual ~SourceModuleEntity() noexcept override {}
@@ -114,9 +120,107 @@ private:
     { return std::vector<OUString>(); } //TODO
 
     virtual rtl::Reference< MapCursor > createCursor() const override
-    { return new Cursor; }
+    { return new Cursor(manager_, uri_); }
+
+    Manager& manager_;
+    OUString uri_;
 };
 
+bool isValidFileName(OUString const & name, bool directory) {
+    for (sal_Int32 i = 0;; ++i) {
+        if (i == name.getLength()) {
+            if (i == 0) {
+                return false;
+            }
+            return directory;
+        }
+        auto const c = name[i];
+        if (c == '.') {
+            if (i == 0 || name[i - 1] == '_') {
+                return false;
+            }
+            return !directory && name.subView(i + 1) == u"idl";
+        } else if (c == '_') {
+            //TODO: Ignore case of name[0] only for case-insensitive file systems:
+            if (i == 0 || name[i - 1] == '_') {
+                return false;
+            }
+        } else if (rtl::isAsciiDigit(c)) {
+            if (i == 0) {
+                return false;
+            }
+        } else if (!rtl::isAsciiAlpha(c)) {
+            return false;
+        }
+    }
+}
+
+}
+
+rtl::Reference<Entity> Cursor::getNext(OUString * name) {
+    assert(name != nullptr);
+    for (;;) {
+        osl::DirectoryItem i;
+        auto rc = directory_.getNextItem(i);
+        switch (rc) {
+        case osl::FileBase::E_None:
+            {
+                osl::FileStatus stat(
+                    osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileName |
+                    osl_FileStatus_Mask_FileURL);
+                rc = i.getFileStatus(stat);
+                if (rc != osl::FileBase::E_None) {
+                    SAL_WARN(
+                        "unoidl",
+                        "getFileSatus in <" << directory_.getURL() << "> failed with " << +rc);
+                    continue;
+                }
+                auto const dir = stat.getFileType() == osl::FileStatus::Directory;
+                if (!isValidFileName(stat.getFileName(), dir)) {
+                    continue;
+                }
+                if (dir) {
+                    //TODO: Using osl::FileStatus::getFileName can likely cause issues on case-
+                    // insensitive/preserving file systems, see the free getFileName function above
+                    // (which likely goes unnoticed if module identifiers follow the convention of
+                    // being all-lowercase):
+                    *name = stat.getFileName();
+                    return new SourceModuleEntity(manager_, stat.getFileURL());
+                } else {
+                    SourceProviderScannerData data(&manager_);
+                    if (!parse(stat.getFileURL(), &data)) {
+                        SAL_WARN("unoidl", "cannot parse <" << stat.getFileURL() << ">");
+                        continue;
+                    }
+                    auto ent = data.entities.end();
+                    for (auto j = data.entities.begin(); j != data.entities.end(); ++j) {
+                        if (j->second.kind == SourceProviderEntity::KIND_EXTERNAL
+                            || j->second.kind == SourceProviderEntity::KIND_MODULE)
+                        {
+                            continue;
+                        }
+                        if (ent != data.entities.end()) {
+                            throw FileFormatException(
+                                stat.getFileURL(), "source file defines more than one entity");
+                        }
+                        ent = j;
+                    }
+                    if (ent == data.entities.end()) {
+                        throw FileFormatException(
+                            stat.getFileURL(), "source file defines no entity");
+                    }
+                    //TODO: Check that the entity's name matches the suffix of stat.getFileURL():
+                    *name = ent->first.copy(ent->first.lastIndexOf('.') + 1);
+                    return ent->second.entity;
+                }
+            }
+        default:
+            SAL_WARN( "unoidl", "getNext from <" << directory_.getURL() << "> failed with " << +rc);
+            [[fallthrough]];
+        case osl::FileBase::E_NOENT:
+            return {};
+        }
+    }
 }
 
 SourceTreeProvider::SourceTreeProvider(Manager & manager, OUString const & uri):
@@ -124,7 +228,7 @@ SourceTreeProvider::SourceTreeProvider(Manager & manager, OUString const & uri):
 {}
 
 rtl::Reference<MapCursor> SourceTreeProvider::createRootCursor() const {
-    return new Cursor;
+    return new Cursor(manager_, uri_);
 }
 
 rtl::Reference<Entity> SourceTreeProvider::findEntity(OUString const & name)
@@ -184,7 +288,7 @@ rtl::Reference<Entity> SourceTreeProvider::findEntity(OUString const & name)
     // Prevent conflicts between foo/ and Foo.idl on case-preserving file
     // systems:
     if (exists(uri, true) && !exists(uri + ".idl", false)) {
-        ent = new SourceModuleEntity;
+        ent = new SourceModuleEntity(manager_, uri);
     } else {
         uri += ".idl";
         SourceProviderScannerData data(&manager_);


More information about the Libreoffice-commits mailing list