From 67fb9254b7000c396942ac95b577efaab5081165 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Sun, 19 Jan 2025 21:01:31 -0600 Subject: [PATCH] Feature: Add several reverse string search functions. These "_back" functions work based on the stop position of the range. --- build/stand_alone/byte_dump.config.h | 12 ++ build/stand_alone/example.config.h | 12 ++ build/stand_alone/fake.config.h | 12 ++ build/stand_alone/firewall.config.h | 12 ++ build/stand_alone/utf8.config.h | 12 ++ level_0/f_string/c/string.c | 59 +++++++++ level_0/f_string/c/string.h | 71 +++++++++++ level_0/f_string/c/string/dynamic.c | 65 ++++++++++ level_0/f_string/c/string/dynamic.h | 76 ++++++++++++ level_0/f_string/data/build/settings-tests | 4 +- .../unit/c/test-string-dynamic_seek_line_back.c | 82 +++++++++++++ .../unit/c/test-string-dynamic_seek_line_back.h | 48 ++++++++ .../unit/c/test-string-dynamic_seek_line_to_back.c | 104 ++++++++++++++++ .../unit/c/test-string-dynamic_seek_line_to_back.h | 55 +++++++++ .../unit/c/test-string-dynamic_seek_to_back.c | 87 +++++++++++++ .../unit/c/test-string-dynamic_seek_to_back.h | 48 ++++++++ .../tests/unit/c/test-string-seek_line_back.c | 66 ++++++++++ .../tests/unit/c/test-string-seek_line_back.h | 41 +++++++ .../tests/unit/c/test-string-seek_line_to_back.c | 87 +++++++++++++ .../tests/unit/c/test-string-seek_line_to_back.h | 48 ++++++++ .../tests/unit/c/test-string-seek_to_back.c | 70 +++++++++++ .../tests/unit/c/test-string-seek_to_back.h | 41 +++++++ level_0/f_string/tests/unit/c/test-string.c | 29 +++++ level_0/f_string/tests/unit/c/test-string.h | 6 + level_0/f_utf/c/utf/dynamic.c | 70 +++++++++++ level_0/f_utf/c/utf/dynamic.h | 79 ++++++++++++ level_0/f_utf/c/utf/string.c | 61 ++++++++++ level_0/f_utf/c/utf/string.h | 71 +++++++++++ level_0/f_utf/c/utf/strings.c | 61 ++++++++++ level_0/f_utf/c/utf/strings.h | 71 +++++++++++ level_0/f_utf/c/utf/stringss.c | 61 ++++++++++ level_0/f_utf/c/utf/stringss.h | 71 +++++++++++ level_0/f_utf/data/build/settings-tests | 4 +- .../tests/unit/c/test-utf-dynamic_seek_line_back.c | 82 +++++++++++++ .../tests/unit/c/test-utf-dynamic_seek_line_back.h | 48 ++++++++ .../unit/c/test-utf-dynamic_seek_line_to_back.c | 104 ++++++++++++++++ .../unit/c/test-utf-dynamic_seek_line_to_back.h | 55 +++++++++ .../tests/unit/c/test-utf-dynamic_seek_to_back.c | 135 +++++++++++++++++++++ .../tests/unit/c/test-utf-dynamic_seek_to_back.h | 55 +++++++++ .../f_utf/tests/unit/c/test-utf-seek_line_back.c | 66 ++++++++++ .../f_utf/tests/unit/c/test-utf-seek_line_back.h | 41 +++++++ .../tests/unit/c/test-utf-seek_line_to_back.c | 87 +++++++++++++ .../tests/unit/c/test-utf-seek_line_to_back.h | 48 ++++++++ level_0/f_utf/tests/unit/c/test-utf-seek_to_back.c | 87 +++++++++++++ level_0/f_utf/tests/unit/c/test-utf-seek_to_back.h | 48 ++++++++ level_0/f_utf/tests/unit/c/test-utf.c | 31 +++++ level_0/f_utf/tests/unit/c/test-utf.h | 6 + 47 files changed, 2585 insertions(+), 4 deletions(-) create mode 100644 level_0/f_string/tests/unit/c/test-string-dynamic_seek_line_back.c create mode 100644 level_0/f_string/tests/unit/c/test-string-dynamic_seek_line_back.h create mode 100644 level_0/f_string/tests/unit/c/test-string-dynamic_seek_line_to_back.c create mode 100644 level_0/f_string/tests/unit/c/test-string-dynamic_seek_line_to_back.h create mode 100644 level_0/f_string/tests/unit/c/test-string-dynamic_seek_to_back.c create mode 100644 level_0/f_string/tests/unit/c/test-string-dynamic_seek_to_back.h create mode 100644 level_0/f_string/tests/unit/c/test-string-seek_line_back.c create mode 100644 level_0/f_string/tests/unit/c/test-string-seek_line_back.h create mode 100644 level_0/f_string/tests/unit/c/test-string-seek_line_to_back.c create mode 100644 level_0/f_string/tests/unit/c/test-string-seek_line_to_back.h create mode 100644 level_0/f_string/tests/unit/c/test-string-seek_to_back.c create mode 100644 level_0/f_string/tests/unit/c/test-string-seek_to_back.h create mode 100644 level_0/f_utf/tests/unit/c/test-utf-dynamic_seek_line_back.c create mode 100644 level_0/f_utf/tests/unit/c/test-utf-dynamic_seek_line_back.h create mode 100644 level_0/f_utf/tests/unit/c/test-utf-dynamic_seek_line_to_back.c create mode 100644 level_0/f_utf/tests/unit/c/test-utf-dynamic_seek_line_to_back.h create mode 100644 level_0/f_utf/tests/unit/c/test-utf-dynamic_seek_to_back.c create mode 100644 level_0/f_utf/tests/unit/c/test-utf-dynamic_seek_to_back.h create mode 100644 level_0/f_utf/tests/unit/c/test-utf-seek_line_back.c create mode 100644 level_0/f_utf/tests/unit/c/test-utf-seek_line_back.h create mode 100644 level_0/f_utf/tests/unit/c/test-utf-seek_line_to_back.c create mode 100644 level_0/f_utf/tests/unit/c/test-utf-seek_line_to_back.h create mode 100644 level_0/f_utf/tests/unit/c/test-utf-seek_to_back.c create mode 100644 level_0/f_utf/tests/unit/c/test-utf-seek_to_back.h diff --git a/build/stand_alone/byte_dump.config.h b/build/stand_alone/byte_dump.config.h index 9b00419..5b5a939 100644 --- a/build/stand_alone/byte_dump.config.h +++ b/build/stand_alone/byte_dump.config.h @@ -833,8 +833,11 @@ #define _di_f_string_dynamic_prepend_assure_nulless_ #define _di_f_string_dynamic_prepend_nulless_ #define _di_f_string_dynamic_seek_line_ +#define _di_f_string_dynamic_seek_line_back_ #define _di_f_string_dynamic_seek_line_to_ +#define _di_f_string_dynamic_seek_line_to_back_ #define _di_f_string_dynamic_seek_to_ +#define _di_f_string_dynamic_seek_to_back_ #define _di_f_string_dynamic_strip_null_ #define _di_f_string_dynamic_strip_null_range_ //#define _di_f_string_dynamic_t_ @@ -999,8 +1002,11 @@ #define _di_f_string_prepend_assure_nulless_ #define _di_f_string_prepend_nulless_ #define _di_f_string_seek_line_ +#define _di_f_string_seek_line_back_ #define _di_f_string_seek_line_to_ +#define _di_f_string_seek_line_to_back_ #define _di_f_string_seek_to_ +#define _di_f_string_seek_to_back_ //#define _di_f_string_space_s_ //#define _di_f_string_static_t_ //#define _di_f_string_statics_t_ @@ -1374,8 +1380,11 @@ #define _di_f_utf_string_dynamic_prepend_assure_nulless_ #define _di_f_utf_string_dynamic_prepend_nulless_ #define _di_f_utf_string_dynamic_seek_line_ +#define _di_f_utf_string_dynamic_seek_line_back_ #define _di_f_utf_string_dynamic_seek_line_to_ +#define _di_f_utf_string_dynamic_seek_line_to_back_ #define _di_f_utf_string_dynamic_seek_to_ +#define _di_f_utf_string_dynamic_seek_to_back_ //#define _di_f_utf_string_dynamic_t_ #define _di_f_utf_string_dynamic_terminate_ #define _di_f_utf_string_dynamic_terminate_after_ @@ -1421,8 +1430,11 @@ #define _di_f_utf_string_prepend_assure_nulless_ #define _di_f_utf_string_prepend_nulless_ #define _di_f_utf_string_seek_line_ +#define _di_f_utf_string_seek_line_back_ #define _di_f_utf_string_seek_line_to_ +#define _di_f_utf_string_seek_line_to_back_ #define _di_f_utf_string_seek_to_ +#define _di_f_utf_string_seek_to_back_ //#define _di_f_utf_string_static_t_ #define _di_f_utf_string_statics_t_ #define _di_f_utf_string_staticss_t_ diff --git a/build/stand_alone/example.config.h b/build/stand_alone/example.config.h index de4490e..f489fc1 100644 --- a/build/stand_alone/example.config.h +++ b/build/stand_alone/example.config.h @@ -784,8 +784,11 @@ #define _di_f_string_dynamic_prepend_assure_nulless_ #define _di_f_string_dynamic_prepend_nulless_ #define _di_f_string_dynamic_seek_line_ +#define _di_f_string_dynamic_seek_line_back_ #define _di_f_string_dynamic_seek_line_to_ +#define _di_f_string_dynamic_seek_line_to_back_ #define _di_f_string_dynamic_seek_to_ +#define _di_f_string_dynamic_seek_to_back_ #define _di_f_string_dynamic_strip_null_ #define _di_f_string_dynamic_strip_null_range_ //#define _di_f_string_dynamic_t_ @@ -950,8 +953,11 @@ #define _di_f_string_prepend_assure_nulless_ #define _di_f_string_prepend_nulless_ #define _di_f_string_seek_line_ +#define _di_f_string_seek_line_back_ #define _di_f_string_seek_line_to_ +#define _di_f_string_seek_line_to_back_ #define _di_f_string_seek_to_ +#define _di_f_string_seek_to_back_ #define _di_f_string_space_s_ //#define _di_f_string_static_t_ //#define _di_f_string_statics_t_ @@ -1339,8 +1345,11 @@ #define _di_f_utf_string_dynamic_prepend_assure_nulless_ #define _di_f_utf_string_dynamic_prepend_nulless_ #define _di_f_utf_string_dynamic_seek_line_ +#define _di_f_utf_string_dynamic_seek_line_back_ #define _di_f_utf_string_dynamic_seek_line_to_ +#define _di_f_utf_string_dynamic_seek_line_to_back_ #define _di_f_utf_string_dynamic_seek_to_ +#define _di_f_utf_string_dynamic_seek_to_back_ #define _di_f_utf_string_dynamic_t_ #define _di_f_utf_string_dynamic_terminate_ #define _di_f_utf_string_dynamic_terminate_after_ @@ -1386,8 +1395,11 @@ #define _di_f_utf_string_prepend_assure_nulless_ #define _di_f_utf_string_prepend_nulless_ #define _di_f_utf_string_seek_line_ +#define _di_f_utf_string_seek_line_back_ #define _di_f_utf_string_seek_line_to_ +#define _di_f_utf_string_seek_line_to_back_ #define _di_f_utf_string_seek_to_ +#define _di_f_utf_string_seek_to_back_ #define _di_f_utf_string_static_t_ #define _di_f_utf_string_statics_t_ #define _di_f_utf_string_staticss_t_ diff --git a/build/stand_alone/fake.config.h b/build/stand_alone/fake.config.h index e534272..c8d3981 100644 --- a/build/stand_alone/fake.config.h +++ b/build/stand_alone/fake.config.h @@ -1265,8 +1265,11 @@ #define _di_f_string_dynamic_prepend_assure_nulless_ #define _di_f_string_dynamic_prepend_nulless_ #define _di_f_string_dynamic_seek_line_ +#define _di_f_string_dynamic_seek_line_back_ #define _di_f_string_dynamic_seek_line_to_ +#define _di_f_string_dynamic_seek_line_to_back_ #define _di_f_string_dynamic_seek_to_ +#define _di_f_string_dynamic_seek_to_back_ #define _di_f_string_dynamic_strip_null_ #define _di_f_string_dynamic_strip_null_range_ //#define _di_f_string_dynamic_t_ @@ -1431,8 +1434,11 @@ #define _di_f_string_prepend_assure_nulless_ #define _di_f_string_prepend_nulless_ #define _di_f_string_seek_line_ +#define _di_f_string_seek_line_back_ #define _di_f_string_seek_line_to_ +#define _di_f_string_seek_line_to_back_ #define _di_f_string_seek_to_ +#define _di_f_string_seek_to_back_ //#define _di_f_string_space_s_ //#define _di_f_string_static_t_ //#define _di_f_string_statics_t_ @@ -1806,8 +1812,11 @@ #define _di_f_utf_string_dynamic_prepend_assure_nulless_ #define _di_f_utf_string_dynamic_prepend_nulless_ #define _di_f_utf_string_dynamic_seek_line_ +#define _di_f_utf_string_dynamic_seek_line_back_ #define _di_f_utf_string_dynamic_seek_line_to_ +#define _di_f_utf_string_dynamic_seek_line_to_back_ #define _di_f_utf_string_dynamic_seek_to_ +#define _di_f_utf_string_dynamic_seek_to_back_ //#define _di_f_utf_string_dynamic_t_ #define _di_f_utf_string_dynamic_terminate_ //#define _di_f_utf_string_dynamic_terminate_after_ @@ -1853,8 +1862,11 @@ #define _di_f_utf_string_prepend_assure_nulless_ #define _di_f_utf_string_prepend_nulless_ #define _di_f_utf_string_seek_line_ +#define _di_f_utf_string_seek_line_back_ #define _di_f_utf_string_seek_line_to_ +#define _di_f_utf_string_seek_line_to_back_ #define _di_f_utf_string_seek_to_ +#define _di_f_utf_string_seek_to_back_ //#define _di_f_utf_string_static_t_ //#define _di_f_utf_string_statics_t_ #define _di_f_utf_string_staticss_t_ diff --git a/build/stand_alone/firewall.config.h b/build/stand_alone/firewall.config.h index 5926c4a..95ec51a 100644 --- a/build/stand_alone/firewall.config.h +++ b/build/stand_alone/firewall.config.h @@ -1314,8 +1314,11 @@ #define _di_f_string_dynamic_prepend_assure_nulless_ #define _di_f_string_dynamic_prepend_nulless_ #define _di_f_string_dynamic_seek_line_ +#define _di_f_string_dynamic_seek_line_back_ #define _di_f_string_dynamic_seek_line_to_ +#define _di_f_string_dynamic_seek_line_to_back_ #define _di_f_string_dynamic_seek_to_ +#define _di_f_string_dynamic_seek_to_back_ #define _di_f_string_dynamic_strip_null_ #define _di_f_string_dynamic_strip_null_range_ //#define _di_f_string_dynamic_t_ @@ -1480,8 +1483,11 @@ #define _di_f_string_prepend_assure_nulless_ #define _di_f_string_prepend_nulless_ #define _di_f_string_seek_line_ +#define _di_f_string_seek_line_back_ #define _di_f_string_seek_line_to_ +#define _di_f_string_seek_line_to_back_ #define _di_f_string_seek_to_ +#define _di_f_string_seek_to_back_ #define _di_f_string_space_s_ //#define _di_f_string_static_t_ //#define _di_f_string_statics_t_ @@ -1869,8 +1875,11 @@ #define _di_f_utf_string_dynamic_prepend_assure_nulless_ #define _di_f_utf_string_dynamic_prepend_nulless_ #define _di_f_utf_string_dynamic_seek_line_ +#define _di_f_utf_string_dynamic_seek_line_back_ #define _di_f_utf_string_dynamic_seek_line_to_ +#define _di_f_utf_string_dynamic_seek_line_to_back_ #define _di_f_utf_string_dynamic_seek_to_ +#define _di_f_utf_string_dynamic_seek_to_back_ #define _di_f_utf_string_dynamic_t_ #define _di_f_utf_string_dynamic_terminate_ #define _di_f_utf_string_dynamic_terminate_after_ @@ -1916,8 +1925,11 @@ #define _di_f_utf_string_prepend_assure_nulless_ #define _di_f_utf_string_prepend_nulless_ #define _di_f_utf_string_seek_line_ +#define _di_f_utf_string_seek_line_back_ #define _di_f_utf_string_seek_line_to_ +#define _di_f_utf_string_seek_line_to_back_ #define _di_f_utf_string_seek_to_ +#define _di_f_utf_string_seek_to_back_ #define _di_f_utf_string_static_t_ #define _di_f_utf_string_statics_t_ #define _di_f_utf_string_staticss_t_ diff --git a/build/stand_alone/utf8.config.h b/build/stand_alone/utf8.config.h index 34d2160..0be76fc 100644 --- a/build/stand_alone/utf8.config.h +++ b/build/stand_alone/utf8.config.h @@ -851,8 +851,11 @@ #define _di_f_string_dynamic_prepend_assure_nulless_ #define _di_f_string_dynamic_prepend_nulless_ #define _di_f_string_dynamic_seek_line_ +#define _di_f_string_dynamic_seek_line_back_ #define _di_f_string_dynamic_seek_line_to_ +#define _di_f_string_dynamic_seek_line_to_back_ #define _di_f_string_dynamic_seek_to_ +#define _di_f_string_dynamic_seek_to_back_ #define _di_f_string_dynamic_strip_null_ #define _di_f_string_dynamic_strip_null_range_ //#define _di_f_string_dynamic_t_ @@ -1017,8 +1020,11 @@ #define _di_f_string_prepend_assure_nulless_ #define _di_f_string_prepend_nulless_ #define _di_f_string_seek_line_ +#define _di_f_string_seek_line_back_ #define _di_f_string_seek_line_to_ +#define _di_f_string_seek_line_to_back_ #define _di_f_string_seek_to_ +#define _di_f_string_seek_to_back_ //#define _di_f_string_space_s_ //#define _di_f_string_static_t_ //#define _di_f_string_statics_t_ @@ -1392,8 +1398,11 @@ #define _di_f_utf_string_dynamic_prepend_assure_nulless_ #define _di_f_utf_string_dynamic_prepend_nulless_ #define _di_f_utf_string_dynamic_seek_line_ +#define _di_f_utf_string_dynamic_seek_line_back_ #define _di_f_utf_string_dynamic_seek_line_to_ +#define _di_f_utf_string_dynamic_seek_line_to_back_ #define _di_f_utf_string_dynamic_seek_to_ +#define _di_f_utf_string_dynamic_seek_to_back_ //#define _di_f_utf_string_dynamic_t_ #define _di_f_utf_string_dynamic_terminate_ #define _di_f_utf_string_dynamic_terminate_after_ @@ -1439,8 +1448,11 @@ #define _di_f_utf_string_prepend_assure_nulless_ #define _di_f_utf_string_prepend_nulless_ #define _di_f_utf_string_seek_line_ +#define _di_f_utf_string_seek_line_back_ #define _di_f_utf_string_seek_line_to_ +#define _di_f_utf_string_seek_line_to_back_ #define _di_f_utf_string_seek_to_ +#define _di_f_utf_string_seek_to_back_ //#define _di_f_utf_string_static_t_ #define _di_f_utf_string_statics_t_ #define _di_f_utf_string_staticss_t_ diff --git a/level_0/f_string/c/string.c b/level_0/f_string/c/string.c index 5b26bc2..cf9b27f 100644 --- a/level_0/f_string/c/string.c +++ b/level_0/f_string/c/string.c @@ -292,6 +292,25 @@ extern "C" { } #endif // _di_f_string_seek_line_ +#ifndef _di_f_string_seek_line_back_ + f_status_t f_string_seek_line_back(const f_string_t string, f_range_t * const range) { + #ifndef _di_level_0_parameter_checking_ + if (!range) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (range->start > range->stop) return F_data_not_stop; + + while (string[range->stop] != f_string_eol_s.string[0]) { + + --range->stop; + + if (range->start > range->stop) return F_okay_stop; + } // while + + return F_okay; + } +#endif // _di_f_string_seek_line_back_ + #ifndef _di_f_string_seek_line_to_ f_status_t f_string_seek_line_to(const f_string_t string, const f_char_t seek_to, f_range_t * const range) { #ifndef _di_level_0_parameter_checking_ @@ -313,6 +332,27 @@ extern "C" { } #endif // _di_f_string_seek_line_to_ +#ifndef _di_f_string_seek_line_to_back_ + f_status_t f_string_seek_line_to_back(const f_string_t string, const f_char_t seek_to, f_range_t * const range) { + #ifndef _di_level_0_parameter_checking_ + if (!range) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (range->start > range->stop) return F_data_not_stop; + + while (string[range->stop] != seek_to) { + + if (string[range->stop] == f_string_eol_s.string[0]) return F_okay_eol; + + --range->stop; + + if (range->start > range->stop) return F_okay_stop; + } // while + + return F_okay; + } +#endif // _di_f_string_seek_line_to_back_ + #ifndef _di_f_string_seek_to_ f_status_t f_string_seek_to(const f_string_t string, const f_char_t seek_to, f_range_t * const range) { #ifndef _di_level_0_parameter_checking_ @@ -332,6 +372,25 @@ extern "C" { } #endif // _di_f_string_seek_to_ +#ifndef _di_f_string_seek_to_back_ + f_status_t f_string_seek_to_back(const f_string_t string, const f_char_t seek_to, f_range_t * const range) { + #ifndef _di_level_0_parameter_checking_ + if (!range) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (range->start > range->stop) return F_data_not_stop; + + while (string[range->stop] != seek_to) { + + --range->stop; + + if (range->start > range->stop) return F_okay_stop; + } // while + + return F_okay; + } +#endif // _di_f_string_seek_to_back_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_0/f_string/c/string.h b/level_0/f_string/c/string.h index a869348..c902e61 100644 --- a/level_0/f_string/c/string.h +++ b/level_0/f_string/c/string.h @@ -419,6 +419,30 @@ extern "C" { #endif // _di_f_string_seek_line_ /** + * Seek the string location backward until EOL is reached. + * + * @param string + * The string to traverse. + * @param range + * A range within the buffer representing the start and stop locations. + * The stop location will be decremented by the seek. + * + * @return + * F_okay on success. + * F_okay_stop on success, but stopped at end of range. + * F_data_not_stop on success, but the range.start > range.stop. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_memory_resize(). + * + * @see f_memory_resize() + */ +#ifndef _di_f_string_seek_line_back_ + extern f_status_t f_string_seek_line_back(const f_string_t string, f_range_t * const range); +#endif // _di_f_string_seek_line_back_ + +/** * Seek the string location forward until the character (1-byte wide) or EOL is reached. * * @param string @@ -442,6 +466,29 @@ extern "C" { #endif // _di_f_string_seek_line_to_ /** + * Seek the string location backward until the character (1-byte wide) or EOL is reached. + * + * @param string + * The string to traverse. + * @param seek_to + * A single-width character representing a character to seek to. + * @param range + * A range within the buffer representing the start and stop locations. + * The stop location will be decrementd by the seek. + * + * @return + * F_okay on success. + * F_okay_eol on success, but stopped at EOL. + * F_okay_stop on success, but stopped at the stop location. + * F_data_not_stop if range.start > range.stop. + * + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_string_seek_line_to_back_ + extern f_status_t f_string_seek_line_to_back(const f_string_t string, const f_char_t seek_to, f_range_t * const range); +#endif // _di_f_string_seek_line_to_back_ + +/** * Seek the string location forward until the character (1-byte wide) is reached. * * @param string @@ -465,6 +512,30 @@ extern "C" { extern f_status_t f_string_seek_to(const f_string_t string, const f_char_t seek_to, f_range_t * const range); #endif // _di_f_string_seek_to_ +/** + * Seek the string location backward until the character (1-byte wide) is reached. + * + * @param string + * The string to traverse. + * @param seek_to + * A single-width character representing a character to seek to. + * @param range + * A range within the buffer representing the start and stop locations. + * The stop location will be decremented by the seek. + * + * @return + * F_okay on success. + * F_okay_stop on success, but stopped at the stop location. + * F_data_not_stop if range.start > range.stop. + * + * F_complete_not_utf (with error bit) if character is an incomplete UTF-8 fragment. + * F_complete_not_utf_stop (with error bit) if the stop location is reached before the complete UTF-8 character can be processed. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_string_seek_to_back_ + extern f_status_t f_string_seek_to_back(const f_string_t string, const f_char_t seek_to, f_range_t * const range); +#endif // _di_f_string_seek_to_back_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_0/f_string/c/string/dynamic.c b/level_0/f_string/c/string/dynamic.c index 8806fff..604bc6c 100644 --- a/level_0/f_string/c/string/dynamic.c +++ b/level_0/f_string/c/string/dynamic.c @@ -578,6 +578,27 @@ extern "C" { } #endif // _di_f_string_dynamic_seek_line_ +#ifndef _di_f_string_dynamic_seek_line_back_ + f_status_t f_string_dynamic_seek_line_back(const f_string_static_t buffer, f_range_t * const range) { + #ifndef _di_level_0_parameter_checking_ + if (!range) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.used) return F_data_not; + if (range->start > range->stop) return F_data_not_stop; + + while (buffer.string[range->stop] != f_string_eol_s.string[0]) { + + --range->stop; + + if (!range->stop) return (buffer.string[range->stop] == f_string_eol_s.string[0]) ? F_okay : F_okay_eos; + if (range->start > range->stop) return F_okay_stop; + } // while + + return F_okay; + } +#endif // _di_f_string_dynamic_seek_line_back_ + #ifndef _di_f_string_dynamic_seek_line_to_ f_status_t f_string_dynamic_seek_line_to(const f_string_static_t buffer, const f_char_t seek_to_this, f_range_t * const range) { #ifndef _di_level_0_parameter_checking_ @@ -601,6 +622,29 @@ extern "C" { } #endif // _di_f_string_dynamic_seek_line_to_ +#ifndef _di_f_string_dynamic_seek_line_to_back_ + f_status_t f_string_dynamic_seek_line_to_back(const f_string_static_t buffer, const f_char_t seek_to_this, f_range_t * const range) { + #ifndef _di_level_0_parameter_checking_ + if (!range) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.used) return F_data_not; + if (range->start > range->stop) return F_data_not_stop; + + while (buffer.string[range->stop] != seek_to_this) { + + if (buffer.string[range->stop] == f_string_eol_s.string[0]) return F_okay_eol; + + --range->stop; + + if (!range->stop) return (buffer.string[0] == seek_to_this) ? F_okay : F_okay_eos; + if (range->start > range->stop) return F_okay_stop; + } // while + + return F_okay; + } +#endif // _di_f_string_dynamic_seek_line_to_back_ + #ifndef _di_f_string_dynamic_seek_to_ f_status_t f_string_dynamic_seek_to(const f_string_static_t buffer, const f_char_t seek_to_this, f_range_t * const range) { #ifndef _di_level_0_parameter_checking_ @@ -622,6 +666,27 @@ extern "C" { } #endif // _di_f_string_dynamic_seek_to_ +#ifndef _di_f_string_dynamic_seek_to_back_ + f_status_t f_string_dynamic_seek_to_back(const f_string_static_t buffer, const f_char_t seek_to_this, f_range_t * const range) { + #ifndef _di_level_0_parameter_checking_ + if (!range) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.used) return F_data_not; + if (range->start > range->stop) return F_data_not_stop; + + while (buffer.string[range->stop] != seek_to_this) { + + --range->stop; + + if (!range->stop) return (buffer.string[0] == seek_to_this) ? F_okay : F_okay_eos; + if (range->start > range->stop) return F_okay_stop; + } // while + + return F_okay; + } +#endif // _di_f_string_dynamic_seek_to_back_ + #ifndef _di_f_string_dynamic_strip_null_ f_status_t f_string_dynamic_strip_null(f_string_dynamic_t * const buffer) { #ifndef _di_level_0_parameter_checking_ diff --git a/level_0/f_string/c/string/dynamic.h b/level_0/f_string/c/string/dynamic.h index d18299c..96add53 100644 --- a/level_0/f_string/c/string/dynamic.h +++ b/level_0/f_string/c/string/dynamic.h @@ -690,6 +690,30 @@ extern "C" { #endif // _di_f_string_dynamic_seek_line_ /** + * Seek the buffer location backward until EOL is reached. + * + * @param buffer + * The buffer to traverse. + * @param range + * A range within the buffer representing the start and stop locations. + * The stop location will be decremented by the seek. + * + * @return + * F_okay on success. + * F_okay_eos on success, but stopped at end of string. + * F_okay_stop on success, but stopped at end of range. + * F_data_not on success, but there was no string data to seek. + * F_data_not_stop on success, but the range.start > range.stop. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_memory_resize(). + */ +#ifndef _di_f_string_dynamic_seek_line_back_ + extern f_status_t f_string_dynamic_seek_line_back(const f_string_static_t buffer, f_range_t * const range); +#endif // _di_f_string_dynamic_seek_line_back_ + +/** * Seek the buffer location forward until the character (1-byte wide) or EOL is reached. * * @param buffer @@ -716,6 +740,32 @@ extern "C" { #endif // _di_f_string_dynamic_seek_line_to_ /** + * Seek the buffer location backward until the character (1-byte wide) or EOL is reached. + * + * @param buffer + * The buffer to traverse. + * @param seek_to_this + * A single-width character representing a character to seek to. + * @param range + * A range within the buffer representing the start and stop locations. + * The stop location will be decremented by the seek. + * + * @return + * F_okay on success. + * F_okay_eos on success, but stopped at end of string. + * F_okay_stop on success, but stopped at end of range. + * F_data_not on success, but there was no string data to seek. + * F_data_not_stop on success, but the range.start > range.stop. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_memory_resize(). + */ +#ifndef _di_f_string_dynamic_seek_line_to_back_ + extern f_status_t f_string_dynamic_seek_line_to_back(const f_string_static_t buffer, const f_char_t seek_to_this, f_range_t * const range); +#endif // _di_f_string_dynamic_seek_line_to_back_ + +/** * Seek the buffer location forward until the character (1-byte wide) is reached. * * @param buffer @@ -742,6 +792,32 @@ extern "C" { #endif // _di_f_string_dynamic_seek_to_ /** + * Seek the buffer location backward until the character (1-byte wide) is reached. + * + * @param buffer + * The buffer to traverse. + * @param seek_to_this + * A single-width character representing a character to seek to. + * @param range + * A range within the buffer representing the start and stop locations. + * The stop location will be decremented by the seek. + * + * @return + * F_okay on success. + * F_okay_eos on success, but stopped at end of string. + * F_okay_stop on success, but stopped at end of range. + * F_data_not on success, but there was no string data to seek. + * F_data_not_stop on success, but the range.start > range.stop. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_memory_resize(). + */ +#ifndef _di_f_string_dynamic_seek_to_back_ + extern f_status_t f_string_dynamic_seek_to_back(const f_string_static_t buffer, const f_char_t seek_to_this, f_range_t * const range); +#endif // _di_f_string_dynamic_seek_to_back_ + +/** * String all NULLs from the given string. * * This does not resize the string. diff --git a/level_0/f_string/data/build/settings-tests b/level_0/f_string/data/build/settings-tests index d2f5822..8278496 100644 --- a/level_0/f_string/data/build/settings-tests +++ b/level_0/f_string/data/build/settings-tests @@ -34,7 +34,7 @@ build_sources_program test-string-dynamic_partial_mash.c test-string-dynamic_par build_sources_program test-string-dynamic_partial_mish.c test-string-dynamic_partial_mish_nulless.c build_sources_program test-string-dynamic_partial_prepend.c test-string-dynamic_partial_prepend_assure.c test-string-dynamic_partial_prepend_assure_nulless.c test-string-dynamic_partial_prepend_nulless.c build_sources_program test-string-dynamic_prepend.c test-string-dynamic_prepend_assure.c test-string-dynamic_prepend_assure_nulless.c test-string-dynamic_prepend_nulless.c -build_sources_program test-string-dynamic_seek_line.c test-string-dynamic_seek_line_to.c test-string-dynamic_seek_to.c +build_sources_program test-string-dynamic_seek_line.c test-string-dynamic_seek_line_back.c test-string-dynamic_seek_line_to.c test-string-dynamic_seek_line_to_back.c test-string-dynamic_seek_to.c test-string-dynamic_seek_to_back.c build_sources_program test-string-dynamic_strip_null.c test-string-dynamic_strip_null_range.c build_sources_program test-string-dynamic_terminate.c test-string-dynamic_terminate_after.c build_sources_program test-string-dynamics_append.c test-string-dynamics_append_all.c test-string-dynamicss_append.c test-string-dynamicss_append_all.c @@ -49,7 +49,7 @@ build_sources_program test-string-mapss_delete_callback.c test-string-mapss_dest build_sources_program test-string-mash.c test-string-mash_nulless.c build_sources_program test-string-mish.c test-string-mish_nulless.c build_sources_program test-string-prepend.c test-string-prepend_assure.c test-string-prepend_assure_nulless.c test-string-prepend_nulless.c -build_sources_program test-string-seek_line.c test-string-seek_line_to.c test-string-seek_to.c +build_sources_program test-string-seek_line.c test-string-seek_line_back.c test-string-seek_line_to.c test-string-seek_line_to_back.c test-string-seek_to.c test-string-seek_to_back.c build_sources_program test-string-triples_append.c test-string-triples_append_all.c test-string-tripless_append.c test-string-tripless_append_all.c build_sources_program test-string-triples_delete_callback.c test-string-triples_destroy_callback.c build_sources_program test-string-tripless_delete_callback.c test-string-tripless_destroy_callback.c diff --git a/level_0/f_string/tests/unit/c/test-string-dynamic_seek_line_back.c b/level_0/f_string/tests/unit/c/test-string-dynamic_seek_line_back.c new file mode 100644 index 0000000..b065ebd --- /dev/null +++ b/level_0/f_string/tests/unit/c/test-string-dynamic_seek_line_back.c @@ -0,0 +1,82 @@ +#include "test-string.h" +#include "test-string-dynamic_seek_line_back.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_string_dynamic_seek_line_back__parameter_checking(void **state) { + + const f_string_static_t source = macro_f_string_static_t_initialize_1("teX\nst", 0, 6); + + { + const f_status_t status = f_string_dynamic_seek_line_back(source, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +void test__f_string_dynamic_seek_line_back__returns_data_not_stop(void **state) { + + const f_string_static_t source = macro_f_string_static_t_initialize_1("test\nafter", 0, 10); + + { + f_range_t range = f_range_t_initialize; + + const f_status_t status = f_string_dynamic_seek_line_back(source, &range); + + assert_int_equal(status, F_data_not_stop); + } +} + +void test__f_string_dynamic_seek_line_back__returns_none_eos(void **state) { + + const f_string_static_t source = macro_f_string_static_t_initialize_1("test", 0, 4); + + { + f_range_t range = macro_f_range_t_initialize_1(0, source.used - 1); + + const f_status_t status = f_string_dynamic_seek_line_back(source, &range); + + assert_int_equal(status, F_okay_eos); + + assert_int_equal(range.start, 0); + assert_int_equal(range.stop, 0); + } +} + +void test__f_string_dynamic_seek_line_back__returns_none_stop(void **state) { + + const f_string_static_t source = macro_f_string_static_t_initialize_1("test", 0, 4); + + { + f_range_t range = macro_f_range_t_initialize_1(2, source.used - 1); + + const f_status_t status = f_string_dynamic_seek_line_back(source, &range); + + assert_int_equal(status, F_okay_stop); + + assert_int_equal(range.start, 2); + assert_int_equal(range.stop, 1); + } +} + +void test__f_string_dynamic_seek_line_back__works(void **state) { + + const f_string_static_t source = macro_f_string_static_t_initialize_1("test\nafter", 0, 10); + + { + f_range_t range = macro_f_range_t_initialize_1(0, source.used - 1); + + const f_status_t status = f_string_dynamic_seek_line_back(source, &range); + + assert_int_equal(status, F_okay); + + assert_int_equal(range.start, 0); + assert_int_equal(range.stop, 4); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_string/tests/unit/c/test-string-dynamic_seek_line_back.h b/level_0/f_string/tests/unit/c/test-string-dynamic_seek_line_back.h new file mode 100644 index 0000000..d2f821d --- /dev/null +++ b/level_0/f_string/tests/unit/c/test-string-dynamic_seek_line_back.h @@ -0,0 +1,48 @@ +/** + * FLL - Level 0 + * + * Project: String + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the functions in the string project. + */ +#ifndef _TEST__F_string_dynamic_seek_line_back_h +#define _TEST__F_string_dynamic_seek_line_back_h + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_string_dynamic_seek_line_back() + */ +extern void test__f_string_dynamic_seek_line_back__parameter_checking(void **state); + +/** + * Test that the function returns F_data_not_stop because range is an empty range (range.start > range.stop). + * + * @see f_string_dynamic_seek_line_back() + */ +extern void test__f_string_dynamic_seek_line_back__returns_data_not_stop(void **state); + +/** + * Test that the function returns F_okay_eos stopped after end of string because no newline is found. + * + * @see f_string_dynamic_seek_line_back() + */ +extern void test__f_string_dynamic_seek_line_back__returns_none_eos(void **state); + +/** + * Test that the function returns F_okay_stop stopped after end of range because no newline is found. + * + * @see f_string_dynamic_seek_line_back() + */ +extern void test__f_string_dynamic_seek_line_back__returns_none_stop(void **state); + +/** + * Test that the function works. + * + * @see f_string_dynamic_seek_line_back() + */ +extern void test__f_string_dynamic_seek_line_back__works(void **state); + +#endif // _TEST__F_string_dynamic_seek_line_back_h diff --git a/level_0/f_string/tests/unit/c/test-string-dynamic_seek_line_to_back.c b/level_0/f_string/tests/unit/c/test-string-dynamic_seek_line_to_back.c new file mode 100644 index 0000000..3a6f83b --- /dev/null +++ b/level_0/f_string/tests/unit/c/test-string-dynamic_seek_line_to_back.c @@ -0,0 +1,104 @@ +#include "test-string.h" +#include "test-string-dynamic_seek_line_to_back.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_string_dynamic_seek_line_to_back__at_newline(void **state) { + + const f_string_static_t to = macro_f_string_static_t_initialize_1("X", 0, 1); + const f_string_static_t source = macro_f_string_static_t_initialize_1("te\nXst", 0, 6); + + { + f_range_t range = macro_f_range_t_initialize_1(0, source.used - 1); + + const f_status_t status = f_string_dynamic_seek_line_to_back(source, to.string[0], &range); + + assert_int_equal(status, F_okay); + + assert_int_equal(range.start, 0); + assert_int_equal(range.stop, 3); + } +} + +void test__f_string_dynamic_seek_line_to_back__parameter_checking(void **state) { + + const f_string_static_t to = macro_f_string_static_t_initialize_1("X", 0, 1); + const f_string_static_t source = macro_f_string_static_t_initialize_1("teX\nst", 0, 6); + + { + const f_status_t status = f_string_dynamic_seek_line_to_back(source, to.string[0], 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +void test__f_string_dynamic_seek_line_to_back__returns_data_not_stop(void **state) { + + const f_string_static_t to = macro_f_string_static_t_initialize_1("X", 0, 1); + const f_string_static_t source = macro_f_string_static_t_initialize_1("test\nafter", 0, 10); + + { + f_range_t range = f_range_t_initialize; + + const f_status_t status = f_string_dynamic_seek_line_to_back(source, to.string[0], &range); + + assert_int_equal(status, F_data_not_stop); + } +} + +void test__f_string_dynamic_seek_line_to_back__returns_none_eos(void **state) { + + const f_string_static_t to = macro_f_string_static_t_initialize_1("X", 0, 1); + const f_string_static_t source = macro_f_string_static_t_initialize_1("test", 0, 4); + + { + f_range_t range = macro_f_range_t_initialize_1(0, source.used - 1); + + const f_status_t status = f_string_dynamic_seek_line_to_back(source, to.string[0], &range); + + assert_int_equal(status, F_okay_eos); + + assert_int_equal(range.start, 0); + assert_int_equal(range.stop, 0); + } +} + +void test__f_string_dynamic_seek_line_to_back__returns_none_stop(void **state) { + + const f_string_static_t to = macro_f_string_static_t_initialize_1("X", 0, 1); + const f_string_static_t source = macro_f_string_static_t_initialize_1("test", 0, 4); + + { + f_range_t range = macro_f_range_t_initialize_1(2, source.used - 1); + + const f_status_t status = f_string_dynamic_seek_line_to_back(source, to.string[0], &range); + + assert_int_equal(status, F_okay_stop); + + assert_int_equal(range.start, 2); + assert_int_equal(range.stop, 1); + } +} + +void test__f_string_dynamic_seek_line_to_back__works(void **state) { + + const f_string_static_t to = macro_f_string_static_t_initialize_1("X", 0, 1); + const f_string_static_t source = macro_f_string_static_t_initialize_1("teX\nst", 0, 6); + + { + f_range_t range = macro_f_range_t_initialize_1(0, source.used - 1); + + const f_status_t status = f_string_dynamic_seek_line_to_back(source, to.string[0], &range); + + assert_int_equal(status, F_okay_eol); + + assert_int_equal(range.start, 0); + assert_int_equal(range.stop, 3); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_string/tests/unit/c/test-string-dynamic_seek_line_to_back.h b/level_0/f_string/tests/unit/c/test-string-dynamic_seek_line_to_back.h new file mode 100644 index 0000000..c197d48 --- /dev/null +++ b/level_0/f_string/tests/unit/c/test-string-dynamic_seek_line_to_back.h @@ -0,0 +1,55 @@ +/** + * FLL - Level 0 + * + * Project: String + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the functions in the string project. + */ +#ifndef _TEST__F_string_dynamic_seek_line_to_back_h +#define _TEST__F_string_dynamic_seek_line_to_back_h + +/** + * Test that the function works but stops at newline rather than search string. + * + * @see f_string_dynamic_seek_line_to_back() + */ +extern void test__f_string_dynamic_seek_line_to_back__at_newline(void **state); + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_string_dynamic_seek_line_to_back() + */ +extern void test__f_string_dynamic_seek_line_to_back__parameter_checking(void **state); + +/** + * Test that the function returns F_data_not_stop because range is an empty range (range.start > range.stop). + * + * @see f_string_dynamic_seek_line_to_back() + */ +extern void test__f_string_dynamic_seek_line_to_back__returns_data_not_stop(void **state); + +/** + * Test that the function returns F_okay_eos stopped after end of string because no newline is found. + * + * @see f_string_dynamic_seek_line_to_back() + */ +extern void test__f_string_dynamic_seek_line_to_back__returns_none_eos(void **state); + +/** + * Test that the function returns F_okay_stop stopped after end of range because no newline is found. + * + * @see f_string_dynamic_seek_line_to_back() + */ +extern void test__f_string_dynamic_seek_line_to_back__returns_none_stop(void **state); + +/** + * Test that the function works. + * + * @see f_string_dynamic_seek_line_to_back() + */ +extern void test__f_string_dynamic_seek_line_to_back__works(void **state); + +#endif // _TEST__F_string_dynamic_seek_line_to_back_h diff --git a/level_0/f_string/tests/unit/c/test-string-dynamic_seek_to_back.c b/level_0/f_string/tests/unit/c/test-string-dynamic_seek_to_back.c new file mode 100644 index 0000000..2fd2df4 --- /dev/null +++ b/level_0/f_string/tests/unit/c/test-string-dynamic_seek_to_back.c @@ -0,0 +1,87 @@ +#include "test-string.h" +#include "test-string-dynamic_seek_to_back.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_string_dynamic_seek_to_back__parameter_checking(void **state) { + + const f_string_static_t to = macro_f_string_static_t_initialize_1("X", 0, 1); + const f_string_static_t source = macro_f_string_static_t_initialize_1("teX\nst", 0, 6); + + { + const f_status_t status = f_string_dynamic_seek_to_back(source, to.string[0], 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +void test__f_string_dynamic_seek_to_back__returns_data_not_stop(void **state) { + + const f_string_static_t to = macro_f_string_static_t_initialize_1("X", 0, 1); + const f_string_static_t source = macro_f_string_static_t_initialize_1("test\nafter", 0, 10); + + { + f_range_t range = f_range_t_initialize; + + const f_status_t status = f_string_dynamic_seek_to_back(source, to.string[0], &range); + + assert_int_equal(status, F_data_not_stop); + } +} + +void test__f_string_dynamic_seek_to_back__returns_none_eos(void **state) { + + const f_string_static_t to = macro_f_string_static_t_initialize_1("X", 0, 1); + const f_string_static_t source = macro_f_string_static_t_initialize_1("test\nafter", 0, 10); + + { + f_range_t range = macro_f_range_t_initialize_1(0, source.used - 1); + + const f_status_t status = f_string_dynamic_seek_to_back(source, to.string[0], &range); + + assert_int_equal(status, F_okay_eos); + + assert_int_equal(range.start, 0); + assert_int_equal(range.stop, 0); + } +} + +void test__f_string_dynamic_seek_to_back__returns_none_stop(void **state) { + + const f_string_static_t to = macro_f_string_static_t_initialize_1("X", 0, 1); + const f_string_static_t source = macro_f_string_static_t_initialize_1("test\nafter", 0, 10); + + { + f_range_t range = macro_f_range_t_initialize_1(2, source.used - 1); + + const f_status_t status = f_string_dynamic_seek_to_back(source, to.string[0], &range); + + assert_int_equal(status, F_okay_stop); + + assert_int_equal(range.start, 2); + assert_int_equal(range.stop, 1); + } +} + +void test__f_string_dynamic_seek_to_back__works(void **state) { + + const f_string_static_t to = macro_f_string_static_t_initialize_1("X", 0, 1); + const f_string_static_t source = macro_f_string_static_t_initialize_1("te\nXst", 0, 6); + + { + f_range_t range = macro_f_range_t_initialize_1(0, source.used - 1); + + const f_status_t status = f_string_dynamic_seek_to_back(source, to.string[0], &range); + + assert_int_equal(status, F_okay); + + assert_int_equal(range.start, 0); + assert_int_equal(range.stop, 3); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_string/tests/unit/c/test-string-dynamic_seek_to_back.h b/level_0/f_string/tests/unit/c/test-string-dynamic_seek_to_back.h new file mode 100644 index 0000000..e62069b --- /dev/null +++ b/level_0/f_string/tests/unit/c/test-string-dynamic_seek_to_back.h @@ -0,0 +1,48 @@ +/** + * FLL - Level 0 + * + * Project: String + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the functions in the string project. + */ +#ifndef _TEST__F_string_dynamic_seek_to_back_h +#define _TEST__F_string_dynamic_seek_to_back_h + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_string_dynamic_seek_to_back() + */ +extern void test__f_string_dynamic_seek_to_back__parameter_checking(void **state); + +/** + * Test that the function returns F_data_not_stop because range is an empty range (range.start > range.stop). + * + * @see f_string_dynamic_seek_to_back() + */ +extern void test__f_string_dynamic_seek_to_back__returns_data_not_stop(void **state); + +/** + * Test that the function returns F_okay_eos stopped after end of string because no newline is found. + * + * @see f_string_dynamic_seek_to_back() + */ +extern void test__f_string_dynamic_seek_to_back__returns_none_eos(void **state); + +/** + * Test that the function returns F_okay_stop stopped after end of range because no newline is found. + * + * @see f_string_dynamic_seek_to_back() + */ +extern void test__f_string_dynamic_seek_to_back__returns_none_stop(void **state); + +/** + * Test that the function works. + * + * @see f_string_dynamic_seek_to_back() + */ +extern void test__f_string_dynamic_seek_to_back__works(void **state); + +#endif // _TEST__F_string_dynamic_seek_to_back_h diff --git a/level_0/f_string/tests/unit/c/test-string-seek_line_back.c b/level_0/f_string/tests/unit/c/test-string-seek_line_back.c new file mode 100644 index 0000000..e8422b3 --- /dev/null +++ b/level_0/f_string/tests/unit/c/test-string-seek_line_back.c @@ -0,0 +1,66 @@ +#include "test-string.h" +#include "test-string-seek_line_back.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_string_seek_line_back__parameter_checking(void **state) { + + const f_string_static_t source = macro_f_string_static_t_initialize_1("teX\nst", 0, 6); + + { + const f_status_t status = f_string_seek_line_back(source.string, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +void test__f_string_seek_line_back__returns_data_not_stop(void **state) { + + const f_string_static_t source = macro_f_string_static_t_initialize_1("test\nafter", 0, 10); + + { + f_range_t range = f_range_t_initialize; + + const f_status_t status = f_string_seek_line_back(source.string, &range); + + assert_int_equal(status, F_data_not_stop); + } +} + +void test__f_string_seek_line_back__returns_none_stop(void **state) { + + const f_string_static_t source = macro_f_string_static_t_initialize_1("test", 0, 4); + + { + f_range_t range = macro_f_range_t_initialize_1(2, source.used - 1); + + const f_status_t status = f_string_seek_line_back(source.string, &range); + + assert_int_equal(status, F_okay_stop); + + assert_int_equal(range.start, 2); + assert_int_equal(range.stop, 1); + } +} + +void test__f_string_seek_line_back__works(void **state) { + + const f_string_static_t source = macro_f_string_static_t_initialize_1("test\nafter", 0, 10); + + { + f_range_t range = macro_f_range_t_initialize_1(0, source.used - 1); + + const f_status_t status = f_string_seek_line_back(source.string, &range); + + assert_int_equal(status, F_okay); + + assert_int_equal(range.start, 0); + assert_int_equal(range.stop, 4); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_string/tests/unit/c/test-string-seek_line_back.h b/level_0/f_string/tests/unit/c/test-string-seek_line_back.h new file mode 100644 index 0000000..f36a17c --- /dev/null +++ b/level_0/f_string/tests/unit/c/test-string-seek_line_back.h @@ -0,0 +1,41 @@ +/** + * FLL - Level 0 + * + * Project: String + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the functions in the string project. + */ +#ifndef _TEST__F_string_seek_line_back_h +#define _TEST__F_string_seek_line_back_h + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_string_seek_line_back() + */ +extern void test__f_string_seek_line_back__parameter_checking(void **state); + +/** + * Test that the function returns F_data_not_stop because range is an empty range (range.start > range.stop). + * + * @see f_string_seek_line_back() + */ +extern void test__f_string_seek_line_back__returns_data_not_stop(void **state); + +/** + * Test that the function returns F_okay_stop stopped after end of range because no newline is found. + * + * @see f_string_seek_line_back() + */ +extern void test__f_string_seek_line_back__returns_none_stop(void **state); + +/** + * Test that the function works. + * + * @see f_string_seek_line_back() + */ +extern void test__f_string_seek_line_back__works(void **state); + +#endif // _TEST__F_string_seek_line_back_h diff --git a/level_0/f_string/tests/unit/c/test-string-seek_line_to_back.c b/level_0/f_string/tests/unit/c/test-string-seek_line_to_back.c new file mode 100644 index 0000000..7ade414 --- /dev/null +++ b/level_0/f_string/tests/unit/c/test-string-seek_line_to_back.c @@ -0,0 +1,87 @@ +#include "test-string.h" +#include "test-string-seek_line_to_back.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_string_seek_line_to_back__at_newline(void **state) { + + const f_string_static_t to = macro_f_string_static_t_initialize_1("X", 0, 1); + const f_string_static_t source = macro_f_string_static_t_initialize_1("te\nXst", 0, 6); + + { + f_range_t range = macro_f_range_t_initialize_1(0, source.used - 1); + + const f_status_t status = f_string_seek_line_to_back(source.string, to.string[0], &range); + + assert_int_equal(status, F_okay); + + assert_int_equal(range.start, 0); + assert_int_equal(range.stop, 3); + } +} + +void test__f_string_seek_line_to_back__parameter_checking(void **state) { + + const f_string_static_t to = macro_f_string_static_t_initialize_1("X", 0, 1); + const f_string_static_t source = macro_f_string_static_t_initialize_1("teX\nst", 0, 6); + + { + const f_status_t status = f_string_seek_line_to_back(source.string, to.string[0], 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +void test__f_string_seek_line_to_back__returns_data_not_stop(void **state) { + + const f_string_static_t to = macro_f_string_static_t_initialize_1("X", 0, 1); + const f_string_static_t source = macro_f_string_static_t_initialize_1("test\nafter", 0, 10); + + { + f_range_t range = f_range_t_initialize; + + const f_status_t status = f_string_seek_line_to_back(source.string, to.string[0], &range); + + assert_int_equal(status, F_data_not_stop); + } +} + +void test__f_string_seek_line_to_back__returns_none_stop(void **state) { + + const f_string_static_t to = macro_f_string_static_t_initialize_1("X", 0, 1); + const f_string_static_t source = macro_f_string_static_t_initialize_1("test", 0, 4); + + { + f_range_t range = macro_f_range_t_initialize_1(2, source.used - 1); + + const f_status_t status = f_string_seek_line_to_back(source.string, to.string[0], &range); + + assert_int_equal(status, F_okay_stop); + + assert_int_equal(range.start, 2); + assert_int_equal(range.stop, 1); + } +} + +void test__f_string_seek_line_to_back__works(void **state) { + + const f_string_static_t to = macro_f_string_static_t_initialize_1("X", 0, 1); + const f_string_static_t source = macro_f_string_static_t_initialize_1("teX\nst", 0, 6); + + { + f_range_t range = macro_f_range_t_initialize_1(0, source.used - 1); + + const f_status_t status = f_string_seek_line_to_back(source.string, to.string[0], &range); + + assert_int_equal(status, F_okay_eol); + + assert_int_equal(range.start, 0); + assert_int_equal(range.stop, 3); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_string/tests/unit/c/test-string-seek_line_to_back.h b/level_0/f_string/tests/unit/c/test-string-seek_line_to_back.h new file mode 100644 index 0000000..00e5753 --- /dev/null +++ b/level_0/f_string/tests/unit/c/test-string-seek_line_to_back.h @@ -0,0 +1,48 @@ +/** + * FLL - Level 0 + * + * Project: String + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the functions in the string project. + */ +#ifndef _TEST__F_string_seek_line_to_back_h +#define _TEST__F_string_seek_line_to_back_h + +/** + * Test that the function works but stops at newline rather than search string. + * + * @see f_string_seek_line_to_back() + */ +extern void test__f_string_seek_line_to_back__at_newline(void **state); + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_string_seek_line_to_back() + */ +extern void test__f_string_seek_line_to_back__parameter_checking(void **state); + +/** + * Test that the function returns F_data_not_stop because range is an empty range (range.start > range.stop). + * + * @see f_string_seek_line_to_back() + */ +extern void test__f_string_seek_line_to_back__returns_data_not_stop(void **state); + +/** + * Test that the function returns F_okay_stop stopped after end of range because no newline is found. + * + * @see f_string_seek_line_to_back() + */ +extern void test__f_string_seek_line_to_back__returns_none_stop(void **state); + +/** + * Test that the function works. + * + * @see f_string_seek_line_to_back() + */ +extern void test__f_string_seek_line_to_back__works(void **state); + +#endif // _TEST__F_string_seek_line_to_back_h diff --git a/level_0/f_string/tests/unit/c/test-string-seek_to_back.c b/level_0/f_string/tests/unit/c/test-string-seek_to_back.c new file mode 100644 index 0000000..18fe24a --- /dev/null +++ b/level_0/f_string/tests/unit/c/test-string-seek_to_back.c @@ -0,0 +1,70 @@ +#include "test-string.h" +#include "test-string-seek_to.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_string_seek_to_back__parameter_checking(void **state) { + + const f_string_static_t to = macro_f_string_static_t_initialize_1("X", 0, 1); + const f_string_static_t source = macro_f_string_static_t_initialize_1("teX\nst", 0, 6); + + { + const f_status_t status = f_string_seek_to_back(source.string, to.string[0], 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +void test__f_string_seek_to_back__returns_data_not_stop(void **state) { + + const f_string_static_t to = macro_f_string_static_t_initialize_1("X", 0, 1); + const f_string_static_t source = macro_f_string_static_t_initialize_1("test\nafter", 0, 10); + + { + f_range_t range = f_range_t_initialize; + + const f_status_t status = f_string_seek_to_back(source.string, to.string[0], &range); + + assert_int_equal(status, F_data_not_stop); + } +} + +void test__f_string_seek_to_back__returns_none_stop(void **state) { + + const f_string_static_t to = macro_f_string_static_t_initialize_1("X", 0, 1); + const f_string_static_t source = macro_f_string_static_t_initialize_1("test\nafter", 0, 10); + + { + f_range_t range = macro_f_range_t_initialize_1(2, source.used - 1); + + const f_status_t status = f_string_seek_to_back(source.string, to.string[0], &range); + + assert_int_equal(status, F_okay_stop); + + assert_int_equal(range.start, 2); + assert_int_equal(range.stop, 1); + } +} + +void test__f_string_seek_to_back__works(void **state) { + + const f_string_static_t to = macro_f_string_static_t_initialize_1("X", 0, 1); + const f_string_static_t source = macro_f_string_static_t_initialize_1("te\nXst", 0, 6); + + { + f_range_t range = macro_f_range_t_initialize_1(0, source.used - 1); + + const f_status_t status = f_string_seek_to_back(source.string, to.string[0], &range); + + assert_int_equal(status, F_okay); + + assert_int_equal(range.start, 0); + assert_int_equal(range.stop, 3); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_string/tests/unit/c/test-string-seek_to_back.h b/level_0/f_string/tests/unit/c/test-string-seek_to_back.h new file mode 100644 index 0000000..966f563 --- /dev/null +++ b/level_0/f_string/tests/unit/c/test-string-seek_to_back.h @@ -0,0 +1,41 @@ +/** + * FLL - Level 0 + * + * Project: String + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the functions in the string project. + */ +#ifndef _TEST__F_string_seek_to_back_h +#define _TEST__F_string_seek_to_back_h + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_string_seek_to_back() + */ +extern void test__f_string_seek_to_back__parameter_checking(void **state); + +/** + * Test that the function returns F_data_not_stop because range is an empty range (range.start > range.stop). + * + * @see f_string_seek_to_back() + */ +extern void test__f_string_seek_to_back__returns_data_not_stop(void **state); + +/** + * Test that the function returns F_okay_stop stopped after end of range because no newline is found. + * + * @see f_string_seek_to_back() + */ +extern void test__f_string_seek_to_back__returns_none_stop(void **state); + +/** + * Test that the function works. + * + * @see f_string_seek_to_back() + */ +extern void test__f_string_seek_to_back__works(void **state); + +#endif // _TEST__F_string_seek_to_back_h diff --git a/level_0/f_string/tests/unit/c/test-string.c b/level_0/f_string/tests/unit/c/test-string.c index 7abebf3..167046b 100644 --- a/level_0/f_string/tests/unit/c/test-string.c +++ b/level_0/f_string/tests/unit/c/test-string.c @@ -61,17 +61,33 @@ int main(void) { cmocka_unit_test(test__f_string_dynamic_seek_line__returns_none_stop), cmocka_unit_test(test__f_string_dynamic_seek_line__works), + cmocka_unit_test(test__f_string_dynamic_seek_line_back__returns_data_not_stop), + cmocka_unit_test(test__f_string_dynamic_seek_line_back__returns_none_eos), + cmocka_unit_test(test__f_string_dynamic_seek_line_back__returns_none_stop), + cmocka_unit_test(test__f_string_dynamic_seek_line_back__works), + cmocka_unit_test(test__f_string_dynamic_seek_line_to__at_newline), cmocka_unit_test(test__f_string_dynamic_seek_line_to__returns_data_not_stop), cmocka_unit_test(test__f_string_dynamic_seek_line_to__returns_none_eos), cmocka_unit_test(test__f_string_dynamic_seek_line_to__returns_none_stop), cmocka_unit_test(test__f_string_dynamic_seek_line_to__works), + cmocka_unit_test(test__f_string_dynamic_seek_line_to_back__at_newline), + cmocka_unit_test(test__f_string_dynamic_seek_line_to_back__returns_data_not_stop), + cmocka_unit_test(test__f_string_dynamic_seek_line_to_back__returns_none_eos), + cmocka_unit_test(test__f_string_dynamic_seek_line_to_back__returns_none_stop), + cmocka_unit_test(test__f_string_dynamic_seek_line_to_back__works), + cmocka_unit_test(test__f_string_dynamic_seek_to__returns_data_not_stop), cmocka_unit_test(test__f_string_dynamic_seek_to__returns_none_eos), cmocka_unit_test(test__f_string_dynamic_seek_to__returns_none_stop), cmocka_unit_test(test__f_string_dynamic_seek_to__works), + cmocka_unit_test(test__f_string_dynamic_seek_to_back__returns_data_not_stop), + cmocka_unit_test(test__f_string_dynamic_seek_to_back__returns_none_eos), + cmocka_unit_test(test__f_string_dynamic_seek_to_back__returns_none_stop), + cmocka_unit_test(test__f_string_dynamic_seek_to_back__works), + cmocka_unit_test(test__f_string_dynamic_strip_null__returns_data_not), cmocka_unit_test(test__f_string_dynamic_strip_null__works), @@ -137,15 +153,28 @@ int main(void) { cmocka_unit_test(test__f_string_seek_line__returns_none_stop), cmocka_unit_test(test__f_string_seek_line__works), + cmocka_unit_test(test__f_string_seek_line_back__returns_data_not_stop), + cmocka_unit_test(test__f_string_seek_line_back__returns_none_stop), + cmocka_unit_test(test__f_string_seek_line_back__works), + cmocka_unit_test(test__f_string_seek_line_to__at_newline), cmocka_unit_test(test__f_string_seek_line_to__returns_data_not_stop), cmocka_unit_test(test__f_string_seek_line_to__returns_none_stop), cmocka_unit_test(test__f_string_seek_line_to__works), + cmocka_unit_test(test__f_string_seek_line_to_back__at_newline), + cmocka_unit_test(test__f_string_seek_line_to_back__returns_data_not_stop), + cmocka_unit_test(test__f_string_seek_line_to_back__returns_none_stop), + cmocka_unit_test(test__f_string_seek_line_to_back__works), + cmocka_unit_test(test__f_string_seek_to__returns_data_not_stop), cmocka_unit_test(test__f_string_seek_to__returns_none_stop), cmocka_unit_test(test__f_string_seek_to__works), + cmocka_unit_test(test__f_string_seek_to_back__returns_data_not_stop), + cmocka_unit_test(test__f_string_seek_to_back__returns_none_stop), + cmocka_unit_test(test__f_string_seek_to_back__works), + cmocka_unit_test(test__f_string_dynamics_delete_callback__fails), cmocka_unit_test(test__f_string_dynamics_destroy_callback__fails), cmocka_unit_test(test__f_string_dynamics_delete_callback__works), diff --git a/level_0/f_string/tests/unit/c/test-string.h b/level_0/f_string/tests/unit/c/test-string.h index fbe350c..440fee3 100644 --- a/level_0/f_string/tests/unit/c/test-string.h +++ b/level_0/f_string/tests/unit/c/test-string.h @@ -55,8 +55,11 @@ #include "test-string-dynamic_prepend_assure_nulless.h" #include "test-string-dynamic_prepend_nulless.h" #include "test-string-dynamic_seek_line.h" +#include "test-string-dynamic_seek_line_back.h" #include "test-string-dynamic_seek_line_to.h" +#include "test-string-dynamic_seek_line_to_back.h" #include "test-string-dynamic_seek_to.h" +#include "test-string-dynamic_seek_to_back.h" #include "test-string-dynamic_strip_null.h" #include "test-string-dynamic_strip_null_range.h" #include "test-string-dynamic_terminate.h" @@ -94,8 +97,11 @@ #include "test-string-prepend_assure_nulless.h" #include "test-string-prepend_nulless.h" #include "test-string-seek_line.h" +#include "test-string-seek_line_back.h" #include "test-string-seek_line_to.h" +#include "test-string-seek_line_to_back.h" #include "test-string-seek_to.h" +#include "test-string-seek_to_back.h" #include "test-string-triples_append.h" #include "test-string-triples_append_all.h" #include "test-string-triples_delete_callback.h" diff --git a/level_0/f_utf/c/utf/dynamic.c b/level_0/f_utf/c/utf/dynamic.c index 01e7052..bec54be 100644 --- a/level_0/f_utf/c/utf/dynamic.c +++ b/level_0/f_utf/c/utf/dynamic.c @@ -613,6 +613,29 @@ extern "C" { } #endif // _di_f_utf_string_dynamic_seek_line_ +#ifndef _di_f_utf_string_dynamic_seek_line_back_ + f_status_t f_utf_string_dynamic_seek_line_back(const f_utf_string_static_t buffer, f_range_t * const range) { + #ifndef _di_level_0_parameter_checking_ + if (!range) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.used) return F_data_not; + if (range->start > range->stop) return F_data_not_stop; + + while (buffer.string[range->stop] != f_utf_char_eol_s) { + + if (macro_f_utf_char_t_width_is(buffer.string[range->stop]) == 1) return F_status_set_error(F_utf_fragment); + + --range->stop; + + if (!range->stop) return (buffer.string[range->stop] == f_utf_char_eol_s) ? F_okay : F_okay_eos; + if (range->start > range->stop) return F_okay_stop; + } // while + + return F_okay; + } +#endif // _di_f_utf_string_dynamic_seek_line_back_ + #ifndef _di_f_utf_string_dynamic_seek_line_to_ f_status_t f_utf_string_dynamic_seek_line_to(const f_utf_string_static_t buffer, const f_utf_char_t seek_to_this, f_range_t * const range) { #ifndef _di_level_0_parameter_checking_ @@ -637,6 +660,30 @@ extern "C" { } #endif // _di_f_utf_string_dynamic_seek_line_to_ +#ifndef _di_f_utf_string_dynamic_seek_line_to_back_ + f_status_t f_utf_string_dynamic_seek_line_to_back(const f_utf_string_static_t buffer, const f_utf_char_t seek_to_this, f_range_t * const range) { + #ifndef _di_level_0_parameter_checking_ + if (!range) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.used) return F_data_not; + if (range->start > range->stop) return F_data_not_stop; + + while (buffer.string[range->stop] != seek_to_this) { + + if (macro_f_utf_char_t_width_is(buffer.string[range->stop]) == 1) return F_status_set_error(F_utf_fragment); + if (buffer.string[range->stop] == f_utf_char_eol_s) return F_okay_eol; + + --range->stop; + + if (!range->stop) return (buffer.string[range->stop] == f_utf_char_eol_s) ? F_okay : F_okay_eos; + if (range->start > range->stop) return F_okay_stop; + } // while + + return F_okay; + } +#endif // _di_f_utf_string_dynamic_seek_line_to_back_ + #ifndef _di_f_utf_string_dynamic_seek_to_ f_status_t f_utf_string_dynamic_seek_to(const f_utf_string_static_t buffer, const f_utf_char_t seek_to_this, f_range_t * const range) { #ifndef _di_level_0_parameter_checking_ @@ -660,6 +707,29 @@ extern "C" { } #endif // _di_f_utf_string_dynamic_seek_to_ +#ifndef _di_f_utf_string_dynamic_seek_to_back_ + f_status_t f_utf_string_dynamic_seek_to_back(const f_utf_string_static_t buffer, const f_utf_char_t seek_to_this, f_range_t * const range) { + #ifndef _di_level_0_parameter_checking_ + if (!range) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!buffer.used) return F_data_not; + if (range->start > range->stop) return F_data_not_stop; + + while (buffer.string[range->stop] != seek_to_this) { + + if (macro_f_utf_char_t_width_is(buffer.string[range->stop]) == 1) return F_status_set_error(F_utf_fragment); + + --range->stop; + + if (!range->stop) return (buffer.string[range->stop] == f_utf_char_eol_s) ? F_okay : F_okay_eos; + if (range->start > range->stop) return F_okay_stop; + } // while + + return F_okay; + } +#endif // _di_f_utf_string_dynamic_seek_to_back_ + #ifndef _di_f_utf_string_dynamic_terminate_ f_status_t f_utf_string_dynamic_terminate(f_utf_string_dynamic_t * const destination) { #ifndef _di_level_0_parameter_checking_ diff --git a/level_0/f_utf/c/utf/dynamic.h b/level_0/f_utf/c/utf/dynamic.h index f546614..0243a09 100644 --- a/level_0/f_utf/c/utf/dynamic.h +++ b/level_0/f_utf/c/utf/dynamic.h @@ -689,6 +689,31 @@ extern "C" { #endif // _di_f_utf_string_dynamic_seek_line_ /** + * Seek the buffer location backward until EOL is reached. + * + * @param buffer + * The buffer to traverse. + * @param range + * A range within the buffer representing the start and stop locations. + * The stop location will be decremented by the seek. + * + * @return + * F_okay on success. + * F_okay_eos on success, but stopped at end of string. + * F_okay_stop on success, but stopped at end of range. + * F_data_not on success, but there was no string data to seek. + * F_data_not_stop on success, but the range.start > range.stop. + * + * F_parameter (with error bit) if a parameter is invalid. + * F_utf_fragment (with error bit) if character is a UTF-8 fragment. + * + * Errors (with error bit) from: f_memory_resize(). + */ +#ifndef _di_f_utf_string_dynamic_seek_line_back_ + extern f_status_t f_utf_string_dynamic_seek_line_back(const f_utf_string_static_t buffer, f_range_t * const range); +#endif // _di_f_utf_string_dynamic_seek_line_back_ + +/** * Seek the buffer location forward until the character (1-byte wide) or EOL is reached. * * @param buffer @@ -716,6 +741,33 @@ extern "C" { #endif // _di_f_utf_string_dynamic_seek_line_to_ /** + * Seek the buffer location backward until the character (1-byte wide) or EOL is reached. + * + * @param buffer + * The buffer to traverse. + * @param seek_to_this + * A single-width character representing a character to seek to. + * @param range + * A range within the buffer representing the start and stop locations. + * The stop location will be decremented by the seek. + * + * @return + * F_okay on success. + * F_okay_eos on success, but stopped at end of string. + * F_okay_stop on success, but stopped at end of range. + * F_data_not on success, but there was no string data to seek. + * F_data_not_stop on success, but the range.start > range.stop. + * + * F_parameter (with error bit) if a parameter is invalid. + * F_utf_fragment (with error bit) if character is a UTF-8 fragment. + * + * Errors (with error bit) from: f_memory_resize(). + */ +#ifndef _di_f_utf_string_dynamic_seek_line_to_back_ + extern f_status_t f_utf_string_dynamic_seek_line_to_back(const f_utf_string_static_t buffer, const f_utf_char_t seek_to_this, f_range_t * const range); +#endif // _di_f_utf_string_dynamic_seek_line_to_back_ + +/** * Seek the buffer location forward until the character (1-byte wide) is reached. * * @param buffer @@ -743,6 +795,33 @@ extern "C" { #endif // _di_f_utf_string_dynamic_seek_to_ /** + * Seek the buffer location backward until the character (1-byte wide) is reached. + * + * @param buffer + * The buffer to traverse. + * @param seek_to_this + * A single-width character representing a character to seek to. + * @param range + * A range within the buffer representing the start and stop locations. + * The stop location will be decremented by the seek. + * + * @return + * F_okay on success. + * F_okay_eos on success, but stopped at end of string. + * F_okay_stop on success, but stopped at end of range. + * F_data_not on success, but there was no string data to seek. + * F_data_not_stop on success, but the range.start > range.stop. + * + * F_parameter (with error bit) if a parameter is invalid. + * F_utf_fragment (with error bit) if character is a UTF-8 fragment. + * + * Errors (with error bit) from: f_memory_resize(). + */ +#ifndef _di_f_utf_string_dynamic_seek_to_back_ + extern f_status_t f_utf_string_dynamic_seek_to_back(const f_utf_string_static_t buffer, const f_utf_char_t seek_to_this, f_range_t * const range); +#endif // _di_f_utf_string_dynamic_seek_to_back_ + +/** * Guarantee that an end of string (NULL) exists at the end of the string. * * This is intended to be used for anything requiring NULL terminated strings. diff --git a/level_0/f_utf/c/utf/string.c b/level_0/f_utf/c/utf/string.c index 25dd41a..868820c 100644 --- a/level_0/f_utf/c/utf/string.c +++ b/level_0/f_utf/c/utf/string.c @@ -314,6 +314,27 @@ extern "C" { } #endif // _di_f_utf_string_seek_line_ +#ifndef _di_f_utf_string_seek_line_back_ + f_status_t f_utf_string_seek_line_back(const f_utf_string_t string, f_range_t * const range) { + #ifndef _di_level_0_parameter_checking_ + if (!range) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (range->start > range->stop) return F_data_not_stop; + + while (string[range->stop] != f_utf_char_eol_s) { + + if (macro_f_utf_char_t_width_is(string[range->stop]) == 1) return F_status_set_error(F_utf_fragment); + + --range->stop; + + if (range->start > range->stop) return F_okay_stop; + } // while + + return F_okay; + } +#endif // _di_f_utf_string_seek_line_back_ + #ifndef _di_f_utf_string_seek_line_to_ f_status_t f_utf_string_seek_line_to(const f_utf_string_t string, const f_utf_char_t seek_to, f_range_t * const range) { #ifndef _di_level_0_parameter_checking_ @@ -335,6 +356,27 @@ extern "C" { } #endif // _di_f_utf_string_seek_line_to_ +#ifndef _di_f_utf_string_seek_line_to_back_ + f_status_t f_utf_string_seek_line_to_back(const f_utf_string_t string, const f_utf_char_t seek_to, f_range_t * const range) { + #ifndef _di_level_0_parameter_checking_ + if (!range) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (range->start > range->stop) return F_data_not_stop; + + while (string[range->stop] != seek_to) { + + if (string[range->stop] == f_utf_char_eol_s) return F_okay_eol; + + --range->stop; + + if (range->start > range->stop) return F_okay_stop; + } // while + + return F_okay; + } +#endif // _di_f_utf_string_seek_line_to_back_ + #ifndef _di_f_utf_string_seek_to_ f_status_t f_utf_string_seek_to(const f_utf_string_t string, const f_utf_char_t seek_to, f_range_t * const range) { #ifndef _di_level_0_parameter_checking_ @@ -354,6 +396,25 @@ extern "C" { } #endif // _di_f_utf_string_seek_to_ +#ifndef _di_f_utf_string_seek_to_back_ + f_status_t f_utf_string_seek_to_back(const f_utf_string_t string, const f_utf_char_t seek_to, f_range_t * const range) { + #ifndef _di_level_0_parameter_checking_ + if (!range) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (range->start > range->stop) return F_data_not_stop; + + while (string[range->stop] != seek_to) { + + --range->stop; + + if (range->start > range->stop) return F_okay_stop; + } // while + + return F_okay; + } +#endif // _di_f_utf_string_seek_to_back_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_0/f_utf/c/utf/string.h b/level_0/f_utf/c/utf/string.h index c419b78..cbccc4d 100644 --- a/level_0/f_utf/c/utf/string.h +++ b/level_0/f_utf/c/utf/string.h @@ -372,6 +372,30 @@ extern "C" { #endif // _di_f_utf_string_seek_line_ /** + * Seek the string location backward until EOL is reached. + * + * @param string + * The string to traverse. + * @param range + * A range within the buffer representing the start and stop locations. + * The stop location will be decremented by the seek. + * + * @return + * F_okay on success. + * F_okay_stop on success, but stopped at end of range. + * F_data_not_stop on success, but the range.start > range.stop. + * + * F_parameter (with error bit) if a parameter is invalid. + * F_utf_fragment (with error bit) if character is a UTF-8 fragment. + * F_utf_not (with error bit) if unicode is an invalid Unicode character. + * + * Errors (with error bit) from: f_memory_resize(). + */ +#ifndef _di_f_utf_string_seek_line_back_ + extern f_status_t f_utf_string_seek_line_back(const f_utf_string_t string, f_range_t * const range); +#endif // _di_f_utf_string_seek_line_back_ + +/** * Seek the string location forward until the character (1-byte wide) or EOL is reached. * * @param string @@ -395,6 +419,29 @@ extern "C" { #endif // _di_f_utf_string_seek_line_to_ /** + * Seek the string location backward until the character (1-byte wide) or EOL is reached. + * + * @param string + * The string to traverse. + * @param seek_to + * A character representing a character to seek to. + * @param range + * A range within the buffer representing the start and stop locations. + * The stop location will be decremented by the seek. + * + * @return + * F_okay on success. + * F_okay_eol on success, but stopped at EOL. + * F_okay_stop on success, but stopped at the stop location. + * F_data_not_stop if range.start > range.stop. + * + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_utf_string_seek_line_to_back_ + extern f_status_t f_utf_string_seek_line_to_back(const f_utf_string_t string, const f_utf_char_t seek_to, f_range_t * const range); +#endif // _di_f_utf_string_seek_line_to_back_ + +/** * Seek the string location forward until the character (1-byte wide) is reached. * * @param string @@ -418,6 +465,30 @@ extern "C" { extern f_status_t f_utf_string_seek_to(const f_utf_string_t string, const f_utf_char_t seek_to, f_range_t * const range); #endif // _di_f_utf_string_seek_to_ +/** + * Seek the string location backward until the character (1-byte wide) is reached. + * + * @param string + * The string to traverse. + * @param seek_to + * A character representing a character to seek to. + * @param range + * A range within the buffer representing the start and stop locations. + * The stop location will be decremented by the seek. + * + * @return + * F_okay on success. + * F_okay_stop on success, but stopped at the stop location. + * F_data_not_stop if range.start > range.stop. + * + * F_parameter (with error bit) if a parameter is invalid. + * F_utf_fragment (with error bit) if character is a UTF-8 fragment. + * F_utf_not (with error bit) if unicode is an invalid Unicode character. + */ +#ifndef _di_f_utf_string_seek_to_back_ + extern f_status_t f_utf_string_seek_to_back(const f_utf_string_t string, const f_utf_char_t seek_to, f_range_t * const range); +#endif // _di_f_utf_string_seek_to_back_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_0/f_utf/c/utf/strings.c b/level_0/f_utf/c/utf/strings.c index 7639bc7..12aefb4 100644 --- a/level_0/f_utf/c/utf/strings.c +++ b/level_0/f_utf/c/utf/strings.c @@ -302,6 +302,27 @@ extern "C" { } #endif // _di_f_utf_string_seek_line_ +#ifndef _di_f_utf_string_seek_line_back + f_status_t f_utf_string_seek_line_back(const f_utf_string_t string, f_range_t * const range) { + #ifndef _di_level_0_parameter_checking_ + if (!range) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (range->start > range->stop) return F_data_not_stop; + + while (string[range->stop] != f_utf_char_t_eol_s) { + + if (macro_f_utf_char_t_width_is(string[range->stop]) == 1) return F_status_set_error(F_utf_fragment); + + --range->stop; + + if (range->start > range->stop) return F_okay_stop; + } // while + + return F_okay; + } +#endif // _di_f_utf_string_seek_line_back_ + #ifndef _di_f_utf_string_seek_line_to_ f_status_t f_utf_string_seek_line_to(const f_utf_string_t string, const f_utf_char_t seek_to, f_range_t * const range) { #ifndef _di_level_0_parameter_checking_ @@ -323,6 +344,27 @@ extern "C" { } #endif // _di_f_utf_string_seek_line_to_ +#ifndef _di_f_utf_string_seek_line_to_back_ + f_status_t f_utf_string_seek_line_to_back(const f_utf_string_t string, const f_utf_char_t seek_to, f_range_t * const range) { + #ifndef _di_level_0_parameter_checking_ + if (!range) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (range->start > range->stop) return F_data_not_stop; + + while (string[range->stop] != seek_to) { + + if (string[range->stop] == f_utf_char_t_eol_s) return F_okay_eol; + + --range->stop; + + if (range->start > range->stop) return F_okay_stop; + } // while + + return F_okay; + } +#endif // _di_f_utf_string_seek_line_to_back_ + #ifndef _di_f_utf_string_seek_to_ f_status_t f_utf_string_seek_to(const f_utf_string_t string, const f_utf_char_t seek_to, f_range_t * const range) { #ifndef _di_level_0_parameter_checking_ @@ -342,6 +384,25 @@ extern "C" { } #endif // _di_f_utf_string_seek_to_ +#ifndef _di_f_utf_string_seek_to_back_ + f_status_t f_utf_string_seek_to_back(const f_utf_string_t string, const f_utf_char_t seek_to, f_range_t * const range) { + #ifndef _di_level_0_parameter_checking_ + if (!range) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (range->start > range->stop) return F_data_not_stop; + + while (string[range->stop] != seek_to) { + + --range->stop; + + if (range->start > range->stop) return F_okay_stop; + } // while + + return F_okay; + } +#endif // _di_f_utf_string_seek_to_back_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_0/f_utf/c/utf/strings.h b/level_0/f_utf/c/utf/strings.h index c419b78..cbccc4d 100644 --- a/level_0/f_utf/c/utf/strings.h +++ b/level_0/f_utf/c/utf/strings.h @@ -372,6 +372,30 @@ extern "C" { #endif // _di_f_utf_string_seek_line_ /** + * Seek the string location backward until EOL is reached. + * + * @param string + * The string to traverse. + * @param range + * A range within the buffer representing the start and stop locations. + * The stop location will be decremented by the seek. + * + * @return + * F_okay on success. + * F_okay_stop on success, but stopped at end of range. + * F_data_not_stop on success, but the range.start > range.stop. + * + * F_parameter (with error bit) if a parameter is invalid. + * F_utf_fragment (with error bit) if character is a UTF-8 fragment. + * F_utf_not (with error bit) if unicode is an invalid Unicode character. + * + * Errors (with error bit) from: f_memory_resize(). + */ +#ifndef _di_f_utf_string_seek_line_back_ + extern f_status_t f_utf_string_seek_line_back(const f_utf_string_t string, f_range_t * const range); +#endif // _di_f_utf_string_seek_line_back_ + +/** * Seek the string location forward until the character (1-byte wide) or EOL is reached. * * @param string @@ -395,6 +419,29 @@ extern "C" { #endif // _di_f_utf_string_seek_line_to_ /** + * Seek the string location backward until the character (1-byte wide) or EOL is reached. + * + * @param string + * The string to traverse. + * @param seek_to + * A character representing a character to seek to. + * @param range + * A range within the buffer representing the start and stop locations. + * The stop location will be decremented by the seek. + * + * @return + * F_okay on success. + * F_okay_eol on success, but stopped at EOL. + * F_okay_stop on success, but stopped at the stop location. + * F_data_not_stop if range.start > range.stop. + * + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_utf_string_seek_line_to_back_ + extern f_status_t f_utf_string_seek_line_to_back(const f_utf_string_t string, const f_utf_char_t seek_to, f_range_t * const range); +#endif // _di_f_utf_string_seek_line_to_back_ + +/** * Seek the string location forward until the character (1-byte wide) is reached. * * @param string @@ -418,6 +465,30 @@ extern "C" { extern f_status_t f_utf_string_seek_to(const f_utf_string_t string, const f_utf_char_t seek_to, f_range_t * const range); #endif // _di_f_utf_string_seek_to_ +/** + * Seek the string location backward until the character (1-byte wide) is reached. + * + * @param string + * The string to traverse. + * @param seek_to + * A character representing a character to seek to. + * @param range + * A range within the buffer representing the start and stop locations. + * The stop location will be decremented by the seek. + * + * @return + * F_okay on success. + * F_okay_stop on success, but stopped at the stop location. + * F_data_not_stop if range.start > range.stop. + * + * F_parameter (with error bit) if a parameter is invalid. + * F_utf_fragment (with error bit) if character is a UTF-8 fragment. + * F_utf_not (with error bit) if unicode is an invalid Unicode character. + */ +#ifndef _di_f_utf_string_seek_to_back_ + extern f_status_t f_utf_string_seek_to_back(const f_utf_string_t string, const f_utf_char_t seek_to, f_range_t * const range); +#endif // _di_f_utf_string_seek_to_back_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_0/f_utf/c/utf/stringss.c b/level_0/f_utf/c/utf/stringss.c index 5d5386c..de80b56 100644 --- a/level_0/f_utf/c/utf/stringss.c +++ b/level_0/f_utf/c/utf/stringss.c @@ -302,6 +302,27 @@ extern "C" { } #endif // _di_f_utf_string_seek_line_ +#ifndef _di_f_utf_string_seek_line_back_ + f_status_t f_utf_string_seek_line_back(const f_utf_string_t string, f_range_t * const range) { + #ifndef _di_level_0_parameter_checking_ + if (!range) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (range->start > range->stop) return F_data_not_stop; + + while (string[range->stop] != f_utf_char_t_eol_s) { + + if (macro_f_utf_char_t_width_is(string[range->stop]) == 1) return F_status_set_error(F_utf_fragment); + + --range->stop; + + if (range->start > range->stop) return F_okay_stop; + } // while + + return F_okay; + } +#endif // _di_f_utf_string_seek_line_back_ + #ifndef _di_f_utf_string_seek_line_to_ f_status_t f_utf_string_seek_line_to(const f_utf_string_t string, const f_utf_char_t seek_to, f_range_t * const range) { #ifndef _di_level_0_parameter_checking_ @@ -323,6 +344,27 @@ extern "C" { } #endif // _di_f_utf_string_seek_line_to_ +#ifndef _di_f_utf_string_seek_line_to_back_ + f_status_t f_utf_string_seek_line_to_back(const f_utf_string_t string, const f_utf_char_t seek_to, f_range_t * const range) { + #ifndef _di_level_0_parameter_checking_ + if (!range) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (range->start > range->stop) return F_data_not_stop; + + while (string[range->stop] != seek_to) { + + if (string[range->stop] == f_utf_char_t_eol_s) return F_okay_eol; + + --range->stop; + + if (range->start > range->stop) return F_okay_stop; + } // while + + return F_okay; + } +#endif // _di_f_utf_string_seek_line_to_back_ + #ifndef _di_f_utf_string_seek_to_ f_status_t f_utf_string_seek_to(const f_utf_string_t string, const f_utf_char_t seek_to, f_range_t * const range) { #ifndef _di_level_0_parameter_checking_ @@ -342,6 +384,25 @@ extern "C" { } #endif // _di_f_utf_string_seek_to_ +#ifndef _di_f_utf_string_seek_to_back_ + f_status_t f_utf_string_seek_to_back(const f_utf_string_t string, const f_utf_char_t seek_to, f_range_t * const range) { + #ifndef _di_level_0_parameter_checking_ + if (!range) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (range->start > range->stop) return F_data_not_stop; + + while (string[range->stop] != seek_to) { + + --range->stop; + + if (range->start > range->stop) return F_okay_stop; + } // while + + return F_okay; + } +#endif // _di_f_utf_string_seek_to_back_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_0/f_utf/c/utf/stringss.h b/level_0/f_utf/c/utf/stringss.h index c419b78..cbccc4d 100644 --- a/level_0/f_utf/c/utf/stringss.h +++ b/level_0/f_utf/c/utf/stringss.h @@ -372,6 +372,30 @@ extern "C" { #endif // _di_f_utf_string_seek_line_ /** + * Seek the string location backward until EOL is reached. + * + * @param string + * The string to traverse. + * @param range + * A range within the buffer representing the start and stop locations. + * The stop location will be decremented by the seek. + * + * @return + * F_okay on success. + * F_okay_stop on success, but stopped at end of range. + * F_data_not_stop on success, but the range.start > range.stop. + * + * F_parameter (with error bit) if a parameter is invalid. + * F_utf_fragment (with error bit) if character is a UTF-8 fragment. + * F_utf_not (with error bit) if unicode is an invalid Unicode character. + * + * Errors (with error bit) from: f_memory_resize(). + */ +#ifndef _di_f_utf_string_seek_line_back_ + extern f_status_t f_utf_string_seek_line_back(const f_utf_string_t string, f_range_t * const range); +#endif // _di_f_utf_string_seek_line_back_ + +/** * Seek the string location forward until the character (1-byte wide) or EOL is reached. * * @param string @@ -395,6 +419,29 @@ extern "C" { #endif // _di_f_utf_string_seek_line_to_ /** + * Seek the string location backward until the character (1-byte wide) or EOL is reached. + * + * @param string + * The string to traverse. + * @param seek_to + * A character representing a character to seek to. + * @param range + * A range within the buffer representing the start and stop locations. + * The stop location will be decremented by the seek. + * + * @return + * F_okay on success. + * F_okay_eol on success, but stopped at EOL. + * F_okay_stop on success, but stopped at the stop location. + * F_data_not_stop if range.start > range.stop. + * + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_utf_string_seek_line_to_back_ + extern f_status_t f_utf_string_seek_line_to_back(const f_utf_string_t string, const f_utf_char_t seek_to, f_range_t * const range); +#endif // _di_f_utf_string_seek_line_to_back_ + +/** * Seek the string location forward until the character (1-byte wide) is reached. * * @param string @@ -418,6 +465,30 @@ extern "C" { extern f_status_t f_utf_string_seek_to(const f_utf_string_t string, const f_utf_char_t seek_to, f_range_t * const range); #endif // _di_f_utf_string_seek_to_ +/** + * Seek the string location backward until the character (1-byte wide) is reached. + * + * @param string + * The string to traverse. + * @param seek_to + * A character representing a character to seek to. + * @param range + * A range within the buffer representing the start and stop locations. + * The stop location will be decremented by the seek. + * + * @return + * F_okay on success. + * F_okay_stop on success, but stopped at the stop location. + * F_data_not_stop if range.start > range.stop. + * + * F_parameter (with error bit) if a parameter is invalid. + * F_utf_fragment (with error bit) if character is a UTF-8 fragment. + * F_utf_not (with error bit) if unicode is an invalid Unicode character. + */ +#ifndef _di_f_utf_string_seek_to_back_ + extern f_status_t f_utf_string_seek_to_back(const f_utf_string_t string, const f_utf_char_t seek_to, f_range_t * const range); +#endif // _di_f_utf_string_seek_to_back_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_0/f_utf/data/build/settings-tests b/level_0/f_utf/data/build/settings-tests index 85d7ba0..5acc23b 100644 --- a/level_0/f_utf/data/build/settings-tests +++ b/level_0/f_utf/data/build/settings-tests @@ -58,7 +58,7 @@ build_sources_program test-utf-dynamic_partial_mash.c test-utf-dynamic_partial_m build_sources_program test-utf-dynamic_partial_mish.c test-utf-dynamic_partial_mish_nulless.c build_sources_program test-utf-dynamic_partial_prepend.c test-utf-dynamic_partial_prepend_assure.c test-utf-dynamic_partial_prepend_assure_nulless.c test-utf-dynamic_partial_prepend_nulless.c build_sources_program test-utf-dynamic_prepend.c test-utf-dynamic_prepend_assure.c test-utf-dynamic_prepend_assure_nulless.c test-utf-dynamic_prepend_nulless.c -build_sources_program test-utf-dynamic_seek_line.c test-utf-dynamic_seek_line_to.c test-utf-dynamic_seek_to.c +build_sources_program test-utf-dynamic_seek_line.c test-utf-dynamic_seek_line_back.c test-utf-dynamic_seek_line_to.c test-utf-dynamic_seek_line_to_back.c test-utf-dynamic_seek_to.c test-utf-dynamic_seek_to_back.c build_sources_program test-utf-dynamic_terminate.c test-utf-dynamic_terminate_after.c build_sources_program test-utf-dynamics_append.c test-utf-dynamics_append_all.c test-utf-dynamicss_append.c test-utf-dynamicss_append_all.c build_sources_program test-utf-dynamicss_delete_callback.c test-utf-dynamicss_destroy_callback.c @@ -71,7 +71,7 @@ build_sources_program test-utf-map_multiss_delete_callback.c test-utf-map_multis build_sources_program test-utf-mash.c test-utf-mash_nulless.c build_sources_program test-utf-mish.c test-utf-mish_nulless.c build_sources_program test-utf-prepend.c test-utf-prepend_assure.c test-utf-prepend_assure_nulless.c test-utf-prepend_nulless.c -build_sources_program test-utf-seek_line.c test-utf-seek_line_to.c test-utf-seek_to.c +build_sources_program test-utf-seek_line.c test-utf-seek_line_back.c test-utf-seek_line_to.c test-utf-seek_line_to_back.c test-utf-seek_to.c test-utf-seek_to_back.c build_sources_program test-utf-triples_append.c test-utf-triples_append_all.c test-utf-tripless_append.c test-utf-tripless_append_all.c build_sources_program test-utf-triples_delete_callback.c test-utf-triples_destroy_callback.c build_sources_program test-utf-tripless_delete_callback.c test-utf-tripless_destroy_callback.c diff --git a/level_0/f_utf/tests/unit/c/test-utf-dynamic_seek_line_back.c b/level_0/f_utf/tests/unit/c/test-utf-dynamic_seek_line_back.c new file mode 100644 index 0000000..f10621a --- /dev/null +++ b/level_0/f_utf/tests/unit/c/test-utf-dynamic_seek_line_back.c @@ -0,0 +1,82 @@ +#include "test-utf.h" +#include "test-utf-dynamic_seek_line_back.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_utf_string_dynamic_seek_line_back__parameter_checking(void **state) { + + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0X\0\0\0\n\0\0\0s\0\0\0t", 0, 6); + + { + const f_status_t status = f_utf_string_dynamic_seek_line_back(source, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +void test__f_utf_string_dynamic_seek_line_back__returns_data_not_stop(void **state) { + + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0s\0\0\0t\0\0\0\n\0\0\0a\0\0\0f\0\0\0t\0\0\0e\0\0\0r", 0, 10); + + { + f_range_t range = f_range_t_initialize; + + const f_status_t status = f_utf_string_dynamic_seek_line_back(source, &range); + + assert_int_equal(status, F_data_not_stop); + } +} + +void test__f_utf_string_dynamic_seek_line_back__returns_none_eos(void **state) { + + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0s\0\0\0t", 0, 4); + + { + f_range_t range = macro_f_range_t_initialize_1(0, source.used - 1); + + const f_status_t status = f_utf_string_dynamic_seek_line_back(source, &range); + + assert_int_equal(status, F_okay_eos); + + assert_int_equal(range.start, 0); + assert_int_equal(range.stop, 0); + } +} + +void test__f_utf_string_dynamic_seek_line_back__returns_none_stop(void **state) { + + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0s\0\0\0t", 0, 4); + + { + f_range_t range = macro_f_range_t_initialize_1(2, source.used - 1); + + const f_status_t status = f_utf_string_dynamic_seek_line_back(source, &range); + + assert_int_equal(status, F_okay_stop); + + assert_int_equal(range.start, 2); + assert_int_equal(range.stop, 1); + } +} + +void test__f_utf_string_dynamic_seek_line_back__works(void **state) { + + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0s\0\0\0t\0\0\0\n\0\0\0a\0\0\0f\0\0\0t\0\0\0e\0\0\0r", 0, 10); + + { + f_range_t range = macro_f_range_t_initialize_1(0, source.used - 1); + + const f_status_t status = f_utf_string_dynamic_seek_line_back(source, &range); + + assert_int_equal(status, F_okay); + + assert_int_equal(range.start, 0); + assert_int_equal(range.stop, 4); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_utf/tests/unit/c/test-utf-dynamic_seek_line_back.h b/level_0/f_utf/tests/unit/c/test-utf-dynamic_seek_line_back.h new file mode 100644 index 0000000..9072e45 --- /dev/null +++ b/level_0/f_utf/tests/unit/c/test-utf-dynamic_seek_line_back.h @@ -0,0 +1,48 @@ +/** + * FLL - Level 0 + * + * Project: UTF + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the functions in the utf project. + */ +#ifndef _TEST__F_utf_dynamic_seek_line_back_h +#define _TEST__F_utf_dynamic_seek_line_back_h + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_utf_string_dynamic_seek_line_back() + */ +extern void test__f_utf_string_dynamic_seek_line_back__parameter_checking(void **state); + +/** + * Test that the function returns F_data_not_stop because range is an empty range (range.start > range.stop). + * + * @see f_utf_string_dynamic_seek_line_back() + */ +extern void test__f_utf_string_dynamic_seek_line_back__returns_data_not_stop(void **state); + +/** + * Test that the function returns F_okay_eos stopped after end of string because no newline is found. + * + * @see f_utf_string_dynamic_seek_line_back() + */ +extern void test__f_utf_string_dynamic_seek_line_back__returns_none_eos(void **state); + +/** + * Test that the function returns F_okay_stop stopped after end of range because no newline is found. + * + * @see f_utf_string_dynamic_seek_line_back() + */ +extern void test__f_utf_string_dynamic_seek_line_back__returns_none_stop(void **state); + +/** + * Test that the function works. + * + * @see f_utf_string_dynamic_seek_line_back() + */ +extern void test__f_utf_string_dynamic_seek_line_back__works(void **state); + +#endif // _TEST__F_utf_dynamic_seek_line_back_h diff --git a/level_0/f_utf/tests/unit/c/test-utf-dynamic_seek_line_to_back.c b/level_0/f_utf/tests/unit/c/test-utf-dynamic_seek_line_to_back.c new file mode 100644 index 0000000..fac88f9 --- /dev/null +++ b/level_0/f_utf/tests/unit/c/test-utf-dynamic_seek_line_to_back.c @@ -0,0 +1,104 @@ +#include "test-utf.h" +#include "test-utf-dynamic_seek_line_to_back.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_utf_string_dynamic_seek_line_to_back__after_newline(void **state) { + + const f_utf_string_static_t to = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0X", 0, 1); + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0X\0\0\0\n\0\0\0s\0\0\0t", 0, 6); + + { + f_range_t range = macro_f_range_t_initialize_1(0, source.used - 1); + + const f_status_t status = f_utf_string_dynamic_seek_line_to_back(source, to.string[0], &range); + + assert_int_equal(status, F_okay_eol); + + assert_int_equal(range.start, 0); + assert_int_equal(range.stop, 3); + } +} + +void test__f_utf_string_dynamic_seek_line_to_back__before_newline(void **state) { + + const f_utf_string_static_t to = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0X", 0, 1); + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0\n\0\0\0X\0\0\0s\0\0\0t", 0, 6); + + { + f_range_t range = macro_f_range_t_initialize_1(0, source.used - 1); + + const f_status_t status = f_utf_string_dynamic_seek_line_to_back(source, to.string[0], &range); + + assert_int_equal(status, F_okay); + + assert_int_equal(range.start, 0); + assert_int_equal(range.stop, 3); + } +} + +void test__f_utf_string_dynamic_seek_line_to_back__parameter_checking(void **state) { + + const f_utf_string_static_t to = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0X", 0, 1); + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0X\0\0\0\n\0\0\0s\0\0\0t", 0, 6); + + { + const f_status_t status = f_utf_string_dynamic_seek_line_to_back(source, to.string[0], 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +void test__f_utf_string_dynamic_seek_line_to_back__returns_data_not_stop(void **state) { + + const f_utf_string_static_t to = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0X", 0, 1); + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0s\0\0\0t\0\0\0\n\0\0\0a\0\0\0f\0\0\0t\0\0\0e\0\0\0r", 0, 10); + + { + f_range_t range = f_range_t_initialize; + + const f_status_t status = f_utf_string_dynamic_seek_line_to_back(source, to.string[0], &range); + + assert_int_equal(status, F_data_not_stop); + } +} + +void test__f_utf_string_dynamic_seek_line_to_back__returns_none_eos(void **state) { + + const f_utf_string_static_t to = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0X", 0, 1); + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0s\0\0\0t", 0, 4); + + { + f_range_t range = macro_f_range_t_initialize_1(0, source.used - 1); + + const f_status_t status = f_utf_string_dynamic_seek_line_to_back(source, to.string[0], &range); + + assert_int_equal(status, F_okay_eos); + + assert_int_equal(range.start, 0); + assert_int_equal(range.stop, 0); + } +} + +void test__f_utf_string_dynamic_seek_line_to_back__returns_none_stop(void **state) { + + const f_utf_string_static_t to = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0X", 0, 1); + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0s\0\0\0t", 0, 4); + + { + f_range_t range = macro_f_range_t_initialize_1(2, source.used - 1); + + const f_status_t status = f_utf_string_dynamic_seek_line_to_back(source, to.string[0], &range); + + assert_int_equal(status, F_okay_stop); + + assert_int_equal(range.start, 2); + assert_int_equal(range.stop, 1); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_utf/tests/unit/c/test-utf-dynamic_seek_line_to_back.h b/level_0/f_utf/tests/unit/c/test-utf-dynamic_seek_line_to_back.h new file mode 100644 index 0000000..a1a17d5 --- /dev/null +++ b/level_0/f_utf/tests/unit/c/test-utf-dynamic_seek_line_to_back.h @@ -0,0 +1,55 @@ +/** + * FLL - Level 0 + * + * Project: UTF + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the functions in the utf project. + */ +#ifndef _TEST__F_utf_dynamic_seek_line_to_back_h +#define _TEST__F_utf_dynamic_seek_line_to_back_h + +/** + * Test that the function works where seek target is after a newline. + * + * @see f_utf_string_dynamic_seek_line_to_back() + */ +extern void test__f_utf_string_dynamic_seek_line_to_back__after_newline(void **state); + +/** + * Test that the function works where seek target is before a newline. + * + * @see f_utf_string_dynamic_seek_line_to_back() + */ +extern void test__f_utf_string_dynamic_seek_line_to_back__before_newline(void **state); + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_utf_string_dynamic_seek_line_to_back() + */ +extern void test__f_utf_string_dynamic_seek_line_to_back__parameter_checking(void **state); + +/** + * Test that the function returns F_data_not_stop because range is an empty range (range.start > range.stop). + * + * @see f_utf_string_dynamic_seek_line_to_back() + */ +extern void test__f_utf_string_dynamic_seek_line_to_back__returns_data_not_stop(void **state); + +/** + * Test that the function returns F_okay_eos stopped after end of string because no newline is found. + * + * @see f_utf_string_dynamic_seek_line_to_back() + */ +extern void test__f_utf_string_dynamic_seek_line_to_back__returns_none_eos(void **state); + +/** + * Test that the function returns F_okay_stop stopped after end of range because no newline is found. + * + * @see f_utf_string_dynamic_seek_line_to_back() + */ +extern void test__f_utf_string_dynamic_seek_line_to_back__returns_none_stop(void **state); + +#endif // _TEST__F_utf_dynamic_seek_line_to_back_h diff --git a/level_0/f_utf/tests/unit/c/test-utf-dynamic_seek_to_back.c b/level_0/f_utf/tests/unit/c/test-utf-dynamic_seek_to_back.c new file mode 100644 index 0000000..aa39502 --- /dev/null +++ b/level_0/f_utf/tests/unit/c/test-utf-dynamic_seek_to_back.c @@ -0,0 +1,135 @@ +#include "test-utf.h" +#include "test-utf-dynamic_seek_to_back.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_utf_string_dynamic_seek_to_back__after_newline(void **state) { + + const f_utf_string_static_t to = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0X", 0, 1); + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0X\0\0\0\n\0\0\0s\0\0\0t", 0, 6); + + { + f_range_t range = macro_f_range_t_initialize_1(0, source.used - 1); + + const f_status_t status = f_utf_string_dynamic_seek_to_back(source, to.string[0], &range); + + assert_int_equal(status, F_okay); + + assert_int_equal(range.start, 0); + assert_int_equal(range.stop, 2); + } +} + +void test__f_utf_string_dynamic_seek_to_back__before_newline(void **state) { + + const f_utf_string_static_t to = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0X", 0, 1); + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0\n\0\0\0X\0\0\0s\0\0\0t", 0, 6); + + { + f_range_t range = macro_f_range_t_initialize_1(0, source.used - 1); + + const f_status_t status = f_utf_string_dynamic_seek_to_back(source, to.string[0], &range); + + assert_int_equal(status, F_okay); + + assert_int_equal(range.start, 0); + assert_int_equal(range.stop, 3); + } +} + +void test__f_utf_string_dynamic_seek_to_back__parameter_checking(void **state) { + + const f_utf_string_static_t to = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0X", 0, 1); + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0X\0\0\0\n\0\0\0s\0\0\0t", 0, 6); + + { + const f_status_t status = f_utf_string_dynamic_seek_to_back(source, to.string[0], 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +void test__f_utf_string_dynamic_seek_to_back__returns_data_not_stop(void **state) { + + const f_utf_string_static_t to = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0X", 0, 1); + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0s\0\0\0t\0\0\0\n\0\0\0a\0\0\0f\0\0\0t\0\0\0e\0\0\0r", 0, 10); + + { + f_range_t range = f_range_t_initialize; + + const f_status_t status = f_utf_string_dynamic_seek_to_back(source, to.string[0], &range); + + assert_int_equal(status, F_data_not_stop); + } +} + +void test__f_utf_string_dynamic_seek_to_back__returns_none_eos(void **state) { + + const f_utf_string_static_t to = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0X", 0, 1); + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0s\0\0\0t\0\0\0\n\0\0\0a\0\0\0f\0\0\0t\0\0\0e\0\0\0r", 0, 10); + + { + f_range_t range = macro_f_range_t_initialize_1(0, source.used - 1); + + const f_status_t status = f_utf_string_dynamic_seek_to_back(source, to.string[0], &range); + + assert_int_equal(status, F_okay_eos); + + assert_int_equal(range.start, 0); + assert_int_equal(range.stop, 0); + } +} + +void test__f_utf_string_dynamic_seek_to_back__returns_none_stop(void **state) { + + const f_utf_string_static_t to = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0X", 0, 1); + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0s\0\0\0t\0\0\0\n\0\0\0a\0\0\0f\0\0\0t\0\0\0e\0\0\0r", 0, 10); + + { + f_range_t range = macro_f_range_t_initialize_1(2, source.used - 1); + + const f_status_t status = f_utf_string_dynamic_seek_to_back(source, to.string[0], &range); + + assert_int_equal(status, F_okay_stop); + + assert_int_equal(range.start, 2); + assert_int_equal(range.stop, 1); + } +} + +void test__f_utf_string_dynamic_seek_to_back__works(void **state) { + + const f_utf_string_static_t to = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0X", 0, 1); + + // Test where newline is before "X". + { + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0\n\0\0\0X\0\0\0s\0\0\0t", 0, 6); + f_range_t range = macro_f_range_t_initialize_1(0, source.used - 1); + + const f_status_t status = f_utf_string_dynamic_seek_to_back(source, to.string[0], &range); + + assert_int_equal(status, F_okay); + + assert_int_equal(range.start, 0); + assert_int_equal(range.stop, 3); + } + + // Test where newline is after "X". + { + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0X\0\0\0\n\0\0\0s\0\0\0t", 0, 6); + f_range_t range = macro_f_range_t_initialize_1(0, source.used - 1); + + const f_status_t status = f_utf_string_dynamic_seek_to_back(source, to.string[0], &range); + + assert_int_equal(status, F_okay); + + assert_int_equal(range.start, 0); + assert_int_equal(range.stop, 2); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_utf/tests/unit/c/test-utf-dynamic_seek_to_back.h b/level_0/f_utf/tests/unit/c/test-utf-dynamic_seek_to_back.h new file mode 100644 index 0000000..ff87eca --- /dev/null +++ b/level_0/f_utf/tests/unit/c/test-utf-dynamic_seek_to_back.h @@ -0,0 +1,55 @@ +/** + * FLL - Level 0 + * + * Project: UTF + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the functions in the utf project. + */ +#ifndef _TEST__F_utf_dynamic_seek_to_back_h +#define _TEST__F_utf_dynamic_seek_to_back_h + +/** + * Test that the function works where seek target is after a newline. + * + * @see f_utf_string_dynamic_seek_to_back() + */ +extern void test__f_utf_string_dynamic_seek_to_back__after_newline(void **state); + +/** + * Test that the function works where seek target is before a newline. + * + * @see f_utf_string_dynamic_seek_to_back() + */ +extern void test__f_utf_string_dynamic_seek_to_back__before_newline(void **state); + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_utf_string_dynamic_seek_to_back() + */ +extern void test__f_utf_string_dynamic_seek_to_back__parameter_checking(void **state); + +/** + * Test that the function returns F_data_not_stop because range is an empty range (range.start > range.stop). + * + * @see f_utf_string_dynamic_seek_to_back() + */ +extern void test__f_utf_string_dynamic_seek_to_back__returns_data_not_stop(void **state); + +/** + * Test that the function returns F_okay_eos stopped after end of string because no newline is found. + * + * @see f_utf_string_dynamic_seek_to_back() + */ +extern void test__f_utf_string_dynamic_seek_to_back__returns_none_eos(void **state); + +/** + * Test that the function returns F_okay_stop stopped after end of range because no newline is found. + * + * @see f_utf_string_dynamic_seek_to_back() + */ +extern void test__f_utf_string_dynamic_seek_to_back__returns_none_stop(void **state); + +#endif // _TEST__F_utf_dynamic_seek_to_back_h diff --git a/level_0/f_utf/tests/unit/c/test-utf-seek_line_back.c b/level_0/f_utf/tests/unit/c/test-utf-seek_line_back.c new file mode 100644 index 0000000..b6c75f2 --- /dev/null +++ b/level_0/f_utf/tests/unit/c/test-utf-seek_line_back.c @@ -0,0 +1,66 @@ +#include "test-utf.h" +#include "test-utf-seek_line_back.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_utf_seek_line_back__parameter_checking(void **state) { + + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0X\0\0\0\n\0\0\0s\0\0\0t", 0, 6); + + { + const f_status_t status = f_utf_string_seek_line_back(source.string, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +void test__f_utf_seek_line_back__returns_data_not_stop(void **state) { + + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0s\0\0\0t\0\0\0\n\0\0\0a\0\0\0f\0\0\0t\0\0\0e\0\0\0r", 0, 10); + + { + f_range_t range = f_range_t_initialize; + + const f_status_t status = f_utf_string_seek_line_back(source.string, &range); + + assert_int_equal(status, F_data_not_stop); + } +} + +void test__f_utf_seek_line_back__returns_none_stop(void **state) { + + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0s\0\0\0t", 0, 4); + + { + f_range_t range = macro_f_range_t_initialize_1(2, source.used - 1); + + const f_status_t status = f_utf_string_seek_line_back(source.string, &range); + + assert_int_equal(status, F_okay_stop); + + assert_int_equal(range.start, 2); + assert_int_equal(range.stop, 1); + } +} + +void test__f_utf_seek_line_back__works(void **state) { + + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0s\0\0\0t\0\0\0\n\0\0\0a\0\0\0f\0\0\0t\0\0\0e\0\0\0r", 0, 10); + + { + f_range_t range = macro_f_range_t_initialize_1(0, source.used - 1); + + const f_status_t status = f_utf_string_seek_line_back(source.string, &range); + + assert_int_equal(status, F_okay); + + assert_int_equal(range.start, 0); + assert_int_equal(range.stop, 4); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_utf/tests/unit/c/test-utf-seek_line_back.h b/level_0/f_utf/tests/unit/c/test-utf-seek_line_back.h new file mode 100644 index 0000000..b29663d --- /dev/null +++ b/level_0/f_utf/tests/unit/c/test-utf-seek_line_back.h @@ -0,0 +1,41 @@ +/** + * FLL - Level 0 + * + * Project: UTF + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the functions in the utf project. + */ +#ifndef _TEST__F_utf_seek_line_back_h +#define _TEST__F_utf_seek_line_back_h + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_utf_string_seek_line_back() + */ +extern void test__f_utf_seek_line_back__parameter_checking(void **state); + +/** + * Test that the function returns F_data_not_stop because range is an empty range (range.start > range.stop). + * + * @see f_utf_string_seek_line_back() + */ +extern void test__f_utf_seek_line_back__returns_data_not_stop(void **state); + +/** + * Test that the function returns F_okay_stop stopped after end of range because no newline is found. + * + * @see f_utf_string_seek_line_back() + */ +extern void test__f_utf_seek_line_back__returns_none_stop(void **state); + +/** + * Test that the function works. + * + * @see f_utf_string_seek_line_back() + */ +extern void test__f_utf_seek_line_back__works(void **state); + +#endif // _TEST__F_utf_seek_line_back_h diff --git a/level_0/f_utf/tests/unit/c/test-utf-seek_line_to_back.c b/level_0/f_utf/tests/unit/c/test-utf-seek_line_to_back.c new file mode 100644 index 0000000..1fcc41a --- /dev/null +++ b/level_0/f_utf/tests/unit/c/test-utf-seek_line_to_back.c @@ -0,0 +1,87 @@ +#include "test-utf.h" +#include "test-utf-seek_line_to_back.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_utf_seek_line_to_back__after_newline(void **state) { + + const f_utf_string_static_t to = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0X", 0, 1); + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0X\0\0\0\n\0\0\0s\0\0\0t", 0, 6); + + { + f_range_t range = macro_f_range_t_initialize_1(0, source.used - 1); + + const f_status_t status = f_utf_string_seek_line_to_back(source.string, to.string[0], &range); + + assert_int_equal(status, F_okay_eol); + + assert_int_equal(range.start, 0); + assert_int_equal(range.stop, 3); + } +} + +void test__f_utf_seek_line_to_back__before_newline(void **state) { + + const f_utf_string_static_t to = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0X", 0, 1); + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0\n\0\0\0X\0\0\0s\0\0\0t", 0, 6); + + { + f_range_t range = macro_f_range_t_initialize_1(0, source.used - 1); + + const f_status_t status = f_utf_string_seek_line_to_back(source.string, to.string[0], &range); + + assert_int_equal(status, F_okay); + + assert_int_equal(range.start, 0); + assert_int_equal(range.stop, 3); + } +} + +void test__f_utf_seek_line_to_back__parameter_checking(void **state) { + + const f_utf_string_static_t to = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0X", 0, 1); + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0X\0\0\0\n\0\0\0s\0\0\0t", 0, 6); + + { + const f_status_t status = f_utf_string_seek_line_to_back(source.string, to.string[0], 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +void test__f_utf_seek_line_to_back__returns_data_not_stop(void **state) { + + const f_utf_string_static_t to = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0X", 0, 1); + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0s\0\0\0t\0\0\0\n\0\0\0a\0\0\0f\0\0\0t\0\0\0e\0\0\0r", 0, 10); + + { + f_range_t range = f_range_t_initialize; + + const f_status_t status = f_utf_string_seek_line_to_back(source.string, to.string[0], &range); + + assert_int_equal(status, F_data_not_stop); + } +} + +void test__f_utf_seek_line_to_back__returns_none_stop(void **state) { + + const f_utf_string_static_t to = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0X", 0, 1); + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0s\0\0\0t", 0, 4); + + { + f_range_t range = macro_f_range_t_initialize_1(2, source.used - 1); + + const f_status_t status = f_utf_string_seek_line_to_back(source.string, to.string[0], &range); + + assert_int_equal(status, F_okay_stop); + + assert_int_equal(range.start, 2); + assert_int_equal(range.stop, 1); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_utf/tests/unit/c/test-utf-seek_line_to_back.h b/level_0/f_utf/tests/unit/c/test-utf-seek_line_to_back.h new file mode 100644 index 0000000..2081091 --- /dev/null +++ b/level_0/f_utf/tests/unit/c/test-utf-seek_line_to_back.h @@ -0,0 +1,48 @@ +/** + * FLL - Level 0 + * + * Project: UTF + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the functions in the utf project. + */ +#ifndef _TEST__F_utf_seek_line_to_back_h +#define _TEST__F_utf_seek_line_to_back_h + +/** + * Test that the function works where seek target is after a newline. + * + * @see f_utf_string_seek_line_to_back() + */ +extern void test__f_utf_seek_line_to_back__after_newline(void **state); + +/** + * Test that the function works where seek target is before a newline. + * + * @see f_utf_string_seek_line_to_back() + */ +extern void test__f_utf_seek_line_to_back__before_newline(void **state); + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_utf_string_seek_line_to_back() + */ +extern void test__f_utf_seek_line_to_back__parameter_checking(void **state); + +/** + * Test that the function returns F_data_not_stop because range is an empty range (range.start > range.stop). + * + * @see f_utf_string_seek_line_to_back() + */ +extern void test__f_utf_seek_line_to_back__returns_data_not_stop(void **state); + +/** + * Test that the function returns F_okay_stop stopped after end of range because no newline is found. + * + * @see f_utf_string_seek_line_to_back() + */ +extern void test__f_utf_seek_line_to_back__returns_none_stop(void **state); + +#endif // _TEST__F_utf_seek_line_to_back_h diff --git a/level_0/f_utf/tests/unit/c/test-utf-seek_to_back.c b/level_0/f_utf/tests/unit/c/test-utf-seek_to_back.c new file mode 100644 index 0000000..50421fd --- /dev/null +++ b/level_0/f_utf/tests/unit/c/test-utf-seek_to_back.c @@ -0,0 +1,87 @@ +#include "test-utf.h" +#include "test-utf-seek_to_back.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_utf_seek_to_back__after_newline(void **state) { + + const f_utf_string_static_t to = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0X", 0, 1); + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0X\0\0\0\n\0\0\0s\0\0\0t", 0, 6); + + { + f_range_t range = macro_f_range_t_initialize_1(0, source.used - 1); + + const f_status_t status = f_utf_string_seek_to_back(source.string, to.string[0], &range); + + assert_int_equal(status, F_okay); + + assert_int_equal(range.start, 0); + assert_int_equal(range.stop, 2); + } +} + +void test__f_utf_seek_to_back__before_newline(void **state) { + + const f_utf_string_static_t to = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0X", 0, 1); + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0\n\0\0\0X\0\0\0s\0\0\0t", 0, 6); + + { + f_range_t range = macro_f_range_t_initialize_1(0, source.used - 1); + + const f_status_t status = f_utf_string_seek_to_back(source.string, to.string[0], &range); + + assert_int_equal(status, F_okay); + + assert_int_equal(range.start, 0); + assert_int_equal(range.stop, 3); + } +} + +void test__f_utf_seek_to_back__parameter_checking(void **state) { + + const f_utf_string_static_t to = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0X", 0, 1); + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0X\0\0\0\n\0\0\0s\0\0\0t", 0, 6); + + { + const f_status_t status = f_utf_string_seek_to_back(source.string, to.string[0], 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +void test__f_utf_seek_to_back__returns_data_not_stop(void **state) { + + const f_utf_string_static_t to = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0X", 0, 1); + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0s\0\0\0t\0\0\0\n\0\0\0a\0\0\0f\0\0\0t\0\0\0e\0\0\0r", 0, 10); + + { + f_range_t range = f_range_t_initialize; + + const f_status_t status = f_utf_string_seek_to_back(source.string, to.string[0], &range); + + assert_int_equal(status, F_data_not_stop); + } +} + +void test__f_utf_seek_to_back__returns_none_stop(void **state) { + + const f_utf_string_static_t to = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0X", 0, 1); + const f_utf_string_static_t source = macro_f_utf_string_static_t_initialize_1((f_utf_string_t) "\0\0\0t\0\0\0e\0\0\0s\0\0\0t\0\0\0\n\0\0\0a\0\0\0f\0\0\0t\0\0\0e\0\0\0r", 0, 10); + + { + f_range_t range = macro_f_range_t_initialize_1(2, source.used - 1); + + const f_status_t status = f_utf_string_seek_to_back(source.string, to.string[0], &range); + + assert_int_equal(status, F_okay_stop); + + assert_int_equal(range.start, 2); + assert_int_equal(range.stop, 1); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_utf/tests/unit/c/test-utf-seek_to_back.h b/level_0/f_utf/tests/unit/c/test-utf-seek_to_back.h new file mode 100644 index 0000000..c846604 --- /dev/null +++ b/level_0/f_utf/tests/unit/c/test-utf-seek_to_back.h @@ -0,0 +1,48 @@ +/** + * FLL - Level 0 + * + * Project: UTF + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the functions in the utf project. + */ +#ifndef _TEST__F_utf_seek_to_back_h +#define _TEST__F_utf_seek_to_back_h + +/** + * Test that the function works where seek target is after a newline. + * + * @see f_utf_string_seek_to_back() + */ +extern void test__f_utf_seek_to_back__after_newline(void **state); + +/** + * Test that the function works where seek target is before a newline. + * + * @see f_utf_string_seek_to_back() + */ +extern void test__f_utf_seek_to_back__before_newline(void **state); + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_utf_string_seek_to_back() + */ +extern void test__f_utf_seek_to_back__parameter_checking(void **state); + +/** + * Test that the function returns F_data_not_stop because range is an empty range (range.start > range.stop). + * + * @see f_utf_string_seek_to_back() + */ +extern void test__f_utf_seek_to_back__returns_data_not_stop(void **state); + +/** + * Test that the function returns F_okay_stop stopped after end of range because no newline is found. + * + * @see f_utf_string_seek_to_back() + */ +extern void test__f_utf_seek_to_back__returns_none_stop(void **state); + +#endif // _TEST__F_utf_seek_to_back_h diff --git a/level_0/f_utf/tests/unit/c/test-utf.c b/level_0/f_utf/tests/unit/c/test-utf.c index 3b969f9..e60c5db 100644 --- a/level_0/f_utf/tests/unit/c/test-utf.c +++ b/level_0/f_utf/tests/unit/c/test-utf.c @@ -92,18 +92,35 @@ int main(void) { cmocka_unit_test(test__f_utf_string_dynamic_seek_line__returns_none_stop), cmocka_unit_test(test__f_utf_string_dynamic_seek_line__works), + cmocka_unit_test(test__f_utf_string_dynamic_seek_line_back__returns_data_not_stop), + cmocka_unit_test(test__f_utf_string_dynamic_seek_line_back__returns_none_eos), + cmocka_unit_test(test__f_utf_string_dynamic_seek_line_back__returns_none_stop), + cmocka_unit_test(test__f_utf_string_dynamic_seek_line_back__works), + cmocka_unit_test(test__f_utf_string_dynamic_seek_line_to__after_newline), cmocka_unit_test(test__f_utf_string_dynamic_seek_line_to__before_newline), cmocka_unit_test(test__f_utf_string_dynamic_seek_line_to__returns_data_not_stop), cmocka_unit_test(test__f_utf_string_dynamic_seek_line_to__returns_none_eos), cmocka_unit_test(test__f_utf_string_dynamic_seek_line_to__returns_none_stop), + cmocka_unit_test(test__f_utf_string_dynamic_seek_line_to_back__after_newline), + cmocka_unit_test(test__f_utf_string_dynamic_seek_line_to_back__before_newline), + cmocka_unit_test(test__f_utf_string_dynamic_seek_line_to_back__returns_data_not_stop), + cmocka_unit_test(test__f_utf_string_dynamic_seek_line_to_back__returns_none_eos), + cmocka_unit_test(test__f_utf_string_dynamic_seek_line_to_back__returns_none_stop), + cmocka_unit_test(test__f_utf_string_dynamic_seek_to__after_newline), cmocka_unit_test(test__f_utf_string_dynamic_seek_to__before_newline), cmocka_unit_test(test__f_utf_string_dynamic_seek_to__returns_data_not_stop), cmocka_unit_test(test__f_utf_string_dynamic_seek_to__returns_none_eos), cmocka_unit_test(test__f_utf_string_dynamic_seek_to__returns_none_stop), + cmocka_unit_test(test__f_utf_string_dynamic_seek_to_back__after_newline), + cmocka_unit_test(test__f_utf_string_dynamic_seek_to_back__before_newline), + cmocka_unit_test(test__f_utf_string_dynamic_seek_to_back__returns_data_not_stop), + cmocka_unit_test(test__f_utf_string_dynamic_seek_to_back__returns_none_eos), + cmocka_unit_test(test__f_utf_string_dynamic_seek_to_back__returns_none_stop), + cmocka_unit_test(test__f_utf_string_dynamic_terminate__appends_null), cmocka_unit_test(test__f_utf_string_dynamic_terminate__doesnt_append_null), @@ -192,16 +209,30 @@ int main(void) { cmocka_unit_test(test__f_utf_seek_line__returns_none_stop), cmocka_unit_test(test__f_utf_seek_line__works), + cmocka_unit_test(test__f_utf_seek_line_back__returns_data_not_stop), + cmocka_unit_test(test__f_utf_seek_line_back__returns_none_stop), + cmocka_unit_test(test__f_utf_seek_line_back__works), + cmocka_unit_test(test__f_utf_seek_line_to__after_newline), cmocka_unit_test(test__f_utf_seek_line_to__before_newline), cmocka_unit_test(test__f_utf_seek_line_to__returns_data_not_stop), cmocka_unit_test(test__f_utf_seek_line_to__returns_none_stop), + cmocka_unit_test(test__f_utf_seek_line_to_back__after_newline), + cmocka_unit_test(test__f_utf_seek_line_to_back__before_newline), + cmocka_unit_test(test__f_utf_seek_line_to_back__returns_data_not_stop), + cmocka_unit_test(test__f_utf_seek_line_to_back__returns_none_stop), + cmocka_unit_test(test__f_utf_seek_to__after_newline), cmocka_unit_test(test__f_utf_seek_to__before_newline), cmocka_unit_test(test__f_utf_seek_to__returns_data_not_stop), cmocka_unit_test(test__f_utf_seek_to__returns_none_stop), + cmocka_unit_test(test__f_utf_seek_to_back__after_newline), + cmocka_unit_test(test__f_utf_seek_to_back__before_newline), + cmocka_unit_test(test__f_utf_seek_to_back__returns_data_not_stop), + cmocka_unit_test(test__f_utf_seek_to_back__returns_none_stop), + cmocka_unit_test(test__f_utf_string_dynamicss_delete_callback__fails), cmocka_unit_test(test__f_utf_string_dynamicss_destroy_callback__fails), diff --git a/level_0/f_utf/tests/unit/c/test-utf.h b/level_0/f_utf/tests/unit/c/test-utf.h index a5ecd13..0650dfb 100644 --- a/level_0/f_utf/tests/unit/c/test-utf.h +++ b/level_0/f_utf/tests/unit/c/test-utf.h @@ -83,8 +83,11 @@ #include "test-utf-dynamic_prepend_assure_nulless.h" #include "test-utf-dynamic_prepend_nulless.h" #include "test-utf-dynamic_seek_line.h" +#include "test-utf-dynamic_seek_line_back.h" #include "test-utf-dynamic_seek_line_to.h" +#include "test-utf-dynamic_seek_line_to_back.h" #include "test-utf-dynamic_seek_to.h" +#include "test-utf-dynamic_seek_to_back.h" #include "test-utf-dynamic_terminate.h" #include "test-utf-dynamic_terminate_after.h" #include "test-utf-dynamics_append.h" @@ -145,8 +148,11 @@ #include "test-utf-prepend_assure_nulless.h" #include "test-utf-prepend_nulless.h" #include "test-utf-seek_line.h" +#include "test-utf-seek_line_back.h" #include "test-utf-seek_line_to.h" +#include "test-utf-seek_line_to_back.h" #include "test-utf-seek_to.h" +#include "test-utf-seek_to_back.h" #include "test-utf-triples_append.h" #include "test-utf-triples_append_all.h" #include "test-utf-triples_delete_callback.h" -- 1.8.3.1