The ability to strip out NULLs from a given string as a common function is needed.
Provide two similar but different functions.
The f_string_dynamic_strip_null() moves the NULLs to the end of the string and the shrinks the string used length as appropriate.
The f_string_dynamic_strip_null_range() shifts all of the NULLs found to the end of the given range without modifying the array used length.
Unit tests are added.
Only basic logic is applied and so there is no especially focused optimization in the parsing logic.
}
#endif // _di_f_string_dynamic_seek_to_
+#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_
+ if (!buffer) return F_status_set_error(F_parameter);
+ #endif // _di_level_0_parameter_checking_
+
+ if (!buffer->used) return F_data_not;
+
+ // Skip past trailing NULLs.
+ while (buffer->used && !buffer->string[buffer->used - 1]) {
+ --buffer->used;
+ } // while
+
+ if (!buffer->used) return F_okay;
+
+ f_number_unsigned_t i = buffer->used - 1;
+ f_number_unsigned_t j = 0;
+
+ do {
+ if (!buffer->string[i]) {
+
+ // Set index j to the left-most consecutive NULL from index i, with index i being the right-most NULL.
+ if (i) {
+ for (j = i - 1; j && !buffer->string[j]; --j) {
+ // Do nothing.
+ } // for
+
+ if (buffer->string[j]) {
+ ++j;
+ }
+ }
+ else {
+ j = i;
+ }
+
+ memmove(buffer->string + j, buffer->string + i + 1, buffer->used - i);
+ memset(buffer->string + (buffer->used - (i - j) - 1), 0, (i - j) + 1);
+
+ buffer->used -= (i - j) + 1;
+ i = j;
+ }
+
+ } while (i--);
+
+ return F_okay;
+ }
+#endif // _di_f_string_dynamic_strip_null_
+
+#ifndef _di_f_string_dynamic_strip_null_range_
+ f_status_t f_string_dynamic_strip_null_range(const f_range_t range, f_string_dynamic_t * const buffer) {
+ #ifndef _di_level_0_parameter_checking_
+ if (!buffer) 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;
+ if (range.start >= buffer->used) return F_data_not_eos;
+
+ f_number_unsigned_t last = range.stop;
+ f_number_unsigned_t i = range.stop + 1;
+ f_number_unsigned_t j = 0;
+
+ // Skip past trailing NULLs.
+ while (i-- > range.start && i) {
+ if (buffer->string[i]) break;
+ } // while
+
+ if (i) {
+ do {
+ if (!buffer->string[i]) {
+
+ // Set index j to the left-most consecutive NULL from index i, with index i being the right-most NULL.
+ if (i) {
+ for (j = i - 1; j && !buffer->string[j]; --j) {
+ // Do nothing.
+ } // for
+
+ if (buffer->string[j]) {
+ ++j;
+ }
+ }
+ else {
+ j = i;
+ }
+
+ memmove(buffer->string + j, buffer->string + i + 1, last - i);
+ memset(buffer->string + (last - (i - j)), 0, (i - j) + 1);
+
+ last -= (i - j) + 1;
+ i = j;
+ }
+
+ } while (i-- > range.start);
+ }
+
+ return F_okay;
+ }
+#endif // _di_f_string_dynamic_strip_null_range_
+
#ifndef _di_f_string_dynamic_terminate_
f_status_t f_string_dynamic_terminate(f_string_dynamic_t * const destination) {
#ifndef _di_level_0_parameter_checking_
#endif // _di_f_string_dynamic_seek_to_
/**
+ * String all NULLs from the given string.
+ *
+ * This does not resize the string.
+ * The string used length of the buffer is shrunk based on the NULLs removed.
+ *
+ * @param buffer
+ * The string to strip the NULLs from.
+ *
+ * @return
+ * F_okay on success.
+ * F_data_not if source length is 0.
+ *
+ * F_parameter (with error bit) if a parameter is invalid.
+ * F_string_too_large (with error bit) if the combined string is too large.
+ */
+#ifndef _di_f_string_dynamic_strip_null_
+ extern f_status_t f_string_dynamic_strip_null(f_string_dynamic_t * const buffer);
+#endif // _di_f_string_dynamic_strip_null_
+
+/**
+ * String all NULLs from the given string within the specified range.
+ *
+ * This does not resize the string.
+ * Unlike f_string_dynamic_strip_null(), this does not alter the string used length of the buffer.
+ *
+ * Any found NULLs are moved to the end of the range in the buffer.
+ *
+ * @param range
+ * The given range within the buffer to strip.
+ * @param buffer
+ * The string to strip the NULLs from.
+ *
+ * @return
+ * F_okay on success.
+ * F_data_not if source length is 0.
+ * F_data_not_eos if range.start >= source.used.
+ * F_data_not_stop if range.start > range.stop.
+ *
+ * F_parameter (with error bit) if a parameter is invalid.
+ * F_string_too_large (with error bit) if the combined string is too large.
+ */
+#ifndef _di_f_string_dynamic_strip_null_range_
+ extern f_status_t f_string_dynamic_strip_null_range(const f_range_t range, f_string_dynamic_t * const buffer);
+#endif // _di_f_string_dynamic_strip_null_range_
+
+/**
* 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.
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_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
build_sources_program test-string-dynamics_delete_callback.c test-string-dynamics_destroy_callback.c
--- /dev/null
+#include "test-string.h"
+#include "test-string-dynamic_strip_null.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_string_dynamic_strip_null__returns_data_not(void **state) {
+
+ f_string_static_t buffer = f_string_static_t_initialize;
+
+ {
+ const f_status_t status = f_string_dynamic_strip_null(&buffer);
+
+ assert_int_equal(status, F_data_not);
+ }
+}
+
+void test__f_string_dynamic_strip_null__works(void **state) {
+
+ const f_string_static_t sources[] = {
+
+ // First Set.
+ macro_f_string_static_t_initialize_1("test", 0, 4),
+ macro_f_string_static_t_initialize_1("test", 0, 5),
+ macro_f_string_static_t_initialize_1("te\0st", 0, 5),
+ macro_f_string_static_t_initialize_1("te\0st", 0, 6),
+ macro_f_string_static_t_initialize_1("te\0\0st", 0, 6),
+ macro_f_string_static_t_initialize_1("te\0\0st", 0, 7),
+ macro_f_string_static_t_initialize_1("te\0\0s\0t", 0, 7),
+ macro_f_string_static_t_initialize_1("te\0\0s\0t", 0, 8),
+ macro_f_string_static_t_initialize_1("te\0\0s\0\0\0t", 0, 9),
+ macro_f_string_static_t_initialize_1("te\0\0s\0\0\0t", 0, 10),
+
+ // Second Set.
+ macro_f_string_static_t_initialize_1("test", 0, 4),
+ macro_f_string_static_t_initialize_1("test", 0, 5),
+ macro_f_string_static_t_initialize_1("te\0st", 0, 5),
+ macro_f_string_static_t_initialize_1("te\0st", 0, 6),
+ macro_f_string_static_t_initialize_1("te\0\0st", 0, 6),
+ macro_f_string_static_t_initialize_1("te\0\0st", 0, 7),
+ macro_f_string_static_t_initialize_1("te\0\0s\0t", 0, 7),
+ macro_f_string_static_t_initialize_1("te\0\0s\0t", 0, 8),
+ macro_f_string_static_t_initialize_1("te\0\0s\0\0\0t", 0, 9),
+ macro_f_string_static_t_initialize_1("te\0\0s\0\0\0t", 0, 10),
+
+ // Third Set.
+ macro_f_string_static_t_initialize_1("\0\0test", 0, 6),
+ macro_f_string_static_t_initialize_1("\0\0test", 0, 7),
+ macro_f_string_static_t_initialize_1("\0\0te\0st", 0, 7),
+ macro_f_string_static_t_initialize_1("\0\0te\0st", 0, 8),
+ macro_f_string_static_t_initialize_1("\0\0te\0\0st", 0, 8),
+ macro_f_string_static_t_initialize_1("\0\0te\0\0st", 0, 9),
+ macro_f_string_static_t_initialize_1("\0\0te\0\0s\0t", 0, 9),
+ macro_f_string_static_t_initialize_1("\0\0te\0\0s\0t", 0, 10),
+ macro_f_string_static_t_initialize_1("\0\0te\0\0s\0\0\0t", 0, 11),
+ macro_f_string_static_t_initialize_1("\0\0te\0\0s\0\0\0t", 0, 12),
+
+ // Fourth Set.
+ macro_f_string_static_t_initialize_1("\0\0\0\0", 0, 4),
+ macro_f_string_static_t_initialize_1("\0\0\0\0", 0, 4),
+ macro_f_string_static_t_initialize_1("\0", 0, 1),
+ macro_f_string_static_t_initialize_1("t", 0, 1),
+ };
+
+ const f_string_static_t expects[] = {
+
+ // First Set.
+ macro_f_string_static_t_initialize_1("test", 0, 4),
+ macro_f_string_static_t_initialize_1("test", 0, 4),
+ macro_f_string_static_t_initialize_1("test\0", 0, 4),
+ macro_f_string_static_t_initialize_1("test\0", 0, 4),
+ macro_f_string_static_t_initialize_1("test\0\0", 0, 4),
+ macro_f_string_static_t_initialize_1("test\0\0", 0, 4),
+ macro_f_string_static_t_initialize_1("test\0\0\0", 0, 4),
+ macro_f_string_static_t_initialize_1("test\0\0\0", 0, 4),
+ macro_f_string_static_t_initialize_1("test\0\0\0\0\0", 0, 4),
+ macro_f_string_static_t_initialize_1("test\0\0\0\0\0", 0, 4),
+
+ // Second Set.
+ macro_f_string_static_t_initialize_1("test", 0, 4),
+ macro_f_string_static_t_initialize_1("test", 0, 4),
+ macro_f_string_static_t_initialize_1("test\0", 0, 4),
+ macro_f_string_static_t_initialize_1("test\0", 0, 4),
+ macro_f_string_static_t_initialize_1("test\0\0", 0, 4),
+ macro_f_string_static_t_initialize_1("test\0\0", 0, 4),
+ macro_f_string_static_t_initialize_1("test\0\0\0", 0, 4),
+ macro_f_string_static_t_initialize_1("test\0\0\0", 0, 4),
+ macro_f_string_static_t_initialize_1("test\0\0\0\0\0", 0, 4),
+ macro_f_string_static_t_initialize_1("test\0\0\0\0\0", 0, 4),
+
+ // Third Set.
+ macro_f_string_static_t_initialize_1("test\0\0", 0, 4),
+ macro_f_string_static_t_initialize_1("test\0\0", 0, 4),
+ macro_f_string_static_t_initialize_1("test\0\0\0", 0, 4),
+ macro_f_string_static_t_initialize_1("test\0\0\0", 0, 4),
+ macro_f_string_static_t_initialize_1("test\0\0\0\0", 0, 4),
+ macro_f_string_static_t_initialize_1("test\0\0\0\0", 0, 4),
+ macro_f_string_static_t_initialize_1("test\0\0\0\0\0", 0, 4),
+ macro_f_string_static_t_initialize_1("test\0\0\0\0\0", 0, 4),
+ macro_f_string_static_t_initialize_1("test\0\0\0\0\0\0\0", 0, 4),
+ macro_f_string_static_t_initialize_1("test\0\0\0\0\0\0\0", 0, 4),
+
+ // Fourth Set.
+ macro_f_string_static_t_initialize_1("\0\0\0\0", 0, 0),
+ macro_f_string_static_t_initialize_1("\0\0\0\0", 0, 0),
+ macro_f_string_static_t_initialize_1("\0", 0, 0),
+ macro_f_string_static_t_initialize_1("t", 0, 1),
+ };
+
+ for (uint8_t i = 0; i < 34; ++i) {
+
+ char string[sources[i].used];
+ f_string_static_t buffer = macro_f_string_static_t_initialize_1(string, 0, sources[i].used);
+
+ memcpy(string, sources[i].string, sources[i].used);
+
+ const f_status_t status = f_string_dynamic_strip_null(&buffer);
+
+ assert_int_equal(status, F_okay);
+ assert_int_equal(buffer.used, expects[i].used);
+
+ // Compare strings using integer tests because assert_string_equal() assumes NULL terminated strings (using souces to confirm that the NULLs are moved).
+ for (uint8_t j = 0; j < sources[i].used; ++j) {
+ assert_int_equal(buffer.string[j], expects[i].string[j]);
+ } // for
+ } // for
+}
+
+void test__f_string_dynamic_strip_null__parameter_checking(void **state) {
+
+ {
+ const f_status_t status = f_string_dynamic_strip_null(0);
+
+ assert_int_equal(status, F_status_set_error(F_parameter));
+ }
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * FLL - Level 0
+ *
+ * Project: String
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the array types in the type project.
+ */
+#ifndef _TEST__F_dynamic_strip_null_h
+#define _TEST__F_dynamic_strip_null_h
+
+/**
+ * Test that the function returns F_data_not because the buffer is empty.
+ *
+ * @see f_string_dynamic_strip_null()
+ */
+extern void test__f_string_dynamic_strip_null__returns_data_not(void **state);
+
+/**
+ * Test that the function works.
+ *
+ * @see f_string_dynamic_strip_null()
+ */
+extern void test__f_string_dynamic_strip_null__works(void **state);
+
+/**
+ * Test that the function correctly fails on invalid parameter.
+ *
+ * @see f_string_dynamic_strip_null()
+ */
+extern void test__f_string_dynamic_strip_null__parameter_checking(void **state);
+
+#endif // _TEST__F_dynamic_strip_null_h
--- /dev/null
+#include "test-string.h"
+#include "test-string-dynamic_strip_null_range.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_string_dynamic_strip_null_range__returns_data_not(void **state) {
+
+ f_string_static_t buffer = f_string_static_t_initialize;
+ const f_range_t range = macro_f_range_t_initialize_1(0, 0);
+
+ {
+ const f_status_t status = f_string_dynamic_strip_null_range(range, &buffer);
+
+ assert_int_equal(status, F_data_not);
+ }
+}
+
+void test__f_string_dynamic_strip_null_range__returns_data_not_eos(void **state) {
+
+ f_string_static_t buffer = macro_f_string_static_t_initialize_1("test", 0, 4);
+ const f_range_t range = macro_f_range_t_initialize_1(buffer.used, buffer.used);
+
+ {
+ const f_status_t status = f_string_dynamic_strip_null_range(range, &buffer);
+
+ assert_int_equal(status, F_data_not_eos);
+ }
+}
+
+void test__f_string_dynamic_strip_null_range__returns_data_not_stop(void **state) {
+
+ f_string_static_t buffer = macro_f_string_static_t_initialize_1("test", 0, 4);
+ const f_range_t range = f_range_t_initialize;
+
+ {
+ const f_status_t status = f_string_dynamic_strip_null_range(range, &buffer);
+
+ assert_int_equal(status, F_data_not_stop);
+ }
+}
+
+void test__f_string_dynamic_strip_null_range__works(void **state) {
+
+ const f_string_static_t sources[] = {
+
+ // First Set.
+ macro_f_string_static_t_initialize_1("test", 0, 4),
+ macro_f_string_static_t_initialize_1("test", 0, 5),
+ macro_f_string_static_t_initialize_1("te\0st", 0, 5),
+ macro_f_string_static_t_initialize_1("te\0st", 0, 6),
+ macro_f_string_static_t_initialize_1("te\0\0st", 0, 6),
+ macro_f_string_static_t_initialize_1("te\0\0st", 0, 7),
+ macro_f_string_static_t_initialize_1("te\0\0s\0t", 0, 7),
+ macro_f_string_static_t_initialize_1("te\0\0s\0t", 0, 8),
+ macro_f_string_static_t_initialize_1("te\0\0s\0\0\0t", 0, 9),
+ macro_f_string_static_t_initialize_1("te\0\0s\0\0\0t", 0, 10),
+
+ // Second Set.
+ macro_f_string_static_t_initialize_1("test", 0, 4),
+ macro_f_string_static_t_initialize_1("test", 0, 5),
+ macro_f_string_static_t_initialize_1("te\0st", 0, 5),
+ macro_f_string_static_t_initialize_1("te\0st", 0, 6),
+ macro_f_string_static_t_initialize_1("te\0\0st", 0, 6),
+ macro_f_string_static_t_initialize_1("te\0\0st", 0, 7),
+ macro_f_string_static_t_initialize_1("te\0\0s\0t", 0, 7),
+ macro_f_string_static_t_initialize_1("te\0\0s\0t", 0, 8),
+ macro_f_string_static_t_initialize_1("te\0\0s\0\0\0t", 0, 9),
+ macro_f_string_static_t_initialize_1("te\0\0s\0\0\0t", 0, 10),
+
+ // Third Set.
+ macro_f_string_static_t_initialize_1("\0\0test", 0, 6),
+ macro_f_string_static_t_initialize_1("\0\0test", 0, 7),
+ macro_f_string_static_t_initialize_1("\0\0te\0st", 0, 7),
+ macro_f_string_static_t_initialize_1("\0\0te\0st", 0, 8),
+ macro_f_string_static_t_initialize_1("\0\0te\0\0st", 0, 8),
+ macro_f_string_static_t_initialize_1("\0\0te\0\0st", 0, 9),
+ macro_f_string_static_t_initialize_1("\0\0te\0\0s\0t", 0, 9),
+ macro_f_string_static_t_initialize_1("\0\0te\0\0s\0t", 0, 10),
+ macro_f_string_static_t_initialize_1("\0\0te\0\0s\0\0\0t", 0, 11),
+ macro_f_string_static_t_initialize_1("\0\0te\0\0s\0\0\0t", 0, 12),
+
+ // Fourth Set.
+ macro_f_string_static_t_initialize_1("\0\0\0\0", 0, 4),
+ macro_f_string_static_t_initialize_1("\0\0\0\0", 0, 4),
+ macro_f_string_static_t_initialize_1("\0", 0, 1),
+ macro_f_string_static_t_initialize_1("t", 0, 1),
+ };
+
+ const f_string_static_t expects[] = {
+
+ // First Set.
+ macro_f_string_static_t_initialize_1("test", 0, 4),
+ macro_f_string_static_t_initialize_1("test", 0, 5),
+ macro_f_string_static_t_initialize_1("test\0", 0, 5),
+ macro_f_string_static_t_initialize_1("test\0", 0, 6),
+ macro_f_string_static_t_initialize_1("test\0\0", 0, 6),
+ macro_f_string_static_t_initialize_1("test\0\0", 0, 7),
+ macro_f_string_static_t_initialize_1("test\0\0\0", 0, 7),
+ macro_f_string_static_t_initialize_1("test\0\0\0", 0, 8),
+ macro_f_string_static_t_initialize_1("test\0\0\0\0\0", 0, 9),
+ macro_f_string_static_t_initialize_1("test\0\0\0\0\0", 0, 10),
+
+ // Second Set.
+ macro_f_string_static_t_initialize_1("test", 0, 4),
+ macro_f_string_static_t_initialize_1("test", 0, 5),
+ macro_f_string_static_t_initialize_1("test\0", 0, 5),
+ macro_f_string_static_t_initialize_1("test\0", 0, 6),
+ macro_f_string_static_t_initialize_1("test\0\0", 0, 6),
+ macro_f_string_static_t_initialize_1("test\0\0", 0, 7),
+ macro_f_string_static_t_initialize_1("test\0\0\0", 0, 7),
+ macro_f_string_static_t_initialize_1("test\0\0\0", 0, 8),
+ macro_f_string_static_t_initialize_1("test\0\0\0\0\0", 0, 9),
+ macro_f_string_static_t_initialize_1("test\0\0\0\0\0", 0, 10),
+
+ // Third Set.
+ macro_f_string_static_t_initialize_1("te\0\0st", 0, 6),
+ macro_f_string_static_t_initialize_1("te\0\0st", 0, 7),
+ macro_f_string_static_t_initialize_1("te\0\0\0st", 0, 7),
+ macro_f_string_static_t_initialize_1("te\0\0\0st", 0, 8),
+ macro_f_string_static_t_initialize_1("te\0\0\0\0st", 0, 8),
+ macro_f_string_static_t_initialize_1("te\0\0\0\0st", 0, 9),
+ macro_f_string_static_t_initialize_1("te\0\0\0\0s\0t", 0, 9),
+ macro_f_string_static_t_initialize_1("te\0\0\0\0s\0t", 0, 10),
+ macro_f_string_static_t_initialize_1("te\0\0\0\0s\0\0\0t", 0, 11),
+ macro_f_string_static_t_initialize_1("te\0\0\0\0s\0\0\0t", 0, 12),
+
+ // Fourth Set.
+ macro_f_string_static_t_initialize_1("\0\0\0\0", 0, 4),
+ macro_f_string_static_t_initialize_1("\0\0\0\0", 0, 4),
+ macro_f_string_static_t_initialize_1("\0", 0, 1),
+ macro_f_string_static_t_initialize_1("t", 0, 1),
+ };
+
+ const f_range_t ranges[] = {
+
+ // First Set.
+ macro_f_range_t_initialize_1(0, sources[0].used - 1),
+ macro_f_range_t_initialize_1(0, sources[1].used - 1),
+ macro_f_range_t_initialize_1(0, sources[2].used - 1),
+ macro_f_range_t_initialize_1(0, sources[3].used - 1),
+ macro_f_range_t_initialize_1(0, sources[4].used - 1),
+ macro_f_range_t_initialize_1(0, sources[5].used - 1),
+ macro_f_range_t_initialize_1(0, sources[6].used - 1),
+ macro_f_range_t_initialize_1(0, sources[7].used - 1),
+ macro_f_range_t_initialize_1(0, sources[8].used - 1),
+ macro_f_range_t_initialize_1(0, sources[9].used - 1),
+
+ // Second Set.
+ macro_f_range_t_initialize_1(2, 3),
+ macro_f_range_t_initialize_1(2, 3),
+ macro_f_range_t_initialize_1(2, 4),
+ macro_f_range_t_initialize_1(2, 4),
+ macro_f_range_t_initialize_1(2, 5),
+ macro_f_range_t_initialize_1(2, 5),
+ macro_f_range_t_initialize_1(2, 6),
+ macro_f_range_t_initialize_1(2, 6),
+ macro_f_range_t_initialize_1(2, 8),
+ macro_f_range_t_initialize_1(2, 8),
+
+ // Third Set.
+ macro_f_range_t_initialize_1(0, 3),
+ macro_f_range_t_initialize_1(0, 3),
+ macro_f_range_t_initialize_1(0, 3),
+ macro_f_range_t_initialize_1(0, 3),
+ macro_f_range_t_initialize_1(0, 3),
+ macro_f_range_t_initialize_1(0, 3),
+ macro_f_range_t_initialize_1(0, 3),
+ macro_f_range_t_initialize_1(0, 3),
+ macro_f_range_t_initialize_1(0, 3),
+ macro_f_range_t_initialize_1(0, 3),
+
+ // Fourth Set.
+ macro_f_range_t_initialize_1(0, 0),
+ macro_f_range_t_initialize_1(0, 3),
+ macro_f_range_t_initialize_1(0, 0),
+ macro_f_range_t_initialize_1(0, 0),
+ };
+
+ for (uint8_t i = 0; i < 34; ++i) {
+
+ char string[sources[i].used];
+ f_string_static_t buffer = macro_f_string_static_t_initialize_1(string, 0, sources[i].used);
+
+ memcpy(string, sources[i].string, sources[i].used);
+
+ const f_status_t status = f_string_dynamic_strip_null_range(ranges[i], &buffer);
+
+ assert_int_equal(status, F_okay);
+ assert_int_equal(buffer.used, expects[i].used);
+
+ // Compare strings using integer tests because assert_string_equal() assumes NULL terminated strings.
+ for (uint8_t j = 0; j < buffer.used; ++j) {
+ assert_int_equal(buffer.string[j], expects[i].string[j]);
+ } // for
+ } // for
+}
+
+void test__f_string_dynamic_strip_null_range__parameter_checking(void **state) {
+
+ const f_range_t range = f_range_t_initialize;
+
+ {
+ const f_status_t status = f_string_dynamic_strip_null_range(range, 0);
+
+ assert_int_equal(status, F_status_set_error(F_parameter));
+ }
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * FLL - Level 0
+ *
+ * Project: String
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the array types in the type project.
+ */
+#ifndef _TEST__F_dynamic_strip_null_range_h
+#define _TEST__F_dynamic_strip_null_range_h
+
+/**
+ * Test that the function returns F_data_not because the buffer is empty.
+ *
+ * @see f_string_dynamic_strip_null_range()
+ */
+extern void test__f_string_dynamic_strip_null_range__returns_data_not(void **state);
+
+/**
+ * Test that the function returns F_data_not_eos because range stops after buffer ends (range.stop >= buffer.used).
+ *
+ * @see f_string_dynamic_strip_null_range()
+ */
+extern void test__f_string_dynamic_strip_null_range__returns_data_not_eos(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_strip_null_range()
+ */
+extern void test__f_string_dynamic_strip_null_range__returns_data_not_stop(void **state);
+
+/**
+ * Test that the function works.
+ *
+ * @see f_string_dynamic_strip_null_range()
+ */
+extern void test__f_string_dynamic_strip_null_range__works(void **state);
+
+/**
+ * Test that the function correctly fails on invalid parameter.
+ *
+ * @see f_string_dynamic_strip_null_range()
+ */
+extern void test__f_string_dynamic_strip_null_range__parameter_checking(void **state);
+
+#endif // _TEST__F_dynamic_strip_null_range_h
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_strip_null__returns_data_not),
+ cmocka_unit_test(test__f_string_dynamic_strip_null__works),
+
+ cmocka_unit_test(test__f_string_dynamic_strip_null_range__returns_data_not),
+ cmocka_unit_test(test__f_string_dynamic_strip_null_range__returns_data_not_eos),
+ cmocka_unit_test(test__f_string_dynamic_strip_null_range__returns_data_not_stop),
+ cmocka_unit_test(test__f_string_dynamic_strip_null_range__works),
+
cmocka_unit_test(test__f_string_dynamic_terminate__appends_null),
cmocka_unit_test(test__f_string_dynamic_terminate__doesnt_append_null),
cmocka_unit_test(test__f_string_dynamic_seek_line_to__parameter_checking),
cmocka_unit_test(test__f_string_dynamic_seek_to__parameter_checking),
+ cmocka_unit_test(test__f_string_dynamic_strip_null__parameter_checking),
+ cmocka_unit_test(test__f_string_dynamic_strip_null_range__parameter_checking),
+
cmocka_unit_test(test__f_string_dynamic_terminate__parameter_checking),
cmocka_unit_test(test__f_string_dynamic_terminate_after__parameter_checking),
#include "test-string-dynamic_seek_line.h"
#include "test-string-dynamic_seek_line_to.h"
#include "test-string-dynamic_seek_to.h"
+#include "test-string-dynamic_strip_null.h"
+#include "test-string-dynamic_strip_null_range.h"
#include "test-string-dynamic_terminate.h"
#include "test-string-dynamic_terminate_after.h"
#include "test-string-dynamics_append.h"