From 260e27500fc562ffeca4adcef9777765ff27d765 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Sun, 26 Apr 2020 17:12:27 -0500 Subject: [PATCH] Feature: add fl_console_parameter_to_string_dynamic_directory to fl_console Provide a console argument handler for parsing out a directory path and returning it in a dynamic string. --- level_1/fl_console/c/console.c | 151 +++++++++++++++++++++++++++++++++ level_1/fl_console/c/console.h | 35 +++++++- level_1/fl_console/data/build/settings | 2 +- 3 files changed, 185 insertions(+), 3 deletions(-) diff --git a/level_1/fl_console/c/console.c b/level_1/fl_console/c/console.c index 9037ab9..3fdcac4 100644 --- a/level_1/fl_console/c/console.c +++ b/level_1/fl_console/c/console.c @@ -4,6 +4,157 @@ extern "C" { #endif +#ifndef _fl_console_parameter_to_string_dynamic_directory_ + f_return_status fl_console_parameter_to_string_dynamic_directory(const f_string argument, f_string_dynamic *directory) { + f_status status = f_none; + f_string_length length = strlen(argument); + + if (length == 0) { + directory->used = 0; + return f_none; + } + + if (length > 1) { + while (length > 1 && argument[length - 1] == '/') { + length--; + } // while + + if (argument[0] == '/') { + f_string_length begin = 1; + + while (begin < length && argument[begin] == '/') { + begin++; + } // while + + length -= begin; + + if (length > 0) { + length += 2; + + f_macro_string_dynamic_new(status, (*directory), length); + if (f_status_is_error(status)) return status; + + memcpy(directory->string + 1, argument + begin, length - 2); + + directory->used = length; + directory->size = length; + directory->string[0] = '/'; + directory->string[length - 1] = '/'; + } + else { + f_macro_string_dynamic_new(status, (*directory), 1); + if (f_status_is_error(status)) return status; + + directory->used = 1; + directory->size = 1; + directory->string[0] = '/'; + } + } + else if (length > 3 && argument[0] == '.' && argument[1] == '.' && argument[2] == '/') { + f_string_length begin = 3; + + while (begin < length && argument[begin] == '/') { + begin++; + } // while + + length -= begin; + + if (length > 0) { + length += 4; + + f_macro_string_dynamic_new(status, (*directory), length); + if (f_status_is_error(status)) return status; + + memcpy(directory->string + 3, argument + begin, length - 4); + + directory->used = length; + directory->size = length; + directory->string[0] = '.'; + directory->string[1] = '.'; + directory->string[2] = '/'; + directory->string[length - 1] = '/'; + } + else { + f_macro_string_dynamic_new(status, (*directory), 3); + if (f_status_is_error(status)) return status; + + directory->used = 3; + directory->size = 3; + directory->string[0] = '.'; + directory->string[1] = '.'; + directory->string[2] = '/'; + } + } + else if (length > 2 && argument[0] == '.' && argument[1] == '/') { + f_string_length begin = 2; + + while (begin < length && argument[begin] == '/') { + begin++; + } // while + + length -= begin; + + if (length > 0) { + length += 3; + + f_macro_string_dynamic_new(status, (*directory), length); + if (f_status_is_error(status)) return status; + + memcpy(directory->string + 2, argument + begin, length - 3); + + directory->used = length; + directory->size = length; + directory->string[0] = '.'; + directory->string[1] = '/'; + directory->string[length - 1] = '/'; + } + else { + f_macro_string_dynamic_new(status, (*directory), 2); + if (f_status_is_error(status)) return status; + + directory->used = 2; + directory->size = 2; + directory->string[0] = '.'; + directory->string[1] = '/'; + } + } + else { + length++; + + f_macro_string_dynamic_new(status, (*directory), length); + if (f_status_is_error(status)) return status; + + memcpy(directory->string, argument, length - 1); + + directory->used = length; + directory->size = length; + directory->string[length - 1] = '/'; + } + } + else if (argument[0] != '/') { + f_macro_string_dynamic_new(status, (*directory), 2); + if (f_status_is_error(status)) return status; + + memcpy(directory->string, argument, 2); + + directory->used = 2; + directory->size = 2; + directory->string[1] = '/'; + } + else { + f_macro_string_dynamic_new(status, (*directory), 1); + if (f_status_is_error(status)) return status; + + memcpy(directory->string, argument, 1); + + directory->used = 1; + directory->size = 1; + } + + return f_none; + } +#endif // _fl_console_parameter_to_string_dynamic_directory_ + #ifndef _fl_console_parameter_to_number_signed_ f_return_status fl_console_parameter_to_number_signed(const f_string argument, f_number_signed *number) { #ifndef _di_level_0_parameter_checking_ diff --git a/level_1/fl_console/c/console.h b/level_1/fl_console/c/console.h index 20eb871..57aac4f 100644 --- a/level_1/fl_console/c/console.h +++ b/level_1/fl_console/c/console.h @@ -13,6 +13,7 @@ // libc include #include #include +#include // fll-0 includes #include @@ -27,6 +28,36 @@ extern "C" { #endif /** + * Validate and convert a console parameter additional argument to a file directory in a dynamic string. + * + * The directory path is validated to exist. + * + * The path to a directy has the following very basic cleanup operations performed: + * - Ensures that it always ends in a '/'. + * - Ensures that multiple '/' in front or multiple '/' at end of string is reduced to a single '/' in front and a single '/' at end. + * - Ensures that multiple '/' following './' at the start of the string is reduced to only './' ('.////' would become './'). + * - Ensures that multiple '/' following '../' at the start of the string is reduced to only '../' ('..////' would become '../'). + * + * This does not perform complex cleanup, such as '..///..///' to '../../'. + * + * The purpose of the cleanups is to ensure/enforce a consistent beginning and ending of the path strings. + * These path strings can then, very simply, be checked to see how to join them with another string, such as a filename. + * + * @param argv + * The argument string expected to be a number. + * This is generally passed from the argv[]. + * @param directory + * The dynamically allocated processed directory string. + * + * @return + * f_none on success. + * f_error_allocation (with error bit) on allocation error. + */ +#ifndef _fl_console_parameter_to_string_dynamic_directory_ + extern f_return_status fl_console_parameter_to_string_dynamic_directory(const f_string argument, f_string_dynamic *directory); +#endif // _fl_console_parameter_to_string_dynamic_directory_ + +/** * Convert a console parameter additional argument to a signed integer. * * This will detect based types as follows: @@ -58,7 +89,7 @@ extern "C" { * @see f_conversion_string_to_number_signed() */ #ifndef _fl_console_parameter_to_number_signed_ - f_return_status fl_console_parameter_to_number_signed(const f_string argument, f_number_signed *number); + extern f_return_status fl_console_parameter_to_number_signed(const f_string argument, f_number_signed *number); #endif // _fl_console_parameter_to_number_signed_ /** @@ -93,7 +124,7 @@ extern "C" { * @see f_conversion_string_to_number_unsigned() */ #ifndef _fl_console_parameter_to_number_unsigned_ - f_return_status fl_console_parameter_to_number_unsigned(const f_string argument, f_number_unsigned *number); + extern f_return_status fl_console_parameter_to_number_unsigned(const f_string argument, f_number_unsigned *number); #endif // _fl_console_parameter_to_number_unsigned_ #ifdef __cplusplus diff --git a/level_1/fl_console/data/build/settings b/level_1/fl_console/data/build/settings index 1914c68..d889225 100644 --- a/level_1/fl_console/data/build/settings +++ b/level_1/fl_console/data/build/settings @@ -10,7 +10,7 @@ version_micro 0 build_compiler gcc build_linker ar build_libraries -lc -build_libraries_fll -lf_utf -lf_console -lf_conversion -lf_memory +build_libraries_fll -lf_console -lf_conversion -lf_memory -lf_utf build_sources_library console.c build_sources_program build_sources_headers console.h -- 1.8.3.1