[retro-gtk: 2/2] module-query: Allow to iterate recursively



commit d6f741d6ed7a32eadcd4fb11cd11a860809b3381
Author: Adrien Plazas <kekun plazas laposte net>
Date:   Thu Mar 9 12:30:38 2017 +0100

    module-query: Allow to iterate recursively
    
    Allow ModuleQuery and ModuleIterator to iterate recursively on the
    Libretro core search paths.
    
    This is needed to support Flatpak extension points and hence to have
    Libretro cores as extensions.

 retro-gtk/retro-module-iterator.vala |   62 ++++++++++++++++++++++++++++++++-
 retro-gtk/retro-module-query.vala    |    8 ++++-
 2 files changed, 67 insertions(+), 3 deletions(-)
---
diff --git a/retro-gtk/retro-module-iterator.vala b/retro-gtk/retro-module-iterator.vala
index 88dae34..309f6b8 100644
--- a/retro-gtk/retro-module-iterator.vala
+++ b/retro-gtk/retro-module-iterator.vala
@@ -2,12 +2,23 @@
 
 public class Retro.ModuleIterator {
        private string[] directories;
+       private bool recursive;
        private int current_directory;
        private FileEnumerator file_enumerator;
        private CoreDescriptor? core_descriptor;
+       private ModuleIterator? sub_directory;
+       private GenericSet<string> visited;
 
-       internal ModuleIterator (string[] lookup_paths) {
+       internal ModuleIterator (string[] lookup_paths, bool recursive) {
                directories = lookup_paths;
+               this.recursive = recursive;
+               visited = new GenericSet<string> (str_hash, str_equal);
+       }
+
+       private ModuleIterator.for_subdirectory (string lookup_path, GenericSet<string> visited_paths) {
+               directories = { lookup_path };
+               recursive = true;
+               visited = visited_paths;
        }
 
        public new CoreDescriptor? get () {
@@ -16,6 +27,8 @@ public class Retro.ModuleIterator {
 
        public bool next () {
                while (current_directory < directories.length) {
+                       set_current_directory_as_visited ();
+
                        try {
                                if (next_in_current_path ())
                                        return true;
@@ -24,16 +37,21 @@ public class Retro.ModuleIterator {
                                debug (e.message);
                        }
 
-                       current_directory++;
+                       while (current_directory < directories.length && was_current_directory_visited ())
+                               current_directory++;
                }
 
                file_enumerator = null;
                core_descriptor = null;
+               sub_directory = null;
 
                return false;
        }
 
        private bool next_in_current_path () throws Error {
+               if (sub_directory != null && next_in_sub_directory ())
+                       return true;
+
                var directory = File.new_for_path (directories[current_directory]);
 
                if (file_enumerator == null)
@@ -43,6 +61,21 @@ public class Retro.ModuleIterator {
                        return false;
 
                for (var info = file_enumerator.next_file () ; info != null ; info = 
file_enumerator.next_file ()) {
+                       if (recursive && info.get_file_type () == FileType.DIRECTORY && sub_directory == 
null) {
+                               var sub_directory_basename = info.get_name ();
+                               var sub_directory_file = directory.get_child (sub_directory_basename);
+                               var sub_directory_path = sub_directory_file.get_path ();
+
+                               if (visited.contains (sub_directory_path))
+                                       continue;
+
+                               sub_directory = new ModuleIterator.for_subdirectory (sub_directory_path, 
visited);
+                               if (next_in_sub_directory ())
+                                       return true;
+                               else
+                                       continue;
+                       }
+
                        var core_descriptor_basename = info.get_name ();
                        if (!core_descriptor_basename.has_suffix (".libretro"))
                                continue;
@@ -63,5 +96,30 @@ public class Retro.ModuleIterator {
 
                return false;
        }
+
+       private bool next_in_sub_directory () throws Error {
+               if (sub_directory.next ()) {
+                       core_descriptor = sub_directory.get ();
+
+                       return true;
+               }
+
+               sub_directory = null;
+
+               return false;
+       }
+
+       private void set_current_directory_as_visited () {
+               var current_directory_file = File.new_for_path (directories[current_directory]);
+               var current_directory_path = current_directory_file.get_path ();
+               visited.add (current_directory_path);
+       }
+
+       private bool was_current_directory_visited () {
+               var current_directory_file = File.new_for_path (directories[current_directory]);
+               var current_directory_path = current_directory_file.get_path ();
+
+               return visited.contains (current_directory_path);
+       }
 }
 
diff --git a/retro-gtk/retro-module-query.vala b/retro-gtk/retro-module-query.vala
index 8b6437b..2f11d0a 100644
--- a/retro-gtk/retro-module-query.vala
+++ b/retro-gtk/retro-module-query.vala
@@ -3,10 +3,16 @@
 public class Retro.ModuleQuery {
        private const string ENV_PLUGIN_PATH = "LIBRETRO_PLUGIN_PATH";
 
+       private bool recursive;
+
+       public ModuleQuery (bool recursive) {
+               this.recursive = recursive;
+       }
+
        public ModuleIterator iterator () {
                var paths = get_plugin_lookup_paths ();
 
-               return new ModuleIterator (paths);
+               return new ModuleIterator (paths, recursive);
        }
 
        private static string[] get_plugin_lookup_paths () {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]