From 75d83bf14808c308eb1591c3f33255569c7442a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20Sch=C3=B6bel?= <jonathan@xn--schbel-yxa.info> Date: Wed, 7 Jun 2023 11:43:28 +0200 Subject: [PATCH] NodeFragment: changed semantics of insert_attr_new When there are methods in the api/abi, that take pointers to strings to store them in the library, there are two methods to do so. Either they are copying the string and leaving it intact, or they directly assign the given pointer to some internal storage. While the former method, is safer in terms of memory, as the user doesn't have to remember that he can't use the string anymore, the latter can be more efficient, as there is no extra strdup call, but the user is not allowed to change the pointer, free it and also can't use the pointer, because it can't be known whether it is already freed by the library. As it should be decideable by the user, the library often implements both approaches, where the method, that directly store pointers without creating a copy contains the raw_ prefix. The insert_attr_new methods were somewhat confusing in this regard, as it is likely to be expected, that they were copying the string, while in fact they did not. This is now fixed. The insert_attr_new methods copy the strings, while the added insert_attr_raw_new methods preserve the old behaviour of the insert_attr_new methods, thus allowing to let the user choose, what is more appropriate. --- sefht.geany | 6 +- src/lib/sefht/node_fragment.c | 142 +++++++++- src/lib/sefht/node_fragment.h | 46 +++- tests/test_node_fragment.c | 482 ++++++++++++++++++++++++++++++---- 4 files changed, 614 insertions(+), 62 deletions(-) diff --git a/sefht.geany b/sefht.geany index 9a1bbac..c48d879 100644 --- a/sefht.geany +++ b/sefht.geany @@ -43,8 +43,8 @@ FILE_NAME_10=1550;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fp FILE_NAME_11=1562;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ffragment.h;0;8 FILE_NAME_12=2022;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ffragment_data.c;0;8 FILE_NAME_13=2558;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ffragment_class.c;0;8 -FILE_NAME_14=9423;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fnode_fragment.c;0;8 -FILE_NAME_15=6811;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fnode_fragment.h;0;8 +FILE_NAME_14=12922;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fnode_fragment.c;0;8 +FILE_NAME_15=6478;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fnode_fragment.h;0;8 FILE_NAME_16=4590;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fattr.c;0;8 FILE_NAME_17=2828;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fattr.h;0;8 FILE_NAME_18=3893;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fattr_static.c;0;8 @@ -63,7 +63,7 @@ FILE_NAME_30=555;Make;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2 FILE_NAME_31=218;Sh;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Fno_test.sh.in;0;8 FILE_NAME_32=1085;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_cms.c;0;8 FILE_NAME_33=3283;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_data.c;0;8 -FILE_NAME_34=28347;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_node_fragment.c;0;8 +FILE_NAME_34=126847;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_node_fragment.c;0;8 FILE_NAME_35=11319;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_attr.c;0;8 FILE_NAME_36=11068;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_text.c;0;8 FILE_NAME_37=5744;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_validator.c;0;8 diff --git a/src/lib/sefht/node_fragment.c b/src/lib/sefht/node_fragment.c index b1ac83c..308536f 100644 --- a/src/lib/sefht/node_fragment.c +++ b/src/lib/sefht/node_fragment.c @@ -617,13 +617,81 @@ insert_attr (struct SH_NodeFragment * fragment, static inline bool insert_attr_new (struct SH_NodeFragment * fragment, - /*@only@*/ char * name, - /*@null@*/ /*@only@*/ char * value, + const char * name, + /*@null@*/ const char * value, size_t position, /*@out@*/ /*@null@*/ struct SH_Status * status) /*@modifies fragment->attrs@*/ /*@modifies fragment->attr_s@*/ /*@modifies fragment->attr_n@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/ +{ + size_t new_size; + size_t index; + struct SH_Attr attr; + typeof (fragment->attrs) new_attrs; + + if (!Attr_init (&attr, name, value, status)) + { + return FALSE; + } + + new_size = get_attr_alloc_size (fragment->attr_n + 1); + if (new_size > fragment->attr_s) + { + if ((SIZE_MAX / sizeof (*new_attrs)) < new_size) + { + set_status (status, E_DOMAIN, -6, + "maximum number of " + "attrs reached.\n"); + Attr_free (&attr); + return FALSE; + } + + new_attrs = realloc (fragment->attrs, new_size + * sizeof (*new_attrs)); + + if (new_attrs == NULL) + { + set_status (status, E_ALLOC, 5, + "malloc failed\n"); + +/* bad code to silence splint, should never be executed. */ +#ifdef S_SPLINT_S + fragment->attrs = (void *) 0x12345; +#endif + Attr_free (&attr); + return FALSE; + } + + fragment->attrs = new_attrs; + fragment->attr_s = new_size; + } + + for (index = fragment->attr_n; index > position; index--) + { + fragment->attrs[index] = fragment->attrs[index-1]; + } + Attr_move (&(fragment->attrs[position]), &attr); + fragment->attr_n++; + + set_success (status); + + return TRUE; +} + +static inline +bool +insert_attr_raw_new (struct SH_NodeFragment * fragment, + /*@only@*/ char * name, + /*@null@*/ /*@only@*/ char * value, + size_t position, + /*@out@*/ /*@null@*/ struct SH_Status * status) + /*@modifies fragment->attrs@*/ + /*@modifies fragment->attr_s@*/ + /*@modifies fragment->attr_n@*/ /*@modifies name@*/ /*@modifies value@*/ /*@globals fileSystem@*/ @@ -769,8 +837,8 @@ SH_NodeFragment_insert_attr (struct SH_NodeFragment * fragment, bool SH_NodeFragment_insert_attr_new (struct SH_NodeFragment * fragment, - /*@only@*/ char * name, - /*@null@*/ /*@only@*/ char * value, + const char * name, + /*@null@*/ const char * value, size_t position, /*@out@*/ /*@null@*/ struct SH_Status * status) @@ -791,6 +859,31 @@ SH_NodeFragment_insert_attr_new (struct SH_NodeFragment * fragment, return insert_attr_new (fragment, name, value, position, status); } +bool +SH_NodeFragment_insert_attr_raw_new (struct SH_NodeFragment * fragment, + /*@only@*/ char * name, + /*@null@*/ /*@only@*/ char * value, + size_t position, + /*@out@*/ /*@null@*/ + struct SH_Status * status) + /*@modifies fragment->attrs@*/ + /*@modifies fragment->attr_s@*/ + /*@modifies fragment->attr_n@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/ +{ + if (position > fragment->attr_n) + { + set_status (status, E_VALUE, 2, + "index out of range.\n"); + return FALSE; + } + + return insert_attr_raw_new (fragment, name, value, position, + status); +} + bool SH_NodeFragment_insert_attr_copy (struct SH_NodeFragment * fragment, const SH_Attr * attr, @@ -831,8 +924,8 @@ SH_NodeFragment_prepend_attr (struct SH_NodeFragment * fragment, bool SH_NodeFragment_prepend_attr_new (struct SH_NodeFragment * fragment, - /*@only@*/ char * name, - /*@null@*/ /*@only@*/ char * value, + const char * name, + /*@null@*/ const char * value, /*@out@*/ /*@null@*/ struct SH_Status * status) /*@modifies fragment->attrs@*/ @@ -845,6 +938,22 @@ SH_NodeFragment_prepend_attr_new (struct SH_NodeFragment * fragment, return insert_attr_new (fragment, name, value, 0, status); } +bool +SH_NodeFragment_prepend_attr_raw_new (struct SH_NodeFragment * fragment, + /*@only@*/ char * name, + /*@null@*/ /*@only@*/ char * value, + /*@out@*/ /*@null@*/ + struct SH_Status * status) + /*@modifies fragment->attrs@*/ + /*@modifies fragment->attr_s@*/ + /*@modifies fragment->attr_n@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/ +{ + return insert_attr_raw_new (fragment, name, value, 0, status); +} + bool SH_NodeFragment_prepend_attr_copy (struct SH_NodeFragment * fragment, const SH_Attr * attr, @@ -877,8 +986,8 @@ SH_NodeFragment_append_attr (struct SH_NodeFragment * fragment, bool SH_NodeFragment_append_attr_new (struct SH_NodeFragment * fragment, - /*@only@*/ char * name, - /*@null@*/ /*@only@*/ char * value, + const char * name, + /*@null@*/ const char * value, /*@out@*/ /*@null@*/ struct SH_Status * status) /*@modifies fragment->attrs@*/ @@ -892,6 +1001,23 @@ SH_NodeFragment_append_attr_new (struct SH_NodeFragment * fragment, fragment->attr_n, status); } +bool +SH_NodeFragment_append_attr_raw_new (struct SH_NodeFragment * fragment, + /*@only@*/ char * name, + /*@null@*/ /*@only@*/ char * value, + /*@out@*/ /*@null@*/ + struct SH_Status * status) + /*@modifies fragment->attrs@*/ + /*@modifies fragment->attr_s@*/ + /*@modifies fragment->attr_n@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/ +{ + return insert_attr_raw_new (fragment, name, value, + fragment->attr_n, status); +} + bool SH_NodeFragment_append_attr_copy (struct SH_NodeFragment * fragment, const SH_Attr * attr, diff --git a/src/lib/sefht/node_fragment.h b/src/lib/sefht/node_fragment.h index a12cd21..160e86c 100644 --- a/src/lib/sefht/node_fragment.h +++ b/src/lib/sefht/node_fragment.h @@ -115,8 +115,8 @@ SH_NodeFragment_insert_attr (SH_NodeFragment * fragment, bool SH_NodeFragment_insert_attr_new (SH_NodeFragment * fragment, - /*@only@*/ char * name, - /*@null@*/ /*@only@*/ char * value, + const char * name, + /*@null@*/ const char * value, size_t position, /*@out@*/ /*@null@*/ struct SH_Status * status) @@ -125,6 +125,18 @@ SH_NodeFragment_insert_attr_new (SH_NodeFragment * fragment, /*@modifies fileSystem@*/ /*@modifies status@*/; +bool +SH_NodeFragment_insert_attr_raw_new (SH_NodeFragment * fragment, + /*@only@*/ char * name, + /*@null@*/ /*@only@*/ char * value, + size_t position, + /*@out@*/ /*@null@*/ + struct SH_Status * status) + /*@modifies fragment@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/; + bool SH_NodeFragment_insert_attr_copy (SH_NodeFragment * fragment, const SH_Attr * attr, @@ -148,8 +160,8 @@ SH_NodeFragment_prepend_attr (SH_NodeFragment * fragment, bool SH_NodeFragment_prepend_attr_new (SH_NodeFragment * fragment, - /*@only@*/ char * name, - /*@null@*/ /*@only@*/ char * value, + const char * name, + /*@null@*/ const char * value, /*@out@*/ /*@null@*/ struct SH_Status * status) /*@modifies fragment@*/ @@ -157,6 +169,17 @@ SH_NodeFragment_prepend_attr_new (SH_NodeFragment * fragment, /*@modifies fileSystem@*/ /*@modifies status@*/; +bool +SH_NodeFragment_prepend_attr_raw_new (SH_NodeFragment * fragment, + /*@only@*/ char * name, + /*@null@*/ /*@only@*/ char * value, + /*@out@*/ /*@null@*/ + struct SH_Status * status) + /*@modifies fragment@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/; + bool SH_NodeFragment_prepend_attr_copy (SH_NodeFragment * fragment, const SH_Attr * attr, @@ -179,14 +202,25 @@ SH_NodeFragment_append_attr (SH_NodeFragment * fragment, bool SH_NodeFragment_append_attr_new (SH_NodeFragment * fragment, - /*@only@*/ char * name, - /*@null@*/ /*@only@*/ char * value, + const char * name, + /*@null@*/ const char * value, /*@out@*/ /*@null@*/ struct SH_Status * status) /*@modifies fragment@*/ /*@globals fileSystem@*/ /*@modifies fileSystem@*/ /*@modifies status@*/; + +bool +SH_NodeFragment_append_attr_raw_new (SH_NodeFragment * fragment, + /*@only@*/ char * name, + /*@null@*/ /*@only@*/ char * value, + /*@out@*/ /*@null@*/ + struct SH_Status * status) + /*@modifies fragment@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/; bool SH_NodeFragment_append_attr_copy (SH_NodeFragment * fragment, const SH_Attr * attr, diff --git a/tests/test_node_fragment.c b/tests/test_node_fragment.c index 8e56365..61e6796 100644 --- a/tests/test_node_fragment.c +++ b/tests/test_node_fragment.c @@ -719,6 +719,207 @@ START_TEST(test_node_fragment_attr_insert_new_no_status) ck_assert_int_le (1, fragment->attr_s); ck_assert_int_eq (ATTR_CHUNK, fragment->attr_s); + ck_assert_ptr_ne (attr1->name, fragment->attrs[0].name); + ck_assert_ptr_ne (attr1->value, fragment->attrs[0].value); + + ck_assert_str_eq (attr1->name, fragment->attrs[0].name); + ck_assert_str_eq (attr1->value, fragment->attrs[0].value); + + /* test insert before - success */ + name = Attr_get_name (attr2); + value = Attr_get_value (attr2); + + result = insert_attr_new (fragment, name, value, 0, NULL); + ck_assert_int_eq (TRUE, result); + + ck_assert_int_eq (2, fragment->attr_n); + ck_assert_int_le (2, fragment->attr_s); + ck_assert_int_eq (ATTR_CHUNK, fragment->attr_s); + + ck_assert_ptr_ne (attr2->name, fragment->attrs[0].name); + ck_assert_ptr_ne (attr2->value, fragment->attrs[0].value); + + ck_assert_str_eq (attr2->name, fragment->attrs[0].name); + ck_assert_str_eq (attr2->value, fragment->attrs[0].value); + + ck_assert_str_eq (attr1->name, fragment->attrs[1].name); + ck_assert_str_eq (attr1->value, fragment->attrs[1].value); + + /* test insert after - success */ + name = Attr_get_name (attr3); + value = Attr_get_value (attr3); + + result = insert_attr_new (fragment, name, value, 2, NULL); + ck_assert_int_eq (TRUE, result); + + ck_assert_int_eq (3, fragment->attr_n); + ck_assert_int_le (3, fragment->attr_s); + ck_assert_int_eq (ATTR_CHUNK, fragment->attr_s); + + ck_assert_ptr_ne (attr3->name, fragment->attrs[2].name); + ck_assert_ptr_ne (attr3->value, fragment->attrs[2].value); + + ck_assert_str_eq (attr2->name, fragment->attrs[0].name); + ck_assert_str_eq (attr2->value, fragment->attrs[0].value); + + ck_assert_str_eq (attr1->name, fragment->attrs[1].name); + ck_assert_str_eq (attr1->value, fragment->attrs[1].value); + + ck_assert_str_eq (attr3->name, fragment->attrs[2].name); + ck_assert_str_eq (attr3->value, fragment->attrs[2].value); + + /* cleanup */ + SH_NodeFragment_free (fragment); + SH_Data_free (data); + SH_Attr_free (attr1); + SH_Attr_free (attr2); + SH_Attr_free (attr3); +} +END_TEST + +START_TEST(test_node_fragment_attr_insert_new_with_status) +{ + struct SH_Status status; + char * name; + char * value; + SH_Attr * attr1; + SH_Attr * attr2; + SH_Attr * attr3; + SH_Data * data; + struct SH_NodeFragment * fragment; + bool result; + + /* setup */ + attr1 = SH_Attr_new ("name1", "value1", NULL); + ck_assert_ptr_ne (NULL, attr1); + + attr2 = SH_Attr_new ("name2", "value2", NULL); + ck_assert_ptr_ne (NULL, attr2); + + attr3 = SH_Attr_new ("name3", "value3", NULL); + ck_assert_ptr_ne (NULL, attr3); + + data = SH_Data_new (NULL); + ck_assert_ptr_ne (NULL, data); + + fragment = (SH_NodeFragment *)SH_NodeFragment_new ("html", data, + NULL); + ck_assert_ptr_ne (NULL, fragment); + + /* test insert - success */ + name = Attr_get_name (attr1); + value = Attr_get_value (attr1); + + _status_preinit (status); + result = insert_attr_new (fragment, name, value, 0, &status); + ck_assert_int_eq (TRUE, result); + ck_assert_int_eq (SUCCESS, status.status); + + ck_assert_int_eq (1, fragment->attr_n); + ck_assert_int_le (1, fragment->attr_s); + ck_assert_int_eq (ATTR_CHUNK, fragment->attr_s); + + ck_assert_ptr_ne (attr1->name, fragment->attrs[0].name); + ck_assert_ptr_ne (attr1->value, fragment->attrs[0].value); + + ck_assert_str_eq (attr1->name, fragment->attrs[0].name); + ck_assert_str_eq (attr1->value, fragment->attrs[0].value); + + /* test insert before - success */ + name = Attr_get_name (attr2); + value = Attr_get_value (attr2); + + _status_preinit (status); + result = insert_attr_new (fragment, name, value, 0, &status); + ck_assert_int_eq (TRUE, result); + ck_assert_int_eq (SUCCESS, status.status); + + ck_assert_int_eq (2, fragment->attr_n); + ck_assert_int_le (2, fragment->attr_s); + ck_assert_int_eq (ATTR_CHUNK, fragment->attr_s); + + ck_assert_ptr_ne (attr2->name, fragment->attrs[0].name); + ck_assert_ptr_ne (attr2->value, fragment->attrs[0].value); + + ck_assert_str_eq (attr2->name, fragment->attrs[0].name); + ck_assert_str_eq (attr2->value, fragment->attrs[0].value); + + ck_assert_str_eq (attr1->name, fragment->attrs[1].name); + ck_assert_str_eq (attr1->value, fragment->attrs[1].value); + + /* test insert after - success */ + name = Attr_get_name (attr3); + value = Attr_get_value (attr3); + + _status_preinit (status); + result = insert_attr_new (fragment, name, value, 2, &status); + ck_assert_int_eq (TRUE, result); + ck_assert_int_eq (SUCCESS, status.status); + + ck_assert_int_eq (3, fragment->attr_n); + ck_assert_int_le (3, fragment->attr_s); + ck_assert_int_eq (ATTR_CHUNK, fragment->attr_s); + + ck_assert_ptr_ne (attr3->name, fragment->attrs[2].name); + ck_assert_ptr_ne (attr3->value, fragment->attrs[2].value); + + ck_assert_str_eq (attr2->name, fragment->attrs[0].name); + ck_assert_str_eq (attr2->value, fragment->attrs[0].value); + + ck_assert_str_eq (attr1->name, fragment->attrs[1].name); + ck_assert_str_eq (attr1->value, fragment->attrs[1].value); + + ck_assert_str_eq (attr3->name, fragment->attrs[2].name); + ck_assert_str_eq (attr3->value, fragment->attrs[2].value); + + /* cleanup */ + SH_NodeFragment_free (fragment); + SH_Data_free (data); + SH_Attr_free (attr1); + SH_Attr_free (attr2); + SH_Attr_free (attr3); +} +END_TEST + +START_TEST(test_node_fragment_attr_insert_raw_new_no_status) +{ + char * name; + char * value; + SH_Attr * attr1; + SH_Attr * attr2; + SH_Attr * attr3; + SH_Data * data; + struct SH_NodeFragment * fragment; + bool result; + + /* setup */ + attr1 = SH_Attr_new ("name1", "value1", NULL); + ck_assert_ptr_ne (NULL, attr1); + + attr2 = SH_Attr_new ("name2", "value2", NULL); + ck_assert_ptr_ne (NULL, attr2); + + attr3 = SH_Attr_new ("name3", "value3", NULL); + ck_assert_ptr_ne (NULL, attr3); + + data = SH_Data_new (NULL); + ck_assert_ptr_ne (NULL, data); + + fragment = (SH_NodeFragment *)SH_NodeFragment_new ("html", data, + NULL); + ck_assert_ptr_ne (NULL, fragment); + + /* test insert - success */ + name = Attr_get_name (attr1); + value = Attr_get_value (attr1); + + result = insert_attr_raw_new (fragment, name, value, 0, NULL); + ck_assert_int_eq (TRUE, result); + + ck_assert_int_eq (1, fragment->attr_n); + ck_assert_int_le (1, fragment->attr_s); + ck_assert_int_eq (ATTR_CHUNK, fragment->attr_s); + ck_assert_ptr_eq (attr1->name, fragment->attrs[0].name); ck_assert_ptr_eq (attr1->value, fragment->attrs[0].value); @@ -726,7 +927,7 @@ START_TEST(test_node_fragment_attr_insert_new_no_status) name = Attr_get_name (attr2); value = Attr_get_value (attr2); - result = insert_attr_new (fragment, name, value, 0, NULL); + result = insert_attr_raw_new (fragment, name, value, 0, NULL); ck_assert_int_eq (TRUE, result); ck_assert_int_eq (2, fragment->attr_n); @@ -743,7 +944,7 @@ START_TEST(test_node_fragment_attr_insert_new_no_status) name = Attr_get_name (attr3); value = Attr_get_value (attr3); - result = insert_attr_new (fragment, name, value, 2, NULL); + result = insert_attr_raw_new (fragment, name, value, 2, NULL); ck_assert_int_eq (TRUE, result); ck_assert_int_eq (3, fragment->attr_n); @@ -768,7 +969,7 @@ START_TEST(test_node_fragment_attr_insert_new_no_status) } END_TEST -START_TEST(test_node_fragment_attr_insert_new_with_status) +START_TEST(test_node_fragment_attr_insert_raw_new_with_status) { struct SH_Status status; char * name; @@ -802,7 +1003,7 @@ START_TEST(test_node_fragment_attr_insert_new_with_status) value = Attr_get_value (attr1); _status_preinit (status); - result = insert_attr_new (fragment, name, value, 0, &status); + result = insert_attr_raw_new (fragment, name, value, 0, &status); ck_assert_int_eq (TRUE, result); ck_assert_int_eq (SUCCESS, status.status); @@ -818,7 +1019,7 @@ START_TEST(test_node_fragment_attr_insert_new_with_status) value = Attr_get_value (attr2); _status_preinit (status); - result = insert_attr_new (fragment, name, value, 0, &status); + result = insert_attr_raw_new (fragment, name, value, 0, &status); ck_assert_int_eq (TRUE, result); ck_assert_int_eq (SUCCESS, status.status); @@ -837,7 +1038,7 @@ START_TEST(test_node_fragment_attr_insert_new_with_status) value = Attr_get_value (attr3); _status_preinit (status); - result = insert_attr_new (fragment, name, value, 2, &status); + result = insert_attr_raw_new (fragment, name, value, 2, &status); ck_assert_int_eq (TRUE, result); ck_assert_int_eq (SUCCESS, status.status); @@ -1263,8 +1464,11 @@ START_TEST(test_node_fragment_attr_insert_insert_new_no_status) 0, NULL); ck_assert_int_eq (TRUE, result); - ck_assert_ptr_eq (name, fragment->attrs[0].name); - ck_assert_ptr_eq (value, fragment->attrs[0].value); + ck_assert_ptr_ne (name, fragment->attrs[0].name); + ck_assert_ptr_ne (value, fragment->attrs[0].value); + + ck_assert_str_eq (name, fragment->attrs[0].name); + ck_assert_str_eq (value, fragment->attrs[0].value); /* test - insert before */ name = Attr_get_name (attr1); @@ -1274,8 +1478,11 @@ START_TEST(test_node_fragment_attr_insert_insert_new_no_status) NULL); ck_assert_int_eq (TRUE, result); - ck_assert_ptr_eq (name, fragment->attrs[0].name); - ck_assert_ptr_eq (value, fragment->attrs[0].value); + ck_assert_ptr_ne (name, fragment->attrs[0].name); + ck_assert_ptr_ne (value, fragment->attrs[0].value); + + ck_assert_str_eq (name, fragment->attrs[0].name); + ck_assert_str_eq (value, fragment->attrs[0].value); /* test - insert after */ name = Attr_get_name (attr3); @@ -1285,8 +1492,11 @@ START_TEST(test_node_fragment_attr_insert_insert_new_no_status) NULL); ck_assert_int_eq (TRUE, result); - ck_assert_ptr_eq (name, fragment->attrs[2].name); - ck_assert_ptr_eq (value, fragment->attrs[2].value); + ck_assert_ptr_ne (name, fragment->attrs[2].name); + ck_assert_ptr_ne (value, fragment->attrs[2].value); + + ck_assert_str_eq (name, fragment->attrs[2].name); + ck_assert_str_eq (value, fragment->attrs[2].value); ck_assert_int_eq (3, fragment->attr_n); ck_assert (Attr_is_equal (attr1, &fragment->attrs[0])); @@ -1296,9 +1506,9 @@ START_TEST(test_node_fragment_attr_insert_insert_new_no_status) /* cleanup */ SH_NodeFragment_free (fragment); SH_Data_free (data); - free (attr1); - free (attr2); - free (attr3); + SH_Attr_free (attr1); + SH_Attr_free (attr2); + SH_Attr_free (attr3); } END_TEST @@ -1351,8 +1561,11 @@ START_TEST(test_node_fragment_attr_insert_insert_new_with_status) ck_assert_int_eq (TRUE, result); ck_assert_int_eq (SUCCESS, status.status); - ck_assert_ptr_eq (name, fragment->attrs[0].name); - ck_assert_ptr_eq (value, fragment->attrs[0].value); + ck_assert_ptr_ne (name, fragment->attrs[0].name); + ck_assert_ptr_ne (value, fragment->attrs[0].value); + + ck_assert_str_eq (name, fragment->attrs[0].name); + ck_assert_str_eq (value, fragment->attrs[0].value); /* test - insert before */ name = Attr_get_name (attr1); @@ -1364,8 +1577,11 @@ START_TEST(test_node_fragment_attr_insert_insert_new_with_status) ck_assert_int_eq (TRUE, result); ck_assert_int_eq (SUCCESS, status.status); - ck_assert_ptr_eq (name, fragment->attrs[0].name); - ck_assert_ptr_eq (value, fragment->attrs[0].value); + ck_assert_ptr_ne (name, fragment->attrs[0].name); + ck_assert_ptr_ne (value, fragment->attrs[0].value); + + ck_assert_str_eq (name, fragment->attrs[0].name); + ck_assert_str_eq (value, fragment->attrs[0].value); /* test - insert after */ name = Attr_get_name (attr3); @@ -1377,6 +1593,192 @@ START_TEST(test_node_fragment_attr_insert_insert_new_with_status) ck_assert_int_eq (TRUE, result); ck_assert_int_eq (SUCCESS, status.status); + ck_assert_ptr_ne (name, fragment->attrs[2].name); + ck_assert_ptr_ne (value, fragment->attrs[2].value); + + ck_assert_str_eq (name, fragment->attrs[2].name); + ck_assert_str_eq (value, fragment->attrs[2].value); + + ck_assert_int_eq (3, fragment->attr_n); + ck_assert (Attr_is_equal (attr1, &fragment->attrs[0])); + ck_assert (Attr_is_equal (attr2, &fragment->attrs[1])); + ck_assert (Attr_is_equal (attr3, &fragment->attrs[2])); + + /* cleanup */ + SH_NodeFragment_free (fragment); + SH_Data_free (data); + SH_Attr_free (attr1); + SH_Attr_free (attr2); + SH_Attr_free (attr3); +} +END_TEST + +START_TEST(test_node_fragment_attr_insert_insert_raw_new_no_status) +{ + char * name; + char * value; + SH_Attr * attr1; + SH_Attr * attr2; + SH_Attr * attr3; + SH_Data * data; + SH_NodeFragment * fragment; + bool result; + + /* setup */ + attr1 = SH_Attr_new ("name1", "value1", NULL); + ck_assert_ptr_ne (NULL, attr1); + + attr2 = SH_Attr_new ("name2", "value2", NULL); + ck_assert_ptr_ne (NULL, attr2); + + attr3 = SH_Attr_new ("name3", "value3", NULL); + ck_assert_ptr_ne (NULL, attr3); + + data = SH_Data_new (NULL); + ck_assert_ptr_ne (NULL, data); + + fragment = (SH_NodeFragment *)SH_NodeFragment_new ("html", data, + NULL); + ck_assert_ptr_ne (NULL, fragment); + + /* test - out of bounds */ + name = Attr_get_name (attr1); + value = Attr_get_value (attr1); + + result = SH_NodeFragment_insert_attr_raw_new (fragment, + name, value, 1, + NULL); + ck_assert_int_eq (FALSE, result); + + /* test */ + name = Attr_get_name (attr2); + value = Attr_get_value (attr2); + + result = SH_NodeFragment_insert_attr_raw_new (fragment, + name, value, 0, + NULL); + ck_assert_int_eq (TRUE, result); + + ck_assert_ptr_eq (name, fragment->attrs[0].name); + ck_assert_ptr_eq (value, fragment->attrs[0].value); + + /* test - insert before */ + name = Attr_get_name (attr1); + value = Attr_get_value (attr1); + + result = SH_NodeFragment_prepend_attr_raw_new (fragment, + name, value, + NULL); + ck_assert_int_eq (TRUE, result); + + ck_assert_ptr_eq (name, fragment->attrs[0].name); + ck_assert_ptr_eq (value, fragment->attrs[0].value); + + /* test - insert after */ + name = Attr_get_name (attr3); + value = Attr_get_value (attr3); + + result = SH_NodeFragment_append_attr_raw_new (fragment, + name, value, + NULL); + ck_assert_int_eq (TRUE, result); + + ck_assert_ptr_eq (name, fragment->attrs[2].name); + ck_assert_ptr_eq (value, fragment->attrs[2].value); + + ck_assert_int_eq (3, fragment->attr_n); + ck_assert (Attr_is_equal (attr1, &fragment->attrs[0])); + ck_assert (Attr_is_equal (attr2, &fragment->attrs[1])); + ck_assert (Attr_is_equal (attr3, &fragment->attrs[2])); + + /* cleanup */ + SH_NodeFragment_free (fragment); + SH_Data_free (data); + free (attr1); + free (attr2); + free (attr3); +} +END_TEST + +START_TEST(test_node_fragment_attr_insert_insert_raw_new_with_status) +{ + struct SH_Status status; + char * name; + char * value; + SH_Attr * attr1; + SH_Attr * attr2; + SH_Attr * attr3; + SH_Data * data; + SH_NodeFragment * fragment; + bool result; + + /* setup */ + attr1 = SH_Attr_new ("name1", "value1", NULL); + ck_assert_ptr_ne (NULL, attr1); + + attr2 = SH_Attr_new ("name2", "value2", NULL); + ck_assert_ptr_ne (NULL, attr2); + + attr3 = SH_Attr_new ("name3", "value3", NULL); + ck_assert_ptr_ne (NULL, attr3); + + data = SH_Data_new (NULL); + ck_assert_ptr_ne (NULL, data); + + fragment = (SH_NodeFragment *)SH_NodeFragment_new ("html", data, + NULL); + ck_assert_ptr_ne (NULL, fragment); + + /* test - out of bounds */ + name = Attr_get_name (attr1); + value = Attr_get_value (attr1); + + _status_preinit (status); + result = SH_NodeFragment_insert_attr_raw_new (fragment, + name, value, 1, + &status); + ck_assert_int_eq (FALSE, result); + ck_assert_int_eq (E_VALUE, status.status); + + /* test */ + name = Attr_get_name (attr2); + value = Attr_get_value (attr2); + + _status_preinit (status); + result = SH_NodeFragment_insert_attr_raw_new (fragment, + name, value, 0, + &status); + ck_assert_int_eq (TRUE, result); + ck_assert_int_eq (SUCCESS, status.status); + + ck_assert_ptr_eq (name, fragment->attrs[0].name); + ck_assert_ptr_eq (value, fragment->attrs[0].value); + + /* test - insert before */ + name = Attr_get_name (attr1); + value = Attr_get_value (attr1); + + _status_preinit (status); + result = SH_NodeFragment_prepend_attr_raw_new (fragment, + name, value, + &status); + ck_assert_int_eq (TRUE, result); + ck_assert_int_eq (SUCCESS, status.status); + + ck_assert_ptr_eq (name, fragment->attrs[0].name); + ck_assert_ptr_eq (value, fragment->attrs[0].value); + + /* test - insert after */ + name = Attr_get_name (attr3); + value = Attr_get_value (attr3); + + _status_preinit (status); + result = SH_NodeFragment_append_attr_raw_new (fragment, + name, value, + &status); + ck_assert_int_eq (TRUE, result); + ck_assert_int_eq (SUCCESS, status.status); + ck_assert_ptr_eq (name, fragment->attrs[2].name); ck_assert_ptr_eq (value, fragment->attrs[2].value); @@ -3636,23 +4038,18 @@ START_TEST(test_node_fragment_html_inline_no_status) ck_assert_ptr_ne (NULL, fragment); result = SH_NodeFragment_append_attr_new (fragment, - strdup ("lang"), - strdup ("de"), - NULL); + "lang", "de", NULL); ck_assert_int_eq (TRUE, result); child = SH_NodeFragment_new ("body", data, NULL); ck_assert_ptr_ne (NULL, child); result = SH_NodeFragment_append_attr_new ((SH_NodeFragment *)child, - strdup ("id"), - strdup ("body"), - NULL); + "id", "body", NULL); ck_assert_int_eq (TRUE, result); result = SH_NodeFragment_append_attr_new ((SH_NodeFragment *)child, - strdup ("attr"), - NULL, NULL); + "attr", NULL, NULL); ck_assert_int_eq (TRUE, result); result = SH_NodeFragment_append_child (fragment, child, NULL); @@ -3698,8 +4095,7 @@ START_TEST(test_node_fragment_html_inline_with_status) ck_assert_ptr_ne (NULL, fragment); result = SH_NodeFragment_append_attr_new (fragment, - strdup ("lang"), - strdup ("de"), + "lang", "de", NULL); ck_assert_int_eq (TRUE, result); @@ -3707,14 +4103,12 @@ START_TEST(test_node_fragment_html_inline_with_status) ck_assert_ptr_ne (NULL, child); result = SH_NodeFragment_append_attr_new ((SH_NodeFragment *)child, - strdup ("id"), - strdup ("body"), + "id", "body", NULL); ck_assert_int_eq (TRUE, result); result = SH_NodeFragment_append_attr_new ((SH_NodeFragment *)child, - strdup ("attr"), - NULL, NULL); + "attr", NULL, NULL); ck_assert_int_eq (TRUE, result); result = SH_NodeFragment_append_child (fragment, child, NULL); @@ -3761,8 +4155,7 @@ START_TEST(test_node_fragment_html_wrap_no_status) ck_assert_ptr_ne (NULL, fragment); result = SH_NodeFragment_append_attr_new (fragment, - strdup ("lang"), - strdup ("de"), + "lang", "de", NULL); ck_assert_int_eq (TRUE, result); @@ -3770,14 +4163,12 @@ START_TEST(test_node_fragment_html_wrap_no_status) ck_assert_ptr_ne (NULL, child); result = SH_NodeFragment_append_attr_new ((SH_NodeFragment *)child, - strdup ("id"), - strdup ("body"), + "id", "body", NULL); ck_assert_int_eq (TRUE, result); result = SH_NodeFragment_append_attr_new ((SH_NodeFragment *)child, - strdup ("attr"), - NULL, NULL); + "attr", NULL, NULL); ck_assert_int_eq (TRUE, result); result = SH_NodeFragment_append_child (fragment, child, NULL); @@ -3823,8 +4214,7 @@ START_TEST(test_node_fragment_html_wrap_with_status) ck_assert_ptr_ne (NULL, fragment); result = SH_NodeFragment_append_attr_new (fragment, - strdup ("lang"), - strdup ("de"), + "lang", "de", NULL); ck_assert_int_eq (TRUE, result); @@ -3832,14 +4222,12 @@ START_TEST(test_node_fragment_html_wrap_with_status) ck_assert_ptr_ne (NULL, child); result = SH_NodeFragment_append_attr_new ((SH_NodeFragment *)child, - strdup ("id"), - strdup ("body"), + "id", "body", NULL); ck_assert_int_eq (TRUE, result); result = SH_NodeFragment_append_attr_new ((SH_NodeFragment *)child, - strdup ("attr"), - NULL, NULL); + "attr", NULL, NULL); ck_assert_int_eq (TRUE, result); result = SH_NodeFragment_append_child (fragment, child, NULL); @@ -3895,12 +4283,16 @@ Suite * fragment_suite (void) tcase_add_test (tc_core, test_node_fragment_attr_insert_with_status); tcase_add_test (tc_core, test_node_fragment_attr_insert_new_no_status); tcase_add_test (tc_core, test_node_fragment_attr_insert_new_with_status); + tcase_add_test (tc_core, test_node_fragment_attr_insert_raw_new_no_status); + tcase_add_test (tc_core, test_node_fragment_attr_insert_raw_new_with_status); tcase_add_test (tc_core, test_node_fragment_attr_insert_copy_no_status); tcase_add_test (tc_core, test_node_fragment_attr_insert_copy_with_status); tcase_add_test (tc_core, test_node_fragment_attr_insert_insert_no_status); tcase_add_test (tc_core, test_node_fragment_attr_insert_insert_with_status); tcase_add_test (tc_core, test_node_fragment_attr_insert_insert_new_no_status); tcase_add_test (tc_core, test_node_fragment_attr_insert_insert_new_with_status); + tcase_add_test (tc_core, test_node_fragment_attr_insert_insert_raw_new_no_status); + tcase_add_test (tc_core, test_node_fragment_attr_insert_insert_raw_new_with_status); tcase_add_test (tc_core, test_node_fragment_attr_insert_insert_copy_no_status); tcase_add_test (tc_core, test_node_fragment_attr_insert_insert_copy_with_status); tcase_add_test (tc_core, test_node_fragment_attr_remove1_no_status); -- GitLab