diff options
author | Sven Gothel <[email protected]> | 2022-07-29 16:32:34 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2022-07-29 16:32:34 +0200 |
commit | 4dce23836ac967527794e4e418020147abfcaeac (patch) | |
tree | 6c64b148d8a249d5916aa5c0de5ee2d478277bd2 | |
parent | 5dec9ae8d9583920b6718ba3ee399769bb882f30 (diff) |
Add traverse_options::lexicographical_order as required when computing an order dependent outcome like a hash value
Implementation only performs the default sort algo on the dir_item::basename() for each directory,
when recursing through the directories.
-rw-r--r-- | include/jau/file_util.hpp | 7 | ||||
-rw-r--r-- | java_jni/org/jau/fs/FileUtil.java | 12 | ||||
-rw-r--r-- | java_jni/org/jau/fs/TraverseOptions.java | 7 | ||||
-rw-r--r-- | src/file_util.cpp | 8 |
4 files changed, 30 insertions, 4 deletions
diff --git a/include/jau/file_util.hpp b/include/jau/file_util.hpp index 503cc99..9f9ac06 100644 --- a/include/jau/file_util.hpp +++ b/include/jau/file_util.hpp @@ -807,11 +807,14 @@ namespace jau { /** Traverse through symbolic linked directories if traverse_options::recursive is set, i.e. directories with property fmode_t::link set. */ follow_symlinks = 1 << 1, + /** Traverse through elements in lexicographical order. This might be required when computing an order dependent outcome like a hash value. */ + lexicographical_order = 1 << 2, + /** Visit the content's parent directory at entry. Both, dir_entry and dir_exit can be set, only one or none. */ - dir_entry = 1 << 2, + dir_entry = 1 << 8, /** Visit the content's parent directory at exit. Both, dir_entry and dir_exit can be set, only one or none. */ - dir_exit = 1 << 3, + dir_exit = 1 << 9, /** Enable verbosity mode, potentially used by a path_visitor implementation like remove(). */ verbose = 1 << 15 diff --git a/java_jni/org/jau/fs/FileUtil.java b/java_jni/org/jau/fs/FileUtil.java index 178e2d0..c7ea8a7 100644 --- a/java_jni/org/jau/fs/FileUtil.java +++ b/java_jni/org/jau/fs/FileUtil.java @@ -24,6 +24,7 @@ package org.jau.fs; import java.time.Instant; +import java.util.Comparator; import java.util.List; /** @@ -183,8 +184,19 @@ public final class FileUtil { return false; } } + + final Comparator<DirItem> dirItemComparator = new Comparator<DirItem> () { + @Override + public int compare(final DirItem o1, final DirItem o2) { + return o1.basename().compareTo(o2.basename()); + } + }; + final List<DirItem> content = get_dir_content(item_stats.path()); if( null != content && content.size() > 0 ) { + if( topts.isSet(TraverseOptions.Bit.lexicographical_order) ) { + content.sort(dirItemComparator); + } for (final DirItem element : content) { final FileStats element_stats = new FileStats( element.path() ); if( element_stats.is_dir() ) { // an OK dir diff --git a/java_jni/org/jau/fs/TraverseOptions.java b/java_jni/org/jau/fs/TraverseOptions.java index 15e1add..19722c4 100644 --- a/java_jni/org/jau/fs/TraverseOptions.java +++ b/java_jni/org/jau/fs/TraverseOptions.java @@ -45,11 +45,14 @@ public class TraverseOptions { /** Traverse through symbolic linked directories if traverse_options::recursive is set, i.e. directories with property fmode_t::link set. */ follow_symlinks ( (short) ( 1 << 1 ) ), + /** Traverse through elements in lexicographical order. This might be required when computing an order dependent outcome like a hash value. */ + lexicographical_order ( (short) ( 1 << 2 ) ), + /** Visit the content's parent directory at entry. Both, dir_entry and dir_exit can be set, only one or none. */ - dir_entry ( (short) ( 1 << 2 ) ), + dir_entry ( (short) ( 1 << 8 ) ), /** Visit the content's parent directory at exit. Both, dir_entry and dir_exit can be set, only one or none. */ - dir_exit ( (short) ( 1 << 3 ) ), + dir_exit ( (short) ( 1 << 9 ) ), /** Enable verbosity mode, potentially used by a path_visitor implementation like remove(). */ verbose ( (short) ( 1 << 15 ) ); diff --git a/src/file_util.cpp b/src/file_util.cpp index f1aad97..b283cf3 100644 --- a/src/file_util.cpp +++ b/src/file_util.cpp @@ -929,6 +929,7 @@ std::string jau::fs::to_string(const traverse_event mask) noexcept { #define TRAVERSEOPTIONS_ENUM(X,M) \ X(traverse_options,recursive,M) \ X(traverse_options,follow_symlinks,M) \ + X(traverse_options,lexicographical_order,M) \ X(traverse_options,dir_entry,M) \ X(traverse_options,dir_exit,M) @@ -940,6 +941,10 @@ std::string jau::fs::to_string(const traverse_options mask) noexcept { return out; } +static bool _dir_item_basename_compare(const dir_item& a, const dir_item& b) { + return a.basename() < b.basename(); +} + static bool _visit(const file_stats& item_stats, const traverse_options topts, const path_visitor& visitor, std::vector<int>& dirfds) noexcept { if( item_stats.is_dir() ) { if( item_stats.is_link() && !is_set(topts, traverse_options::follow_symlinks) ) { @@ -971,6 +976,9 @@ static bool _visit(const file_stats& item_stats, const traverse_options topts, c ( [](std::vector<dir_item>* receiver, const dir_item& item) -> void { receiver->push_back( item ); } ) ); if( get_dir_content(this_dirfd, item_stats.path(), cs) && content.size() > 0 ) { + if( is_set(topts, traverse_options::lexicographical_order) ) { + std::sort(content.begin(), content.end(), _dir_item_basename_compare); + } for (const dir_item& element : content) { const file_stats element_stats( this_dirfd, element, true /* dirfd_is_item_dirname */ ); if( element_stats.is_dir() ) { // an OK dir |