From: Kevin Day Date: Sat, 19 Apr 2025 02:54:23 +0000 (-0500) Subject: Update: The fl_directory_do() documentation comments and tweak flags. X-Git-Url: https://git.kevux.org/?a=commitdiff_plain;h=a65987fc2931d94d95dcd67c223c99ba7869b8d2;p=fll Update: The fl_directory_do() documentation comments and tweak flags. 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. --- diff --git a/level_0/f_directory/c/directory/common.h b/level_0/f_directory/c/directory/common.h index d215687..9b14ca4 100644 --- a/level_0/f_directory/c/directory/common.h +++ b/level_0/f_directory/c/directory/common.h @@ -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 diff --git a/level_1/fl_directory/c/directory.c b/level_1/fl_directory/c/directory.c index a046944..0da3bde 100644 --- a/level_1/fl_directory/c/directory.c +++ b/level_1/fl_directory/c/directory.c @@ -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) { diff --git a/level_1/fl_directory/c/directory.h b/level_1/fl_directory/c/directory.h index 55468e2..6cbbea7 100644 --- a/level_1/fl_directory/c/directory.h +++ b/level_1/fl_directory/c/directory.h @@ -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. diff --git a/level_1/fl_directory/c/private-directory.c b/level_1/fl_directory/c/private-directory.c index 370d21e..59e0c35 100644 --- a/level_1/fl_directory/c/private-directory.c +++ b/level_1/fl_directory/c/private-directory.c @@ -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) {