From: Kevin Day Date: Tue, 28 Apr 2020 05:46:11 +0000 (-0500) Subject: Feature: implement string mash support X-Git-Tag: 0.5.0~318 X-Git-Url: https://git.kevux.org/?a=commitdiff_plain;h=a5f8f8fc61dd2821d304886fbaf23977cd10d2b5;p=fll Feature: implement string mash support String mashing is a way to append a string to another with a glue string in between. The idea is that a space could be placed between the two strings. A string is primarily used as the mash character so that UTF-8 can be natively supported as the glue character. --- diff --git a/level_1/fl_string/c/private-string.c b/level_1/fl_string/c/private-string.c index 99976c3..ee01f3f 100644 --- a/level_1/fl_string/c/private-string.c +++ b/level_1/fl_string/c/private-string.c @@ -170,6 +170,43 @@ extern "C" { } #endif // !defined(_di_fl_string_compare_trim_) || !defined(_di_fl_string_dynamic_compare_trim_) || !defined(_di_fl_string_dynamic_partial_compare_trim_) +#if !defined(_di_fl_string_mash_) || !defined(_di_fl_string_dynamic_mash_) || !defined(_di_fl_string_dynamic_partial_mash_) + f_return_status private_fl_string_mash(const f_string glue, const f_string_length glue_length, const f_string source, const f_string_length source_length, f_string_dynamic *destination) { + f_status status = f_none; + + if (destination->used == 0) { + if (source_length > f_string_max_size) return f_status_set_error(f_string_too_large); + + f_macro_string_dynamic_resize(status, (*destination), source_length); + if (f_status_is_error(status)) return status; + + memcpy(destination->string, source, source_length); + + destination->used = source_length; + } + else { + f_string_length total = destination->used + source_length + glue_length; + + if (total > f_string_max_size) return f_status_set_error(f_string_too_large); + + if (total > destination->size) { + f_macro_string_dynamic_resize(status, (*destination), total); + if (f_status_is_error(status)) return status; + } + + for (f_string_length i = 0; i < glue_length; i++) { + destination->string[destination->used + i] = glue[i]; + } // for + + memcpy(destination->string + destination->used + glue_length, source, source_length); + + destination->used = total; + } + + return f_none; + } +#endif // !defined(_di_fl_string_mash_) || !defined(_di_fl_string_dynamic_mash_) || !defined(_di_fl_string_dynamic_partial_mash_) + #if !defined(_di_fl_string_rip_) || !defined(_di_fl_string_dynamic_rip_) f_return_status private_fl_string_rip(const f_string string, const f_string_length start, const f_string_length stop, f_string_dynamic *result) { // The start and stop point are inclusive locations, and therefore start - stop is actually 1 too few locations. diff --git a/level_1/fl_string/c/private-string.h b/level_1/fl_string/c/private-string.h index cb7e011..6c339fe 100644 --- a/level_1/fl_string/c/private-string.h +++ b/level_1/fl_string/c/private-string.h @@ -80,6 +80,37 @@ extern "C" { #endif // !defined(_di_fl_string_compare_trim_) || !defined(_di_fl_string_dynamic_compare_trim_) || !defined(_di_fl_string_dynamic_partial_compare_trim_) /** + * Private implementation of fl_string_mash(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param glue + * A string to append between the source and destination, such as a space: ' '. + * @param glue_length + * The number of bytes the glue takes up. + * @param source + * The source string to append. + * @param source_length + * Total number of bytes to copy from source string. + * @param destination + * The destination string the source and glue are appended onto. + * + * @return + * f_none on success. + * f_string_max_size (with error bit) if the combined string is too large. + * f_invalid_parameter (with error bit) if a parameter is invalid. + * f_error_allocation (with error bit) on memory allocation error. + * f_error_reallocation (with error bit) on memory reallocation error. + * + * @see fl_string_mash() + * @see fl_string_dynamic_mash() + * @see fl_string_dynamic_partial_mash() + */ +#if !defined(_di_fl_string_mash_) || !defined(_di_fl_string_dynamic_mash_) || !defined(_di_fl_string_dynamic_partial_mash_) + extern f_return_status private_fl_string_mash(const f_string glue, const f_string_length glue_length, const f_string source, const f_string_length source_length, f_string_dynamic *destination) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_fl_string_mash_) || !defined(_di_fl_string_dynamic_mash_) || !defined(_di_fl_string_dynamic_partial_mash_) + +/** * Private implementation of fl_string_rip(). * * Intended to be shared to each of the different implementation variations. diff --git a/level_1/fl_string/c/string.c b/level_1/fl_string/c/string.c index 2b87b86..4b3c1c0 100644 --- a/level_1/fl_string/c/string.c +++ b/level_1/fl_string/c/string.c @@ -49,6 +49,18 @@ extern "C" { } #endif // _di_fl_string_dynamic_compare_trim_ +#ifndef _di_fl_string_dynamic_mash_ + f_return_status fl_string_dynamic_mash(const f_string glue, const f_string_length glue_length, const f_string_dynamic source, f_string_dynamic *destination) { + #ifndef _di_level_1_parameter_checking_ + if (glue_length < 1) return f_status_set_error(f_invalid_parameter); + if (source.used < 1) return f_status_set_error(f_invalid_parameter); + if (destination == 0) return f_status_set_error(f_invalid_parameter); + #endif // _di_level_1_parameter_checking_ + + return private_fl_string_mash(glue, glue_length, source.string, source.used, destination); + } +#endif // _di_fl_string_dynamic_mash_ + #ifndef _di_fl_string_dynamic_partial_compare_ f_return_status fl_string_dynamic_partial_compare(const f_string_dynamic string1, const f_string_dynamic string2, const f_string_location offset1, const f_string_location offset2) { #ifndef _di_level_1_parameter_checking_ @@ -83,6 +95,21 @@ extern "C" { } #endif // _di_fl_string_dynamic_partial_compare_trim_ +#ifndef _di_fl_string_dynamic_partial_mash_ + f_return_status fl_string_dynamic_partial_mash(const f_string glue, const f_string_length glue_length, const f_string_dynamic source, const f_string_location offset, f_string_dynamic *destination) { + #ifndef _di_level_1_parameter_checking_ + if (glue_length < 1) return f_status_set_error(f_invalid_parameter); + if (source.used < 1) return f_status_set_error(f_invalid_parameter); + if (destination == 0) return f_status_set_error(f_invalid_parameter); + + if (offset.start > offset.stop) return f_status_set_error(f_invalid_parameter); + if (source.used <= offset.stop) return f_status_set_error(f_invalid_parameter); + #endif // _di_level_1_parameter_checking_ + + return private_fl_string_mash(glue, glue_length, source.string + offset.start, (offset.stop - offset.start) + 1, destination); + } +#endif // _di_fl_string_dynamic_partial_mash_ + #ifndef _di_fl_string_dynamic_rip_ f_return_status fl_string_dynamic_rip(const f_string_dynamic buffer, const f_string_location location, f_string_dynamic *result) { #ifndef _di_level_1_parameter_checking_ @@ -413,6 +440,18 @@ extern "C" { } #endif // _di_fl_string_dynamic_seek_to_utf_character_ +#ifndef _di_fl_string_mash_ + f_return_status fl_string_mash(const f_string glue, const f_string_length glue_length, const f_string source, const f_string_length source_length, f_string_dynamic *destination) { + #ifndef _di_level_1_parameter_checking_ + if (glue_length < 1) return f_status_set_error(f_invalid_parameter); + if (source_length < 1) return f_status_set_error(f_invalid_parameter); + if (destination == 0) return f_status_set_error(f_invalid_parameter); + #endif // _di_level_1_parameter_checking_ + + return private_fl_string_mash(glue, glue_length, source, source_length, destination); + } +#endif // _di_fl_string_mash_ + #ifndef _di_fl_string_rip_ f_return_status fl_string_rip(const f_string string, const f_string_length start, const f_string_length stop, f_string_dynamic *result) { #ifndef _di_level_1_parameter_checking_ diff --git a/level_1/fl_string/c/string.h b/level_1/fl_string/c/string.h index 81434fe..1a1bf94 100644 --- a/level_1/fl_string/c/string.h +++ b/level_1/fl_string/c/string.h @@ -145,6 +145,35 @@ extern "C" { #endif // _di_fl_string_dynamic_compare_trim_ /** + * Append the source string onto the destination with the glue in between. + * + * If the destination string is empty, then no glue is appended. + * + * @param glue + * A string to append between the source and destination, such as a space: ' '. + * @param glue_length + * The number of bytes the glue takes up. + * @param source + * The source string to append. + * @param destination + * The destination string the source and glue are appended onto. + * + * @return + * f_none on success. + * f_string_max_size (with error bit) if the combined string is too large. + * f_invalid_parameter (with error bit) if a parameter is invalid. + * f_error_allocation (with error bit) on memory allocation error. + * f_error_reallocation (with error bit) on memory reallocation error. + * + * @see fl_string_mash() + * @see fl_string_dynamic_mash() + * @see fl_string_dynamic_partial_mash() + */ +#ifndef _di_fl_string_dynamic_mash_ + extern f_return_status fl_string_dynamic_mash(const f_string glue, const f_string_length glue_length, const f_string_dynamic source, f_string_dynamic *destination); +#endif // _di_fl_string_dynamic_mash_ + +/** * Compare two strings, similar to strncmp(), but restricted to the given ranges. * * This does not stop on NULL. @@ -204,6 +233,37 @@ extern "C" { #endif // _di_fl_string_dynamic_partial_compare_trim_ /** + * Append the source string onto the destination with the glue in between. + * + * If the destination string is empty, then no glue is appended. + * + * @param glue + * A string to append between the source and destination, such as a space: ' '. + * @param glue_length + * The number of bytes the glue takes up. + * @param source + * The source string to append. + * @param offset + * A range within the source to restrict the append from. + * @param destination + * The destination string the source and glue are appended onto. + * + * @return + * f_none on success. + * f_string_max_size (with error bit) if the combined string is too large. + * f_invalid_parameter (with error bit) if a parameter is invalid. + * f_error_allocation (with error bit) on memory allocation error. + * f_error_reallocation (with error bit) on memory reallocation error. + * + * @see fl_string_mash() + * @see fl_string_dynamic_mash() + * @see fl_string_dynamic_partial_mash() + */ +#ifndef _di_fl_string_dynamic_partial_mash_ + extern f_return_status fl_string_dynamic_partial_mash(const f_string glue, const f_string_length glue_length, const f_string_dynamic source, const f_string_location offset, f_string_dynamic *destination); +#endif // _di_fl_string_dynamic_partial_mash_ + +/** * Allocate a new string from the provided range in the buffer. * * @param buffer @@ -422,6 +482,37 @@ extern "C" { #endif // _di_fl_string_dynamic_seek_to_utf_character_ /** + * Append the source string onto the destination with the glue in between. + * + * If the destination string is empty, then no glue is appended. + * + * @param glue + * A string to append between the source and destination, such as a space: ' '. + * @param glue_length + * The number of bytes the glue takes up. + * @param source + * The source string to append. + * @param source_length + * Total number of bytes to copy from source string. + * @param destination + * The destination string the source and glue are appended onto. + * + * @return + * f_none on success. + * f_string_max_size (with error bit) if the combined string is too large. + * f_invalid_parameter (with error bit) if a parameter is invalid. + * f_error_allocation (with error bit) on memory allocation error. + * f_error_reallocation (with error bit) on memory reallocation error. + * + * @see fl_string_mash() + * @see fl_string_dynamic_mash() + * @see fl_string_dynamic_partial_mash() + */ +#ifndef _di_fl_string_mash_ + extern f_return_status fl_string_mash(const f_string glue, const f_string_length glue_length, const f_string source, const f_string_length source_length, f_string_dynamic *destination); +#endif // _di_fl_string_mash_ + +/** * Allocate a new string from the provided range in the string. * * @param string