diff --git a/sefht.geany b/sefht.geany index 663751ddb6d2418d84c0c168180fe417a7e7ca6a..0a026ac40541ee526454bbe4981a96f14793e255 100644 --- a/sefht.geany +++ b/sefht.geany @@ -60,7 +60,7 @@ FILE_NAME_27=900;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fpr FILE_NAME_28=1867;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ftext_mark_static.c;0;8 FILE_NAME_29=1798;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator.c;0;8 FILE_NAME_30=24;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator.h;0;8 -FILE_NAME_31=10810;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_tag.c;0;8 +FILE_NAME_31=6351;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_tag.c;0;8 FILE_NAME_32=1148;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_tag.h;0;8 FILE_NAME_33=924;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fstatus.h;0;8 FILE_NAME_34=18;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Flog.h;0;4 @@ -76,7 +76,7 @@ FILE_NAME_43=5714;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fp FILE_NAME_44=24;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_attr.c;0;8 FILE_NAME_45=4221;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_text.c;0;8 FILE_NAME_46=994;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_text_mark.c;0;8 -FILE_NAME_47=6893;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_validator.c;0;8 +FILE_NAME_47=3101;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_validator.c;0;8 FILE_NAME_48=536;None;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftodo.txt;0;8 FILE_NAME_49=201;YAML;0;EUTF-8;0;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2F.gitlab-ci.yml;0;4 FILE_NAME_50=71;Sh;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fgitlab-ci%2Fupload.sh.in;0;8 diff --git a/src/lib/sefht/validator_tag.c b/src/lib/sefht/validator_tag.c index 696bd845095982a0288593c95970082b52ff40f9..4e9aa5428036136d2387536fb1ac2cc2d8d77693 100644 --- a/src/lib/sefht/validator_tag.c +++ b/src/lib/sefht/validator_tag.c @@ -82,10 +82,18 @@ free_tags (/*@special@*/ struct SH_Validator * validator) /*@modifies validator->tags@*/ /*@releases validator->tags@*/; +static inline +bool +find_tag (const struct SH_Validator * validator, + const char * tag, + /*@out@*/ size_t * index) + /*@modifies index@*/; + static inline Tag add_tag (struct SH_Validator * validator, const char * tag, + size_t index, /*@null@*/ /*@out@*/ struct SH_Status * status) /*@modifies validator->tags@*/ /*@modifies validator->tag_n@*/ @@ -119,8 +127,9 @@ get_tag_name_by_id (const struct SH_Validator * validator, Tag id, static inline Tag get_tag_id_by_name (const struct SH_Validator * validator, - const char * name) - /*@*/; + const char * name, + /*@out@*/ size_t * index) + /*@modifies index@*/; static inline bool @@ -242,10 +251,51 @@ free_tags (/*@special@*/ struct SH_Validator * validator) return; } +static inline +bool +find_tag (const struct SH_Validator * validator, + const char * tag, + /*@out@*/ size_t * index) + /*@modifies index@*/ +{ + size_t start; + size_t end; + size_t pivot; + + start = 0; + end = validator->tag_n; + pivot = (end - start) / 2; + + while (start != end) + { + int cmp = strcmp (tag, validator->tags[pivot].name); + + if (0 > cmp) + { + end = pivot; + pivot = (pivot - start) / 2 + start; + } + else if (0 == cmp) + { + *index = pivot; + return TRUE; + } + else + { + start = pivot + 1; + pivot = (end - pivot) / 2 + pivot; + } + } + + *index = start; + return FALSE; +} + static inline Tag add_tag (struct SH_Validator * validator, const char * tag, + size_t index, /*@null@*/ /*@out@*/ struct SH_Status * status) /*@modifies validator->tags@*/ /*@modifies validator->tag_n@*/ @@ -255,7 +305,7 @@ add_tag (struct SH_Validator * validator, /*@modifies status@*/ { Tag tag_id; - size_t index; + char * name; struct tag_info * new_tags; /* abort on overflow: @@ -292,18 +342,23 @@ add_tag (struct SH_Validator * validator, } validator->tags = new_tags; - index = validator->tag_n; tag_id = NEXT_TAG (validator->last_tag); - validator->tags[index].id = tag_id; - validator->tags[index].name = strdup (tag); - - if (NULL == validator->tags[index].name) + name = strdup (tag); + if (NULL == name) { set_status (status, E_ALLOC, 4, "strdup failed"); return TAG_ERR; } + for (size_t index2 = validator->tag_n; index2 > index; index2--) + { + validator->tags[index2] = validator->tags[index2-1]; + } + + validator->tags[index].id = tag_id; + validator->tags[index].name = name; + /* commit changes */ validator->tag_n++; validator->last_tag = tag_id; @@ -337,16 +392,7 @@ is_tag_name (const struct SH_Validator * validator, const char * name) /*@*/ { size_t index; - - for (index = 0; index < validator->tag_n; index++) - { - if (0 == strcmp (name, validator->tags[index].name)) - { - return TRUE; - } - } - - return FALSE; + return find_tag (validator, name, &index); } /*@unused@*/ @@ -385,20 +431,16 @@ get_tag_name_by_id (const struct SH_Validator * validator, Tag id, static inline Tag get_tag_id_by_name (const struct SH_Validator * validator, - const char * name) - /*@*/ + const char * name, + /*@out@*/ size_t * index) + /*@modifies index@*/ { - size_t index; - - for (index = 0; index < validator->tag_n; index++) + if (!find_tag (validator, name, index)) { - if (0 == strcmp (name, validator->tags[index].name)) - { - return validator->tags[index].id; - } + return TAG_ERR; } - return TAG_ERR; + return validator->tags[*index].id; } static inline @@ -487,17 +529,18 @@ SH_Validator_register_tag (struct SH_Validator * validator, /*@modifies fileSystem@*/ /*@modifies status@*/ { + size_t index; Tag tag_id; /* tag already registered */ - tag_id = get_tag_id_by_name (validator, tag); + tag_id = get_tag_id_by_name (validator, tag, &index); if (tag_id != TAG_ERR) { set_success (status); return tag_id; } - return add_tag (validator, tag, status); + return add_tag (validator, tag, index, status); } bool diff --git a/tests/test_validator.c b/tests/test_validator.c index 8ea0e0b1c9f58d06c8102ceae17f89fa876fc411..b6b6b493983fd4771765b2a8cfb1d3a399034ae0 100644 --- a/tests/test_validator.c +++ b/tests/test_validator.c @@ -77,6 +77,9 @@ START_TEST(test_validator_tag_register_no_status) struct SH_Validator * validator; const char * tag1 = "html"; const char * tag2 = "head"; + const char * tag3 = "article"; + const char * tag4 = "p"; + const char * tag5 = "img"; char * tagN; Tag tag; Tag tag_; @@ -105,6 +108,23 @@ START_TEST(test_validator_tag_register_no_status) ck_assert_int_eq (validator->tags[0].id, tag); ck_assert_str_eq (validator->tags[0].name, tag1); + /* test - order */ + tag = SH_Validator_register_tag (validator, tag3, NULL); + ck_assert_int_eq (tag, 2); + + tag = SH_Validator_register_tag (validator, tag4, NULL); + ck_assert_int_eq (tag, 3); + + tag = SH_Validator_register_tag (validator, tag5, NULL); + ck_assert_int_eq (tag, 4); + + ck_assert_int_eq (validator->tag_n, 4); + + ck_assert_str_eq (validator->tags[0].name, tag3); + ck_assert_str_eq (validator->tags[1].name, tag1); + ck_assert_str_eq (validator->tags[2].name, tag5); + ck_assert_str_eq (validator->tags[3].name, tag4); + /* test - overflow detection */ /* make method fail by filling with garbage until * upper boundary is reached */ @@ -154,6 +174,9 @@ START_TEST(test_validator_tag_register_with_status) struct SH_Validator * validator; const char * tag1 = "html"; const char * tag2 = "head"; + const char * tag3 = "article"; + const char * tag4 = "p"; + const char * tag5 = "img"; char * tagN; Tag tag; Tag tag_; @@ -186,6 +209,29 @@ START_TEST(test_validator_tag_register_with_status) ck_assert_int_eq (validator->tags[0].id, tag); ck_assert_str_eq (validator->tags[0].name, tag1); + /* test - order */ + _status_preinit (status); + tag = SH_Validator_register_tag (validator, tag3, &status); + ck_assert_int_eq (tag, 2); + ck_assert_int_eq (status.status, SUCCESS); + + _status_preinit (status); + tag = SH_Validator_register_tag (validator, tag4, &status); + ck_assert_int_eq (tag, 3); + ck_assert_int_eq (status.status, SUCCESS); + + _status_preinit (status); + tag = SH_Validator_register_tag (validator, tag5, &status); + ck_assert_int_eq (tag, 4); + ck_assert_int_eq (status.status, SUCCESS); + + ck_assert_int_eq (validator->tag_n, 4); + + ck_assert_str_eq (validator->tags[0].name, tag3); + ck_assert_str_eq (validator->tags[1].name, tag1); + ck_assert_str_eq (validator->tags[2].name, tag5); + ck_assert_str_eq (validator->tags[3].name, tag4); + /* test - overflow detection */ /* make method fail by filling with garbage until * upper boundary is reached */