]> Kevux Git Server - fll/commitdiff
Update: The fl_directory_do() documentation comments and tweak flags. development
authorKevin Day <Kevin@kevux.org>
Sat, 19 Apr 2025 02:54:23 +0000 (21:54 -0500)
committerKevin Day <Kevin@kevux.org>
Sat, 19 Apr 2025 02:54:23 +0000 (21:54 -0500)
The documentation comments on how `fl_directory_do()` operates is now correctly updated.

Add an additional helper flag.

Improve use of flags in the process.

level_0/f_directory/c/directory/common.h
level_1/fl_directory/c/directory.c
level_1/fl_directory/c/directory.h
level_1/fl_directory/c/private-directory.c

index d215687ba91aa0b92eb25df2ab5aa484bbf645ca..9b14ca4bdf5fe9683751867ca048e792f100928a 100644 (file)
@@ -133,6 +133,7 @@ extern "C" {
  *
  *   The helper flags:
  *   - before_after:     Helper flag representing both before and after flags.
+ *   - clean_list:       Helper flag represeting both clean and list flags.
  *   - except_directory: Helper flag representing all type flags except for directory.
  *   - mask_basic:       Helper flag representing the basic flags.
  *   - mask_type:        Helper flag representing the action flags.
@@ -165,6 +166,7 @@ extern "C" {
 
   // The helper flags.
   #define f_directory_recurse_do_flag_before_after_d     0x6
+  #define f_directory_recurse_do_flag_clean_list_d       0x28
   #define f_directory_recurse_do_flag_except_directory_d 0xfd80
   #define f_directory_recurse_do_flag_mask_basic_d       0x7f
   #define f_directory_recurse_do_flag_mask_type_d        0xff80
index a04694434031d36136526c2ebabb7485ef6f99be..0da3bde6f85ba24fc9305311dea912fc4b8b14c3 100644 (file)
@@ -65,7 +65,7 @@ extern "C" {
       if (!recurse->action) {
         recurse->state.status = F_status_set_error(F_parameter);
 
-        private_inline_fl_directory_do_handle(recurse, path, 0);
+        private_inline_fl_directory_do_handle(recurse, path, f_directory_recurse_do_flag_none_d);
         if (F_status_is_error(recurse->state.status)) return;
 
         if (recurse->state.status == F_done) {
index 55468e2508ab4ab506e7f4b4f9acb40b357ec251..6cbbea7d6bd210b4ddad43d64935d30cdbcf3f4d 100644 (file)
@@ -90,71 +90,36 @@ extern "C" {
  *
  * This is intended to be used as an alternative to functions like fl_directory_list(), giving more control over the recursion process.
  *
- * When recursing the directory, except for the top directory, handle() is called after the recurse.path is updated (with both the before and after flags set).
- * For the top directory, handle() is called when the path is not updated (with the before and after flags set).
- *
  * This function is designed and intended to be used on directories.
- * If depth is 0, the operations callacks are still called but are done at the top level.
- * Be sure to use the recurse.path_top when depth is 0 or when f_directory_recurse_do_flag_top_d is set (the recurse.path may have been altered during the recursion).
  *
- * The action callback must set the error bit on recurse.state.status to ensure that the handle callbacks are called or not set the error bit to prevent this behavior.
+ * There are two callbacks directly used by this function:
+ *   - action: This callback is for performing the directory action.
+ *   - handle: This callback is for reacting to failures and other error/exceptional cases.
  *
- * This exits on error if, after the handle callback is called, when the recurse.state.status still has the error bit set.
- * This allows for the caller to inform this function to effectively ignore any errors.
+ * The action() callback must set the error bit on recurse.state.status to trigger the appropriate handle() call.
  *
- * This does not perform the operations on the top level directory when the max depth is set to 0.
- * Use the before and after flags to perform top level directory actions in this situation.
- * This is done so that the caller can better determine if top level directory actions must be performed before or after the recursed operations.
- * Be sure to add the appropriate before and after flags when calling this function in order to make this possible.
+ * This always exits on error if, after the handle() callback is called, the recurse.state.status still has the error bit set.
+ * The handle() gives the caller more power to do things like report errors or even ignore errors.
+ * When ignoring errors, be careful about modifications as some may put the project in an unusual state.
  *
- * The recurse parameter may be NULL if parameter checking fails or may be NULL if no parameter checking is performed.
- * The caller should consider checking if recurse is NULL.
+ * The action() and handle() should check if the recurse is NULL (and any other appropraite NULL checks).
  *
  * General behavior flow:
- *   1. Check recurse.action existence (if not _di_level_1_parameter_checking_), calling recurse.handle with (f_directory_recurse_do_flag_top_d) on error.
- *   2. Check path.used, call recurse.handle with (f_directory_recurse_do_flag_path_d | f_directory_recurse_do_flag_top_d) on error.
- *   3. Prepare recurse.path, call recurse.handle with (f_directory_recurse_do_flag_path_d | f_directory_recurse_do_flag_top_d) on error.
- *   4. If recurse.flag has (f_directory_recurse_do_flag_top_before_e), call recurse.action with (f_directory_recurse_do_flag_top_before_e).
- *     - Call recurse.handle with (f_directory_recurse_do_flag_top_before_e) on error.
- *
- *   5. If recurse.depth_max > 0, perform recursion.
- *     1. Load directory listing, call recurse.handle with (f_directory_recurse_do_flag_list_d | f_directory_recurse_do_flag_path_d) on error.
- *     2. If recurse.flag has (f_directory_recurse_do_flag_list_d), call recurse.action with (f_directory_recurse_do_flag_list_d).
- *       - Call recurse.handle with (f_directory_recurse_do_flag_list_d) on error.
- *
- *     3. For each file type, except directory (optionally calling recurse->state.interrupt() at the top of each loop):
- *       1. Prepare list array, call recurse.handle with (f_directory_recurse_do_flag_directory_d) on error.
- *       2. If recurse.flag has (f_directory_recurse_do_flag_before_d), call recurse.action with (f_directory_recurse_do_flag_before_d | f_directory_recurse_do_flag_*_e, where * represents type).
- *         - Call recurse.handle with (f_directory_recurse_do_flag_before_d | f_directory_recurse_do_flag_*_e, where * represents type) on error.
- *
- *       3. Call recurse.action with (f_directory_recurse_do_flag_action_d | f_directory_recurse_do_flag_*_e, where * represents type).
- *         - Call recurse.handle with (f_directory_recurse_do_flag_action_d | f_directory_recurse_do_flag_*_e, where * represents type) on error.
- *
- *       4. If recurse.flag has (f_directory_recurse_do_flag_after_d), call recurse.action with (f_directory_recurse_do_flag_after_d | f_directory_recurse_do_flag_*_e, where * represents type).
- *         - Call recurse.handle with (f_directory_recurse_do_flag_after_d | f_directory_recurse_do_flag_*_e, where * represents type) on error.
- *
- *     4. For each directory (optionally calling recurse->state.interrupt() at the top of each loop):
- *       1. Prepare list array, call recurse.handle with (f_directory_recurse_do_flag_directory_d) on error.
- *       2. Call recurse.action with (f_directory_recurse_do_flag_action_d| f_directory_recurse_do_flag_before_d | f_directory_recurse_do_flag_directory_d).
- *         - Call recurse.handle with (f_directory_recurse_do_flag_action_d | f_directory_recurse_do_flag_before_d | f_directory_recurse_do_flag_directory_d) on error.
- *
- *       3. If depth max is not reached, perform recursion.
- *       4. If depth max is reached, call recurse.action with (f_directory_recurse_do_flag_action_d | f_directory_recurse_do_flag_directory_d).
- *         - Call recurse.handle with (f_directory_recurse_do_flag_action_d | f_directory_recurse_do_flag_directory_d) on error.
- *
- *       5. Call recurse.action with (f_directory_recurse_do_flag_after_d | f_directory_recurse_do_flag_directory_d).
- *         - Call recurse.handle with (f_directory_recurse_do_flag_after_d | f_directory_recurse_do_flag_directory_d) on error.
- *
- *   6. Else if recurse.depth_max == 0, process directory, call recurse.handle with (f_directory_recurse_do_flag_top_d | f_directory_recurse_do_flag_directory_d) on error.
- *     1. Load directory listing, call recurse.handle with (f_directory_recurse_do_flag_list_d | f_directory_recurse_do_flag_path_d) on error.
- *     2. If recurse.flag has (f_directory_recurse_do_flag_list_d), call recurse.action with (f_directory_recurse_do_flag_list_d).
- *       - Call recurse.handle with (f_directory_recurse_do_flag_list_d) on error.
- *
- *     3. Call recurse.action with (f_directory_recurse_do_flag_action_d | f_directory_recurse_do_flag_directory_d | f_directory_recurse_do_flag_top_d).
- *       - Call recurse.handle with (f_directory_recurse_do_flag_action_d | f_directory_recurse_do_flag_directory_d | f_directory_recurse_do_flag_top_d) on error.
- *
- *   7. If recurse.flag has (f_directory_recurse_do_flag_top_after_e), call recurse.action with (f_directory_recurse_do_flag_top_after_e).
- *     - Call recurse.handle with (f_directory_recurse_do_flag_top_after_e) on error.
+ *   1. Check recurse.action existence (if not _di_level_1_parameter_checking_), flag is f_directory_recurse_do_flag_none_d.
+ *   2. Check path.used and allocation recurse.path, flag is f_directory_recurse_do_flag_path_d (even if handle() changes error bit, if path.used is 0, then the function always returns here).
+ *   3. If recurse.depth < recurse.depth_max, then recurse into directory contents.
+ *     3.1 Open directory stream, flag is f_directory_recurse_do_flag_list_d.
+ *     3.2 Read directory stream, flag is f_directory_recurse_do_flag_path_list_d ('.' and '..' are skipped).
+ *     3.3 Allocate sub-path onto recurse.path, flag is f_directory_recurse_do_flag_path_d.
+ *     3.4 Process before state on path, flag is (type code of file/directory) | f_directory_recurse_do_flag_before_d.
+ *     3.5 Process action state on path, flag is (type code of file/directory) | f_directory_recurse_do_flag_action_d.
+ *       3.5.1 If type is directory (flag has f_directory_recurse_do_flag_directory_d), then increase recurse.depth and recurse (repeat step (3) for this sub-directory).
+ *     3.6 Process after state on path, flag is (type code of file/directory) | f_directory_recurse_do_flag_after_d.
+ *     3.7 Close directory stream, flag is f_directory_recurse_do_flag_clean_d | f_directory_recurse_do_flag_path_list_d.
+ *   4. Process top-level directory.
+ *     4.1 Process before state on path, flag is f_directory_recurse_do_flag_before_d | f_directory_recurse_do_flag_directory_d | recurse.flag.
+ *     4.2 Process action state on path, flag is f_directory_recurse_do_flag_action_d | f_directory_recurse_do_flag_directory_d | recurse.flag.
+ *     4.3 Process after state on path, flag is f_directory_recurse_do_flag_after_d | f_directory_recurse_do_flag_directory_d | recurse.flag.
  *
  * @param path
  *   The directory file path.
index 370d21e5959d380e7a0a3c11a3279b86c304e505..59e0c35bfc9e2c208ef8064973f58e3672e44788 100644 (file)
@@ -8,6 +8,19 @@ extern "C" {
 #if !defined(_di_fl_directory_do_)
   void private_fl_directory_do_recurse(f_directory_recurse_do_t * const recurse) {
 
+    f_directory_stream_t stream = f_directory_stream_t_initialize;
+
+    recurse->state.status = f_directory_stream_open(recurse->path, &stream);
+
+    if (F_status_is_error(recurse->state.status)) {
+      private_inline_fl_directory_do_handle(recurse, recurse->path, f_directory_recurse_do_flag_list_d);
+      if (F_status_is_error(recurse->state.status)) return;
+
+      if (recurse->state.status != F_done) {
+        recurse->state.status = F_okay;
+      }
+    }
+
     const uint32_t flag_actions[] = {
       recurse->flag & f_directory_recurse_do_flag_before_d ? f_directory_recurse_do_flag_before_d : 0,
       f_directory_recurse_do_flag_action_d,
@@ -16,7 +29,6 @@ extern "C" {
 
     const f_number_unsigned_t used_original = recurse->path.used;
 
-    f_directory_stream_t stream = f_directory_stream_t_initialize;
     f_directory_entity_t entity = f_directory_entity_t_initialize;
     f_string_static_t name = f_string_static_t_initialize;
 
@@ -24,17 +36,6 @@ extern "C" {
     uint8_t action = 0;
     f_number_unsigned_t used_directory = 0;
 
-    recurse->state.status = f_directory_stream_open(recurse->path, &stream);
-
-    if (F_status_is_error(recurse->state.status)) {
-      private_inline_fl_directory_do_handle(recurse, recurse->path, f_directory_recurse_do_flag_path_list_d);
-      if (F_status_is_error(recurse->state.status)) return;
-
-      if (recurse->state.status != F_done) {
-        recurse->state.status = F_okay;
-      }
-    }
-
     for (;;) {
       if (recurse->state.interrupt) {
         recurse->state.interrupt((void *) &recurse->state, (void *) recurse);
@@ -45,7 +46,7 @@ extern "C" {
       if (recurse->state.status == F_okay_eos) break;
 
       if (F_status_is_error(recurse->state.status)) {
-        private_inline_fl_directory_do_handle(recurse, recurse->path, f_directory_recurse_do_flag_action_d | f_directory_recurse_do_flag_path_list_d);
+        private_inline_fl_directory_do_handle(recurse, recurse->path, f_directory_recurse_do_flag_path_list_d);
         if (F_status_is_error(recurse->state.status)) return;
 
         if (recurse->state.status != F_done) {
@@ -108,7 +109,7 @@ extern "C" {
       recurse->path.string[recurse->path.used] = 0;
 
       if (F_status_is_error(recurse->state.status)) {
-        private_inline_fl_directory_do_handle(recurse, name, f_directory_recurse_do_flag_directory_d);
+        private_inline_fl_directory_do_handle(recurse, name, f_directory_recurse_do_flag_path_d);
 
         if (F_status_is_error(recurse->state.status)) break;
         if (recurse->state.status == F_break || recurse->state.status == F_done) break;
@@ -172,7 +173,7 @@ extern "C" {
     recurse->state.status = f_directory_stream_close(stream);
 
     if (F_status_is_error(recurse->state.status)) {
-      private_inline_fl_directory_do_handle(recurse, recurse->path, f_directory_recurse_do_flag_clean_d | f_directory_recurse_do_flag_path_list_d);
+      private_inline_fl_directory_do_handle(recurse, recurse->path, f_directory_recurse_do_flag_clean_list_d);
       if (F_status_is_error(recurse->state.status)) return;
 
       if (recurse->state.status != F_done) {