It seems that editors make it difficult to add and manipulate combining characters.
It is possible my test files have lost combining characters without my awareness.
I might have to revisit these later on.
For now, just copy what is there to simplify the work being done.
I used commands like the following to help generate some combining characters:
```sh
echo "first valid.$(utf8 -cB U+0301)" >> basic-combining_read.txt
echo -e " not a valid list{$(utf8 -cB U+0301)\n}" >> extended_list-combining_read.txt
```
--- /dev/null
+ content 1.
--- /dev/null
+ is_second and content 2.
--- /dev/null
+ has ́ content 3.
--- /dev/null
+ has ͜no_space content 4.
--- /dev/null
+ content 5.
--- /dev/null
+ sixtẖ̚ is content 6.
+ not a valid list:́
--- /dev/null
+ content 1.
--- /dev/null
+ is_second and content 2.
--- /dev/null
+ has ́ content 3.
--- /dev/null
+ has ͜no_space content 4.
--- /dev/null
+ content 5.
--- /dev/null
+ sixtẖ̚ is content 6.
--- /dev/null
+ content 1.
--- /dev/null
+ is_second and content 2.
--- /dev/null
+ has ́ content 3.
--- /dev/null
+ has ͜no_space content 4.
--- /dev/null
+ content 5.
--- /dev/null
+ sixtẖ̚ is content 6.
--- /dev/null
+2
+2
+1
+1
+2
+2
--- /dev/null
+first valid.
+is_second and does not have embedded new line.
+ ́
+fourth ͜no_space
+fifth is valid.
+sixtẖ̚ is valid with two combiners.
--- /dev/null
+first valid.
+is_second and does not have embedded new line.
+ ́
+fourth ͜no_space
+fifth is valid.
+sixtẖ̚ is valid with two combiners.
--- /dev/null
+first valid.
+is_second and does not have embedded new line.
+ ́
+fourth ͜no_space
+fifth is valid.
+sixtẖ̚ is valid with two combiners.
--- /dev/null
+first valid.:
+ content 1.
+is_second and does not have embedded new line.:
+ is_second and content 2.
+ ́:
+ has ́ content 3.
+fourth ͜no_space:
+ has ͜no_space content 4.
+fifth is valid.:
+ content 5.
+sixtẖ̚ is valid with two combiners.:
+ sixtẖ̚ is content 6.
+ not a valid list:́
--- /dev/null
+first valid.{
+ content 1.
+}
+is_second and does not have embedded new line.{
+ is_second and content 2.
+}
+ ́{
+ has ́ content 3.
+}
+fourth ͜no_space{
+ has ͜no_space content 4.
+}
+fifth is valid.{
+ content 5.
+}
+sixtẖ̚ is valid with two combiners.{
+ sixtẖ̚ is content 6.
+}
+ not a valid list{́
+}
--- /dev/null
+first valid.{
+ content 1.
+}
+is_second and does not have embedded new line.{
+ is_second and content 2.
+}
+ ́{
+ has ́ content 3.
+}
+fourth ͜no_space{
+ has ͜no_space content 4.
+}
+fifth is valid.{
+ content 5.
+}
+sixtẖ̚ is valid with two combiners.{
+ sixtẖ̚ is content 6.
+}
+ not a valid list{́
+}
}
}
+void test__fl_fss_basic_list_content_read__works_using_combining(void **void_state) {
+
+ {
+ // Note: These files are required to have the same number of lines and each line should probably be at max 255 characters.
+ FILE *file_strings = data__file_open__named("strings", "basic_list", "combining_read");
+
+ FILE *file_contents[] = {
+ data__file_open__named_at("contents", "basic_list", "combining_read", 0),
+ data__file_open__named_at("contents", "basic_list", "combining_read", 1),
+ data__file_open__named_at("contents", "basic_list", "combining_read", 2),
+ data__file_open__named_at("contents", "basic_list", "combining_read", 3),
+ data__file_open__named_at("contents", "basic_list", "combining_read", 4),
+ data__file_open__named_at("contents", "basic_list", "combining_read", 5),
+ };
+
+ assert_non_null(file_strings);
+ assert_non_null(file_contents[0]);
+ assert_non_null(file_contents[1]);
+ assert_non_null(file_contents[2]);
+ assert_non_null(file_contents[3]);
+ assert_non_null(file_contents[4]);
+ assert_non_null(file_contents[5]);
+
+ size_t max = 0;
+ char *line_string = 0;
+ char *line_content[] = {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ };
+ ssize_t result = 0;
+ const uint8_t total_content = 6;
+
+ f_string_static_t buffer_string = f_string_static_t_initialize;
+
+ f_state_t state = f_state_t_initialize;
+ f_range_t range = f_range_t_initialize;
+ f_range_t found_object = f_range_t_initialize;
+ f_ranges_t found = f_ranges_t_initialize;
+ f_ranges_t comments = f_ranges_t_initialize;
+ f_uint8s_t quotes = f_uint8s_t_initialize;
+ f_number_unsigneds_t delimits = f_number_unsigneds_t_initialize;
+ f_string_dynamic_t result_string = f_string_dynamic_t_initialize;
+ f_string_dynamic_t delimit_string = f_string_dynamic_t_initialize;
+ f_status_t status_object = F_okay;
+
+ for (;;) {
+
+ max = 255;
+
+ result = getline(&line_string, &max, file_strings);
+ if (result == -1) break;
+
+ buffer_string.string = line_string;
+ buffer_string.used = (f_number_unsigned_t) result;
+ buffer_string.size = buffer_string.used;
+
+ for (uint8_t i = 0; i < total_content; ++i) {
+
+ max = 255;
+
+ result = getline(&line_content[i], &max, file_contents[i]);
+
+ // The newline is copied by getline(), and so remove that newline before comparing.
+ if (result > 0) {
+ line_content[i][result - 1] = 0;
+ }
+ else {
+ line_content[i][0] = 0;
+ }
+ } // or
+
+ state.status = F_none;
+ range.start = 0;
+ range.stop = buffer_string.used - 1;
+ found_object.start = 1;
+ found_object.stop = 0;
+
+ fl_fss_basic_list_object_read(buffer_string, &range, &found_object, &delimits, &state);
+
+ assert_true(state.status == F_fss_found_object || state.status == F_fss_found_object_not);
+
+ status_object = state.status;
+ state.status = F_none;
+
+ if (status_object == F_fss_found_object) {
+ fl_fss_basic_list_content_read(buffer_string, &range, &found, &delimits, &comments, &state);
+
+ assert_true(state.status == F_fss_found_content || state.status == F_data_not);
+
+ if (state.status == F_fss_found_content) {
+ assert_true(found.used);
+ assert_true(found.used <= (f_number_unsigned_t) total_content);
+
+ {
+ const f_status_t status = f_string_dynamic_append(buffer_string, &delimit_string);
+ assert_int_equal(status, F_okay);
+ }
+
+ state.status = F_none;
+
+ f_fss_apply_delimit(delimits, &delimit_string, &state);
+ assert_int_equal(state.status, F_okay);
+
+ {
+ uint8_t i = 0;
+
+ for (; i < found.used; ++i) {
+
+ result_string.used = 0;
+
+ {
+ const f_status_t status = f_string_dynamic_partial_append_nulless(delimit_string, found.array[i], &result_string);
+ assert_true(status == F_okay || status == F_data_not_eos);
+ }
+
+ {
+ const f_status_t status = f_string_dynamic_terminate_after(&result_string);
+ assert_int_equal(status, F_okay);
+ }
+
+ assert_string_equal(result_string.string, line_content[i]);
+ } // for
+
+ // All remaining positions in the file need to be a zero length string.
+ for (; i < total_content; ++i) {
+ assert_int_equal(line_content[i][0], 0);
+ }
+ }
+ }
+ else {
+ assert_true(!found.used);
+ }
+ }
+
+ if (line_string) free(line_string);
+ if (result_string.string) free(result_string.string);
+ if (delimit_string.string) free(delimit_string.string);
+ if (delimits.array) free(delimits.array);
+ if (found.array) free(found.array);
+ if (comments.array) free(comments.array);
+ if (quotes.array) free(quotes.array);
+
+ for (uint8_t i = 0; i < total_content; ++i) {
+
+ if (line_content[i]) free(line_content[i]);
+
+ line_content[i] = 0;
+ } // for
+
+ line_string = 0;
+ result_string.string = 0;
+ result_string.used = 0;
+ result_string.size = 0;
+ delimit_string.string = 0;
+ delimit_string.used = 0;
+ delimit_string.size = 0;
+ delimits.array = 0;
+ delimits.used = 0;
+ delimits.size = 0;
+ found.array = 0;
+ found.used = 0;
+ found.size = 0;
+ comments.array = 0;
+ comments.used = 0;
+ comments.size = 0;
+ quotes.array = 0;
+ quotes.used = 0;
+ quotes.size = 0;
+ } // for
+
+ for (uint8_t i = 0; i < total_content; ++i) {
+
+ if (file_contents[i]) fclose(file_contents[i]);
+ if (line_content[i]) free(line_content[i]);
+
+ line_content[i] = 0;
+ } // for
+
+ if (file_strings) fclose(file_strings);
+
+ if (delimits.array) free(delimits.array);
+ if (found.array) free(found.array);
+ if (comments.array) free(comments.array);
+ if (quotes.array) free(quotes.array);
+ if (line_string) free(line_string);
+ if (result_string.string) free(result_string.string);
+ if (delimit_string.string) free(delimit_string.string);
+ }
+}
+
#ifdef __cplusplus
} // extern "C"
#endif
*/
extern void test__fl_fss_basic_list_content_read__works(void **state);
+/**
+ * Test that the function works when using combining characters.
+ *
+ * @see fl_fss_basic_list_content_read()
+ */
+extern void test__fl_fss_basic_list_content_read__works_using_combining(void **state);
+
#endif // _TEST__FL_fss_basic_list_content_read_list_h
}
}
+void test__fl_fss_basic_list_object_read__works_using_combining(void **void_state) {
+
+ {
+ FILE *file_strings = data__file_open__named("strings", "basic_list", "combining_read");
+ FILE *file_objects = data__file_open__named("objects", "basic_list", "combining_read");
+
+ assert_non_null(file_strings);
+ assert_non_null(file_objects);
+
+ size_t max = 0;
+ char *line_string = 0;
+ char *line_object = 0;
+ ssize_t result = 0;
+
+ f_string_static_t buffer_string = f_string_static_t_initialize;
+
+ f_state_t state = f_state_t_initialize;
+ f_range_t range = f_range_t_initialize;
+ f_range_t found = f_range_t_initialize;
+ f_number_unsigneds_t delimits = f_number_unsigneds_t_initialize;
+ f_string_dynamic_t result_string = f_string_dynamic_t_initialize;
+ f_string_dynamic_t delimit_string = f_string_dynamic_t_initialize;
+
+ for (int line = 1;; ++line) {
+
+ max = 255;
+
+ result = getline(&line_string, &max, file_strings);
+ if (result == -1) break;
+
+ buffer_string.string = line_string;
+ buffer_string.used = (f_number_unsigned_t) result;
+ buffer_string.size = buffer_string.used;
+
+ state.status = F_none;
+ range.start = 0;
+ range.stop = buffer_string.used - 1;
+ found.start = 1;
+ found.stop = 0;
+
+ fl_fss_basic_list_object_read(buffer_string, &range, &found, &delimits, &state);
+
+ if (!(state.status == F_fss_found_object || state.status == F_fss_found_object_not)) {
+ printf("[ -------> ] --- [00] Failure with line (%u) '%s', status=%u, expected %u or %u.\n", line, line_string, state.status, F_fss_found_object, F_fss_found_object_not);
+ }
+
+ assert_true(state.status == F_fss_found_object || state.status == F_fss_found_object_not);
+
+ if (state.status == F_fss_found_object) {
+ max = 255;
+
+ result = getline(&line_object, &max, file_objects);
+
+ if (!result) {
+ printf("[ -------> ] --- [01] Failure with line (%u) '%s', line_object = '%s', result=%zu.\n", line, line_string, line_object, result);
+ }
+
+ assert_return_code(result, 0);
+
+ // The newline is copied by getline(), and so remove that newline before comparing.
+ line_object[result - 1] = 0;
+
+ if (found.start <= found.stop) {
+ {
+ const f_status_t status = f_string_dynamic_append(buffer_string, &delimit_string);
+
+ if (status != F_okay) {
+ printf("[ -------> ] --- [02] Failure with line (%u) '%s', line_object = '%s', status=%u, expected %u.\n", line, line_string, line_object, status, F_okay);
+ }
+
+ assert_int_equal(status, F_okay);
+ }
+
+ state.status = F_none;
+
+ f_fss_apply_delimit(delimits, &delimit_string, &state);
+
+ if (state.status != F_okay) {
+ printf("[ -------> ] --- [03] Failure with line (%u) '%s', line_object = '%s', status=%u, expected %u.\n", line, line_string, line_object, state.status, F_okay);
+ }
+
+ assert_int_equal(state.status, F_okay);
+
+ {
+ const f_status_t status = f_string_dynamic_partial_append_nulless(delimit_string, found, &result_string);
+
+ if (!(status == F_okay || status == F_data_not_eos)) {
+ printf("[ -------> ] --- [04] Failure with line (%u) '%s', line_object = '%s', status=%u, expected %u or %u.\n", line, line_string, line_object, status, F_okay, F_data_not_eos);
+ }
+
+ assert_true(status == F_okay || status == F_data_not_eos);
+ }
+
+ {
+ const f_status_t status = f_string_dynamic_terminate_after(&result_string);
+
+ if (status != F_okay) {
+ printf("[ -------> ] --- [05] Failure with line (%u) '%s', line_object = '%s', status=%u, expected %u.\n", line, line_string, line_object, status, F_okay);
+ }
+
+ assert_int_equal(status, F_okay);
+ }
+
+ if (strncmp(result_string.string, line_object, result_string.used)) {
+ printf("[ -------> ] --- [06] Failure with line (%u) '%s', line_object = '%s', result '%s'.\n", line, line_string, line_object, result_string.string);
+ }
+
+ assert_string_equal(result_string.string, line_object);
+ }
+ else {
+ if (line_object[0]) {
+ printf("[ -------> ] --- [07] Failure with line (%u) '%s', line_object[0]=%c.\n", line, line_string, line_object[0]);
+ }
+
+ assert_int_equal(line_object[0], 0);
+ }
+ }
+
+ if (line_string) free(line_string);
+ if (line_object) free(line_object);
+ if (result_string.string) free(result_string.string);
+ if (delimit_string.string) free(delimit_string.string);
+ if (delimits.array) free(delimits.array);
+
+ line_string = 0;
+ line_object = 0;
+ result_string.string = 0;
+ result_string.used = 0;
+ result_string.size = 0;
+ delimit_string.string = 0;
+ delimit_string.used = 0;
+ delimit_string.size = 0;
+ delimits.array = 0;
+ delimits.used = 0;
+ delimits.size = 0;
+ } // for
+
+ if (file_strings) fclose(file_strings);
+ if (file_objects) fclose(file_objects);
+
+ if (delimits.array) free(delimits.array);
+ if (line_string) free(line_string);
+ if (line_object) free(line_object);
+ if (result_string.string) free(result_string.string);
+ if (delimit_string.string) free(delimit_string.string);
+ }
+}
+
#ifdef __cplusplus
} // extern "C"
#endif
*/
extern void test__fl_fss_basic_list_object_read__works(void **state);
+/**
+ * Test that the function works when using combining characters.
+ *
+ * @see fl_fss_basic_list_object_read()
+ */
+extern void test__fl_fss_basic_list_object_read__works_using_combining(void **state);
+
#endif // _TEST__FL_fss_basic_list_object_read_list_h
}
}
+void test__fl_fss_embedded_list_content_read__works_using_combining(void **void_state) {
+
+ {
+ // Note: These files are required to have the same number of lines and each line should probably be at max 255 characters.
+ FILE *file_strings = data__file_open__named("strings", "embedded_list", "combining_read");
+
+ FILE *file_contents[] = {
+ data__file_open__named_at("contents", "embedded_list", "combining_read", 0),
+ data__file_open__named_at("contents", "embedded_list", "combining_read", 1),
+ data__file_open__named_at("contents", "embedded_list", "combining_read", 2),
+ data__file_open__named_at("contents", "embedded_list", "combining_read", 3),
+ data__file_open__named_at("contents", "embedded_list", "combining_read", 4),
+ data__file_open__named_at("contents", "embedded_list", "combining_read", 5),
+ };
+
+ assert_non_null(file_strings);
+ assert_non_null(file_contents[0]);
+ assert_non_null(file_contents[1]);
+ assert_non_null(file_contents[2]);
+ assert_non_null(file_contents[3]);
+ assert_non_null(file_contents[4]);
+ assert_non_null(file_contents[5]);
+
+ size_t max = 0;
+ char *line_string = 0;
+ char *line_content[] = {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ };
+ ssize_t result = 0;
+ const uint8_t total_content = 6;
+
+ f_string_static_t buffer_string = f_string_static_t_initialize;
+
+ f_state_t state = f_state_t_initialize;
+ f_range_t range = f_range_t_initialize;
+ f_range_t found_object = f_range_t_initialize;
+ f_fss_nest_t found = f_fss_nest_t_initialize;
+ f_ranges_t comments = f_ranges_t_initialize;
+ f_uint8s_t quotes = f_uint8s_t_initialize;
+ f_number_unsigneds_t delimits = f_number_unsigneds_t_initialize;
+ f_string_dynamic_t result_string = f_string_dynamic_t_initialize;
+ f_string_dynamic_t delimit_string = f_string_dynamic_t_initialize;
+ f_status_t status_object = F_okay;
+
+ f_ranges_t objects = f_ranges_t_initialize;
+ f_number_unsigneds_t positions = f_number_unsigneds_t_initialize;
+ f_number_unsigneds_t slashes = f_number_unsigneds_t_initialize;
+ fl_fss_data_embedded_list_t cache = macro_fl_fss_data_embedded_list_t_initialize_1(&objects, &positions, &slashes);
+
+ state.data = (void *) &cache;
+
+ for (;;) {
+
+ max = 255;
+
+ result = getline(&line_string, &max, file_strings);
+ if (result == -1) break;
+
+ buffer_string.string = line_string;
+ buffer_string.used = (f_number_unsigned_t) result;
+ buffer_string.size = buffer_string.used;
+
+ for (uint8_t i = 0; i < total_content; ++i) {
+
+ max = 255;
+
+ result = getline(&line_content[i], &max, file_contents[i]);
+
+ // The newline is copied by getline(), and so remove that newline before comparing.
+ if (result > 0) {
+ line_content[i][result - 1] = 0;
+ }
+ else {
+ line_content[i][0] = 0;
+ }
+ } // or
+
+ state.status = F_none;
+ range.start = 0;
+ range.stop = buffer_string.used - 1;
+ found_object.start = 1;
+ found_object.stop = 0;
+
+ fl_fss_embedded_list_object_read(buffer_string, &range, &found_object, &delimits, &state);
+
+ assert_true(state.status == F_fss_found_object || state.status == F_fss_found_object_not);
+
+ status_object = state.status;
+ state.status = F_none;
+
+ if (status_object == F_fss_found_object) {
+ fl_fss_embedded_list_content_read(buffer_string, &range, &found, &delimits, &comments, &state);
+
+ assert_true(state.status == F_fss_found_content || state.status == F_data_not);
+
+ if (state.status == F_fss_found_content) {
+ // @todo
+ }
+ else {
+ assert_true(!found.used);
+ }
+ }
+
+ if (line_string) free(line_string);
+ if (result_string.string) free(result_string.string);
+ if (delimit_string.string) free(delimit_string.string);
+ if (delimits.array) free(delimits.array);
+ if (comments.array) free(comments.array);
+ if (quotes.array) free(quotes.array);
+
+ f_fss_nest_delete(&found);
+
+ for (uint8_t i = 0; i < total_content; ++i) {
+
+ if (line_content[i]) free(line_content[i]);
+
+ line_content[i] = 0;
+ } // for
+
+ line_string = 0;
+ result_string.string = 0;
+ result_string.used = 0;
+ result_string.size = 0;
+ delimit_string.string = 0;
+ delimit_string.used = 0;
+ delimit_string.size = 0;
+ delimits.array = 0;
+ delimits.used = 0;
+ delimits.size = 0;
+ found.depth = 0;
+ found.used = 0;
+ found.size = 0;
+ comments.array = 0;
+ comments.used = 0;
+ comments.size = 0;
+ quotes.array = 0;
+ quotes.used = 0;
+ quotes.size = 0;
+ } // for
+
+ for (uint8_t i = 0; i < total_content; ++i) {
+
+ if (file_contents[i]) fclose(file_contents[i]);
+ if (line_content[i]) free(line_content[i]);
+
+ line_content[i] = 0;
+ } // for
+
+ if (file_strings) fclose(file_strings);
+
+ if (delimits.array) free(delimits.array);
+ if (comments.array) free(comments.array);
+ if (quotes.array) free(quotes.array);
+ if (line_string) free(line_string);
+ if (result_string.string) free(result_string.string);
+ if (delimit_string.string) free(delimit_string.string);
+
+ if (objects.array) free(objects.array);
+ if (positions.array) free(positions.array);
+ if (slashes.array) free(slashes.array);
+
+ f_fss_nest_delete(&found);
+ }
+}
+
#ifdef __cplusplus
} // extern "C"
#endif
*/
extern void test__fl_fss_embedded_list_content_read__works(void **state);
+/**
+ * Test that the function works when using combining characters.
+ *
+ * @see fl_fss_embedded_list_content_read()
+ */
+extern void test__fl_fss_embedded_list_content_read__works_using_combining(void **state);
+
#endif // _TEST__FL_fss_embedded_list_content_read_h
}
}
+void test__fl_fss_embedded_list_object_read__works_using_combining(void **void_state) {
+
+ {
+ FILE *file_strings = data__file_open__named("strings", "embedded_list", "combining_read");
+ FILE *file_objects = data__file_open__named("objects", "embedded_list", "combining_read");
+
+ assert_non_null(file_strings);
+ assert_non_null(file_objects);
+
+ size_t max = 0;
+ char *line_string = 0;
+ char *line_object = 0;
+ ssize_t result = 0;
+
+ f_string_static_t buffer_string = f_string_static_t_initialize;
+
+ f_state_t state = f_state_t_initialize;
+ f_range_t range = f_range_t_initialize;
+ f_range_t found = f_range_t_initialize;
+ f_number_unsigneds_t delimits = f_number_unsigneds_t_initialize;
+ f_string_dynamic_t result_string = f_string_dynamic_t_initialize;
+ f_string_dynamic_t delimit_string = f_string_dynamic_t_initialize;
+
+ for (int line = 1;; ++line) {
+
+ max = 255;
+
+ result = getline(&line_string, &max, file_strings);
+ if (result == -1) break;
+
+ buffer_string.string = line_string;
+ buffer_string.used = (f_number_unsigned_t) result;
+ buffer_string.size = buffer_string.used;
+
+ state.status = F_none;
+ range.start = 0;
+ range.stop = buffer_string.used - 1;
+ found.start = 1;
+ found.stop = 0;
+
+ fl_fss_embedded_list_object_read(buffer_string, &range, &found, &delimits, &state);
+
+ if (!(state.status == F_fss_found_object || state.status == F_fss_found_object_not)) {
+ printf("[ -------> ] --- [00] Failure with line (%u) '%s', status=%u, expected %u or %u.\n", line, line_string, state.status, F_fss_found_object, F_fss_found_object_not);
+ }
+
+ assert_true(state.status == F_fss_found_object || state.status == F_fss_found_object_not);
+
+ if (state.status == F_fss_found_object) {
+ max = 255;
+
+ result = getline(&line_object, &max, file_objects);
+
+ if (!result) {
+ printf("[ -------> ] --- [01] Failure with line (%u) '%s', line_object = '%s', result=%zu.\n", line, line_string, line_object, result);
+ }
+
+ assert_return_code(result, 0);
+
+ // The newline is copied by getline(), and so remove that newline before comparing.
+ line_object[result - 1] = 0;
+
+ if (found.start <= found.stop) {
+ {
+ const f_status_t status = f_string_dynamic_append(buffer_string, &delimit_string);
+
+ if (status != F_okay) {
+ printf("[ -------> ] --- [02] Failure with line (%u) '%s', line_object = '%s', status=%u, expected %u.\n", line, line_string, line_object, status, F_okay);
+ }
+
+ assert_int_equal(status, F_okay);
+ }
+
+ state.status = F_none;
+
+ f_fss_apply_delimit(delimits, &delimit_string, &state);
+
+ if (state.status != F_okay) {
+ printf("[ -------> ] --- [03] Failure with line (%u) '%s', line_object = '%s', status=%u, expected %u.\n", line, line_string, line_object, state.status, F_okay);
+ }
+
+ assert_int_equal(state.status, F_okay);
+
+ {
+ const f_status_t status = f_string_dynamic_partial_append_nulless(delimit_string, found, &result_string);
+
+ if (!(status == F_okay || status == F_data_not_eos)) {
+ printf("[ -------> ] --- [04] Failure with line (%u) '%s', line_object = '%s', status=%u, expected %u or %u.\n", line, line_string, line_object, status, F_okay, F_data_not_eos);
+ }
+
+ assert_true(status == F_okay || status == F_data_not_eos);
+ }
+
+ {
+ const f_status_t status = f_string_dynamic_terminate_after(&result_string);
+
+ if (status != F_okay) {
+ printf("[ -------> ] --- [05] Failure with line (%u) '%s', line_object = '%s', status=%u, expected %u.\n", line, line_string, line_object, status, F_okay);
+ }
+
+ assert_int_equal(status, F_okay);
+ }
+
+ if (strncmp(result_string.string, line_object, result_string.used)) {
+ printf("[ -------> ] --- [06] Failure with line (%u) '%s', line_object = '%s', result '%s'.\n", line, line_string, line_object, result_string.string);
+ }
+
+ assert_string_equal(result_string.string, line_object);
+ }
+ else {
+ if (line_object[0]) {
+ printf("[ -------> ] --- [07] Failure with line (%u) '%s', line_object[0]=%c.\n", line, line_string, line_object[0]);
+ }
+
+ assert_int_equal(line_object[0], 0);
+ }
+ }
+
+ if (line_string) free(line_string);
+ if (line_object) free(line_object);
+ if (result_string.string) free(result_string.string);
+ if (delimit_string.string) free(delimit_string.string);
+ if (delimits.array) free(delimits.array);
+
+ line_string = 0;
+ line_object = 0;
+ result_string.string = 0;
+ result_string.used = 0;
+ result_string.size = 0;
+ delimit_string.string = 0;
+ delimit_string.used = 0;
+ delimit_string.size = 0;
+ delimits.array = 0;
+ delimits.used = 0;
+ delimits.size = 0;
+ } // for
+
+ if (file_strings) fclose(file_strings);
+ if (file_objects) fclose(file_objects);
+
+ if (delimits.array) free(delimits.array);
+ if (line_string) free(line_string);
+ if (line_object) free(line_object);
+ if (result_string.string) free(result_string.string);
+ if (delimit_string.string) free(delimit_string.string);
+ }
+}
+
#ifdef __cplusplus
} // extern "C"
#endif
*/
extern void test__fl_fss_embedded_list_object_read__works(void **state);
+/**
+ * Test that the function works when using combining characters.
+ *
+ * @see fl_fss_embedded_list_object_read()
+ */
+extern void test__fl_fss_embedded_list_object_read__works_using_combining(void **state);
+
#endif // _TEST__FL_fss_embedded_list_object_read_h
}
}
+void test__fl_fss_extended_list_content_read__works_using_combining(void **void_state) {
+
+ {
+ // Note: These files are required to have the same number of lines and each line should probably be at max 255 characters.
+ FILE *file_strings = data__file_open__named("strings", "extended_list", "combining_read");
+
+ FILE *file_contents[] = {
+ data__file_open__named_at("contents", "extended_list", "combining_read", 0),
+ data__file_open__named_at("contents", "extended_list", "combining_read", 1),
+ data__file_open__named_at("contents", "extended_list", "combining_read", 2),
+ data__file_open__named_at("contents", "extended_list", "combining_read", 3),
+ data__file_open__named_at("contents", "extended_list", "combining_read", 4),
+ data__file_open__named_at("contents", "extended_list", "combining_read", 5),
+ };
+
+ assert_non_null(file_strings);
+ assert_non_null(file_contents[0]);
+ assert_non_null(file_contents[1]);
+ assert_non_null(file_contents[2]);
+ assert_non_null(file_contents[3]);
+ assert_non_null(file_contents[4]);
+ assert_non_null(file_contents[5]);
+
+ size_t max = 0;
+ char *line_string = 0;
+ char *line_content[] = {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ };
+ ssize_t result = 0;
+ const uint8_t total_content = 6;
+
+ f_string_static_t buffer_string = f_string_static_t_initialize;
+
+ f_state_t state = f_state_t_initialize;
+ f_range_t close = f_range_t_initialize;
+ f_range_t range = f_range_t_initialize;
+ f_range_t found_object = f_range_t_initialize;
+ f_ranges_t found = f_ranges_t_initialize;
+ f_ranges_t comments = f_ranges_t_initialize;
+ f_uint8s_t quotes = f_uint8s_t_initialize;
+ f_number_unsigneds_t delimits = f_number_unsigneds_t_initialize;
+ f_string_dynamic_t result_string = f_string_dynamic_t_initialize;
+ f_string_dynamic_t delimit_string = f_string_dynamic_t_initialize;
+ f_status_t status_object = F_okay;
+
+ for (;;) {
+
+ max = 255;
+
+ result = getline(&line_string, &max, file_strings);
+ if (result == -1) break;
+
+ buffer_string.string = line_string;
+ buffer_string.used = (f_number_unsigned_t) result;
+ buffer_string.size = buffer_string.used;
+
+ for (uint8_t i = 0; i < total_content; ++i) {
+
+ max = 255;
+
+ result = getline(&line_content[i], &max, file_contents[i]);
+
+ // The newline is copied by getline(), and so remove that newline before comparing.
+ if (result > 0) {
+ line_content[i][result - 1] = 0;
+ }
+ else {
+ line_content[i][0] = 0;
+ }
+ } // or
+
+ state.status = F_none;
+ range.start = 0;
+ range.stop = buffer_string.used - 1;
+ found_object.start = 1;
+ found_object.stop = 0;
+
+ fl_fss_extended_list_object_read(buffer_string, &range, &found_object, &delimits, &state);
+
+ assert_true(state.status == F_fss_found_object || state.status == F_fss_found_object_not);
+
+ status_object = state.status;
+ state.status = F_none;
+
+ if (status_object == F_fss_found_object) {
+ fl_fss_extended_list_content_read(buffer_string, &range, &found, &close, &delimits, &comments, &state);
+
+ assert_true(state.status == F_fss_found_content || state.status == F_data_not);
+
+ if (state.status == F_fss_found_content) {
+ assert_true(found.used);
+ assert_true(found.used <= (f_number_unsigned_t) total_content);
+
+ {
+ const f_status_t status = f_string_dynamic_append(buffer_string, &delimit_string);
+ assert_int_equal(status, F_okay);
+ }
+
+ state.status = F_none;
+
+ f_fss_apply_delimit(delimits, &delimit_string, &state);
+ assert_int_equal(state.status, F_okay);
+
+ {
+ uint8_t i = 0;
+
+ for (; i < found.used; ++i) {
+
+ result_string.used = 0;
+
+ {
+ const f_status_t status = f_string_dynamic_partial_append_nulless(delimit_string, found.array[i], &result_string);
+ assert_true(status == F_okay || status == F_data_not_eos);
+ }
+
+ {
+ const f_status_t status = f_string_dynamic_terminate_after(&result_string);
+ assert_int_equal(status, F_okay);
+ }
+
+ assert_string_equal(result_string.string, line_content[i]);
+ } // for
+
+ // All remaining positions in the file need to be a zero length string.
+ for (; i < total_content; ++i) {
+ assert_int_equal(line_content[i][0], 0);
+ }
+ }
+ }
+ else {
+ assert_true(!found.used);
+ }
+ }
+
+ if (line_string) free(line_string);
+ if (result_string.string) free(result_string.string);
+ if (delimit_string.string) free(delimit_string.string);
+ if (delimits.array) free(delimits.array);
+ if (found.array) free(found.array);
+ if (comments.array) free(comments.array);
+ if (quotes.array) free(quotes.array);
+
+ for (uint8_t i = 0; i < total_content; ++i) {
+
+ if (line_content[i]) free(line_content[i]);
+
+ line_content[i] = 0;
+ } // for
+
+ line_string = 0;
+ result_string.string = 0;
+ result_string.used = 0;
+ result_string.size = 0;
+ delimit_string.string = 0;
+ delimit_string.used = 0;
+ delimit_string.size = 0;
+ delimits.array = 0;
+ delimits.used = 0;
+ delimits.size = 0;
+ found.array = 0;
+ found.used = 0;
+ found.size = 0;
+ comments.array = 0;
+ comments.used = 0;
+ comments.size = 0;
+ quotes.array = 0;
+ quotes.used = 0;
+ quotes.size = 0;
+ } // for
+
+ for (uint8_t i = 0; i < total_content; ++i) {
+
+ if (file_contents[i]) fclose(file_contents[i]);
+ if (line_content[i]) free(line_content[i]);
+
+ line_content[i] = 0;
+ } // for
+
+ if (file_strings) fclose(file_strings);
+
+ if (delimits.array) free(delimits.array);
+ if (found.array) free(found.array);
+ if (comments.array) free(comments.array);
+ if (quotes.array) free(quotes.array);
+ if (line_string) free(line_string);
+ if (result_string.string) free(result_string.string);
+ if (delimit_string.string) free(delimit_string.string);
+ }
+}
+
#ifdef __cplusplus
} // extern "C"
#endif
*/
extern void test__fl_fss_extended_list_content_read__works(void **state);
+/**
+ * Test that the function works when using combining characters.
+ *
+ * @see fl_fss_extended_list_content_read()
+ */
+extern void test__fl_fss_extended_list_content_read__works_using_combining(void **state);
+
#endif // _TEST__FL_fss_extended_list_content_read_list_h
}
}
+void test__fl_fss_extended_list_object_read__works_using_combining(void **void_state) {
+
+ {
+ FILE *file_strings = data__file_open__named("strings", "extended_list", "combining_read");
+ FILE *file_objects = data__file_open__named("objects", "extended_list", "combining_read");
+
+ assert_non_null(file_strings);
+ assert_non_null(file_objects);
+
+ size_t max = 0;
+ char *line_string = 0;
+ char *line_object = 0;
+ ssize_t result = 0;
+
+ f_string_static_t buffer_string = f_string_static_t_initialize;
+
+ f_state_t state = f_state_t_initialize;
+ f_range_t range = f_range_t_initialize;
+ f_range_t found = f_range_t_initialize;
+ f_number_unsigneds_t delimits = f_number_unsigneds_t_initialize;
+ f_string_dynamic_t result_string = f_string_dynamic_t_initialize;
+ f_string_dynamic_t delimit_string = f_string_dynamic_t_initialize;
+
+ for (int line = 1;; ++line) {
+
+ max = 255;
+
+ result = getline(&line_string, &max, file_strings);
+ if (result == -1) break;
+
+ buffer_string.string = line_string;
+ buffer_string.used = (f_number_unsigned_t) result;
+ buffer_string.size = buffer_string.used;
+
+ state.status = F_none;
+ range.start = 0;
+ range.stop = buffer_string.used - 1;
+ found.start = 1;
+ found.stop = 0;
+
+ fl_fss_extended_list_object_read(buffer_string, &range, &found, &delimits, &state);
+
+ if (!(state.status == F_fss_found_object || state.status == F_fss_found_object_not)) {
+ printf("[ -------> ] --- [00] Failure with line (%u) '%s', status=%u, expected %u or %u.\n", line, line_string, state.status, F_fss_found_object, F_fss_found_object_not);
+ }
+
+ assert_true(state.status == F_fss_found_object || state.status == F_fss_found_object_not);
+
+ if (state.status == F_fss_found_object) {
+ max = 255;
+
+ result = getline(&line_object, &max, file_objects);
+
+ if (!result) {
+ printf("[ -------> ] --- [01] Failure with line (%u) '%s', line_object = '%s', result=%zu.\n", line, line_string, line_object, result);
+ }
+
+ assert_return_code(result, 0);
+
+ // The newline is copied by getline(), and so remove that newline before comparing.
+ line_object[result - 1] = 0;
+
+ if (found.start <= found.stop) {
+ {
+ const f_status_t status = f_string_dynamic_append(buffer_string, &delimit_string);
+
+ if (status != F_okay) {
+ printf("[ -------> ] --- [02] Failure with line (%u) '%s', line_object = '%s', status=%u, expected %u.\n", line, line_string, line_object, status, F_okay);
+ }
+
+ assert_int_equal(status, F_okay);
+ }
+
+ state.status = F_none;
+
+ f_fss_apply_delimit(delimits, &delimit_string, &state);
+
+ if (state.status != F_okay) {
+ printf("[ -------> ] --- [03] Failure with line (%u) '%s', line_object = '%s', status=%u, expected %u.\n", line, line_string, line_object, state.status, F_okay);
+ }
+
+ assert_int_equal(state.status, F_okay);
+
+ {
+ const f_status_t status = f_string_dynamic_partial_append_nulless(delimit_string, found, &result_string);
+
+ if (!(status == F_okay || status == F_data_not_eos)) {
+ printf("[ -------> ] --- [04] Failure with line (%u) '%s', line_object = '%s', status=%u, expected %u or %u.\n", line, line_string, line_object, status, F_okay, F_data_not_eos);
+ }
+
+ assert_true(status == F_okay || status == F_data_not_eos);
+ }
+
+ {
+ const f_status_t status = f_string_dynamic_terminate_after(&result_string);
+
+ if (status != F_okay) {
+ printf("[ -------> ] --- [05] Failure with line (%u) '%s', line_object = '%s', status=%u, expected %u.\n", line, line_string, line_object, status, F_okay);
+ }
+
+ assert_int_equal(status, F_okay);
+ }
+
+ if (strncmp(result_string.string, line_object, result_string.used)) {
+ printf("[ -------> ] --- [06] Failure with line (%u) '%s', line_object = '%s', result '%s'.\n", line, line_string, line_object, result_string.string);
+ }
+
+ assert_string_equal(result_string.string, line_object);
+ }
+ else {
+ if (line_object[0]) {
+ printf("[ -------> ] --- [07] Failure with line (%u) '%s', line_object[0]=%c.\n", line, line_string, line_object[0]);
+ }
+
+ assert_int_equal(line_object[0], 0);
+ }
+ }
+
+ if (line_string) free(line_string);
+ if (line_object) free(line_object);
+ if (result_string.string) free(result_string.string);
+ if (delimit_string.string) free(delimit_string.string);
+ if (delimits.array) free(delimits.array);
+
+ line_string = 0;
+ line_object = 0;
+ result_string.string = 0;
+ result_string.used = 0;
+ result_string.size = 0;
+ delimit_string.string = 0;
+ delimit_string.used = 0;
+ delimit_string.size = 0;
+ delimits.array = 0;
+ delimits.used = 0;
+ delimits.size = 0;
+ } // for
+
+ if (file_strings) fclose(file_strings);
+ if (file_objects) fclose(file_objects);
+
+ if (delimits.array) free(delimits.array);
+ if (line_string) free(line_string);
+ if (line_object) free(line_object);
+ if (result_string.string) free(result_string.string);
+ if (delimit_string.string) free(delimit_string.string);
+ }
+}
+
#ifdef __cplusplus
} // extern "C"
#endif
*/
extern void test__fl_fss_extended_list_object_read__works(void **state);
+/**
+ * Test that the function works when using combining characters.
+ *
+ * @see fl_fss_extended_list_object_read()
+ */
+extern void test__fl_fss_extended_list_object_read__works_using_combining(void **state);
+
#endif // _TEST__FL_fss_extended_list_object_read_list_h
cmocka_unit_test(test__fl_fss_basic_list_object_write__returns_data_not),
cmocka_unit_test(test__fl_fss_basic_list_content_read__works),
+ //cmocka_unit_test(test__fl_fss_basic_list_content_read__works_using_combining),
cmocka_unit_test(test__fl_fss_basic_list_object_read__works),
+ //cmocka_unit_test(test__fl_fss_basic_list_object_read__works_using_combining),
cmocka_unit_test(test__fl_fss_embedded_list_content_read__returns_data_not),
cmocka_unit_test(test__fl_fss_embedded_list_content_write__returns_data_not),
cmocka_unit_test(test__fl_fss_embedded_list_object_write__returns_data_not),
cmocka_unit_test(test__fl_fss_embedded_list_content_read__works),
+ //cmocka_unit_test(test__fl_fss_embedded_list_content_read__works_using_combining),
cmocka_unit_test(test__fl_fss_embedded_list_object_read__works),
+ //cmocka_unit_test(test__fl_fss_embedded_list_object_read__works_using_combining),
cmocka_unit_test(test__fl_fss_extended_content_read__returns_data_not),
cmocka_unit_test(test__fl_fss_extended_content_write__returns_data_not),
cmocka_unit_test(test__fl_fss_extended_list_object_write__returns_data_not),
cmocka_unit_test(test__fl_fss_extended_list_content_read__works),
+ //cmocka_unit_test(test__fl_fss_extended_list_content_read__works_using_combining),
cmocka_unit_test(test__fl_fss_extended_list_object_read__works),
+ //cmocka_unit_test(test__fl_fss_extended_list_object_read__works_using_combining),
cmocka_unit_test(test__fl_fss_payload_header_map__returns_data_not),
cmocka_unit_test(test__fl_fss_payload_header_map__abstruse_dynamic__works_join),