Sat, 02 Nov 2024 19:27:45 +0100
add support for UCX strings in cxPropertiesFill()
src/cx/properties.h | file | annotate | diff | comparison | revisions | |
src/properties.c | file | annotate | diff | comparison | revisions | |
tests/test_properties.c | file | annotate | diff | comparison | revisions |
--- a/src/cx/properties.h Sat Nov 02 13:48:53 2024 +0100 +++ b/src/cx/properties.h Sat Nov 02 19:27:45 2024 +0100 @@ -42,6 +42,7 @@ #include "array_list.h" #include <stdio.h> +#include <string.h> #ifdef __cplusplus extern "C" { @@ -371,7 +372,13 @@ cxPropertiesInit(prop, cx_properties_config_default) /** - * Sets an input buffer. + * Fills the input buffer with data. + * + * Currently unprocessed data is copied to a temporary buffer. + * This temporary buffer is allocated on the heap, unless you specified + * a buffer on the stack with #cxPropertiesUseStack(). + * In that case, the stack buffer is used, until the capacity is not sufficient + * anymore. * * After calling this function, you can parse the data by calling * cxPropertiesNext() until the status is #CX_PROPERTIES_NO_DATA. @@ -379,18 +386,19 @@ * @param prop the properties interface * @param buf a pointer to data * @param len the length of the data + * @return non-zero when a memory allocation was necessary but failed */ __attribute__((__nonnull__)) -void cxPropertiesInput( +int cxPropertiesFilln( CxProperties *prop, const char *buf, size_t len ); /** - * Sets a new input buffer after copying the current unprocessed data - * to a temporary buffer. + * Fills the input buffer with a string. * + * Currently unprocessed data is copied to a temporary buffer. * This temporary buffer is allocated on the heap, unless you specified * a buffer on the stack with #cxPropertiesUseStack(). * In that case, the stack buffer is used, until the capacity is not sufficient @@ -400,16 +408,60 @@ * copied, it behaves exactly as #cxPropertiesInput(). * * @param prop the properties interface - * @param buf a pointer to data - * @param len the length of the data + * @param str the string + * @return non-zero when a memory allocation was necessary but failed + */ +#define cxPropertiesFill(prop, str) _Generic((str), \ + cxstring: cx_properties_fill_cxstr, \ + cxmutstr: cx_properties_fill_mutstr, \ + char*: cx_properties_fill_str, \ + const char*: cx_properties_fill_str) \ + (prop, str) + +/** + * Implementation of cxPropertiesFill() for cxstring. + * + * @param prop the properties interface + * @param str the string * @return non-zero when a memory allocation was necessary but failed */ __attribute__((__nonnull__)) -int cxPropertiesFill( +static inline int cx_properties_fill_cxstr( + CxProperties *prop, + cxstring str +) { + return cxPropertiesFilln(prop, str.ptr, str.length); +} + +/** + * Implementation of cxPropertiesFill() for cxmutstr. + * + * @param prop the properties interface + * @param str the string + * @return non-zero when a memory allocation was necessary but failed + */ +__attribute__((__nonnull__)) +static inline int cx_properties_fill_mutstr( CxProperties *prop, - const char *buf, - size_t len -); + cxmutstr str +) { + return cxPropertiesFilln(prop, str.ptr, str.length); +} + +/** + * Implementation of cxPropertiesFill() for zero terminated C strings. + * + * @param prop the properties interface + * @param str the string + * @return non-zero when a memory allocation was necessary but failed + */ +__attribute__((__nonnull__)) +static inline int cx_properties_fill_str( + CxProperties *prop, + const char *str +) { + return cxPropertiesFilln(prop, str, strlen(str)); +} /** * Specifies stack memory that shall be used by #cxPropertiesFill().
--- a/src/properties.c Sat Nov 02 13:48:53 2024 +0100 +++ b/src/properties.c Sat Nov 02 19:27:45 2024 +0100 @@ -28,7 +28,6 @@ #include "cx/properties.h" -#include <string.h> #include <assert.h> static const int CX_PROPERTIES_FLAG_USE_STACK = 0x01; @@ -106,23 +105,15 @@ return cx_properties_rescuen_input(prop, len); } -void cxPropertiesInput( - CxProperties *prop, - const char *buf, - size_t len -) { - prop->text = buf; - prop->text_size = len; - prop->text_pos = 0; -} - -int cxPropertiesFill( +int cxPropertiesFilln( CxProperties *prop, const char *buf, size_t len ) { if (cx_properties_rescue_input(prop)) return 1; - cxPropertiesInput(prop, buf, len); + prop->text = buf; + prop->text_size = len; + prop->text_pos = 0; return 0; } @@ -429,7 +420,9 @@ } // set the input buffer and read the k/v-pairs - cxPropertiesInput(prop, input.ptr, input.length); + prop->text = input.ptr; + prop->text_size = input.length; + prop->text_pos = 0; CxPropertiesStatus kv_status; do {
--- a/tests/test_properties.c Sat Nov 02 13:48:53 2024 +0100 +++ b/tests/test_properties.c Sat Nov 02 19:27:45 2024 +0100 @@ -96,7 +96,7 @@ cxstring value; CX_TEST_DO { for (int i = 0; i < 10; i++) { - cxPropertiesInput(&prop, tests[i], strlen(tests[i])); + cxPropertiesFill(&prop, tests[i]); CX_TEST_ASSERT(prop.text == tests[i]); CX_TEST_ASSERT(prop.text_size == strlen(tests[i])); CX_TEST_ASSERT(prop.text_pos == 0); @@ -115,29 +115,42 @@ cxPropertiesDestroy(&prop); } -CX_TEST(test_properties_next_multi) { +CX_TEST_SUBROUTINE(test_properties_next_multi_check, CxProperties *prop) { const char *keys[] = { - "a", - "b", - "c", - "uap", - "name", - "key1", - "key2", - "key3" + "a", + "b", + "c", + "uap", + "name", + "key1", + "key2", + "key3" }; const char *values[] = { - "a value", - "b value", - "core", - "core", - "ucx", - "value1", - "value2", - "value3" + "a value", + "b value", + "core", + "core", + "ucx", + "value1", + "value2", + "value3" }; + CxPropertiesStatus result; + cxstring key; + cxstring value; + for (int i = 0; i < 8; i++) { + result = cxPropertiesNext(prop, &key, &value); + CX_TEST_ASSERT(result == CX_PROPERTIES_NO_ERROR); + CX_TEST_ASSERT(!cx_strcmp(key, cx_str(keys[i]))); + CX_TEST_ASSERT(!cx_strcmp(value, cx_str(values[i]))); + } + result = cxPropertiesNext(prop, &key, &value); + CX_TEST_ASSERT(result == CX_PROPERTIES_NO_DATA); +} +CX_TEST(test_properties_next_multi) { const char *str = "#\n" "# properties\n" "# contains key/value pairs\n" @@ -157,22 +170,25 @@ CxProperties prop; cxPropertiesInitDefault(&prop); - CxPropertiesStatus result; - cxstring key; - cxstring value; CX_TEST_DO { + CxPropertiesStatus result; + cxstring key; + cxstring value; result = cxPropertiesNext(&prop, &key, &value); CX_TEST_ASSERT(result == CX_PROPERTIES_NULL_INPUT); - cxPropertiesInput(&prop, str, strlen(str)); - for (int i = 0; i < 8; i++) { - result = cxPropertiesNext(&prop, &key, &value); - CX_TEST_ASSERT(result == CX_PROPERTIES_NO_ERROR); - CX_TEST_ASSERT(!cx_strcmp(key, cx_str(keys[i]))); - CX_TEST_ASSERT(!cx_strcmp(value, cx_str(values[i]))); - } - result = cxPropertiesNext(&prop, &key, &value); - CX_TEST_ASSERT(result == CX_PROPERTIES_NO_DATA); + + // check for C string + cxPropertiesFill(&prop, str); + CX_TEST_CALL_SUBROUTINE(test_properties_next_multi_check, &prop); + + // check for cxstring + cxPropertiesFill(&prop, cx_str(str)); + CX_TEST_CALL_SUBROUTINE(test_properties_next_multi_check, &prop); + + // check for mutstr + cxPropertiesFill(&prop, cx_mutstr((char*)str)); + CX_TEST_CALL_SUBROUTINE(test_properties_next_multi_check, &prop); } cxPropertiesDestroy(&prop); } @@ -187,35 +203,35 @@ CX_TEST_DO { str = ""; - cxPropertiesFill(&prop, str, strlen(str)); + cxPropertiesFill(&prop, str); result = cxPropertiesNext(&prop, &key, &value); CX_TEST_ASSERT(result == CX_PROPERTIES_NO_DATA); str = " \n"; - cxPropertiesFill(&prop, str, strlen(str)); + cxPropertiesFill(&prop, str); result = cxPropertiesNext(&prop, &key, &value); CX_TEST_ASSERT(result == CX_PROPERTIES_NO_DATA); str = "name"; - cxPropertiesFill(&prop, str, strlen(str)); + cxPropertiesFill(&prop, str); result = cxPropertiesNext(&prop, &key, &value); CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); str = " "; - cxPropertiesFill(&prop, str, strlen(str)); + cxPropertiesFill(&prop, str); result = cxPropertiesNext(&prop, &key, &value); CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); // call fill twice in a row str = "= "; - cxPropertiesFill(&prop, str, strlen(str)); + cxPropertiesFill(&prop, str); str = "value"; - cxPropertiesFill(&prop, str, strlen(str)); + cxPropertiesFill(&prop, str); result = cxPropertiesNext(&prop, &key, &value); CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); str = "\n"; - cxPropertiesFill(&prop, str, strlen(str)); + cxPropertiesFill(&prop, str); result = cxPropertiesNext(&prop, &key, &value); CX_TEST_ASSERT(result == CX_PROPERTIES_NO_ERROR); CX_TEST_ASSERT(0 == cx_strcmp(key, cx_str("name"))); @@ -223,17 +239,17 @@ // second round str = "#comment\n"; - cxPropertiesFill(&prop, str, strlen(str)); + cxPropertiesFill(&prop, str); result = cxPropertiesNext(&prop, &key, &value); CX_TEST_ASSERT(result == CX_PROPERTIES_NO_DATA); str = "#comment\nname2 = "; - cxPropertiesFill(&prop, str, strlen(str)); + cxPropertiesFill(&prop, str); result = cxPropertiesNext(&prop, &key, &value); CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); str = "value2\na = b\n"; - cxPropertiesFill(&prop, str, strlen(str)); + cxPropertiesFill(&prop, str); result = cxPropertiesNext(&prop, &key, &value); CX_TEST_ASSERT(result == CX_PROPERTIES_NO_ERROR); CX_TEST_ASSERT(0 == cx_strcmp(key, cx_str("name2"))); @@ -245,17 +261,17 @@ CX_TEST_ASSERT(0 == cx_strcmp(value, cx_str("b"))); str = "# comment\n#\n#\ntests = "; - cxPropertiesFill(&prop, str, strlen(str)); + cxPropertiesFill(&prop, str); result = cxPropertiesNext(&prop, &key, &value); CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); str = "test1 "; - cxPropertiesFill(&prop, str, strlen(str)); + cxPropertiesFill(&prop, str); result = cxPropertiesNext(&prop, &key, &value); CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); str = "test2 test3 test4\n"; - cxPropertiesFill(&prop, str, strlen(str)); + cxPropertiesFill(&prop, str); result = cxPropertiesNext(&prop, &key, &value); CX_TEST_ASSERT(result == CX_PROPERTIES_NO_ERROR); CX_TEST_ASSERT(0 == cx_strcmp(key, cx_str("tests"))); @@ -263,17 +279,17 @@ // test if cxPropertiesNext finds a name/value after a comment str = "# just a comment"; - cxPropertiesFill(&prop, str, strlen(str)); + cxPropertiesFill(&prop, str); result = cxPropertiesNext(&prop, &key, &value); CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); str = " in 3"; - cxPropertiesFill(&prop, str, strlen(str)); + cxPropertiesFill(&prop, str); result = cxPropertiesNext(&prop, &key, &value); CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); str = " parts\nx = 1\n"; - cxPropertiesFill(&prop, str, strlen(str)); + cxPropertiesFill(&prop, str); result = cxPropertiesNext(&prop, &key, &value); CX_TEST_ASSERT(result == CX_PROPERTIES_NO_ERROR); CX_TEST_ASSERT(0 == cx_strcmp(key, cx_str("x"))); @@ -305,41 +321,41 @@ memset(long_value+1024, 'y', 1024); CX_TEST_DO { - cxPropertiesFill(&prop, long_key, 10); + cxPropertiesFilln(&prop, long_key, 10); result = cxPropertiesNext(&prop, &key, &value); CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); - cxPropertiesFill(&prop, long_key + 10, 202); + cxPropertiesFilln(&prop, long_key + 10, 202); result = cxPropertiesNext(&prop, &key, &value); CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); - cxPropertiesFill(&prop, long_key + 212, 200); + cxPropertiesFilln(&prop, long_key + 212, 200); result = cxPropertiesNext(&prop, &key, &value); CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); - cxPropertiesFill(&prop, long_key + 412, 100); + cxPropertiesFilln(&prop, long_key + 412, 100); result = cxPropertiesNext(&prop, &key, &value); CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); const char *str = " = "; - cxPropertiesFill(&prop, str, strlen(str)); + cxPropertiesFill(&prop, str); result = cxPropertiesNext(&prop, &key, &value); CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); - cxPropertiesFill(&prop, long_value, 512); + cxPropertiesFilln(&prop, long_value, 512); result = cxPropertiesNext(&prop, &key, &value); CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); - cxPropertiesFill(&prop, long_value + 512, 1024); + cxPropertiesFilln(&prop, long_value + 512, 1024); result = cxPropertiesNext(&prop, &key, &value); CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); - cxPropertiesFill(&prop, long_value + 1536, 512); + cxPropertiesFilln(&prop, long_value + 1536, 512); result = cxPropertiesNext(&prop, &key, &value); CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); str = "\n#comment\nkey = value\n"; - cxPropertiesFill(&prop, str, strlen(str)); + cxPropertiesFill(&prop, str); result = cxPropertiesNext(&prop, &key, &value); cxstring k = cx_strn(long_key, key_len); cxstring v = cx_strn(long_value, value_len);