aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2022-07-29 16:32:34 +0200
committerSven Gothel <[email protected]>2022-07-29 16:32:34 +0200
commit4dce23836ac967527794e4e418020147abfcaeac (patch)
tree6c64b148d8a249d5916aa5c0de5ee2d478277bd2
parent5dec9ae8d9583920b6718ba3ee399769bb882f30 (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.hpp7
-rw-r--r--java_jni/org/jau/fs/FileUtil.java12
-rw-r--r--java_jni/org/jau/fs/TraverseOptions.java7
-rw-r--r--src/file_util.cpp8
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