From: Kevin Day Date: Thu, 12 Jun 2025 02:13:26 +0000 (-0500) Subject: Update: Improve status handling of fl_directory_do(). X-Git-Tag: 0.7.2~12 X-Git-Url: https://www.git.kevux.org/?a=commitdiff_plain;h=fb7eafc4d1f50ba09f7155adc98e3d5f5933ec9d;p=fll Update: Improve status handling of fl_directory_do(). Add `F_skip` support to allow skipping the next action for some path. Honor the `F_break`, `F_continue`, `F_done`, and the `F_interrupt` more consistently. Make sure to consistently clean up the directory stream when these are set. --- diff --git a/level_1/fl_directory/c/directory.c b/level_1/fl_directory/c/directory.c index 4250593..b19ccbc 100644 --- a/level_1/fl_directory/c/directory.c +++ b/level_1/fl_directory/c/directory.c @@ -73,9 +73,9 @@ extern "C" { recurse->state.status = F_status_set_error(F_parameter); 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 (F_status_is_error(recurse->state.status) || F_status_set_fine(recurse->state.status) == F_interrupt) return; - if (recurse->state.status == F_done) { + if (recurse->state.status == F_break || recurse->state.status == F_continue || recurse->state.status == F_done) { recurse->state.status = F_okay; return; @@ -119,9 +119,9 @@ extern "C" { if (!path.used || F_status_is_error(recurse->state.status)) { private_inline_fl_directory_do_handle(recurse, path, f_directory_recurse_do_flag_path_d); - if (F_status_is_error(recurse->state.status)) return; + if (F_status_is_error(recurse->state.status) || F_status_set_fine(recurse->state.status) == F_interrupt) return; - if (recurse->state.status == F_done) { + if (recurse->state.status == F_break || recurse->state.status == F_continue || recurse->state.status == F_done) { recurse->state.status = F_okay; return; @@ -136,15 +136,20 @@ extern "C" { recurse->flag & f_directory_recurse_do_flag_after_d ? f_directory_recurse_do_flag_after_d : 0, }; - uint8_t action = 0; - recurse->depth = 0; - for (action = 0; action < 3; ++action) { + for (uint8_t action = 0; action < 3; ++action) { if (recurse->state.interrupt) { recurse->state.interrupt((void *) &recurse->state, (void *) recurse); - if (F_status_set_fine(recurse->state.status) == F_interrupt) break; + if (F_status_set_fine(recurse->state.status) == F_interrupt) return; + } + + // Support F_skip for skipping the next action. + if (recurse->state.status == F_skip) { + recurse->state.status = F_okay; + + continue; } if (flag_actions[action]) { @@ -158,17 +163,17 @@ extern "C" { --recurse->depth; - if (F_status_is_error(recurse->state.status)) return; + // Reset the path after operating on child directories. + recurse->path.used = path.used; + recurse->path.string[recurse->path.used] = 0; + + if (F_status_is_error(recurse->state.status) || F_status_set_fine(recurse->state.status) == F_interrupt) return; - if (recurse->state.status == F_done) { + if (recurse->state.status == F_break || recurse->state.status == F_continue || recurse->state.status == F_done) { recurse->state.status = F_okay; return; } - - // Reset the path after operating on child directories. - recurse->path.used = path.used; - recurse->path.string[recurse->path.used] = 0; } } @@ -179,11 +184,10 @@ extern "C" { if (F_status_is_error(recurse->state.status)) { private_inline_fl_directory_do_handle(recurse, path, flag_actions[action] | f_directory_recurse_do_flag_directory_d); - if (F_status_is_error(recurse->state.status)) break; } - // There is nothing to continue onto, so all of these result in a break out of the loop. - if (recurse->state.status == F_break || recurse->state.status == F_done || recurse->state.status == F_continue || F_status_set_fine(recurse->state.status) == F_interrupt) break; + if (F_status_is_error(recurse->state.status) || F_status_set_fine(recurse->state.status) == F_interrupt) return; + if (recurse->state.status == F_break || recurse->state.status == F_continue || recurse->state.status == F_done) break; } } } // for diff --git a/level_1/fl_directory/c/directory.h b/level_1/fl_directory/c/directory.h index a83ed7a..489ffe8 100644 --- a/level_1/fl_directory/c/directory.h +++ b/level_1/fl_directory/c/directory.h @@ -110,6 +110,12 @@ extern "C" { * The action only happens if recurse.flag has f_directory_recurse_do_flag_action_d. * The after only happens if recurse.flag has f_directory_recurse_do_flag_after_d. * + * Setting the recurse.state.status to the following for the designated effects: + * - F_break: Break out of the current depth; Is the same as F_done at depth 0. + * - F_continue: Continue to the next sibling file at the current depth; Is the same as F_done at depth 0. + * - F_done: Done all directory operations, immediately return. + * - F_skip: Skip the next action, resetting the recurse.state.status to F_okay; Is the same as F_okay if on the last action for some path. + * * The action() and handle() should check if the recurse is NULL (and any other appropraite NULL checks). * * General behavior flow: diff --git a/level_1/fl_directory/c/private-directory.c b/level_1/fl_directory/c/private-directory.c index edf1970..2654057 100644 --- a/level_1/fl_directory/c/private-directory.c +++ b/level_1/fl_directory/c/private-directory.c @@ -14,160 +14,172 @@ extern "C" { 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 (F_status_is_error(recurse->state.status) || F_status_set_fine(recurse->state.status) == F_interrupt) return; - if (recurse->state.status != F_done) { + if (recurse->state.status != F_break && recurse->state.status != F_continue && recurse->state.status != F_done) { recurse->state.status = F_okay; } } - const uint64_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, - recurse->flag & f_directory_recurse_do_flag_after_d ? f_directory_recurse_do_flag_after_d : 0, - }; - const f_number_unsigned_t used_original = recurse->path.used; - f_directory_entity_t entity = f_directory_entity_t_initialize; - f_string_static_t name = f_string_static_t_initialize; + if (recurse->state.status == F_okay) { + const uint64_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, + recurse->flag & f_directory_recurse_do_flag_after_d ? f_directory_recurse_do_flag_after_d : 0, + }; - uint64_t flag = 0; - uint8_t action = 0; - f_number_unsigned_t used_directory = 0; + f_directory_entity_t entity = f_directory_entity_t_initialize; + f_string_static_t name = f_string_static_t_initialize; - for (;;) { - if (recurse->state.interrupt) { - recurse->state.interrupt((void *) &recurse->state, (void *) recurse); - if (F_status_set_fine(recurse->state.status) == F_interrupt) break; - } + uint64_t flag = 0; + uint8_t action = 0; + f_number_unsigned_t used_directory = 0; - recurse->state.status = f_directory_stream_read(stream, &entity); - if (recurse->state.status == F_okay_eos) break; + for (;;) { + if (recurse->state.interrupt) { + recurse->state.interrupt((void *) &recurse->state, (void *) recurse); + if (F_status_set_fine(recurse->state.status) == F_interrupt) break; + } - 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; + recurse->state.status = f_directory_stream_read(stream, &entity); + if (recurse->state.status == F_okay_eos) break; - if (recurse->state.status != F_done) { - recurse->state.status = F_okay; + 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); } - } - // Never process the '.' and '..' paths. - if (!strncmp(f_directory_current_s.string, entity.d_name, f_directory_current_s.used + 1) || !strncmp(f_directory_back_s.string, entity.d_name, f_directory_back_s.used + 1)) continue; + if (F_status_is_error(recurse->state.status) || F_status_set_fine(recurse->state.status) == F_interrupt) return; - if (entity.d_type == DT_FIFO) { - flag = f_directory_recurse_do_flag_fifo_d; - } - else if (entity.d_type == DT_CHR) { - flag = f_directory_recurse_do_flag_character_d; - } - else if (entity.d_type == DT_DIR) { - flag = f_directory_recurse_do_flag_directory_d; - } - else if (entity.d_type == DT_BLK) { - flag = f_directory_recurse_do_flag_block_d; - } - else if (entity.d_type == DT_REG) { - flag = f_directory_recurse_do_flag_regular_d; - } - else if (entity.d_type == DT_LNK) { - flag = f_directory_recurse_do_flag_link_d; - } - else if (entity.d_type == DT_SOCK) { - flag = f_directory_recurse_do_flag_socket_d; - } + if (recurse->state.status == F_break || recurse->state.status == F_continue || recurse->state.status == F_done) { + if (recurse->state.status == F_continue) continue; - // The DT_WHT may not be defined everywhere. - #ifdef DT_WHT - else if (entity.d_type == DT_WHT) { - flag = f_directory_recurse_do_flag_white_out_d; + break; } - #endif // DT_WHT - else { - flag = f_directory_recurse_do_flag_unknown_d; - } + recurse->state.status = F_okay; - recurse->path.used = used_original; + // Never process the '.' and '..' paths. + if (!strncmp(f_directory_current_s.string, entity.d_name, f_directory_current_s.used + 1) || !strncmp(f_directory_back_s.string, entity.d_name, f_directory_back_s.used + 1)) continue; - name.string = entity.d_name; - name.used = strnlen(entity.d_name, F_directory_max_string_d); + if (entity.d_type == DT_FIFO) { + flag = f_directory_recurse_do_flag_fifo_d; + } + else if (entity.d_type == DT_CHR) { + flag = f_directory_recurse_do_flag_character_d; + } + else if (entity.d_type == DT_DIR) { + flag = f_directory_recurse_do_flag_directory_d; + } + else if (entity.d_type == DT_BLK) { + flag = f_directory_recurse_do_flag_block_d; + } + else if (entity.d_type == DT_REG) { + flag = f_directory_recurse_do_flag_regular_d; + } + else if (entity.d_type == DT_LNK) { + flag = f_directory_recurse_do_flag_link_d; + } + else if (entity.d_type == DT_SOCK) { + flag = f_directory_recurse_do_flag_socket_d; + } - recurse->state.status = f_memory_array_increase_by(f_path_separator_s.used + name.used + 1, sizeof(f_char_t), (void **) &recurse->path.string, &recurse->path.used, &recurse->path.size); + // The DT_WHT may not be defined everywhere. + #ifdef DT_WHT + else if (entity.d_type == DT_WHT) { + flag = f_directory_recurse_do_flag_white_out_d; + } + #endif // DT_WHT - if (F_status_is_error_not(recurse->state.status)) { - recurse->state.status = f_string_dynamic_append_assure(f_path_separator_s, &recurse->path); - } + else { + flag = f_directory_recurse_do_flag_unknown_d; + } - if (F_status_is_error_not(recurse->state.status)) { - recurse->state.status = f_string_dynamic_append_nulless(name, &recurse->path); - } + recurse->path.used = used_original; - // Guarantee NULL termination. - recurse->path.string[recurse->path.used] = 0; + name.string = entity.d_name; + name.used = strnlen(entity.d_name, F_directory_max_string_d); - if (F_status_is_error(recurse->state.status)) { - private_inline_fl_directory_do_handle(recurse, name, f_directory_recurse_do_flag_path_d); + recurse->state.status = f_memory_array_increase_by(f_path_separator_s.used + name.used + 1, sizeof(f_char_t), (void **) &recurse->path.string, &recurse->path.used, &recurse->path.size); + + if (F_status_is_error_not(recurse->state.status)) { + recurse->state.status = f_string_dynamic_append_assure(f_path_separator_s, &recurse->path); + } + + if (F_status_is_error_not(recurse->state.status)) { + recurse->state.status = f_string_dynamic_append_nulless(name, &recurse->path); + } + + // Guarantee NULL termination. + recurse->path.string[recurse->path.used] = 0; - if (F_status_is_error(recurse->state.status)) break; + if (F_status_is_error(recurse->state.status)) { + private_inline_fl_directory_do_handle(recurse, name, f_directory_recurse_do_flag_path_d); + } + + if (F_status_is_error(recurse->state.status) || F_status_set_fine(recurse->state.status) == F_interrupt) break; if (recurse->state.status == F_break || recurse->state.status == F_done) break; if (recurse->state.status == F_continue) continue; - } - for (action = 0; action < 3; ++action) { + for (action = 0; action < 3; ++action) { - if (recurse->state.interrupt) { - recurse->state.interrupt((void *) &recurse->state, (void *) recurse); - if (F_status_set_fine(recurse->state.status) == F_interrupt) break; - } + if (recurse->state.interrupt) { + recurse->state.interrupt((void *) &recurse->state, (void *) recurse); + if (F_status_set_fine(recurse->state.status) == F_interrupt) break; + } - if (flag_actions[action]) { - if ((flag & f_directory_recurse_do_flag_directory_d) && (flag_actions[action] & f_directory_recurse_do_flag_action_d)) { + // Support F_skip for skipping the next action. + if (recurse->state.status == F_skip) { recurse->state.status = F_okay; - used_directory = recurse->path.used; - if (recurse->depth < recurse->depth_max) { - ++recurse->depth; + continue; + } - private_fl_directory_do_recurse(recurse); + if (flag_actions[action]) { + if ((flag & f_directory_recurse_do_flag_directory_d) && (flag_actions[action] & f_directory_recurse_do_flag_action_d)) { + recurse->state.status = F_okay; + used_directory = recurse->path.used; - --recurse->depth; - } + if (recurse->depth < recurse->depth_max) { + ++recurse->depth; - if (F_status_is_error(recurse->state.status)) { - private_inline_fl_directory_do_handle(recurse, name, flag_actions[action] | flag); - if (F_status_is_error(recurse->state.status)) break; - } + private_fl_directory_do_recurse(recurse); - // Reset the path after operating on child directories. - recurse->path.used = used_directory; - recurse->path.string[recurse->path.used] = 0; - - // 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 || F_status_set_fine(recurse->state.status) == F_interrupt) break; - } + --recurse->depth; + } - if (flag_actions[action] != f_directory_recurse_do_flag_action_d || recurse->flag & f_directory_recurse_do_flag_action_d) { - recurse->state.status = F_okay; + if (F_status_is_error(recurse->state.status)) { + private_inline_fl_directory_do_handle(recurse, name, flag_actions[action] | flag); + } - recurse->action(recurse, name, flag_actions[action] | flag); + // Reset the path after operating on child directories. + recurse->path.used = used_directory; + recurse->path.string[recurse->path.used] = 0; - if (F_status_is_error(recurse->state.status)) { - private_inline_fl_directory_do_handle(recurse, name, flag_actions[action] | flag); - if (F_status_is_error(recurse->state.status)) break; + if (F_status_is_error(recurse->state.status) || F_status_set_fine(recurse->state.status) == F_interrupt) break; + if (recurse->state.status == F_break || recurse->state.status == F_done || recurse->state.status == F_continue) break; } - // 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 || F_status_set_fine(recurse->state.status) == F_interrupt) break; + if (flag_actions[action] != f_directory_recurse_do_flag_action_d || recurse->flag & f_directory_recurse_do_flag_action_d) { + recurse->state.status = F_okay; + + recurse->action(recurse, name, flag_actions[action] | flag); + + if (F_status_is_error(recurse->state.status)) { + private_inline_fl_directory_do_handle(recurse, name, flag_actions[action] | flag); + } + + if (F_status_is_error(recurse->state.status) || F_status_set_fine(recurse->state.status) == F_interrupt) break; + if (recurse->state.status == F_break || recurse->state.status == F_done || recurse->state.status == F_continue) break; + } } - } - } // for + } // for - if (F_status_is_error(recurse->state.status) || recurse->state.status == F_break || recurse->state.status == F_done) break; - if (recurse->state.status == F_continue) continue; - } // for + if (F_status_is_error(recurse->state.status) || F_status_set_fine(recurse->state.status) == F_interrupt || recurse->state.status == F_break || recurse->state.status == F_done) break; + if (recurse->state.status == F_continue) continue; + } // for + } { const f_status_t status_original = recurse->state.status; @@ -176,16 +188,18 @@ extern "C" { if (F_status_is_error(recurse->state.status)) { 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 (F_status_is_error(status_original) || F_status_set_fine(status_original) == F_interrupt || status_original == F_break || status_original == F_continue || status_original == F_done) { + recurse->state.status = status_original; + } + else if (F_status_is_error_not(recurse->state.status)) { + recurse->state.status = status_original; if (recurse->state.status != F_done) { recurse->state.status = F_okay; } } - - if (F_status_is_error(status_original) || F_status_is_error_not(recurse->state.status)) { - recurse->state.status = status_original; - } } recurse->path.used = used_original;