From ae37b7db1ca55d44d3e38c220fea6613d0873f97 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Sat, 16 May 2020 22:42:49 -0500 Subject: [PATCH] Update: add path expode using normal order Oops. For reasons unknown to me, I seem to have written the path explode in reverse order. The path is intended to be processed from left to right. Rename the old functions appending _reverse to their name. --- level_0/f_path/c/path.c | 237 ++++++++++++++++++++++++++++++++++++++++++++---- level_0/f_path/c/path.h | 52 +++++++++++ 2 files changed, 272 insertions(+), 17 deletions(-) diff --git a/level_0/f_path/c/path.c b/level_0/f_path/c/path.c index c5aae1c..6b2e988 100644 --- a/level_0/f_path/c/path.c +++ b/level_0/f_path/c/path.c @@ -15,8 +15,207 @@ extern "C" { const f_string_length length = strnlen(path, PATH_MAX); if (length == 0) { - // When PATH is "", this is actually a valid search path for CWD. - // Therefore append an equivalent representation of CWD (string used length is 0). + // When PATH is "", this is actually a valid search path for PWD. + // Therefore append an equivalent representation of PWD (string used length is 0). + if (paths->used + 1 > paths->size) { + if (paths->size + f_memory_default_allocation_step > f_array_length_size) { + if (paths->size + 1 > f_array_length_size) { + return f_status_set_error(f_buffer_too_large); + } + + f_macro_string_dynamics_resize(status, (*paths), paths->used + 1); + if (f_status_is_error(status)) return status; + } + else { + f_macro_string_dynamics_resize(status, (*paths), paths->used + f_memory_default_allocation_step); + if (f_status_is_error(status)) return status; + } + } + + f_macro_string_dynamic_clear(paths->array[paths->used]); + paths->used++; + + return f_none; + } + + f_string_length i = length; + f_string_length first = 0; + f_string_length total = 0; + + for (i = 0; i <= length; i++) { + if (i == length || path[i] == f_path_separator_variable[0]) { + if (paths->used + 1 > paths->size) { + if (paths->size + f_memory_default_allocation_step > f_array_length_size) { + if (paths->size + 1 > f_array_length_size) { + return f_status_set_error(f_buffer_too_large); + } + + f_macro_string_dynamics_resize(status, (*paths), paths->used + 1); + if (f_status_is_error(status)) return status; + } + else { + f_macro_string_dynamics_resize(status, (*paths), paths->used + f_memory_default_allocation_step); + if (f_status_is_error(status)) return status; + } + } + + if (i == 0) { + f_macro_string_dynamic_clear(paths->array[paths->used]); + paths->used++; + + first = 1; + continue; + } + + f_string_dynamic part = f_string_dynamic_initialize; + + total = i - first; + + if (total > 0) { + if (path[i - 1] == f_path_separator[0]) { + f_macro_string_dynamic_new(status, part, total); + if (f_status_is_error(status)) return status; + + part.used = total; + } + else { + f_macro_string_dynamic_new(status, part, total + 1); + if (f_status_is_error(status)) return status; + + part.string[total] = f_path_separator[0]; + part.used = total + 1; + } + + memcpy(part.string, path + first, total); + } + + paths->array[paths->used].string = part.string; + paths->array[paths->used].used = part.used; + paths->array[paths->used].size = part.size; + paths->used++; + + first = i + 1; + } + } // for + + return f_none; + } +#endif // _di_f_path_explode_ + +#ifndef _di_f_path_explode_dynamic_ + f_return_status f_path_explode_dynamic(const f_string_static path, f_string_dynamics *paths) { + #ifndef _di_level_0_parameter_checking_ + if (path.used > path.size) return f_status_set_error(f_invalid_parameter); + if (paths == 0) return f_status_set_error(f_invalid_parameter); + if (paths->used > paths->size) return f_status_set_error(f_invalid_parameter); + #endif // _di_level_0_parameter_checking_ + + f_status status = f_none; + + if (path.used == 0) { + // When PATH is "", this is actually a valid search path for PWD. + // Therefore append an equivalent representation of PWD (string used length is 0). + if (paths->used + 1 > paths->size) { + if (paths->size + f_memory_default_allocation_step > f_array_length_size) { + if (paths->size + 1 > f_array_length_size) { + return f_status_set_error(f_buffer_too_large); + } + + f_macro_string_dynamics_resize(status, (*paths), paths->used + 1); + if (f_status_is_error(status)) return status; + } + else { + f_macro_string_dynamics_resize(status, (*paths), paths->used + f_memory_default_allocation_step); + if (f_status_is_error(status)) return status; + } + } + + f_macro_string_dynamic_clear(paths->array[paths->used]); + paths->used++; + + return f_none; + } + + f_string_length i = 0; + f_string_length j = 0; + f_string_length first = 0; + f_string_length total = 0; + + f_string_dynamic part = f_string_dynamic_initialize; + + for (i = 0; i <= path.used; i++) { + if (i == path.used || path.string[i] == f_path_separator_variable[0]) { + if (paths->used + 1 > paths->size) { + if (paths->size + f_memory_default_allocation_step > f_array_length_size) { + if (paths->size + 1 > f_array_length_size) { + return f_status_set_error(f_buffer_too_large); + } + + f_macro_string_dynamics_resize(status, (*paths), paths->used + 1); + if (f_status_is_error(status)) return status; + } + else { + f_macro_string_dynamics_resize(status, (*paths), paths->used + f_memory_default_allocation_step); + if (f_status_is_error(status)) return status; + } + } + + if (i == 0) { + f_macro_string_dynamic_clear(paths->array[paths->used]); + paths->used++; + + first = 1; + continue; + } + + total = i - first; + + if (total > 0) { + f_macro_string_dynamic_new(status, part, total); + if (f_status_is_error(status)) return status; + + for (j = 0; j < total; j++) { + if (path.string[first + j] == 0) continue; + + part.string[part.used] = path.string[first + j]; + part.used++; + } // for + + if (part.string[part.used - 1] != f_path_separator[0]) { + f_macro_string_dynamic_resize(status, part, total + 1); + if (f_status_is_error(status)) return status; + + part.string[part.used] = f_path_separator[0]; + part.used++; + } + } + + paths->array[paths->used].string = part.string; + paths->array[paths->used].used = part.used; + paths->array[paths->used].size = part.size; + paths->used++; + + first = i + 1; + } + } // for + + return f_none; + } +#endif // _di_f_path_explode_dynamic_ + +#ifndef _di_f_path_explode_reverse_ + f_return_status f_path_explode_reverse(const f_string path, f_string_dynamics *paths) { + #ifndef _di_level_0_parameter_checking_ + if (paths == 0) return f_status_set_error(f_invalid_parameter); + if (paths->used > paths->size) return f_status_set_error(f_invalid_parameter); + #endif // _di_level_0_parameter_checking_ + + f_status status = f_none; + const f_string_length length = strnlen(path, PATH_MAX); + + if (length == 0) { + // When PATH is "", this is actually a valid search path for PWD. + // Therefore append an equivalent representation of PWD (string used length is 0). if (paths->used + 1 > paths->size) { if (paths->size + f_memory_default_allocation_step > f_array_length_size) { if (paths->size + 1 > f_array_length_size) { @@ -45,6 +244,8 @@ extern "C" { f_string_length last = length; f_string_length total = 0; + f_string_dynamic part = f_string_dynamic_initialize; + for (; i > 0; i--) { j--; @@ -64,8 +265,6 @@ extern "C" { } } - f_string_dynamic part = f_string_dynamic_initialize; - if (path[j] == f_path_separator_variable[0]) { total = last - i; @@ -121,10 +320,10 @@ extern "C" { return f_none; } -#endif // _di_f_path_explode_ +#endif // _di_f_path_explode_reverse_ -#ifndef _di_f_path_explode_dynamic_ - f_return_status f_path_explode_dynamic(const f_string_static path, f_string_dynamics *paths) { +#ifndef _di_f_path_explode_reverse_dynamic_ + f_return_status f_path_explode_reverse_dynamic(const f_string_static path, f_string_dynamics *paths) { #ifndef _di_level_0_parameter_checking_ if (path.used > path.size) return f_status_set_error(f_invalid_parameter); if (paths == 0) return f_status_set_error(f_invalid_parameter); @@ -134,8 +333,8 @@ extern "C" { f_status status = f_none; if (path.used == 0) { - // When PATH is "", this is actually a valid search path for CWD. - // Therefore append an equivalent representation of CWD (string used length is 0). + // When PATH is "", this is actually a valid search path for PWD. + // Therefore append an equivalent representation of PWD (string used length is 0). if (paths->used + 1 > paths->size) { if (paths->size + f_memory_default_allocation_step > f_array_length_size) { if (paths->size + 1 > f_array_length_size) { @@ -151,9 +350,7 @@ extern "C" { } } - paths->array[paths->used].string = 0; - paths->array[paths->used].used = 0; - paths->array[paths->used].size = 0; + f_macro_string_dynamic_clear(paths->array[paths->used]); paths->used++; return f_none; @@ -165,6 +362,8 @@ extern "C" { f_string_length last = path.used; f_string_length total = 0; + f_string_dynamic part = f_string_dynamic_initialize; + for (; i > 0; i--) { j--; @@ -184,13 +383,11 @@ extern "C" { } } - f_string_dynamic part = f_string_dynamic_initialize; - if (path.string[j] == f_path_separator_variable[0]) { total = last - i; if (total > 0) { - f_macro_string_dynamic_new(status, part, total + 1); + f_macro_string_dynamic_new(status, part, total); if (f_status_is_error(status)) return status; for (k = 0; k < total; k++) { @@ -201,6 +398,9 @@ extern "C" { } // for if (part.string[part.used - 1] != f_path_separator[0]) { + f_macro_string_dynamic_resize(status, part, total + 1); + if (f_status_is_error(status)) return status; + part.string[part.used] = f_path_separator[0]; part.used++; } @@ -212,7 +412,7 @@ extern "C" { // when j = 0, the total is actually the entire length to max. total = last - j; - f_macro_string_dynamic_new(status, part, total + 1); + f_macro_string_dynamic_new(status, part, total); if (f_status_is_error(status)) return status; for (k = 0; k < total; k++) { @@ -223,6 +423,9 @@ extern "C" { } // for if (part.string[part.used - 1] != f_path_separator[0]) { + f_macro_string_dynamic_resize(status, part, total + 1); + if (f_status_is_error(status)) return status; + part.string[part.used - 1] = f_path_separator[0]; part.used++; } @@ -237,7 +440,7 @@ extern "C" { return f_none; } -#endif // _di_f_path_explode_dynamic_ +#endif // _di_f_path_explode_reverse_dynamic_ #ifdef __cplusplus } // extern "C" diff --git a/level_0/f_path/c/path.h b/level_0/f_path/c/path.h index 149a91a..481c8f5 100644 --- a/level_0/f_path/c/path.h +++ b/level_0/f_path/c/path.h @@ -100,6 +100,58 @@ extern "C" { extern f_return_status f_path_explode_dynamic(const f_string_static path, f_string_dynamics *paths); #endif // _di_f_path_explode_dynamic_ +/** + * Separate a given PATH-style string into multiple separate paths. + * + * The paths are created in reverse order. + * + * @param path + * The string to process that is expected to follow the traditional Linux standard PATH environment variable. + * Each seperate path is separated by a single ':'. + * Must not contain NULLs except for the terminating NULL. + * Must be NULL terminated. + * @param paths + * All of the strings exploded from PATH. + * Each exploded path, when not empty, is guaranteed to have a trailing '/'. + * Each exploded path is not NULL terminated. + * + * @return + * f_none on success. + * f_invalid_parameter (with error bit) if a parameter is invalid. + * f_error_reallocation (with error bit) on reallocation error. + * f_error_allocation (with error bit) on allocation error. + * f_buffer_too_large (with error bit) if paths array is too large for further addressing. + */ +#ifndef _di_f_path_explode_reverse_ + extern f_return_status f_path_explode_reverse(const f_string path, f_string_dynamics *paths); +#endif // _di_f_path_explode_reverse_ + +/** + * Separate a given PATH-style string into multiple separate paths. + * + * The paths are created in reverse order. + * + * @param path + * The string to process that is expected to follow the traditional Linux standard PATH environment variable. + * Each seperate path is separated by a single ':'. + * Need not be NULL terminated. + * NULLs are ignored and are not copied into the exploded paths. + * @param paths + * All of the strings exploded from PATH. + * Each exploded path, when not empty, is guaranteed to have a trailing '/'. + * Each exploded path is not NULL terminated. + * + * @return + * f_none on success. + * f_invalid_parameter (with error bit) if a parameter is invalid. + * f_error_reallocation (with error bit) on reallocation error. + * f_error_allocation (with error bit) on allocation error. + * f_buffer_too_large (with error bit) if paths array is too large for further addressing. + */ +#ifndef _di_f_path_explode_reverse_dynamic_ + extern f_return_status f_path_explode_reverse_dynamic(const f_string_static path, f_string_dynamics *paths); +#endif // _di_f_path_explode_reverse_dynamic_ + #ifdef __cplusplus } // extern "C" #endif -- 1.8.3.1