From 945a3717193d6bc5c04e7c13e42770209a511b3a Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Thu, 12 Jan 2023 21:19:00 -0600 Subject: [PATCH] Progress: Continue working on remove program. Significant development towards completing date and time related checks. This is not yet complete. Fix existence test mistake, do not treat the file not found error as an error during simulation. The settings loading has several loops. Redesign the main function to start the thread. The settings loading now checks in some of its loops for an interrupt signal. --- sources/c/remove/main/common-print.c | 5 +- sources/c/remove/main/common-print.h | 5 +- sources/c/remove/main/common.c | 36 ++- sources/c/remove/main/common.h | 297 ++++++++++++++++----- sources/c/remove/main/convert.c | 486 +++++++++++++++++++++-------------- sources/c/remove/main/convert.h | 73 ++++-- sources/c/remove/main/main.c | 27 +- sources/c/remove/main/print.c | 21 +- sources/c/remove/main/remove.c | 8 - sources/c/remove/main/simulate.c | 203 ++++++++++++--- 10 files changed, 831 insertions(+), 330 deletions(-) diff --git a/sources/c/remove/main/common-print.c b/sources/c/remove/main/common-print.c index bb5295d..7d9a60b 100644 --- a/sources/c/remove/main/common-print.c +++ b/sources/c/remove/main/common-print.c @@ -15,11 +15,14 @@ extern "C" { "f_uint32s_increase_by", "f_utf_is_whitespace", "fl_conversion_dynamic_partial_to_unsigned_detect", + "fl_conversion_dynamic_to_unsigned_detect", "fll_program_parameter_process_empty", + "kt_remove_convert_date_relative", + "kt_remove_convert_timezone", "kt_remove_dates_resize", - "kt_remove_modes_resize", "kt_remove_get_id_group", "kt_remove_get_id_user", + "kt_remove_modes_resize", }; #endif // _di_kt_remove_f_a_ diff --git a/sources/c/remove/main/common-print.h b/sources/c/remove/main/common-print.h index 33d295d..38ee95a 100644 --- a/sources/c/remove/main/common-print.h +++ b/sources/c/remove/main/common-print.h @@ -48,11 +48,14 @@ extern "C" { kt_remove_f_f_utf_is_digit_e, kt_remove_f_f_utf_is_whitespace_e, kt_remove_f_fl_conversion_dynamic_partial_to_unsigned_detect_e, + kt_remove_f_fl_conversion_dynamic_to_unsigned_detect_e, kt_remove_f_fll_program_parameter_process_empty_e, + kt_remove_f_kt_remove_convert_date_relative_e, + kt_remove_f_kt_remove_convert_timezone_e, kt_remove_f_kt_remove_dates_resize_e, - kt_remove_f_kt_remove_modes_resize_e, kt_remove_f_kt_remove_get_id_group_e, kt_remove_f_kt_remove_get_id_user_e, + kt_remove_f_kt_remove_modes_resize_e, }; // enum #endif // _di_kt_remove_f_e_ diff --git a/sources/c/remove/main/common.c b/sources/c/remove/main/common.c index fb659b4..ebd6be8 100644 --- a/sources/c/remove/main/common.c +++ b/sources/c/remove/main/common.c @@ -18,6 +18,38 @@ extern "C" { #endif // _di_utf8_program_help_parameters_s_ #ifndef _di_kt_remove_date_s_ + const f_string_static_t kt_remove_date_format_00_s = macro_f_string_static_t_initialize(KT_REMOVE_date_format_00_s, 0, KT_REMOVE_date_format_00_s_length); + const f_string_static_t kt_remove_date_format_01_s = macro_f_string_static_t_initialize(KT_REMOVE_date_format_01_s, 0, KT_REMOVE_date_format_01_s_length); + const f_string_static_t kt_remove_date_format_02_s = macro_f_string_static_t_initialize(KT_REMOVE_date_format_02_s, 0, KT_REMOVE_date_format_02_s_length); + const f_string_static_t kt_remove_date_format_03_s = macro_f_string_static_t_initialize(KT_REMOVE_date_format_03_s, 0, KT_REMOVE_date_format_03_s_length); + const f_string_static_t kt_remove_date_format_04_s = macro_f_string_static_t_initialize(KT_REMOVE_date_format_04_s, 0, KT_REMOVE_date_format_04_s_length); + const f_string_static_t kt_remove_date_format_05_s = macro_f_string_static_t_initialize(KT_REMOVE_date_format_05_s, 0, KT_REMOVE_date_format_05_s_length); + const f_string_static_t kt_remove_date_format_06_s = macro_f_string_static_t_initialize(KT_REMOVE_date_format_06_s, 0, KT_REMOVE_date_format_06_s_length); + const f_string_static_t kt_remove_date_format_07_s = macro_f_string_static_t_initialize(KT_REMOVE_date_format_07_s, 0, KT_REMOVE_date_format_07_s_length); + const f_string_static_t kt_remove_date_format_08_s = macro_f_string_static_t_initialize(KT_REMOVE_date_format_08_s, 0, KT_REMOVE_date_format_08_s_length); + const f_string_static_t kt_remove_date_format_09_s = macro_f_string_static_t_initialize(KT_REMOVE_date_format_09_s, 0, KT_REMOVE_date_format_09_s_length); + const f_string_static_t kt_remove_date_format_10_s = macro_f_string_static_t_initialize(KT_REMOVE_date_format_10_s, 0, KT_REMOVE_date_format_10_s_length); + const f_string_static_t kt_remove_date_format_11_s = macro_f_string_static_t_initialize(KT_REMOVE_date_format_11_s, 0, KT_REMOVE_date_format_11_s_length); + const f_string_static_t kt_remove_date_format_12_s = macro_f_string_static_t_initialize(KT_REMOVE_date_format_12_s, 0, KT_REMOVE_date_format_12_s_length); + const f_string_static_t kt_remove_date_format_13_s = macro_f_string_static_t_initialize(KT_REMOVE_date_format_13_s, 0, KT_REMOVE_date_format_13_s_length); + const f_string_static_t kt_remove_date_format_14_s = macro_f_string_static_t_initialize(KT_REMOVE_date_format_14_s, 0, KT_REMOVE_date_format_14_s_length); + + const f_string_static_t kt_remove_date_format_example_00_s = macro_f_string_static_t_initialize(KT_REMOVE_date_format_example_00_s, 0, KT_REMOVE_date_format_example_00_s_length); + const f_string_static_t kt_remove_date_format_example_01_s = macro_f_string_static_t_initialize(KT_REMOVE_date_format_example_01_s, 0, KT_REMOVE_date_format_example_01_s_length); + const f_string_static_t kt_remove_date_format_example_02_s = macro_f_string_static_t_initialize(KT_REMOVE_date_format_example_02_s, 0, KT_REMOVE_date_format_example_02_s_length); + const f_string_static_t kt_remove_date_format_example_03_s = macro_f_string_static_t_initialize(KT_REMOVE_date_format_example_03_s, 0, KT_REMOVE_date_format_example_03_s_length); + const f_string_static_t kt_remove_date_format_example_04_s = macro_f_string_static_t_initialize(KT_REMOVE_date_format_example_04_s, 0, KT_REMOVE_date_format_example_04_s_length); + const f_string_static_t kt_remove_date_format_example_05_s = macro_f_string_static_t_initialize(KT_REMOVE_date_format_example_05_s, 0, KT_REMOVE_date_format_example_05_s_length); + const f_string_static_t kt_remove_date_format_example_06_s = macro_f_string_static_t_initialize(KT_REMOVE_date_format_example_06_s, 0, KT_REMOVE_date_format_example_06_s_length); + const f_string_static_t kt_remove_date_format_example_07_s = macro_f_string_static_t_initialize(KT_REMOVE_date_format_example_07_s, 0, KT_REMOVE_date_format_example_07_s_length); + const f_string_static_t kt_remove_date_format_example_08_s = macro_f_string_static_t_initialize(KT_REMOVE_date_format_example_08_s, 0, KT_REMOVE_date_format_example_08_s_length); + const f_string_static_t kt_remove_date_format_example_09_s = macro_f_string_static_t_initialize(KT_REMOVE_date_format_example_09_s, 0, KT_REMOVE_date_format_example_09_s_length); + const f_string_static_t kt_remove_date_format_example_10_s = macro_f_string_static_t_initialize(KT_REMOVE_date_format_example_10_s, 0, KT_REMOVE_date_format_example_10_s_length); + const f_string_static_t kt_remove_date_format_example_11_s = macro_f_string_static_t_initialize(KT_REMOVE_date_format_example_11_s, 0, KT_REMOVE_date_format_example_11_s_length); + const f_string_static_t kt_remove_date_format_example_12_s = macro_f_string_static_t_initialize(KT_REMOVE_date_format_example_12_s, 0, KT_REMOVE_date_format_example_12_s_length); + const f_string_static_t kt_remove_date_format_example_13_s = macro_f_string_static_t_initialize(KT_REMOVE_date_format_example_13_s, 0, KT_REMOVE_date_format_example_13_s_length); + const f_string_static_t kt_remove_date_format_example_14_s = macro_f_string_static_t_initialize(KT_REMOVE_date_format_example_14_s, 0, KT_REMOVE_date_format_example_14_s_length); + const f_string_static_t kt_remove_date_symbol_equal_s = macro_f_string_static_t_initialize(KT_REMOVE_date_symbol_equal_s, 0, KT_REMOVE_date_symbol_equal_s_length); const f_string_static_t kt_remove_date_symbol_less_s = macro_f_string_static_t_initialize(KT_REMOVE_date_symbol_less_s, 0, KT_REMOVE_date_symbol_less_s_length); const f_string_static_t kt_remove_date_symbol_less_equal_s = macro_f_string_static_t_initialize(KT_REMOVE_date_symbol_less_equal_s, 0, KT_REMOVE_date_symbol_less_equal_s_length); @@ -491,13 +523,15 @@ extern "C" { index2 = parameters[p]->values.array[i + 1]; - kt_remove_get_date(main, setting, main->parameters.arguments.array[index2], &dates[p]->array[dates[p]->used].type); + kt_remove_convert_date(main, setting, main->parameters.arguments.array[index2], &dates[p]->array[dates[p]->used]); if (F_status_is_error(setting->status)) return; ++dates[p]->used; break; } + + if (kt_remove_signal_check(main)) return; } // for if (j == 12) { diff --git a/sources/c/remove/main/common.h b/sources/c/remove/main/common.h index d5d55bd..b8f9aa7 100644 --- a/sources/c/remove/main/common.h +++ b/sources/c/remove/main/common.h @@ -118,8 +118,137 @@ extern "C" { /** * Strings associated with the date parameters. + * + * kt_remove_date_format_*_s: + * - 00: The string "YYYY/MM/DD hh:ii:ss a +0000". + * - 01: The string "YYYY/MM/DD HH:ii:ss +0000". + * - 02: The string "YYYY/MM/DD hh:ii a +0000". + * - 03: The string "YYYY/MM/DD HH:ii +0000". + * - 04: The string "YYYY/MM/DD hh a +0000". + * - 05: The string "YYYY/MM/DD HH +0000". + * - 06: The string "YYYY/MM/DD hh:ii:ss a". + * - 07: The string "YYYY/MM/DD HH:ii:ss". + * - 08: The string "YYYY/MM/DD hh:ii a". + * - 09: The string "YYYY/MM/DD HH:ii". + * - 10: The string "YYYY/MM/DD hh a". + * - 11: The string "YYYY/MM/DD HH". + * - 12: The string "YYYY/MM/DD". + * - 13: The string "YYYY/MM". + * - 14: The string "YYYY/". + * + * kt_remove_date_symbol_*_s: + * - equal: Equal to operator. + * - less: Less than operator. + * - less_equal: Less than or equal to operator. + * - more: Greater than operator. + * - more_equal: Greater than or equal to operator. + * - not: Not equal to operator. + * + * kt_remove_date_word_*_s: + * - equal: Equal to words. + * - less: Less than words. + * - less_equal: Less than or equal to words. + * - more: Greater than words. + * - more_equal: Greater than or equal to words. + * - not: Not equal to words. */ #ifndef _di_kt_remove_date_s_ + #define KT_REMOVE_date_format_00_s "%Y/%m/%d %I:%M:%S %p %z" + #define KT_REMOVE_date_format_01_s "%Y/%m/%d %H:%M:%S %z" + #define KT_REMOVE_date_format_02_s "%Y/%m/%d %I:%M %p %z" + #define KT_REMOVE_date_format_03_s "%Y/%m/%d %H:%M %z" + #define KT_REMOVE_date_format_04_s "%Y/%m/%d %I %p %z" + #define KT_REMOVE_date_format_05_s "%Y/%m/%d %H %z" + #define KT_REMOVE_date_format_06_s "%Y/%m/%d %I:%M:%S %p" + #define KT_REMOVE_date_format_07_s "%Y/%m/%d %H:%M:%S" + #define KT_REMOVE_date_format_08_s "%Y/%m/%d %I:%M %p" + #define KT_REMOVE_date_format_09_s "%Y/%m/%d %H:%M" + #define KT_REMOVE_date_format_10_s "%Y/%m/%d %I %p" + #define KT_REMOVE_date_format_11_s "%Y/%m/%d %H" + #define KT_REMOVE_date_format_12_s "%Y/%m/%d" + #define KT_REMOVE_date_format_13_s "%Y/%m" + #define KT_REMOVE_date_format_14_s "%Y/" + + #define KT_REMOVE_date_format_00_s_length 23 + #define KT_REMOVE_date_format_01_s_length 20 + #define KT_REMOVE_date_format_02_s_length 20 + #define KT_REMOVE_date_format_03_s_length 17 + #define KT_REMOVE_date_format_04_s_length 17 + #define KT_REMOVE_date_format_05_s_length 14 + #define KT_REMOVE_date_format_06_s_length 20 + #define KT_REMOVE_date_format_07_s_length 17 + #define KT_REMOVE_date_format_08_s_length 17 + #define KT_REMOVE_date_format_09_s_length 14 + #define KT_REMOVE_date_format_10_s_length 14 + #define KT_REMOVE_date_format_11_s_length 11 + #define KT_REMOVE_date_format_12_s_length 8 + #define KT_REMOVE_date_format_13_s_length 5 + #define KT_REMOVE_date_format_14_s_length 3 + + extern const f_string_static_t kt_remove_date_format_00_s; + extern const f_string_static_t kt_remove_date_format_01_s; + extern const f_string_static_t kt_remove_date_format_02_s; + extern const f_string_static_t kt_remove_date_format_03_s; + extern const f_string_static_t kt_remove_date_format_04_s; + extern const f_string_static_t kt_remove_date_format_05_s; + extern const f_string_static_t kt_remove_date_format_06_s; + extern const f_string_static_t kt_remove_date_format_07_s; + extern const f_string_static_t kt_remove_date_format_08_s; + extern const f_string_static_t kt_remove_date_format_09_s; + extern const f_string_static_t kt_remove_date_format_10_s; + extern const f_string_static_t kt_remove_date_format_11_s; + extern const f_string_static_t kt_remove_date_format_12_s; + extern const f_string_static_t kt_remove_date_format_13_s; + extern const f_string_static_t kt_remove_date_format_14_s; + + #define KT_REMOVE_date_format_example_00_s "2022/12/30 1:45:02 pm +0600" + #define KT_REMOVE_date_format_example_01_s "2022/12/30 13:45:02 +0600" + #define KT_REMOVE_date_format_example_02_s "2022/12/30 1:45 pm +0600" + #define KT_REMOVE_date_format_example_03_s "2022/12/30 13:45 +0600" + #define KT_REMOVE_date_format_example_04_s "2022/12/30 1 pm +0600" + #define KT_REMOVE_date_format_example_05_s "2022/12/30 13 +0600" + #define KT_REMOVE_date_format_example_06_s "2022/12/30 1:45:02 pm" + #define KT_REMOVE_date_format_example_07_s "2022/12/30 13:45:02" + #define KT_REMOVE_date_format_example_08_s "2022/12/30 1:45 pm" + #define KT_REMOVE_date_format_example_09_s "2022/12/30 13:45" + #define KT_REMOVE_date_format_example_10_s "2022/12/30 1 pm" + #define KT_REMOVE_date_format_example_11_s "2022/12/30 13" + #define KT_REMOVE_date_format_example_12_s "2022/12/30" + #define KT_REMOVE_date_format_example_13_s "2022/12" + #define KT_REMOVE_date_format_example_14_s "2022/" + + #define KT_REMOVE_date_format_example_00_s_length 27 + #define KT_REMOVE_date_format_example_01_s_length 25 + #define KT_REMOVE_date_format_example_02_s_length 24 + #define KT_REMOVE_date_format_example_03_s_length 22 + #define KT_REMOVE_date_format_example_04_s_length 21 + #define KT_REMOVE_date_format_example_05_s_length 19 + #define KT_REMOVE_date_format_example_06_s_length 21 + #define KT_REMOVE_date_format_example_07_s_length 19 + #define KT_REMOVE_date_format_example_08_s_length 18 + #define KT_REMOVE_date_format_example_09_s_length 16 + #define KT_REMOVE_date_format_example_10_s_length 15 + #define KT_REMOVE_date_format_example_11_s_length 13 + #define KT_REMOVE_date_format_example_12_s_length 10 + #define KT_REMOVE_date_format_example_13_s_length 9 + #define KT_REMOVE_date_format_example_14_s_length 5 + + extern const f_string_static_t kt_remove_date_format_example_00_s; + extern const f_string_static_t kt_remove_date_format_example_01_s; + extern const f_string_static_t kt_remove_date_format_example_02_s; + extern const f_string_static_t kt_remove_date_format_example_03_s; + extern const f_string_static_t kt_remove_date_format_example_04_s; + extern const f_string_static_t kt_remove_date_format_example_05_s; + extern const f_string_static_t kt_remove_date_format_example_06_s; + extern const f_string_static_t kt_remove_date_format_example_07_s; + extern const f_string_static_t kt_remove_date_format_example_08_s; + extern const f_string_static_t kt_remove_date_format_example_09_s; + extern const f_string_static_t kt_remove_date_format_example_10_s; + extern const f_string_static_t kt_remove_date_format_example_11_s; + extern const f_string_static_t kt_remove_date_format_example_12_s; + extern const f_string_static_t kt_remove_date_format_example_13_s; + extern const f_string_static_t kt_remove_date_format_example_14_s; + #define KT_REMOVE_date_symbol_equal_s "==" #define KT_REMOVE_date_symbol_less_s "<" #define KT_REMOVE_date_symbol_less_equal_s "<=" @@ -165,6 +294,18 @@ extern "C" { /** * Strings associated with the mode parameters. + * + * kt_remove_mode_symbol_*_s: + * - different: The not similar to operator. + * - same: The same as operator. + * - similar: The similar to operator. + * - not: The not same as operator. + * + * kt_remove_mode_word_*_s: + * - different: The not similar to words. + * - same: The same as words. + * - similar: The similar to words. + * - not: The not same as words. */ #ifndef _di_kt_remove_mode_s_ #define KT_REMOVE_mode_symbol_different_s "~~" @@ -200,6 +341,8 @@ extern "C" { /** * Additional strings used for various purposes. + * + * kt_remove_*_s: Arbitrary strings. */ #ifndef _di_kt_remove_s_ #define KT_REMOVE_all_s "all" @@ -257,19 +400,29 @@ extern "C" { /** * A processed Date parameter. * + * The start is inclusive and the stop is exclusive just like with f_string_range_t. + * * operation: The comparison operation. * type: The date type. * - * seconds: The entire date value in seconds. - * nanoseconds: The remaining nanosecond not represented in the seconds. + * start_year: The year in which the seconds is relative to (is only processed when + * start_second: The entire date value in seconds for the date or the start of a date range. + * start_nanosecond: The remaining nanosecond not represented in the seconds for the date or the start of a date range. + * stop_second: The entire date value in seconds for the stop of a date range (not used for non-range dates). + * stop_nanosecond: The remaining nanosecond not represented in the seconds for the stop of a date range (not used for non-range dates). */ #ifndef _di_kt_remove_date_t_ typedef struct { uint8_t operation; uint8_t type; - f_number_unsigned_t seconds; - f_number_unsigned_t nanoseconds; + f_number_unsigned_t start_year; + f_number_unsigned_t start_second; + f_number_unsigned_t start_nanosecond; + + f_number_unsigned_t stop_year; + f_number_unsigned_t stop_second; + f_number_unsigned_t stop_nanosecond; } kt_remove_date_t; #define kt_remove_date_t_initialize { \ @@ -277,6 +430,10 @@ extern "C" { 0, \ 0, \ 0, \ + 0, \ + 0, \ + 0, \ + 0, \ } #endif // _di_kt_remove_date_t_ @@ -358,41 +515,41 @@ extern "C" { * @todo /proc needs to be implemented, but before that try to understand how --one-file-system, --no-preserve-root, and --preserve-root work in coreutils rm command. * * kt_remove_flag_*_e: - * - none: No flags set. - * - block: Remove by file type: block. - * - character: Remove by file type: character. - * - date: Remove by date (separate flag for <, <=, ==, >=, and >). - * - different: Remove by user different from caller. - * - directory: Remove by file type: directory. - * - empty_only: Remove empty directories. - * - empty_only_fail: Fail on empty directories. - * - empty_not: Remove not empty directories. - * - empty_not_fail: Fail on not empty directories. - * - fifo: Remove by file type: FIFO. - * - follow: Follow symbolic links deleting the file being pointed to rather than the link itself (when not set the link itself is deleted). - * - force: Forcibly delete. - * - group: Remove by GID. - * - help: Print help. - * - isolate_all: Isolate to a single file system, error on all outside file system files (@todo requires /proc support). - * - isolate_ignore: Ignore rather than fail for anything on a different file system (@todo requires /proc support). - * - isolate_root: Isolate to a single file system, error on remove on '/' (@todo requires /proc support). - * - link: Remove by file type: link. - * - mode: Remove by mode. - * - option_used: This gets set when when certain options are specified to toggle the default match detection boolean during removal of each file. - * - print_warning: When specified, warnings are still printed even when verbosity is less than verbose. - * - prompt_all: Operate in interactive mode, prompting for every file. - * - prompt_follow: Operate in interactive mode: prompting for every link that is being followed. - * - prompt_never: Do not operate in interactive mode. - * - prompt_once: Operate in interactive mode: prompting if removing 3 or more files. - * - recurse: Recurse directories. - * - regular: Remove by file type: regular. - * - same: Remove by same user as caller. - * - simulate: Do not actually perform deletes, instead print messages (when silent, should still return 0 or 1). - * - socket: Remove by file type: socket. - * - tree: Remove directory tree (parent directories) (remove a/b/c, removes a/b/c, then a/b/, then a). - * - user: Remove by UID. - * - utc: Process dates in UTC mode. - * - version: Print version. + * - none: No flags set. + * - block: Remove by file type: block. + * - character: Remove by file type: character. + * - date: Remove by date (separate flag for <, <=, ==, >=, and >). + * - different: Remove by user different from caller. + * - directory: Remove by file type: directory. + * - empty_only: Remove empty directories. + * - empty_only_fail: Fail on empty directories. + * - empty_not: Remove not empty directories. + * - empty_not_fail: Fail on not empty directories. + * - fifo: Remove by file type: FIFO. + * - follow: Follow symbolic links deleting the file being pointed to rather than the link itself (when not set the link itself is deleted). + * - force: Forcibly delete. + * - group: Remove by GID. + * - help: Print help. + * - isolate_all: Isolate to a single file system, error on all outside file system files (@todo requires /proc support). + * - isolate_ignore: Ignore rather than fail for anything on a different file system (@todo requires /proc support). + * - isolate_root: Isolate to a single file system, error on remove on '/' (@todo requires /proc support). + * - link: Remove by file type: link. + * - mode: Remove by mode. + * - option_used: This gets set when when certain options are specified to toggle the default match detection boolean during removal of each file. + * - print_warning: When specified, warnings are still printed even when verbosity is less than verbose. + * - prompt_all: Operate in interactive mode, prompting for every file. + * - prompt_follow: Operate in interactive mode: prompting for every link that is being followed. + * - prompt_never: Do not operate in interactive mode. + * - prompt_once: Operate in interactive mode: prompting if removing 3 or more files. + * - recurse: Recurse directories. + * - regular: Remove by file type: regular. + * - same: Remove by same user as caller. + * - simulate: Do not actually perform deletes, instead print messages (when silent, should still return 0 or 1). + * - socket: Remove by file type: socket. + * - tree: Remove directory tree (parent directories) (remove a/b/c, removes a/b/c, then a/b/, then a). + * - user: Remove by UID. + * - utc: Process dates in UTC mode. + * - version: Print version. */ #ifndef _di_kt_remove_flag_e_ enum { @@ -437,9 +594,32 @@ extern "C" { #endif // _di_kt_remove_flag_e_ /** - * Flags associated with a date. + * A set of flags used internally in the convert process. * - * @todo Consider (K H D B D C M) for both Time and EpochTime (entire metric?). + * These are generally used during parsing of Time and EpochTime strings. + * + * kt_remove_flag_convert_*_e: + * - colon: Either single or double colon. + * - colon_single: Single colon detected. + * - colon_double: Double colon detected. + * - match: Matched either part. + * - match_first: Matched first (left) part. + * - match_second: Matched second (right) part. + */ +#ifndef _di_kt_remove_flag_convert_e_ + enum { + kt_remove_flag_convert_none_e = 0x0, + kt_remove_flag_convert_colon_e = 0x3, + kt_remove_flag_convert_colon_single_e = 0x1, + kt_remove_flag_convert_colon_double_e = 0x2, + kt_remove_flag_convert_match_e = 0xc, + kt_remove_flag_convert_match_first_e = 0x4, + kt_remove_flag_convert_match_second_e = 0x8, + }; // enum +#endif // _di_kt_remove_flag_convert_e_ + +/** + * Flags associated with a date. * * kt_remove_flag_date_*_e: * - none: No flags set. @@ -450,15 +630,15 @@ extern "C" { * - more_equal: Perform greater than or equal to on date, '>=' or 'more_equal'. * - not: Perform not equal to on date. '<>' or 'not' * - * - has_year: Date has a year. - * - now: Date is relative to 'now'. - * - string: Date is processed via the string date functions (such as via strftime_r() or getdate_r()). - * - time: Date is based off of Time format. - * - time_epoch: Date is based off of EpochTime format. - * - today: Date is relative to 'today'. - * - tomorrow: Date is relative to 'tomorrow'. - * - unix: Date is based off of Unix Epoch format. - * - yesterday: Date is relative to 'yesterday'. + * - year: Date has a year. + * - now: Date is relative to 'now'. + * - string: Date is processed via the string date functions (such as via strftime_r() or getdate_r()). + * - time: Date is based off of Time format. + * - time_epoch: Date is based off of EpochTime format. + * - today: Date is relative to 'today'. + * - tomorrow: Date is relative to 'tomorrow'. + * - unix: Date is based off of Unix Epoch format. + * - yesterday: Date is relative to 'yesterday'. */ #ifndef _di_kt_remove_flag_date_e_ enum { @@ -473,15 +653,14 @@ extern "C" { kt_remove_flag_date_not_e = 0x20, // Used for processing and converting. - kt_remove_flag_date_has_year_e = 0x1, - kt_remove_flag_date_now_e = 0x2, - kt_remove_flag_date_string_e = 0x4, - kt_remove_flag_date_time_e = 0x8, - kt_remove_flag_date_time_epoch_e = 0x10, - kt_remove_flag_date_today_e = 0x20, - kt_remove_flag_date_tomorrow_e = 0x40, - kt_remove_flag_date_unix_e = 0x80, - kt_remove_flag_date_yesterday_e = 0x100, + kt_remove_flag_date_now_e = 0x1, + kt_remove_flag_date_string_e = 0x2, + kt_remove_flag_date_time_e = 0x4, + kt_remove_flag_date_time_epoch_e = 0x8, + kt_remove_flag_date_today_e = 0x10, + kt_remove_flag_date_tomorrow_e = 0x20, + kt_remove_flag_date_unix_e = 0x40, + kt_remove_flag_date_yesterday_e = 0x80, }; // enum #endif // _di_kt_remove_flag_date_e_ diff --git a/sources/c/remove/main/convert.c b/sources/c/remove/main/convert.c index b28891e..7374960 100644 --- a/sources/c/remove/main/convert.c +++ b/sources/c/remove/main/convert.c @@ -4,17 +4,13 @@ extern "C" { #endif -#ifndef _di_kt_remove_get_date_ - struct timespec kt_remove_get_date(fll_program_data_t * const main, kt_remove_setting_t * const setting, const f_string_static_t buffer, uint8_t * const type) { - - if (!setting || !buffer.used) { - struct timespec result; - - memset(&result, 0, sizeof(struct timespec)); +#ifndef _di_kt_remove_convert_date_ + void kt_remove_convert_date(fll_program_data_t * const main, kt_remove_setting_t * const setting, const f_string_static_t buffer, kt_remove_date_t * const date) { + if (!setting || !buffer.used || !date) { if (setting) setting->status = F_data_not; - return result; + return; } { @@ -35,28 +31,23 @@ extern "C" { for (uint8_t i = 0; i < 4; ++i) { if (fl_string_dynamic_compare(buffer, strings[i]) == F_equal_to) { - setting->status = F_none; + date->type = enumerations[i]; + + kt_remove_convert_date_relative(setting, date); - if (type) { - *type = enumerations[i]; + if (F_status_is_error(setting->status)) { + kt_remove_print_error(setting, main->error, macro_kt_remove_f(kt_remove_convert_date_relative)); } - return kt_remove_get_date_relative(setting, enumerations[i]); + return; } } // for } - // 0x1 = single colon, 0x2 = double colon, 0x4 = matched first, 0x8 = matched second, 0x10 = matched negative on first, 0x20 = matched negative on second, 0x40 = matched positive on first, 0x80 = matched positive on second. uint8_t matches = 0; - uint64_t digit_first = 0; - uint64_t digit_second = 0; f_string_range_t range_first = f_string_range_t_initialize; f_string_range_t range_second = f_string_range_t_initialize; - struct timespec result; - - memset(&result, 0, sizeof(struct timespec)); - { uint8_t width = 0; f_string_range_t range = macro_f_string_range_t_initialize2(buffer.used); @@ -64,6 +55,8 @@ extern "C" { for (; range.start <= range.stop; range.start += width, width_max -= width) { + if (kt_remove_signal_check(main)) return; + // Skip past NULL characters. if (!buffer.string[range.start]) { width = 1; @@ -71,15 +64,15 @@ extern "C" { continue; } - width = macro_f_utf_byte_width_is(buffer.string[range.start]); + width = macro_f_utf_byte_width(buffer.string[range.start]); - if (matches & 0x8) { + if (matches & kt_remove_flag_convert_match_second_e) { setting->status = f_utf_is_digit(buffer.string + range.start, width_max, 0); if (F_status_is_error(setting->status)) { kt_remove_print_error(setting, main->error, macro_kt_remove_f(f_utf_is_digit)); - return result; + return; } if (setting->status == F_true) { @@ -94,34 +87,19 @@ extern "C" { break; } - // @todo review this, this is 0x1, 0x2, and 0x20 (why match second negative?). - if (matches & 0x23) { + if (matches & kt_remove_flag_convert_colon_e) { - // Search until a colon, a digit, or a minus is found. + // Search until a colon or a digit is found. if (fl_string_dynamic_compare_string(buffer.string + range.start, f_string_ascii_colon_s, width) == F_equal_to) { // A third colon is not valid. - if (matches & 0x2) { + if (matches & kt_remove_flag_convert_colon_double_e) { matches = 0; break; } - matches |= 0x2; - - continue; - } - - if (fl_string_dynamic_compare_string(buffer.string + range.start, f_string_ascii_minus_s, width) == F_equal_to) { - - // An out of place minus sign is not valid. - if (matches & 0x20) { - matches = 0; - - break; - } - - matches |= 0x20; + matches |= kt_remove_flag_convert_colon_double_e; continue; } @@ -131,53 +109,22 @@ extern "C" { if (F_status_is_error(setting->status)) { kt_remove_print_error(setting, main->error, macro_kt_remove_f(f_utf_is_digit)); - return result; + return; } if (setting->status == F_true) { - matches |= 0x8; + matches |= kt_remove_flag_convert_match_second_e; range_second.start = range.start; + range_second.stop = range.start; } - } - else if (matches & 0x4) { - - // Only a colon is expected. - if (fl_string_dynamic_compare_string(buffer.string + range.start, f_string_ascii_colon_s, width) == F_equal_to) { - matches |= 0x1; - } - else { - matches = 0; - break; - } + continue; } - else { - setting->status = f_utf_is_whitespace(buffer.string + range.start, width_max, F_false); - - if (F_status_is_error(setting->status)) { - kt_remove_print_error(setting, main->error, macro_kt_remove_f(f_utf_is_whitespace)); - - return result; - } - if (setting->status == F_true) continue; + if (matches & kt_remove_flag_convert_match_first_e) { if (fl_string_dynamic_compare_string(buffer.string + range.start, f_string_ascii_colon_s, width) == F_equal_to) { - matches |= 0x1; - - continue; - } - - if (fl_string_dynamic_compare_string(buffer.string + range.start, f_string_ascii_minus_s, width) == F_equal_to) { - - // An out of place minus sign is not valid. - if (matches & 0x50) { - matches = 0; - - break; - } - - matches |= 0x10; + matches |= kt_remove_flag_convert_colon_single_e; continue; } @@ -187,31 +134,54 @@ extern "C" { if (F_status_is_error(setting->status)) { kt_remove_print_error(setting, main->error, macro_kt_remove_f(f_utf_is_digit)); - return result; + return; } if (setting->status == F_true) { - if (matches & 0x4) { - range_first.stop = range.start; - } - else { - matches |= 0x4; - range_first.start = range.start; - - // A digit is found before a leading minus, so assume this is a positive number. - if (!(matches & 0x10)) { - matches |= 0x40; - } - } - } - else if (!(matches & 0x50) && fl_string_dynamic_compare_string(buffer.string + range.start, f_string_ascii_minus_s, width) == F_equal_to) { - matches |= 0x10; + range_first.stop = range.start; } else { matches = 0; break; } + + continue; + } + + setting->status = f_utf_is_whitespace(buffer.string + range.start, width_max, F_false); + + if (F_status_is_error(setting->status)) { + kt_remove_print_error(setting, main->error, macro_kt_remove_f(f_utf_is_whitespace)); + + return; + } + + if (setting->status == F_true) continue; + + if (fl_string_dynamic_compare_string(buffer.string + range.start, f_string_ascii_colon_s, width) == F_equal_to) { + matches |= kt_remove_flag_convert_colon_single_e; + + continue; + } + + setting->status = f_utf_is_digit(buffer.string + range.start, width_max, 0); + + if (F_status_is_error(setting->status)) { + kt_remove_print_error(setting, main->error, macro_kt_remove_f(f_utf_is_digit)); + + return; + } + + if (setting->status == F_true) { + matches |= kt_remove_flag_convert_match_first_e; + range_first.start = range.start; + range_first.stop = range.start; + } + else { + matches = 0; + + break; } } // for @@ -219,176 +189,264 @@ extern "C" { } // If the first and possibly the second digit matches. - if (matches & 0xc) { + if (matches & kt_remove_flag_convert_match_e) { fl_conversion_data_t conversion_data = fl_conversion_data_base_10_c; - // Process the first character. - if (matches & 0x4) { - if (matches & 0x10) { - conversion_data.flag |= FL_conversion_data_flag_negative_d; - } + date->start_year = 0; + date->start_second = 0; + date->start_nanosecond = 0; + date->stop_second = 0; + date->stop_nanosecond = 0; + date->stop_year = 0; + date->type = 0; - setting->status = fl_conversion_dynamic_partial_to_unsigned_detect(conversion_data, buffer, range_first, &digit_first); + // Process the first character. + if (matches & kt_remove_flag_convert_match_first_e) { + setting->status = fl_conversion_dynamic_partial_to_unsigned_detect(conversion_data, buffer, range_first, &date->start_year); if (F_status_is_error(setting->status)) { kt_remove_print_error(setting, main->error, macro_kt_remove_f(fl_conversion_dynamic_partial_to_unsigned_detect)); - return result; + return; } - - // Remove the negative bit for next use. - conversion_data.flag -= conversion_data.flag & FL_conversion_data_flag_negative_d; } else { - if (matches & 0x2) { + if (matches & kt_remove_flag_convert_colon_double_e) { // The Unix Epoch is used for double colons when no year is specified. - digit_first = kt_remove_time_year_unix_epoch_d; - - if (type) { - *type = kt_remove_flag_date_time_epoch_e; - } + date->start_year = kt_remove_time_year_unix_epoch_d; + date->type |= kt_remove_flag_date_time_epoch_e; } else { + struct timespec now; + int result = 0; + + memset(&now, 0, sizeof(struct timespec)); // The current year is used for single colon when no year is specified. - digit_first = (time(0) / kt_remove_time_seconds_in_year_d) + kt_remove_time_year_unix_epoch_d; + { + result = clock_gettime(CLOCK_REALTIME, &now); + + if (!result) { + if (result == EFAULT) { + setting->status = F_status_set_error(F_buffer); + } + else if (result == EINVAL) { + setting->status = F_status_set_error(F_parameter); + } + else if (result == EPERM) { + setting->status = F_status_set_error(F_prohibited); + } + else { + setting->status = F_status_set_error(F_failure); + } - if (type) { - *type = kt_remove_flag_date_time_e; + return; + } } + + date->start_year = now.tv_sec / kt_remove_time_seconds_in_year_d; + date->type |= kt_remove_flag_date_time_e; } } // Process the second character. - if (matches & 0x8) { - if (matches & 0x20) { - conversion_data.flag |= FL_conversion_data_flag_negative_d; - } - - setting->status = fl_conversion_dynamic_partial_to_unsigned_detect(conversion_data, buffer, range_second, &digit_second); + if (matches & kt_remove_flag_convert_match_second_e) { + setting->status = fl_conversion_dynamic_partial_to_unsigned_detect(conversion_data, buffer, range_second, &date->start_second); if (F_status_is_error(setting->status)) { kt_remove_print_error(setting, main->error, macro_kt_remove_f(fl_conversion_dynamic_partial_to_unsigned_detect)); - return result; + return; } - if (matches & 0x2) { - result.tv_sec = setting->flag & kt_remove_flag_utc_e ? digit_second : digit_second - timezone; + if (matches & kt_remove_flag_convert_colon_double_e) { + if (!(setting->flag & kt_remove_flag_utc_e)) { + kt_remove_convert_timezone(setting, &date->start_year, &date->start_second); - // This is a double colon, so it is in UnixTime format. - if (digit_first > kt_remove_time_year_unix_epoch_d) { - result.tv_sec += (digit_first - kt_remove_time_year_unix_epoch_d) * kt_remove_time_seconds_in_year_d; - } - else if (digit_first < kt_remove_time_year_unix_epoch_d) { - result.tv_sec -= (kt_remove_time_year_unix_epoch_d - digit_first) * kt_remove_time_seconds_in_year_d; + if (F_status_is_error(setting->status)) { + kt_remove_print_error(setting, main->error, macro_kt_remove_f(kt_remove_convert_timezone)); + + return; + } } } else { - result.tv_sec = (digit_second / kt_remove_time_seconds_in_nanosecond_d); - result.tv_nsec = digit_second % kt_remove_time_seconds_in_nanosecond_d; + date->start_nanosecond = date->start_second % kt_remove_time_seconds_in_nanosecond_d; + date->start_second = (date->start_second / kt_remove_time_seconds_in_nanosecond_d); - if (setting->flag & kt_remove_flag_utc_e) { - result.tv_sec -= timezone; - } + if (!(setting->flag & kt_remove_flag_utc_e)) { + kt_remove_convert_timezone(setting, &date->start_year, &date->start_second); - const uint64_t year_current = (time(0) / kt_remove_time_seconds_in_year_d) + kt_remove_time_year_unix_epoch_d; + if (F_status_is_error(setting->status)) { + kt_remove_print_error(setting, main->error, macro_kt_remove_f(kt_remove_convert_timezone)); - // This is a single colon, so it is in Time format. - if (digit_first > kt_remove_time_year_unix_epoch_d) { - result.tv_sec += (digit_first - kt_remove_time_year_unix_epoch_d) * kt_remove_time_seconds_in_year_d; - } - else if (digit_first < kt_remove_time_year_unix_epoch_d) { - result.tv_sec -= (kt_remove_time_year_unix_epoch_d - digit_first) * kt_remove_time_seconds_in_year_d; + return; + } } } } else { // A colon after the end without a digit following it is not valid (such as '1234:' or '1234::'). - if (matches & 0x3) { + if (matches & kt_remove_flag_convert_colon_e) { matches = 0; } else { // This is a UNIX timestamp by itself (has no colons). - result.tv_sec = setting->flag & kt_remove_flag_utc_e ? digit_first : digit_first - timezone; + date->start_year = kt_remove_time_year_unix_epoch_d; + date->type = kt_remove_flag_date_unix_e; + + setting->status = fl_conversion_dynamic_to_unsigned_detect(conversion_data, buffer, &date->start_second); + + if (F_status_is_error(setting->status)) { + kt_remove_print_error(setting, main->error, macro_kt_remove_f(fl_conversion_dynamic_to_unsigned_detect)); + + return; + } + + kt_remove_convert_timezone(setting, &date->start_year, &date->start_second); + + if (F_status_is_error(setting->status)) { + kt_remove_print_error(setting, main->error, macro_kt_remove_f(kt_remove_convert_timezone)); + + return; + } } } } - else { - // @todo check to see if this is just a digit, and if so then it is UNIX Epoch time (kt_remove_flag_date_unix_e). - } if (!matches) { - // @todo attempt to process using the string date time conversion libc functions or return an error. - // @todo formats: - // - YYYY/MM/DD hh:ii:ss a +0000 - // - YYYY/MM/DD HH:ii:ss +0000 - // - YYYY/MM/DD hh:ii a +0000 - // - YYYY/MM/DD HH:ii +0000 - // - YYYY/MM/DD hh a +0000 - // - YYYY/MM/DD HH +0000 - // - YYYY/MM/DD hh:ii:ss a - // - YYYY/MM/DD HH:ii:ss - // - YYYY/MM/DD hh:ii a - // - YYYY/MM/DD HH:ii - // - YYYY/MM/DD hh a - // - YYYY/MM/DD HH - // - YYYY/MM/DD - // - YYYY/MM - // - YYYY/ - // (Note how the year by itselfs still has a trailing '/'. this is done to ensure it is not confused with the Unix timestamp. - - //if (type) { - // *type = kt_remove_flag_date_string_e; - //} + const f_string_t formats[] = { + kt_remove_date_format_00_s.string, + kt_remove_date_format_01_s.string, + kt_remove_date_format_02_s.string, + kt_remove_date_format_03_s.string, + kt_remove_date_format_04_s.string, + kt_remove_date_format_05_s.string, + kt_remove_date_format_06_s.string, + kt_remove_date_format_07_s.string, + kt_remove_date_format_08_s.string, + kt_remove_date_format_09_s.string, + kt_remove_date_format_10_s.string, + kt_remove_date_format_11_s.string, + kt_remove_date_format_12_s.string, + kt_remove_date_format_13_s.string, + kt_remove_date_format_14_s.string, + }; + + struct tm time; + + for (f_array_length_t i = 0; i < 15; ++i) { + + if (kt_remove_signal_check(main)) return; + + memset(&time, 0, sizeof(struct tm)); + + if (strptime(buffer.string, formats[i], &time) != 0) { + date->start_year = kt_remove_time_year_unix_epoch_d; + date->start_nanosecond = 0; + date->stop_second = 0; + date->stop_nanosecond = 0; + date->stop_year = 0; + date->type = kt_remove_flag_date_string_e; + + date->start_second = time.tm_sec; + date->start_second += time.tm_min * kt_remove_time_seconds_in_minute_d; + date->start_second += time.tm_hour * kt_remove_time_seconds_in_hour_d; + date->start_second += time.tm_yday * kt_remove_time_seconds_in_day_d; + date->start_nanosecond = 0; + + // @todo investigate whether or not tm_isdst needs to be taken into consideration. + matches = 1; + + break; + } + } // for } setting->status = matches ? F_none : F_status_set_error(F_known_not); - - return result; } -#endif // _di_kt_remove_get_date_ +#endif // _di_kt_remove_convert_date_ -#ifndef _di_kt_remove_get_date_relative_ - struct timespec kt_remove_get_date_relative(kt_remove_setting_t * const setting, const uint8_t type) { +#ifndef _di_kt_remove_convert_date_relative_ + void kt_remove_convert_date_relative(kt_remove_setting_t * const setting, kt_remove_date_t * const date) { - struct timespec result; + if (!setting || !date) { + if (setting) setting->status = F_status_set_error(F_parameter); - memset(&result, 0, sizeof(struct timespec)); + return; + } - if (!setting) return result; + struct timespec now; - const time_t since_epoch = time(0); + memset(&now, 0, sizeof(struct timespec)); - if (type == kt_remove_flag_date_now_e) { - result.tv_sec = since_epoch; + { + const int result = clock_gettime(CLOCK_REALTIME, &now); - if (setting->flag & kt_remove_flag_utc_e) { - result.tv_sec -= timezone; + if (result) { + if (errno == EFAULT) { + setting->status = F_status_set_error(F_buffer); + } + else if (errno == EINVAL) { + setting->status = F_status_set_error(F_parameter); + } + else if (errno == EPERM) { + setting->status = F_status_set_error(F_prohibited); + } + else { + setting->status = F_status_set_error(F_failure); + } + + return; + } + } + + date->start_year = kt_remove_time_year_unix_epoch_d; + date->start_second = now.tv_sec; + date->start_nanosecond = 0; + date->stop_year = kt_remove_time_year_unix_epoch_d; + date->stop_second = 0; + date->stop_nanosecond = 0; + + if (date->type == kt_remove_flag_date_now_e) { + date->start_nanosecond = now.tv_nsec; + + if (!(setting->flag & kt_remove_flag_utc_e)) { + kt_remove_convert_timezone(setting, &date->start_year, &date->start_second); + if (F_status_is_error(setting->status)) return; } - return result; + setting->status = F_none; + + return; } // Determine start of day. - const time_t today = since_epoch - ((setting->flag & kt_remove_flag_utc_e ? since_epoch : since_epoch - timezone) % kt_remove_time_seconds_in_day_d); + if (!(setting->flag & kt_remove_flag_utc_e)) { + kt_remove_convert_timezone(setting, &date->start_year, &date->start_second); + if (F_status_is_error(setting->status)) return; + } + + date->start_second -= date->start_second % kt_remove_time_seconds_in_day_d; - if (type == kt_remove_flag_date_today_e) { - result.tv_sec = today; + if (date->type == kt_remove_flag_date_today_e) { + date->stop_second = date->start_second + kt_remove_time_seconds_in_day_d; // @fixme, check to see if this would overflow and if so increment year. } - else if (type == kt_remove_flag_date_tomorrow_e) { - result.tv_sec = today + kt_remove_time_seconds_in_day_d; + else if (date->type == kt_remove_flag_date_tomorrow_e) { + date->start_second += kt_remove_time_seconds_in_day_d; + date->stop_second = date->start_second + kt_remove_time_seconds_in_day_d; // @fixme, check to see if this would overflow and if so increment year. } - else { - result.tv_sec = today - kt_remove_time_seconds_in_day_d; + else if (date->type == kt_remove_flag_date_yesterday_e) { + date->start_second -= kt_remove_time_seconds_in_day_d; + date->stop_second = date->start_second; } - return result; + setting->status = F_none; } -#endif // _di_kt_remove_get_date_relative_ +#endif // _di_kt_remove_convert_date_relative_ #ifndef _di_kt_remove_get_id_group_ uint32_t kt_remove_get_id_group(kt_remove_setting_t * const setting, const f_string_static_t buffer) { @@ -516,6 +574,52 @@ extern "C" { } #endif // _di_kt_remove_get_mode_ +#ifndef _di_kt_remove_convert_timezone_ + void kt_remove_convert_timezone(kt_remove_setting_t * const setting, f_number_unsigned_t * const year, f_number_unsigned_t * const seconds) { + + if (!setting || !year || !seconds) { + if (setting) setting->status = F_status_set_error(F_parameter); + + return; + } + + if (timezone < 0) { + if (*seconds > kt_remove_time_seconds_in_year_d + timezone) { + if (*year < F_number_t_size_max_unsigned_d) { + ++(*year); + *seconds -= kt_remove_time_seconds_in_year_d + timezone; + } + else { + setting->status = F_status_set_error(F_number_overflow); + + return; + } + } + else { + *seconds -= timezone; + } + } + else { + if (*seconds < timezone) { + if (*year) { + --(*year); + *seconds = kt_remove_time_seconds_in_year_d - (timezone - *seconds); + } + else { + setting->status = F_status_set_error(F_number_underflow); + + return; + } + } + else { + *seconds -= timezone; + } + } + + setting->status = F_none; + } +#endif // _di_kt_remove_convert_timezone_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/sources/c/remove/main/convert.h b/sources/c/remove/main/convert.h index 475906c..8fc1287 100644 --- a/sources/c/remove/main/convert.h +++ b/sources/c/remove/main/convert.h @@ -38,6 +38,12 @@ extern "C" { * F_none on success. * F_data_not on success, but buffer is empty and there is no data to process. * + * F_buffer (with error bit) if the buffer is invalid. + * F_parameter (with error bit) if a parameter is invalid. + * F_prohibited (with error bit) if the system does not permit accessing the system clock. + * F_failure (with error bit) for any other failure. + * + * @todo review codes below. * F_number_too_large (with error bit) if the given ID is too large. * F_number_too_small (with error bit) if the given ID is too small. * F_known_not (with error bit) if the given string is not of a known format @@ -48,23 +54,17 @@ extern "C" { * Errors (with error bit) from: kt_remove_get_date_relative(). * @param buffer * A string containing group name or ID. - * @param type - * (optional) The type of date that is detected from the buffer. - * This is generally only altered on success. - * - * Set to NULL to disable. - * - * @return - * The timestamp structure. + * @param date + * The converted date. * * @see fl_conversion_dynamic_partial_to_unsigned_detect() * @see fl_string_dynamic_partial_rip_nulless() * * @see kt_remove_get_date_relative() */ -#ifndef _di_kt_remove_get_date_ - extern struct timespec kt_remove_get_date(fll_program_data_t * const main, kt_remove_setting_t * const setting, const f_string_static_t buffer, uint8_t * const type); -#endif // _di_kt_remove_get_date_ +#ifndef _di_kt_remove_convert_date_ + extern void kt_remove_convert_date(fll_program_data_t * const main, kt_remove_setting_t * const setting, const f_string_static_t buffer, kt_remove_date_t * const date); +#endif // _di_kt_remove_convert_date_ /** * Convert the string from a string representation of date into the numeric representation of that date in seconds since epoch. @@ -83,15 +83,18 @@ extern "C" { * @param setting * The main program settings. * - * This does not alter setting.status. - * @param type - * The code representing the relative string. - * Use appropriate enumeration type code, such as kt_remove_flag_date_now_e. + * This alters setting.status: + * F_none on success. + * F_data_not on success, but buffer is empty or there is no data to process. * - * @return - * The timestamp structure. + * F_buffer (with error bit) if the buffer is invalid. + * F_parameter (with error bit) if a parameter is invalid. + * F_prohibited (with error bit) if the system does not permit accessing the system clock. + * F_failure (with error bit) for any other failure. + * @param date + * The converted date. * - * @see time() + * @see clock_gettime() * * @see f_utf_is_digit() * @see f_utf_is_whitespace() @@ -99,10 +102,9 @@ extern "C" { * * @see kt_remove_get_date_relative() */ -#ifndef _di_kt_remove_get_date_relative_ - extern struct timespec kt_remove_get_date_relative(kt_remove_setting_t * const setting, const uint8_t type); -#endif // _di_kt_remove_get_date_relative_ - +#ifndef _di_kt_remove_convert_date_relative_ + extern void kt_remove_convert_date_relative(kt_remove_setting_t * const setting, kt_remove_date_t * const date); +#endif // _di_kt_remove_convert_date_relative_ /** * Convert the string from a string representation of an ID or a group name into the numeric representation of that ID or group name. @@ -175,6 +177,33 @@ extern "C" { extern mode_t kt_remove_get_mode(fll_program_data_t * const main, kt_remove_setting_t * const setting, const f_string_static_t buffer); #endif // _di_kt_remove_get_mode_ +/** + * Convert the given date to the local time zone. + * + * This does not check the flags to see if UTC is in used. + * The caller must assure this is appropriate. + * + * @param setting + * The main program settings. + * + * This alters setting.status: + * F_none on success. + * + * F_number_overflow (with error bit) if the date after applying the timezone is too large. + * F_number_underflow (with error bit) if the date after applying the timezone is too small. + * F_parameter (with error bit) if a parameter is invalid. + * @param year + * The year value. + * This is commonly set to UNIX Epoch. + * This is only updated if the timezone would result in a year change. + * @param seconds + * The seconds since the start of the year. + * This is updated based on the global timezone variable. + */ +#ifndef _di_kt_remove_convert_timezone_ + extern void kt_remove_convert_timezone(kt_remove_setting_t * const setting, f_number_unsigned_t * const year, f_number_unsigned_t * const seconds); +#endif // _di_kt_remove_convert_timezone_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/sources/c/remove/main/main.c b/sources/c/remove/main/main.c index 75af494..9fdf62c 100644 --- a/sources/c/remove/main/main.c +++ b/sources/c/remove/main/main.c @@ -22,12 +22,31 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { fll_program_standard_setup(&data.signal); { - const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); + f_thread_id_t id_signal; + kt_remove_arguments_t signal_arguments = macro_kt_remove_arguments_t_initialize(&data, &setting); - kt_remove_setting_load(arguments, &data, &setting); - } + memset(&id_signal, 0, sizeof(f_thread_id_t)); + + setting.status = f_thread_create(0, &id_signal, &kt_remove_thread_signal, (void *) &signal_arguments); + + if (F_status_is_error(setting.status)) { + kt_remove_print_error(&setting, data.error, macro_kt_remove_f(f_thread_create)); + } + else { + { + const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); - kt_remove_main(&data, &setting); + kt_remove_setting_load(arguments, &data, &setting); + } + + if (!kt_remove_signal_check(&data)) { + kt_remove_main(&data, &setting); + } + + f_thread_cancel(id_signal); + f_thread_join(id_signal, 0); + } + } kt_remove_setting_unload(&data, &setting); diff --git a/sources/c/remove/main/print.c b/sources/c/remove/main/print.c index 28d31a0..c7ab947 100644 --- a/sources/c/remove/main/print.c +++ b/sources/c/remove/main/print.c @@ -124,8 +124,8 @@ extern "C" { f_print_dynamic_raw(f_string_eol_s, print.to.stream); - fll_program_print_help_option_long(print.to, context, kt_remove_long_local_s, f_console_symbol_long_enable_s, "Designate dates are in local time."); - fll_program_print_help_option_long(print.to, context, kt_remove_long_utc_s, f_console_symbol_long_enable_s, " Designate dates are in UTC."); + fll_program_print_help_option_long(print.to, context, kt_remove_long_local_s, f_console_symbol_long_enable_s, "Designate dates are in local time, unless time zone is specified."); + fll_program_print_help_option_long(print.to, context, kt_remove_long_utc_s, f_console_symbol_long_enable_s, " Designate dates are in UTC, unless time zone is specified."); fll_program_print_help_usage(print.to, context, kt_remove_program_name_s, kt_remove_program_help_parameters_s); @@ -213,7 +213,22 @@ extern "C" { fl_print_format("'%[1672639985%]'.%r", print.to.stream, context.set.notable, context.set.notable, f_string_eol_s); fl_print_format(" - '%[%r%]': Use the previous day.%r%r", print.to.stream, context.set.notable, kt_remove_yesterday_s, context.set.notable, f_string_eol_s, f_string_eol_s); - // @todo add the additional date string formats once implemented. + fl_print_format(" Valid formats for the date related parameters must be any of the following:%r", print.to.stream, f_string_eol_s); + fl_print_format(" - '%[%r%]': A date like '%[%r%]'.%r", print.to.stream, context.set.notable, kt_remove_date_format_00_s, context.set.notable, context.set.notable, kt_remove_date_format_example_00_s, context.set.notable, f_string_eol_s); + fl_print_format(" - '%[%r%]': A date like '%[%r%]'.%r", print.to.stream, context.set.notable, kt_remove_date_format_01_s, context.set.notable, context.set.notable, kt_remove_date_format_example_01_s, context.set.notable, f_string_eol_s); + fl_print_format(" - '%[%r%]': A date like '%[%r%]'.%r", print.to.stream, context.set.notable, kt_remove_date_format_02_s, context.set.notable, context.set.notable, kt_remove_date_format_example_02_s, context.set.notable, f_string_eol_s); + fl_print_format(" - '%[%r%]': A date like '%[%r%]'.%r", print.to.stream, context.set.notable, kt_remove_date_format_03_s, context.set.notable, context.set.notable, kt_remove_date_format_example_03_s, context.set.notable, f_string_eol_s); + fl_print_format(" - '%[%r%]': A date like '%[%r%]'.%r", print.to.stream, context.set.notable, kt_remove_date_format_04_s, context.set.notable, context.set.notable, kt_remove_date_format_example_04_s, context.set.notable, f_string_eol_s); + fl_print_format(" - '%[%r%]': A date like '%[%r%]'.%r", print.to.stream, context.set.notable, kt_remove_date_format_05_s, context.set.notable, context.set.notable, kt_remove_date_format_example_05_s, context.set.notable, f_string_eol_s); + fl_print_format(" - '%[%r%]': A date like '%[%r%]'.%r", print.to.stream, context.set.notable, kt_remove_date_format_06_s, context.set.notable, context.set.notable, kt_remove_date_format_example_06_s, context.set.notable, f_string_eol_s); + fl_print_format(" - '%[%r%]': A date like '%[%r%]'.%r", print.to.stream, context.set.notable, kt_remove_date_format_07_s, context.set.notable, context.set.notable, kt_remove_date_format_example_07_s, context.set.notable, f_string_eol_s); + fl_print_format(" - '%[%r%]': A date like '%[%r%]'.%r", print.to.stream, context.set.notable, kt_remove_date_format_08_s, context.set.notable, context.set.notable, kt_remove_date_format_example_08_s, context.set.notable, f_string_eol_s); + fl_print_format(" - '%[%r%]': A date like '%[%r%]'.%r", print.to.stream, context.set.notable, kt_remove_date_format_09_s, context.set.notable, context.set.notable, kt_remove_date_format_example_09_s, context.set.notable, f_string_eol_s); + fl_print_format(" - '%[%r%]': A date like '%[%r%]'.%r", print.to.stream, context.set.notable, kt_remove_date_format_10_s, context.set.notable, context.set.notable, kt_remove_date_format_example_10_s, context.set.notable, f_string_eol_s); + fl_print_format(" - '%[%r%]': A date like '%[%r%]'.%r", print.to.stream, context.set.notable, kt_remove_date_format_11_s, context.set.notable, context.set.notable, kt_remove_date_format_example_11_s, context.set.notable, f_string_eol_s); + fl_print_format(" - '%[%r%]': A date like '%[%r%]'.%r", print.to.stream, context.set.notable, kt_remove_date_format_12_s, context.set.notable, context.set.notable, kt_remove_date_format_example_12_s, context.set.notable, f_string_eol_s); + fl_print_format(" - '%[%r%]': A date like '%[%r%]'.%r", print.to.stream, context.set.notable, kt_remove_date_format_13_s, context.set.notable, context.set.notable, kt_remove_date_format_example_13_s, context.set.notable, f_string_eol_s); + fl_print_format(" - '%[%r%]': A date like '%[%r%]'.%r%r", print.to.stream, context.set.notable, kt_remove_date_format_14_s, context.set.notable, context.set.notable, kt_remove_date_format_example_14_s, context.set.notable, f_string_eol_s, f_string_eol_s); fflush(print.to.stream); funlockfile(print.to.stream); diff --git a/sources/c/remove/main/remove.c b/sources/c/remove/main/remove.c index beabe5e..44ed445 100644 --- a/sources/c/remove/main/remove.c +++ b/sources/c/remove/main/remove.c @@ -60,14 +60,6 @@ extern "C" { memset(&id_signal, 0, sizeof(f_thread_id_t)); - macro_kt_remove_setting(void_setting)->status = f_thread_create(0, &id_signal, &kt_remove_thread_signal, (void *) &arguments); - - if (F_status_is_error(macro_kt_remove_setting(void_setting)->status)) { - kt_remove_print_error(macro_kt_remove_setting(void_setting), main->error, macro_kt_remove_f(f_thread_create)); - - return; - } - kt_remove_process_normal_operate(main, macro_kt_remove_setting(void_setting)); f_thread_cancel(id_signal); diff --git a/sources/c/remove/main/simulate.c b/sources/c/remove/main/simulate.c index 2b925fa..8c99117 100644 --- a/sources/c/remove/main/simulate.c +++ b/sources/c/remove/main/simulate.c @@ -48,7 +48,8 @@ extern "C" { f_status_t status = f_file_is(path, F_file_type_link_d, F_false); - if (F_status_is_error(status)) { + + if (F_status_is_error(status) && F_status_set_fine(status) != F_file_found_not) { fl_print_format(" file_read_failure %ui%r", main->output.to.stream, F_status_set_fine(status), f_string_eol_s); return; @@ -213,82 +214,204 @@ extern "C" { &kt_remove_long_updated_s, }; - f_string_static_t name_type = f_string_empty_s; uint8_t p = 0; f_status_t result = F_none; + f_string_static_t name_type = f_string_empty_s; + f_number_unsigned_t match_year = 0; + f_number_unsigned_t match_second = 0; + f_number_unsigned_t start_year = 0; + f_number_unsigned_t start_second = 0; + f_number_unsigned_t stop_year = 0; + f_number_unsigned_t stop_second = 0; - // @todo: these are put drafted implementations, what needs to be done is consider the type as well (for example 'today' would allow anything at all in the day, this requires more complicated logic than what is below (break this into separte functions to simplify). for (; p < 3; ++p) { for (i = 0; i < dates[p]->used; ++i) { + if (kt_remove_signal_check(main)) return; + + match_year = kt_remove_time_year_unix_epoch_d + (times[p].tv_sec / kt_remove_time_seconds_in_year_d); + match_second = times[p].tv_sec % kt_remove_time_seconds_in_year_d; + + start_year = dates[p]->array[i].start_year + (dates[p]->array[i].start_second / kt_remove_time_seconds_in_year_d); + start_second = dates[p]->array[i].start_second % kt_remove_time_seconds_in_year_d; + name_type = f_string_empty_s; result = F_none; - if (dates[p]->array[i].operation == kt_remove_flag_date_equal_e) { - if (times[p].tv_sec == dates[p]->array[i].seconds && times[p].tv_nsec == dates[p]->array[i].nanoseconds) { + if (dates[p]->array[i].type == kt_remove_flag_date_today_e || dates[p]->array[i].type == kt_remove_flag_date_tomorrow_e || dates[p]->array[i].type == kt_remove_flag_date_yesterday_e) { + stop_year = dates[p]->array[i].stop_year + (dates[p]->array[i].stop_second / kt_remove_time_seconds_in_year_d); + stop_second = dates[p]->array[i].stop_second % kt_remove_time_seconds_in_year_d; + + if (dates[p]->array[i].operation == kt_remove_flag_date_equal_e) { name_type = kt_remove_date_symbol_equal_s; - result = F_true; - } - else { result = F_false; + + if (match_year == start_year) { + if (match_second > start_second && match_second < stop_second) { + result = F_true; + } + else if (match_second == start_second && times[p].tv_nsec >= dates[p]->array[i].start_nanosecond && times[p].tv_nsec < dates[p]->array[i].stop_nanosecond) { + result = F_true; + } + } } - } - else if (dates[p]->array[i].operation == kt_remove_flag_date_less_e) { - if (times[p].tv_sec < dates[p]->array[i].seconds) { + else if (dates[p]->array[i].operation == kt_remove_flag_date_less_e) { name_type = kt_remove_date_symbol_less_s; - result = F_true; + result = F_false; + + if (match_year < start_year) { + result = F_true; + } + else if (match_year == start_year) { + if (match_second < start_second) { + result = F_true; + } + else if (match_second == start_second && times[p].tv_nsec < dates[p]->array[i].start_nanosecond) { + result = F_true; + } + } } - else if (times[p].tv_sec == dates[p]->array[i].seconds && times[p].tv_nsec < dates[p]->array[i].nanoseconds) { - name_type = kt_remove_date_symbol_less_s; - result = F_true; + else if (dates[p]->array[i].operation == kt_remove_flag_date_less_equal_e) { + name_type = kt_remove_date_symbol_less_equal_s; + result = F_false; + + if (match_year < start_year) { + result = F_true; + } + else if (match_year == start_year) { + if (match_second < stop_second) { + result = F_true; + } + else if (match_second == stop_second && times[p].tv_nsec < dates[p]->array[i].stop_nanosecond) { + result = F_true; + } + } } - else { + else if (dates[p]->array[i].operation == kt_remove_flag_date_more_e) { + name_type = kt_remove_date_symbol_more_s; result = F_false; + + if (match_year > start_year) { + result = F_true; + } + else if (match_year == start_year) { + if (match_second > stop_second) { + result = F_true; + } + else if (match_second == stop_second && times[p].tv_nsec >= dates[p]->array[i].stop_nanosecond) { + result = F_true; + } + } } - } - else if (dates[p]->array[i].operation == kt_remove_flag_date_less_equal_e) { - if (times[p].tv_sec < dates[p]->array[i].seconds) { - name_type = kt_remove_date_symbol_less_equal_s; + else if (dates[p]->array[i].operation == kt_remove_flag_date_more_equal_e) { + name_type = kt_remove_date_symbol_more_equal_s; + result = F_false; + + if (match_year > start_year) { + result = F_true; + } + else if (match_year == start_year) { + if (match_second > start_second) { + result = F_true; + } + else if (match_second == start_second && times[p].tv_nsec >= dates[p]->array[i].start_nanosecond) { + result = F_true; + } + } + } + else if (dates[p]->array[i].operation == kt_remove_flag_date_not_e) { + name_type = kt_remove_date_symbol_not_s; result = F_true; + + if (match_year == start_year) { + if (match_second > start_second && match_second < stop_second) { + result = F_false; + } + else if (match_second == start_second && times[p].tv_nsec >= dates[p]->array[i].start_nanosecond && times[p].tv_nsec < dates[p]->array[i].stop_nanosecond) { + result = F_false; + } + } } - else if (times[p].tv_sec == dates[p]->array[i].seconds && times[p].tv_nsec <= dates[p]->array[i].nanoseconds) { - name_type = kt_remove_date_symbol_less_equal_s; + } + else if (dates[p]->array[i].operation == kt_remove_flag_date_equal_e) { + name_type = kt_remove_date_symbol_equal_s; + + if (match_year == start_year && match_second == start_second && times[p].tv_nsec == dates[p]->array[i].start_nanosecond) { result = F_true; } else { result = F_false; } } - else if (dates[p]->array[i].operation == kt_remove_flag_date_more_e) { - if (times[p].tv_sec > dates[p]->array[i].seconds) { - name_type = kt_remove_date_symbol_more_s; + else if (dates[p]->array[i].operation == kt_remove_flag_date_less_e) { + name_type = kt_remove_date_symbol_less_s; + result = F_false; + + if (match_year < start_year) { result = F_true; } - else if (times[p].tv_sec == dates[p]->array[i].seconds && times[p].tv_nsec > dates[p]->array[i].nanoseconds) { - name_type = kt_remove_date_symbol_more_s; + else if (match_year == start_year) { + if (match_second < start_second) { + result = F_true; + } + else if (match_second == start_second && times[p].tv_nsec < dates[p]->array[i].start_nanosecond) { + result = F_true; + } + } + } + else if (dates[p]->array[i].operation == kt_remove_flag_date_less_equal_e) { + name_type = kt_remove_date_symbol_less_equal_s; + result = F_false; + + if (match_year < start_year) { result = F_true; } - else { - result = F_false; + else if (match_year == start_year) { + if (match_second < start_second) { + result = F_true; + } + else if (match_second == start_second && times[p].tv_nsec <= dates[p]->array[i].start_nanosecond) { + result = F_true; + } } } - else if (dates[p]->array[i].operation == kt_remove_flag_date_more_equal_e) { - if (times[p].tv_sec > dates[p]->array[i].seconds) { - name_type = kt_remove_date_symbol_more_equal_s; + else if (dates[p]->array[i].operation == kt_remove_flag_date_more_e) { + name_type = kt_remove_date_symbol_more_s; + result = F_false; + + if (match_year > start_year) { result = F_true; } - else if (times[p].tv_sec == dates[p]->array[i].seconds && times[p].tv_nsec >= dates[p]->array[i].nanoseconds) { - name_type = kt_remove_date_symbol_more_equal_s; + else if (match_year == start_year) { + if (match_second > start_second) { + result = F_true; + } + else if (match_second == start_second && times[p].tv_nsec > dates[p]->array[i].start_nanosecond) { + result = F_true; + } + } + } + else if (dates[p]->array[i].operation == kt_remove_flag_date_more_equal_e) { + name_type = kt_remove_date_symbol_more_equal_s; + result = F_false; + + if (match_year > start_year) { result = F_true; } - else { - result = F_false; + else if (match_year == start_year) { + if (match_second > start_second) { + result = F_true; + } + else if (match_second == start_second && times[p].tv_nsec >= dates[p]->array[i].start_nanosecond) { + result = F_true; + } } } else if (dates[p]->array[i].operation == kt_remove_flag_date_not_e) { - if (times[p].tv_sec != dates[p]->array[i].seconds || times[p].tv_nsec != dates[p]->array[i].nanoseconds) { - name_type = kt_remove_date_symbol_not_s; + name_type = kt_remove_date_symbol_not_s; + + if (match_year != start_year || match_second != start_second || times[p].tv_nsec != dates[p]->array[i].start_nanosecond) { result = F_true; } else { @@ -298,8 +421,8 @@ extern "C" { if (name_type.used) { fll_print_format(" %Q %Q ", main->output.to.stream, *names[p], result ? kt_remove_yes_s : kt_remove_no_s); - fll_print_format("%u::%un 0:%un %Q ", main->output.to.stream, kt_remove_time_year_unix_epoch_d, (f_number_unsigned_t) times[p].tv_sec, (f_number_unsigned_t) times[p].tv_nsec, name_type); - fll_print_format("%u::%un 0:%un%r", main->output.to.stream, kt_remove_time_year_unix_epoch_d, dates[p]->array[i].seconds, dates[p]->array[i].nanoseconds, f_string_eol_s); + fll_print_format("%u::%un 0:%un %Q ", main->output.to.stream, match_year, (f_number_unsigned_t) times[p].tv_sec, (f_number_unsigned_t) times[p].tv_nsec, name_type); + fll_print_format("%u::%un 0:%un%r", main->output.to.stream, dates[p]->array[i].start_year, dates[p]->array[i].start_second, dates[p]->array[i].start_nanosecond, f_string_eol_s); break; } -- 1.8.3.1