From 5c0d767f2e772a7e99040dc740886ca8e8d9bb2b Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Thu, 30 Jan 2025 21:45:53 -0600 Subject: [PATCH] Update: Improve directory recursion and its documentation. Fix some problems in the `fl_directory_do()` documentation. Extend the documentation adding more details of the process. Remove redundant "is not error" status checks. The checks like `if (flag_actions[j])` and `if (!flag_actions[j])` are now changed to respect the recently added `f_directory_recurse_do_flag_action_e` flag. --- level_1/fl_directory/c/directory.h | 41 +++++++++++++++++++++++++++--- level_1/fl_directory/c/private-directory.c | 31 +++++++++++----------- 2 files changed, 54 insertions(+), 18 deletions(-) diff --git a/level_1/fl_directory/c/directory.h b/level_1/fl_directory/c/directory.h index fd0a45e..da3e08e 100644 --- a/level_1/fl_directory/c/directory.h +++ b/level_1/fl_directory/c/directory.h @@ -91,21 +91,56 @@ 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() with the before and after flags set is called after the recurse.path is updated. - * For the top directory, handle() is called with the before and after flags set when the path is not updated (that is, the path should be + * For the top directory, handle() is called with the before and after flags set when the path is not updated. * * This function is designed and intended to be used on directories. * If depth is 0, the operations callacks are still called but done at the top level. * - * The action callback must set the error bit to ensure that the handle callbacks are called or not set the error bit to prevent this behavior. + * 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. * - * This exists on error if, after the handle callback is called, that the recurse.state.status still has the error bit set. + * This exits on error if, after the handle callback is called, that the recurse.state.status still has the error bit set. * This allows for the caller to inform this function to effectively ignore any errors. * + * 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_e) on error. + * 2. Check path.used, call recurse.handle with (f_directory_recurse_do_flag_top_e | f_directory_recurse_do_flag_path_e) on error. + * 3. Prepare recurse.path, call recurse.handle with (f_directory_recurse_do_flag_top_e | f_directory_recurse_do_flag_path_e) on error. + * 4. If recurse.flag has (f_directory_recurse_do_flag_top_e) or (f_directory_recurse_do_flag_before_e), call recurse.action with (f_directory_recurse_do_flag_top_e | f_directory_recurse_do_flag_path_e | f_directory_recurse_do_flag_before_e). + * - Call recurse.handle with (f_directory_recurse_do_flag_top_e | f_directory_recurse_do_flag_path_e | f_directory_recurse_do_flag_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_e | f_directory_recurse_do_flag_path_e) on error. + * 2. If recurse.flag has (f_directory_recurse_do_flag_list_e), call recurse.action with (f_directory_recurse_do_flag_list_e). + * - Call recurse.handle with (f_directory_recurse_do_flag_list_e) 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_e) on error. + * 2. Call recurse.action with (f_directory_recurse_do_flag_before_e | f_directory_recurse_do_flag_*_e, where * represents type). + * - Call recurse.handle with (f_directory_recurse_do_flag_before_e | f_directory_recurse_do_flag_*_e, where * represents type) on error. + * 3. Call recurse.action with (f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_*_e, where * represents type). + * - Call recurse.handle with (f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_*_e, where * represents type) on error. + * 4. Call recurse.action with (f_directory_recurse_do_flag_after_e | f_directory_recurse_do_flag_*_e, where * represents type). + * - Call recurse.handle with (f_directory_recurse_do_flag_after_e | 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_e) on error. + * 2. Call recurse.action with (f_directory_recurse_do_flag_before_e | f_directory_recurse_do_flag_directory_e). + * - Call recurse.handle with (f_directory_recurse_do_flag_before_e | f_directory_recurse_do_flag_directory_e) 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_e | f_directory_recurse_do_flag_directory_e). + * - Call recurse.handle with (f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e) on error. + * 5. Call recurse.action with (f_directory_recurse_do_flag_after_e | f_directory_recurse_do_flag_directory_e). + * - Call recurse.handle with (f_directory_recurse_do_flag_after_e | f_directory_recurse_do_flag_directory_e) on error. + * 6. Else if recurse.depth_max == 0, process directory, call recurse.handle with (f_directory_recurse_do_flag_top_e | f_directory_recurse_do_flag_directory_e) on error. + * 1. Call recurse.action with (f_directory_recurse_do_flag_top_e | f_directory_recurse_do_flag_directory_e). + * - Call recurse.handle with (f_directory_recurse_do_flag_top_e | f_directory_recurse_do_flag_directory_e) on error. + * 2. If recurse.flag has (f_directory_recurse_do_flag_top_e) or (f_directory_recurse_do_flag_after_e), call recurse.action with (f_directory_recurse_do_flag_top_e | f_directory_recurse_do_flag_path_e | f_directory_recurse_do_flag_after_e). + * - Call recurse.handle with (f_directory_recurse_do_flag_top_e | f_directory_recurse_do_flag_path_e | f_directory_recurse_do_flag_after_e) on error. + * * @param path * The directory file path. + * * Must be NULL terminated. * @param recurse * The directory recurse data. + * * This must not be NULL. * * This alters recurse.state.status: diff --git a/level_1/fl_directory/c/private-directory.c b/level_1/fl_directory/c/private-directory.c index 48677d5..42b9eac 100644 --- a/level_1/fl_directory/c/private-directory.c +++ b/level_1/fl_directory/c/private-directory.c @@ -55,7 +55,7 @@ extern "C" { if (F_status_is_error(recurse->state.status)) return; } - if (recurse->state.status != F_done && F_status_is_error_not(recurse->state.status)) { + if (recurse->state.status != F_done) { recurse->state.status = F_okay; } } @@ -80,7 +80,7 @@ extern "C" { f_directory_recurse_do_flag_unknown_e, }; - if (recurse->state.status != F_done && F_status_is_error_not(recurse->state.status)) { + if (recurse->state.status != F_done) { f_string_dynamics_t * const list[] = { &recurse->listing.block, &recurse->listing.character, @@ -126,13 +126,13 @@ extern "C" { // Convenience and code simplification loop for processing before action, action, and after action. for (j = 0; j < 3; ++j) { - if (!flag_actions[j] || (recurse->flag & flag_actions[j])) { + if (flag_actions[j] & f_directory_recurse_do_flag_action_e || (recurse->flag & flag_actions[j])) { recurse->state.status = F_okay; recurse->action(recurse, list[k]->array[i], flag_actions[j] | flags[k]); if (F_status_is_error(recurse->state.status)) { - private_inline_fl_directory_do_handle(recurse, recurse->listing.directory.array[i], f_directory_recurse_do_flag_before_e | flags[k]); + private_inline_fl_directory_do_handle(recurse, recurse->listing.directory.array[i], flag_actions[j] | flags[k]); if (F_status_is_error(recurse->state.status)) break; } @@ -183,6 +183,7 @@ extern "C" { if (F_status_is_error(recurse->state.status)) { private_inline_fl_directory_do_handle(recurse, recurse->listing.directory.array[i], f_directory_recurse_do_flag_directory_e); + if (F_status_is_error(recurse->state.status)) break; if (recurse->state.status == F_break || recurse->state.status == F_done) break; if (recurse->state.status == F_continue) continue; @@ -191,17 +192,7 @@ extern "C" { // Convenience and code simplification loop for processing before action, action, and after action. for (j = 0; j < 3; ++j) { - if (flag_actions[j]) { - if (recurse->flag & flag_actions[j]) { - recurse->action(recurse, recurse->listing.directory.array[i], flag_actions[j] | f_directory_recurse_do_flag_directory_e); - - if (F_status_is_error(recurse->state.status)) { - private_inline_fl_directory_do_handle(recurse, recurse->listing.directory.array[i], flag_actions[j] | f_directory_recurse_do_flag_directory_e); - if (F_status_is_error(recurse->state.status)) break; - } - } - } - else { + if (flag_actions[j] & f_directory_recurse_do_flag_action_e) { recurse->state.status = F_okay; if (recurse->depth < recurse->depth_max) { @@ -225,6 +216,16 @@ extern "C" { // This loop is not considered a loop for breaking and continuing. if (recurse->state.status == F_break || recurse->state.status == F_done || recurse->state.status == F_continue) break; } + else { + if (recurse->flag & flag_actions[j]) { + recurse->action(recurse, recurse->listing.directory.array[i], flag_actions[j] | f_directory_recurse_do_flag_directory_e); + + if (F_status_is_error(recurse->state.status)) { + private_inline_fl_directory_do_handle(recurse, recurse->listing.directory.array[i], flag_actions[j] | f_directory_recurse_do_flag_directory_e); + if (F_status_is_error(recurse->state.status)) break; + } + } + } if (F_status_is_error(recurse->state.status)) break; if (recurse->state.status == F_break || recurse->state.status == F_done) break; -- 1.8.3.1