diff --git a/sefht.geany b/sefht.geany index 40265944b6ab0c835a98c6774fd97d45973bd514..f6203e0b09db541fb6a81a47e79449af330b834e 100644 --- a/sefht.geany +++ b/sefht.geany @@ -28,38 +28,43 @@ long_line_behaviour=1 long_line_column=72 [files] -current_page=27 +current_page=31 FILE_NAME_0=923;Sh;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fconfigure.ac;0;8 FILE_NAME_1=73;Make;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2FMakefile.am;0;8 FILE_NAME_2=1143;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Fmain.c;0;8 -FILE_NAME_3=1260;Make;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2FMakefile.am;0;8 +FILE_NAME_3=747;Make;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2FMakefile.am;0;8 FILE_NAME_4=1593;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fcms.c;0;8 FILE_NAME_5=901;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fcms.h;0;8 FILE_NAME_6=2921;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fdata.c;0;8 FILE_NAME_7=904;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fdata.h;0;8 -FILE_NAME_8=1185;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ffragment.c;0;8 -FILE_NAME_9=916;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ffragment.h;0;8 -FILE_NAME_10=1975;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_11=2173;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_12=6499;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_13=2517;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=25820;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ftext.c;0;8 -FILE_NAME_15=904;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ftext.h;0;8 -FILE_NAME_16=1779;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator.c;0;8 -FILE_NAME_17=919;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator.h;0;8 -FILE_NAME_18=14237;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_19=859;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_20=4608;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fstatus.h;0;8 -FILE_NAME_21=901;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Flog.h;0;4 -FILE_NAME_22=907;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fmacro.h;0;8 -FILE_NAME_23=1078;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fsefht.h;0;8 -FILE_NAME_24=290;Make;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2FMakefile.am;0;8 -FILE_NAME_25=1085;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_cms.c;0;8 -FILE_NAME_26=3283;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_data.c;0;8 -FILE_NAME_27=8518;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_node_fragment.c;0;8 -FILE_NAME_28=11068;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_text.c;0;8 -FILE_NAME_29=5744;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_validator.c;0;8 -FILE_NAME_30=165;None;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftodo.txt;0;8 +FILE_NAME_8=1550;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ffragment.c;0;8 +FILE_NAME_9=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_10=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_11=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_12=20283;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_13=6032;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=5204;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fattr.c;0;8 +FILE_NAME_15=3030;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fattr.h;0;8 +FILE_NAME_16=3046;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fattr_static.c;0;8 +FILE_NAME_17=1116;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fattr_data.h;0;8 +FILE_NAME_18=25820;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ftext.c;0;8 +FILE_NAME_19=904;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ftext.h;0;8 +FILE_NAME_20=1779;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator.c;0;8 +FILE_NAME_21=919;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator.h;0;8 +FILE_NAME_22=14237;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_23=859;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_24=4735;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fstatus.h;0;8 +FILE_NAME_25=901;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Flog.h;0;4 +FILE_NAME_26=907;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fmacro.h;0;8 +FILE_NAME_27=1078;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fsefht.h;0;8 +FILE_NAME_28=1044;Make;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2FMakefile.am;0;8 +FILE_NAME_29=1085;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_cms.c;0;8 +FILE_NAME_30=3283;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_data.c;0;8 +FILE_NAME_31=63675;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_node_fragment.c;0;8 +FILE_NAME_32=15195;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_attr.c;0;8 +FILE_NAME_33=11068;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_text.c;0;8 +FILE_NAME_34=5744;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_validator.c;0;8 +FILE_NAME_35=165;None;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftodo.txt;0;8 [VTE] last_dir=/home/jonathan/Documents/projects/prgm/internet/web/SeFHT/tests diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 38a43da3fcc74c31cb77038637ad7ba63fcdee93..5f0ad8ba98f668165eb3101eb0814cd161541bc8 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to produce Makefile.in -AM_CFLAGS = -Wall -Wextra -Wno-nonnull +AM_CFLAGS = -Wall -Wextra -Wno-nonnull -flto lib_LTLIBRARIES = libsefht.la @@ -9,6 +9,7 @@ libsefht_la_SOURCES += sefht/sefht.h libsefht_la_SOURCES += sefht/macro.h libsefht_la_SOURCES += sefht/log.h libsefht_la_SOURCES += sefht/status.h +libsefht_la_SOURCES += sefht/attr.c sefht/attr.h libsefht_la_SOURCES += sefht/cms.c sefht/cms.h libsefht_la_SOURCES += sefht/data.c sefht/data.h libsefht_la_SOURCES += sefht/fragment.c sefht/fragment.h @@ -17,6 +18,7 @@ libsefht_la_SOURCES += sefht/text.c sefht/text.h libsefht_la_SOURCES += sefht/validator.c sefht/validator.h EXTRA_DIST = +EXTRA_DIST += sefht/attr_static.c sefht/attr_data.h EXTRA_DIST += sefht/fragment_class.c EXTRA_DIST += sefht/fragment_data.c EXTRA_DIST += sefht/validator_tag.c @@ -26,6 +28,7 @@ nobase_include_HEADERS += sefht/sefht.h nobase_include_HEADERS += sefht/macro.h nobase_include_HEADERS += sefht/log.h nobase_include_HEADERS += sefht/status.h +nobase_include_HEADERS += sefht/attr.h nobase_include_HEADERS += sefht/cms.h nobase_include_HEADERS += sefht/data.h nobase_include_HEADERS += sefht/fragment.h diff --git a/src/lib/sefht/attr.c b/src/lib/sefht/attr.c new file mode 100644 index 0000000000000000000000000000000000000000..db9cad23acf7c7f359aadb0f852f22230a865cbd --- /dev/null +++ b/src/lib/sefht/attr.c @@ -0,0 +1,274 @@ +/* + * attr.c + * + * Copyright 2022 Jonathan Schöbel <jonathan@Ubermos-2019> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * + */ + + +#include <stdlib.h> + +#include "macro.h" +#include "log.h" +#include "status.h" + +#include "attr.h" + + +#include "attr_static.c" + + +/*@null@*/ +/*@only@*/ +struct SH_Attr * +SH_Attr_new (const char * name, + /*@null@*/ const char * value, + /*@null@*/ /*@out@*/ struct SH_Status * status) + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/ +{ + struct SH_Attr * attr; + + attr = malloc (sizeof (struct SH_Attr)); + if (attr == NULL) + { + set_status (status, E_ALLOC, 4, "malloc failed"); + return NULL; + } + + if (!Attr_init (attr, name, value, status)) + { + free (attr); + return NULL; + } + + set_success (status); + return attr; +} + +/*@null@*/ +/*@only@*/ +struct SH_Attr * +SH_Attr_raw_new (/*@only@*/ char * name, + /*@null@*/ /*@only@*/ char * value, + /*@null@*/ /*@out@*/ struct SH_Status * status) + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/ +{ + struct SH_Attr * attr; + + attr = malloc (sizeof (struct SH_Attr)); + if (attr == NULL) + { + set_status (status, E_ALLOC, 4, "malloc failed"); + return NULL; + } + + Attr_raw_init (attr, name, value); + + set_success (status); + return attr; +} + +/*@null@*/ +/*@only@*/ +struct SH_Attr * +SH_Attr_copy (const struct SH_Attr * attr, + /*@null@*/ /*@out@*/ struct SH_Status * status) + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/ +{ + struct SH_Attr * copy; + + copy = malloc (sizeof (struct SH_Attr)); + if (copy == NULL) + { + set_status (status, E_ALLOC, 4, "malloc failed"); + return NULL; + } + + if (!Attr_copy (copy, attr, status)) + { + free (copy); + return NULL; + } + + set_success (status); + return copy; +} + +void +SH_Attr_free (/*@only@*/ struct SH_Attr * attr) + /*@modifies attr->name@*/ + /*@modifies attr->value@*/ + /*@modifies attr@*/ + /*@releases attr@*/ +{ + Attr_free (attr); + free (attr); + return; +} + +/*@null@*/ +/*@only@*/ +char * +SH_Attr_get_name (const struct SH_Attr * attr, + /*@null@*/ /*@out@*/ struct SH_Status * status) + /*@*/ +{ + char * name; + + name = strdup (Attr_get_name (attr)); + if (NULL == name) + { + set_status (status, E_ALLOC, 3, "strdup failed"); + return NULL; + } + + set_success (status); + return name; +} + +bool +SH_Attr_set_name (struct SH_Attr * attr, + const char * name, + /*@null@*/ /*@out@*/ struct SH_Status * status) + /*@modifies attr->name@*/ +{ + char * name_copy; + + name_copy = strdup (name); + if (NULL == name_copy) + { + set_status (status, E_ALLOC, 3, "strdup failed"); + return FALSE; + } + + Attr_set_name (attr, name_copy); + + set_success (status); + return TRUE; +} + +/*@observer@*/ +const char * +SH_Attr_raw_get_name (const struct SH_Attr * attr) + /*@*/ +{ + return Attr_get_name (attr); +} + +void +SH_Attr_raw_set_name (struct SH_Attr * attr, /*@only@*/ char * name) + /*@modifies attr->name@*/ +{ + Attr_set_name (attr, name); + return; +} + +/*@null@*/ +/*@only@*/ +char * +SH_Attr_get_value (const struct SH_Attr * attr, + /*@null@*/ /*@out@*/ struct SH_Status * status) + /*@*/ +{ + char * value; + + if (NULL == Attr_get_value (attr)) + { + set_success (status); + return NULL; + } + + value = strdup (Attr_get_value (attr)); + if (NULL == value) + { + set_status (status, E_ALLOC, 3, "strdup failed"); + return NULL; + } + + set_success (status); + return value; +} + +bool +SH_Attr_set_value (struct SH_Attr * attr, + /*@null@*/ const char * value, + /*@null@*/ /*@out@*/ struct SH_Status * status) + /*@modifies attr->value@*/ +{ + char * value_copy; + + if (NULL == value) + { + value_copy = NULL; + } + else + { + value_copy = strdup (value); + if (NULL == value_copy) + { + set_status (status, E_ALLOC, 3, "strdup failed"); + return FALSE; + } + } + + Attr_set_value (attr, value_copy); + + set_success (status); + return TRUE; +} + +/*@null@*/ +/*@observer@*/ +char * +SH_Attr_raw_get_value (const struct SH_Attr * attr) + /*@*/ +{ + return Attr_get_value (attr); +} + +void +SH_Attr_raw_set_value (struct SH_Attr * attr, + /*@null@*/ /*@only@*/ char * value) + /*@modifies attr->value@*/ +{ + Attr_set_value (attr, value); + return; +} + +bool +SH_Attr_is_equal (const struct SH_Attr * attr1, + const struct SH_Attr * attr2) + /*@*/ +{ + return Attr_is_equal (attr1, attr2); +} + +bool +SH_Attr_is_equal_name (const struct SH_Attr * attr1, + const struct SH_Attr * attr2) + /*@*/ +{ + return Attr_is_equal_name (attr1, attr2); +} diff --git a/src/lib/sefht/attr.h b/src/lib/sefht/attr.h new file mode 100644 index 0000000000000000000000000000000000000000..a5dabc64549c6a618ade89c19f709a6d65e88258 --- /dev/null +++ b/src/lib/sefht/attr.h @@ -0,0 +1,128 @@ +/* + * attr.h + * + * Copyright 2022 Jonathan Schöbel <jonathan@Ubermos-2019> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * + */ + + +#ifndef SEFHT_ATTR_H +#define SEFHT_ATTR_H + +#if !defined (SEFHT_SEFHT_H_INSIDE) && !defined (SEFHT_COMPILATION) +#error "Only <sefht/sefht.h> can be included directly." +#endif + +#include "status.h" + +#include "data.h" + + +typedef /*@abstract@*/ struct SH_Attr SH_Attr; + + +/*@null@*/ +/*@only@*/ +struct SH_Attr * +SH_Attr_new (const char * name, + /*@null@*/ const char * value, + /*@null@*/ /*@out@*/ struct SH_Status * status) + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/; + +/*@null@*/ +/*@only@*/ +struct SH_Attr * +SH_Attr_raw_new (/*@only@*/ char * name, + /*@null@*/ /*@only@*/ char * value, + /*@null@*/ /*@out@*/ struct SH_Status * status) + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/; + +/*@null@*/ +/*@only@*/ +struct SH_Attr * +SH_Attr_copy (const struct SH_Attr * attr, + /*@null@*/ /*@out@*/ struct SH_Status * status) + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/; + +void +SH_Attr_free (/*@only@*/ SH_Attr * attr) + /*@modifies attr@*/ + /*@releases attr@*/; + +/*@null@*/ +/*@only@*/ +char * +SH_Attr_get_name (const SH_Attr * attr, + /*@null@*/ /*@out@*/ struct SH_Status * status) + /*@*/; + +bool +SH_Attr_set_name (SH_Attr * attr, + const char * name, + /*@null@*/ /*@out@*/ struct SH_Status * status) + /*@modifies attr@*/; + +/*@observer@*/ +const char * +SH_Attr_raw_get_name (const SH_Attr * attr) + /*@*/; + +void +SH_Attr_raw_set_name (SH_Attr * attr, /*@only@*/ char * name) + /*@modifies attr@*/; + +/*@null@*/ +/*@only@*/ +char * +SH_Attr_get_value (const SH_Attr * attr, + /*@null@*/ /*@out@*/ struct SH_Status * status) + /*@*/; + +bool +SH_Attr_set_value (SH_Attr * attr, + const char * value, + /*@null@*/ /*@out@*/ struct SH_Status * status) + /*@modifies attr@*/; + +/*@null@*/ +/*@observer@*/ +char * +SH_Attr_raw_get_value (const SH_Attr * attr) + /*@*/; + +void +SH_Attr_raw_set_value (SH_Attr * attr, + /*@null@*/ /*@only@*/ char * value) + /*@modifies attr@*/; + +bool +SH_Attr_is_equal (const SH_Attr * attr1, const SH_Attr * attr2) + /*@*/; + +bool +SH_Attr_is_equal_name (const SH_Attr * attr1, const SH_Attr * attr2) + /*@*/; + +#endif /* SEFHT_ATTR_H */ diff --git a/src/lib/sefht/attr_data.h b/src/lib/sefht/attr_data.h new file mode 100644 index 0000000000000000000000000000000000000000..7870295f90475b6ee680a23fe2c0c60d5ae2f797 --- /dev/null +++ b/src/lib/sefht/attr_data.h @@ -0,0 +1,38 @@ +/* + * attr_data.h + * + * Copyright 2022 Jonathan Schöbel <jonathan@Ubermos-2019> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * + */ + + +#ifndef SEFHT_ATTR_DATA_H +#define SEFHT_ATTR_DATA_H + +#if !defined (SEFHT_SEFHT_H_INSIDE) && !defined (SEFHT_COMPILATION) +#error "Only <sefht/sefht.h> can be included directly." +#endif + +struct SH_Attr +{ + /*@only@*/ char * name; + /*@null@*/ /*@only@*/ char * value; +}; + +#endif /* SEFHT_ATTR_DATA_H */ diff --git a/src/lib/sefht/attr_static.c b/src/lib/sefht/attr_static.c new file mode 100644 index 0000000000000000000000000000000000000000..d160c8479ed8dccbe2bcd07d8a2bc796ed5fb41b --- /dev/null +++ b/src/lib/sefht/attr_static.c @@ -0,0 +1,211 @@ +/* + * attr_static.c + * + * Copyright 2022 Jonathan Schöbel <jonathan@Ubermos-2019> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * + */ + + +#ifndef SEFHT_ATTR_STATIC_C +#define SEFHT_ATTR_STATIC_C + +#if !defined (SEFHT_SEFHT_H_INSIDE) && !defined (SEFHT_COMPILATION) +#error "Only <sefht/sefht.h> can be included directly." +#endif + +#include "attr_data.h" + + +static inline +bool +Attr_init (struct SH_Attr * attr, + const char * name, + /*@null@*/ const char * value, + /*@null@*/ /*@out@*/ struct SH_Status * status) + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/ +{ + attr->name = strdup (name); + if (NULL == attr->name) + { + set_status (status, E_ALLOC, 2, "strdup failed"); + return FALSE; + } + + if (NULL == value) + { + attr->value = NULL; + } + else + { + attr->value = strdup (value); + if (NULL == attr->value) + { + set_status (status, E_ALLOC, 2, + "strdup failed"); + free (attr->name); + return FALSE; + } + } + + return TRUE; +} + +static inline +void +Attr_raw_init (struct SH_Attr * attr, + /*@only@*/ char * name, + /*@null@*/ /*@only@*/ char * value) + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/ +{ + attr->name = name; + attr->value = value; + return; +} + +static inline +bool +Attr_copy (struct SH_Attr * copy, + const struct SH_Attr * attr, + /*@null@*/ /*@out@*/ struct SH_Status * status) + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/ +{ + + copy->name = strdup (attr->name); + if (NULL == copy->name) + { + set_status (status, E_ALLOC, 2, "strdup failed"); + return FALSE; + } + + if (NULL == attr->value) + { + copy->value = NULL; + } + else + { + copy->value = strdup (attr->value); + if (NULL == copy->value) + { + set_status (status, E_ALLOC, 2, + "strdup failed"); + free (copy->name); + return FALSE; + } + } + + return TRUE; +} + +static inline +void +Attr_free (struct SH_Attr * attr) + /*@modifies attr->name@*/ + /*@modifies attr->value@*/ + /*@releases attr->name@*/ + /*@releases attr->value@*/ +{ + free (attr->name); + if (NULL != attr->value) free (attr->value); + return; +} + +static inline +void +Attr_move (struct SH_Attr * dest, + struct SH_Attr * src) + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/ +{ + + dest->name = src->name; + dest->value = src->value; + free (src); + return; +} + +static inline +/*@observer@*/ +char * +Attr_get_name (const struct SH_Attr * attr) + /*@*/ +{ + return attr->name; +} + +static inline +void +Attr_set_name (struct SH_Attr * attr, char * name) + /*@modifies attr->name@*/ +{ + free (attr->name); + attr->name = name; + return; +} + +static inline +/*@null@*/ +/*@observer@*/ +char * +Attr_get_value (const struct SH_Attr * attr) +{ + return attr->value; +} + +static inline +void +Attr_set_value (struct SH_Attr * attr, /*@null@*/ /*@only@*/ char * value) +{ + if (NULL != attr->value) + { + free (attr->value); + } + + attr->value = value; + return; +} + +static inline +bool +Attr_is_equal (const struct SH_Attr * attr1, + const struct SH_Attr * attr2) + /*@*/ +{ + if (0 != strcmp (attr1->name, attr2->name)) return FALSE; + if (NULL == attr1->value) return (NULL == attr2->value); + if (NULL == attr2->value) return FALSE; + return (0 == strcmp (attr1->value, attr2->value)); +} + +static inline +bool +Attr_is_equal_name (const struct SH_Attr * attr1, + const struct SH_Attr * attr2) + /*@*/ +{ + return (0 == strcmp (attr1->name, attr2->name)); +} + +#endif /* SEFHT_ATTR_STATIC_C */ diff --git a/src/lib/sefht/fragment.c b/src/lib/sefht/fragment.c index 6a306bd388983053c8d14ed6a0d5fd9f9de15a57..72d4707f6988aff1cd2058cdc3cc2993fa42f257 100644 --- a/src/lib/sefht/fragment.c +++ b/src/lib/sefht/fragment.c @@ -27,11 +27,12 @@ #include "status.h" #include "text.h" +#include "node_fragment.h" #include "fragment.h" -#include "fragment_data.c" +#include "fragment_class.c" /*@null@*/ /*@only@*/ @@ -54,6 +55,13 @@ SH_Fragment_free (/*@only@*/ struct SH_Fragment * fragment) return; } +bool +SH_Fragment_is_orphan (const struct SH_Fragment * fragment) + /*@*/ +{ + return get_parent (fragment) == NULL; +} + /*@null@*/ /*@only@*/ SH_Text * diff --git a/src/lib/sefht/fragment.h b/src/lib/sefht/fragment.h index f2602e810ed359ed3ab32df60a59dab440952aa0..b55542c1b508536d0f7c30c5a401b52e8dbf1306 100644 --- a/src/lib/sefht/fragment.h +++ b/src/lib/sefht/fragment.h @@ -58,6 +58,10 @@ SH_Fragment_free (/*@only@*/ SH_Fragment * fragment) /*@modifies fragment@*/ /*@releases fragment@*/; +bool +SH_Fragment_is_orphan (const SH_Fragment * fragment) + /*@*/; + /*@null@*/ /*@only@*/ SH_Text * diff --git a/src/lib/sefht/fragment_class.c b/src/lib/sefht/fragment_class.c index 3a478d1f017f5d57b0554c92f921e7dc0b6eaeeb..8fd9a412c2790cf2c2e6f1c409eb40287e6732ec 100644 --- a/src/lib/sefht/fragment_class.c +++ b/src/lib/sefht/fragment_class.c @@ -41,18 +41,24 @@ static inline void init_fragment (/*@out@*/ struct SH_Fragment * fragment, - /*@dependent@*/ SH_Data * data, const enum SH_FRAGMENT_TYPE type, /*@shared@*/ - const struct fragment_methods * const methods) - /*@modifies fragment->data@*/ + const struct fragment_methods * const methods, + /*@dependent@*/ SH_Data * data, + /*@null@*/ /*@dependent@*/ + struct SH_NodeFragment * parent) /*@modifies fragment->type@*/ /*@modifies fragment->methods@*/ + /*@modifies fragment->data@*/ + /*@modifies fragment->parent@*/ { - fragment->data = data; fragment->type = type; fragment->methods = methods; + fragment->data = data; + + fragment->parent = parent; + return; } @@ -70,14 +76,18 @@ static inline void copy_fragment (/*@out@*/ struct SH_Fragment * copy, const struct SH_Fragment * fragment) - /*@modifies copy->data@*/ /*@modifies copy->type@*/ /*@modifies copy->methods@*/ + /*@modifies copy->data@*/ + /*@modifies copy->parent@*/ { - copy->data = fragment->data; copy->type = fragment->type; copy->methods = fragment->methods; + copy->data = fragment->data; + + copy->parent = NULL; + return; } @@ -89,5 +99,24 @@ get_type (const struct SH_Fragment * fragment) return fragment->type; } +static inline +/*@null@*/ +/*@dependent@*/ +struct SH_NodeFragment * +get_parent (const struct SH_Fragment * fragment) +{ + return fragment->parent; +} + +static inline +void +set_parent (struct SH_Fragment * fragment, + /*@null@*/ /*@dependent@*/ struct SH_NodeFragment * parent) + /*@modifies fragment->parent@*/ +{ + fragment->parent = parent; + return; +} + #endif /* SEFHT_COMPILATION */ #endif /* SEFHT_FRAGMENT_CLASS_C */ diff --git a/src/lib/sefht/fragment_data.c b/src/lib/sefht/fragment_data.c index f55a71c764e29281f9b748ea258d97aab6b7aa31..617f62990e75c5386956fdf888c100734c2debfb 100644 --- a/src/lib/sefht/fragment_data.c +++ b/src/lib/sefht/fragment_data.c @@ -76,10 +76,12 @@ struct fragment_methods struct SH_Fragment { - /*@dependent@*/ SH_Data * data; - enum SH_FRAGMENT_TYPE type; /*@shared@*/ const struct fragment_methods * methods; + + /*@dependent@*/ SH_Data * data; + + /*@null@*/ /*@dependent@*/ struct SH_NodeFragment * parent; }; #endif /* SEFHT_COMPILATION */ diff --git a/src/lib/sefht/node_fragment.c b/src/lib/sefht/node_fragment.c index fdf5c788f7fb8f6989b33bccada71a6bc347c5e0..be8777156ebedb14dd1d6caff8759a92bcd8fcdd 100644 --- a/src/lib/sefht/node_fragment.c +++ b/src/lib/sefht/node_fragment.c @@ -31,6 +31,7 @@ #include "log.h" #include "status.h" +#include "attr_static.c" #include "data.h" #include "text.h" #include "validator.h" @@ -42,14 +43,23 @@ #include "fragment_class.c" +#define CHILD_CHUNK 5 +#define ATTR_CHUNK 5 + + struct SH_NodeFragment { struct SH_Fragment base; - char * tag; + /*@only@*/ char * tag; + + size_t attr_s; /* allocated size */ + size_t attr_n; /* real size */ + /*@only@*/ struct SH_Attr * attrs; - size_t child_n; - struct SH_Fragment ** childs; + size_t child_s; /* allocated size */ + size_t child_n; /* real size */ + /*@only@*/ struct SH_Fragment ** childs; }; #define OPEN_TAG_BEGIN "<" @@ -77,6 +87,53 @@ static const struct fragment_methods methods = { }; +static inline +size_t +get_child_alloc_size (size_t size) + /*@*/ +{ + /* underflow */ + if (size == 0) + { + return 0; + } + /* overflow */ + else if (((SIZE_MAX / CHILD_CHUNK) - 1) + < ((size - 1) / CHILD_CHUNK)) + { + return SIZE_MAX; + } + /* calculate the number of needed chunks */ + else + { + return CHILD_CHUNK * (((size - 1) / CHILD_CHUNK) + 1); + } +} + +static inline +size_t +get_attr_alloc_size (size_t size) + /*@*/ +{ + /* underflow */ + if (size == 0) + { + return 0; + } + /* overflow */ + else if (((SIZE_MAX / ATTR_CHUNK) - 1) + < ((size - 1) / ATTR_CHUNK)) + { + return SIZE_MAX; + } + /* calculate the number of needed chunks */ + else + { + return ATTR_CHUNK * (((size - 1) / ATTR_CHUNK) + 1); + } +} + + /*@null@*/ /*@only@*/ struct SH_Fragment /*@alt struct SH_NodeFragment@*/ * @@ -100,7 +157,7 @@ SH_NodeFragment_new (const char * tag, return NULL; } - init_fragment (&(fragment->base), data, NODE, &methods); + init_fragment (&(fragment->base), NODE, &methods, data, NULL); fragment->tag = strdup (tag); if (fragment->tag == NULL) @@ -115,6 +172,51 @@ SH_NodeFragment_new (const char * tag, } + fragment->attr_s = 0; + fragment->attr_n = 0; + fragment->attrs = malloc (0); + + fragment->child_s = 0; + fragment->child_n = 0; + fragment->childs = malloc (0); + + set_success (status); + + return (struct SH_Fragment *) fragment; +} + +/*@null@*/ +/*@only@*/ +struct SH_Fragment /*@alt struct SH_NodeFragment@*/ * +SH_NodeFragment_raw_new (/*@only@*/ char * tag, + /*@dependent@*/ SH_Data * data, + /*@out@*/ /*@null@*/ struct SH_Status * status) + /*@globals NODE, + fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/ +{ + struct SH_NodeFragment * fragment; + + fragment = malloc (sizeof (struct SH_NodeFragment)); + if (fragment == NULL) + { + set_status (status, E_ALLOC, 3, + "Memory allocation for " + "SH_NodeFragment failed.\n"); + + return NULL; + } + + init_fragment (&(fragment->base), NODE, &methods, data, NULL); + + fragment->tag = tag; + + fragment->attr_s = 0; + fragment->attr_n = 0; + fragment->attrs = malloc (0); + + fragment->child_s = 0; fragment->child_n = 0; fragment->childs = malloc (0); @@ -132,6 +234,12 @@ SH_NodeFragment_free (/*@only@*/ struct SH_NodeFragment * fragment) free (fragment->tag); + for (index = 0; index < fragment->attr_n; index++) + { + Attr_free (&fragment->attrs[index]); + } + free (fragment->attrs); + for (index = 0; index < fragment->child_n; index++) { SH_Fragment_free (fragment->childs[index]); @@ -155,6 +263,7 @@ SH_NodeFragment_copy (const struct SH_NodeFragment * fragment, /*@modifies status@*/ { struct SH_NodeFragment * copy; + size_t index; copy = malloc (sizeof (struct SH_NodeFragment)); if (copy == NULL) @@ -168,6 +277,7 @@ SH_NodeFragment_copy (const struct SH_NodeFragment * fragment, copy_fragment (&(copy->base), &(fragment->base)); + /* copy tag */ copy->tag = strdup (fragment->tag); if (copy->tag == NULL) { @@ -180,7 +290,44 @@ SH_NodeFragment_copy (const struct SH_NodeFragment * fragment, return NULL; } + /* copy attributes */ + copy->attr_n = fragment->attr_n; + copy->attr_s = get_attr_alloc_size (fragment->attr_n); + copy->attrs = malloc (copy->attr_s * sizeof (*copy->attrs)); + + if (copy->attr_s != 0 && copy->attrs == NULL) + { + set_status (status, E_ALLOC, 5, "malloc failed\n"); + + free (copy->tag); +/* dangerous call to silence splint, should never be executed. */ +#ifdef S_SPLINT_S + free (copy->attrs); +#endif + free (copy); + + return NULL; + } + + for (index = 0; index < fragment->attr_n; index++) + { + if (!Attr_copy (©->attrs[index], + &fragment->attrs[index], + status)) + { + while (index > 0) + { + index--; + Attr_free (©->attrs[index]); + } + + free (copy); + return NULL; + } + } + /* don't copy childs */ + copy->child_s = 0; copy->child_n = 0; copy->childs = malloc (0); @@ -215,6 +362,7 @@ SH_NodeFragment_deepcopy (const struct SH_NodeFragment * fragment, copy_fragment (&(copy->base), &(fragment->base)); + /* copy tag */ copy->tag = strdup (fragment->tag); if (copy->tag == NULL) { @@ -227,12 +375,48 @@ SH_NodeFragment_deepcopy (const struct SH_NodeFragment * fragment, return NULL; } + /* copy attributes */ + copy->attr_n = fragment->attr_n; + copy->attr_s = get_attr_alloc_size (fragment->attr_n); + copy->attrs = malloc (copy->attr_s * sizeof (*copy->attrs)); + + if (copy->attr_s != 0 && copy->attrs == NULL) + { + set_status (status, E_ALLOC, 5, "malloc failed\n"); + + free (copy->tag); +/* dangerous call to silence splint, should never be executed. */ +#ifdef S_SPLINT_S + free (copy->attrs); +#endif + free (copy); + + return NULL; + } + + for (index = 0; index < fragment->attr_n; index++) + { + if (!Attr_copy (©->attrs[index], + &fragment->attrs[index], + status)) + { + while (index > 0) + { + index--; + Attr_free (©->attrs[index]); + } + + free (copy); + return NULL; + } + } + /* copy childs */ copy->child_n = fragment->child_n; - copy->childs = malloc (sizeof (struct SH_NodeFragment *) - * fragment->child_n); + copy->child_s = get_child_alloc_size (fragment->child_n); + copy->childs = malloc (copy->child_s * sizeof (*copy->childs)); - if (copy->child_n != 0 && copy->childs == NULL) + if (copy->child_s != 0 && copy->childs == NULL) { set_status (status, E_ALLOC, 5, "Memory allocation for " @@ -262,6 +446,7 @@ SH_NodeFragment_deepcopy (const struct SH_NodeFragment * fragment, } copy->childs[index] = child; + child->parent = copy; } set_success (status); @@ -276,6 +461,15 @@ SH_Fragment_is_NodeFragment (const struct SH_Fragment * fragment) return get_type (fragment) == NODE; } +static inline +/*@observer@*/ +char * +get_tag (const struct SH_NodeFragment * fragment) + /*@*/ +{ + return fragment->tag; +} + /*@null@*/ /*@only@*/ char * @@ -287,7 +481,7 @@ SH_NodeFragment_get_tag (const struct SH_NodeFragment * fragment, { char * tag; - tag = strdup (fragment->tag); + tag = strdup (get_tag (fragment)); if (tag == NULL) { @@ -303,109 +497,892 @@ SH_NodeFragment_get_tag (const struct SH_NodeFragment * fragment, return tag; } +/*@observer@*/ +char * +SH_NodeFragment_raw_get_tag (const struct SH_NodeFragment * fragment) +{ + return get_tag (fragment); +} + +/*@null@*/ +/*@dependent@*/ +struct SH_NodeFragment * +SH_Fragment_get_parent (const struct SH_Fragment * fragment) + /*@*/ +{ + return get_parent (fragment); +} + +size_t +SH_NodeFragment_count_attrs (const struct SH_NodeFragment * fragment) + /*@*/ +{ + return fragment->attr_n; +} + /*@null@*/ /*@observer@*/ -const struct SH_Fragment * -SH_NodeFragment_get_child (const struct SH_NodeFragment * fragment, - size_t index, - /*@out@*/ /*@null@*/ - struct SH_Status * status) +const SH_Attr * +SH_NodeFragment_get_attr (const struct SH_NodeFragment * fragment, + size_t index, + /*@out@*/ /*@null@*/ + struct SH_Status * status) /*@globals fileSystem@*/ /*@modifies fileSystem@*/ /*@modifies status@*/ { - if (index >= fragment->child_n) + if (index >= fragment->attr_n) { set_status (status, E_VALUE, 2, - "Fragment: Child index out of range.\n"); + "Fragment: Attr index out of range.\n"); return NULL; } set_success (status); - return fragment->childs[index]; + return &(fragment->attrs[index]); } +static inline bool -SH_NodeFragment_is_child (const struct SH_NodeFragment * fragment, - const struct SH_Fragment * child) - /*@*/ +insert_attr (struct SH_NodeFragment * fragment, + /*@only@*/ SH_Attr * attr, + size_t position, + /*@out@*/ /*@null@*/ struct SH_Status * status) + /*@modifies fragment->attrs@*/ + /*@modifies fragment->attr_s@*/ + /*@modifies fragment->attr_n@*/ + /*@modifies attr@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/ { + size_t new_size; size_t index; + typeof (fragment->attrs) new_attrs; - for (index = 0; index < fragment->child_n; index++) + new_size = get_attr_alloc_size (fragment->attr_n + 1); + if (new_size > fragment->attr_s) { - if (fragment->childs[index] == child) + if ((SIZE_MAX / sizeof (*new_attrs)) < new_size) { - return TRUE; + set_status (status, E_DOMAIN, -6, + "maximum number of " + "attrs reached.\n"); + 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 + return FALSE; } + + fragment->attrs = new_attrs; + fragment->attr_s = new_size; } - return FALSE; + + 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 -SH_NodeFragment_is_descendant (const struct SH_NodeFragment * fragment, - const struct SH_Fragment * child) - /*@*/ +insert_attr_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@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/ { + size_t new_size; size_t index; + typeof (fragment->attrs) new_attrs; - for (index = 0; index < fragment->child_n; index++) + new_size = get_attr_alloc_size (fragment->attr_n + 1); + if (new_size > fragment->attr_s) { - if (fragment->childs[index] == child - || (SH_Fragment_is_NodeFragment (child) - && SH_NodeFragment_is_descendant ( - (struct SH_NodeFragment *) - fragment->childs[index], - child))) + if ((SIZE_MAX / sizeof (*new_attrs)) < new_size) { - return TRUE; + set_status (status, E_DOMAIN, -6, + "maximum number of " + "attrs reached.\n"); + 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 + return FALSE; } + + fragment->attrs = new_attrs; + fragment->attr_s = new_size; } - return FALSE; + + for (index = fragment->attr_n; index > position; index--) + { + fragment->attrs[index] = fragment->attrs[index-1]; + } + Attr_raw_init (&(fragment->attrs[position]), name, value); + fragment->attr_n++; + + set_success (status); + + return TRUE; } +static inline bool -SH_NodeFragment_append_child (struct SH_NodeFragment * fragment, - /*@only@*/ struct SH_Fragment * child, - /*@out@*/ /*@null@*/ - struct SH_Status * status) - /*@modifies fragment->childs@*/ - /*@modifies fragment->child_n@*/ +insert_attr_copy (struct SH_NodeFragment * fragment, + const SH_Attr * attr, + 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@*/ { - struct SH_Fragment ** new_childs; - - new_childs = realloc (fragment->childs, - sizeof (struct SH_Fragment *) - * (fragment->child_n + 1)); + size_t new_size; + size_t index; + typeof (fragment->attrs) new_attrs; - if (new_childs == NULL) + new_size = get_attr_alloc_size (fragment->attr_n + 1); + if (new_size > fragment->attr_s) { - set_status (status, E_ALLOC, 6, - "Memory allocation for " - "fragment child failed.\n"); + if ((SIZE_MAX / sizeof (*new_attrs)) < new_size) + { + set_status (status, E_DOMAIN, -6, + "maximum number of " + "attrs reached.\n"); + 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->childs = (void *) 0x12345; + fragment->attrs = (void *) 0x12345; #endif - return FALSE; + return FALSE; + } + + fragment->attrs = new_attrs; + fragment->attr_s = new_size; } - new_childs[fragment->child_n] = child; + for (index = fragment->attr_n; index > position; index--) + { + fragment->attrs[index] = fragment->attrs[index-1]; + } - fragment->childs = new_childs; - fragment->child_n++; + if (!Attr_copy (&(fragment->attrs[position]), attr, status)) + { + for (index = position; index < fragment->attr_n; index++) + { + fragment->attrs[index] = fragment->attrs[index+1]; + } + return FALSE; + } + + fragment->attr_n++; set_success (status); return TRUE; } +bool +SH_NodeFragment_insert_attr (struct SH_NodeFragment * fragment, + /*@only@*/ SH_Attr * attr, + 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 (fragment, attr, position, status); +} + +bool +SH_NodeFragment_insert_attr_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_new (fragment, name, value, position, status); +} + +bool +SH_NodeFragment_insert_attr_copy (struct SH_NodeFragment * fragment, + const SH_Attr * attr, + 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_copy (fragment, attr, position, status); +} + +bool +SH_NodeFragment_prepend_attr (struct SH_NodeFragment * fragment, + /*@only@*/ SH_Attr * attr, + /*@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 (fragment, attr, 0, status); +} + +bool +SH_NodeFragment_prepend_attr_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_new (fragment, name, value, 0, status); +} + +bool +SH_NodeFragment_prepend_attr_copy (struct SH_NodeFragment * fragment, + const SH_Attr * attr, + /*@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_copy (fragment, attr, 0, status); +} + +bool +SH_NodeFragment_append_attr (struct SH_NodeFragment * fragment, + /*@only@*/ SH_Attr * attr, + /*@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 (fragment, attr, fragment->attr_n, status); +} + +bool +SH_NodeFragment_append_attr_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_new (fragment, name, value, + fragment->attr_n, status); +} + +bool +SH_NodeFragment_append_attr_copy (struct SH_NodeFragment * fragment, + const SH_Attr * attr, + /*@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_copy (fragment, attr, fragment->attr_n, + status); +} + +size_t +SH_NodeFragment_count_childs (const struct SH_NodeFragment * fragment) + /*@*/ +{ + return fragment->child_n; +} + +/*@null@*/ +/*@observer@*/ +const struct SH_Fragment * +SH_NodeFragment_get_child (const struct SH_NodeFragment * fragment, + size_t index, + /*@out@*/ /*@null@*/ + struct SH_Status * status) + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/ +{ + if (index >= fragment->child_n) + { + set_status (status, E_VALUE, 2, + "Fragment: Child index out of range.\n"); + + return NULL; + } + + set_success (status); + + return fragment->childs[index]; +} + +bool +SH_NodeFragment_is_child (const struct SH_NodeFragment * fragment, + const struct SH_Fragment * child) + /*@*/ +{ + size_t index; + + for (index = 0; index < fragment->child_n; index++) + { + if (fragment->childs[index] == child) + { + return TRUE; + } + } + return FALSE; +} + +bool +SH_NodeFragment_is_descendant (const struct SH_NodeFragment * fragment, + const struct SH_Fragment * child) + /*@*/ +{ + size_t index; + + for (index = 0; index < fragment->child_n; index++) + { + if (fragment->childs[index] == child + || (SH_Fragment_is_NodeFragment (child) + && SH_NodeFragment_is_descendant ( + (struct SH_NodeFragment *) + fragment->childs[index], + child))) + { + return TRUE; + } + } + return FALSE; +} + +bool +SH_NodeFragment_is_parent (const struct SH_Fragment * fragment, + const struct SH_NodeFragment * parent) + /*@*/ +{ + if (parent == get_parent (fragment)) + { + return TRUE; + } + + return FALSE; +} + +bool +SH_NodeFragment_is_ancestor (const struct SH_Fragment * fragment, + const struct SH_NodeFragment * ancestor) + /*@*/ +{ + if ((NULL != get_parent (fragment)) + && ((ancestor == get_parent (fragment)) + || (SH_NodeFragment_is_ancestor ((const struct SH_Fragment *) + get_parent (fragment), + ancestor)))) + { + return TRUE; + } + + return FALSE; +} + +static inline +bool +insert_child (struct SH_NodeFragment * fragment, + /*@only@*/ struct SH_Fragment * child, + size_t position, + /*@out@*/ /*@null@*/ struct SH_Status * status) + /*@modifies fragment->childs@*/ + /*@modifies fragment->child_s@*/ + /*@modifies fragment->child_n@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/ +{ + size_t new_size; + size_t index; + struct SH_Fragment ** new_childs; + + if (!SH_Fragment_is_orphan (child)) + { + set_status (status, E_STATE, 2, + "child is already linked; " + "please unlink first or link a copy.\n"); + return FALSE; + } + + if (SH_Fragment_is_NodeFragment (child) + && SH_NodeFragment_is_ancestor ((struct SH_Fragment *)fragment, + (struct SH_NodeFragment *)child)) + { + set_status (status, E_STATE, 2, + "refusing to make a tree cyclic.\n"); + return FALSE; + } + + new_size = get_child_alloc_size (fragment->child_n + 1); + if (new_size > fragment->child_s) + { + if ((SIZE_MAX / sizeof (*new_childs)) < new_size) + { + set_status (status, E_DOMAIN, -6, + "maximum number of " + "childs reached.\n"); + return FALSE; + } + + new_childs = realloc (fragment->childs, new_size + * sizeof (*new_childs)); + + if (new_childs == NULL) + { + set_status (status, E_ALLOC, 5, + "Memory allocation for " + "fragment child failed.\n"); + +/* bad code to silence splint, should never be executed. */ +#ifdef S_SPLINT_S + fragment->childs = (void *) 0x12345; +#endif + return FALSE; + } + + fragment->childs = new_childs; + fragment->child_s = new_size; + } + + for (index = fragment->child_n; index > position; index--) + { + fragment->childs[index] = fragment->childs[index-1]; + } + fragment->childs[position] = child; + fragment->child_n++; + child->parent = fragment; + + set_success (status); + + return TRUE; +} + +bool +SH_NodeFragment_insert_child (struct SH_NodeFragment * fragment, + /*@only@*/ struct SH_Fragment * child, + size_t position, + /*@out@*/ /*@null@*/ + struct SH_Status * status) + /*@modifies fragment->childs@*/ + /*@modifies fragment->child_s@*/ + /*@modifies fragment->child_n@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/ +{ + if (position > fragment->child_n) + { + set_status (status, E_VALUE, 2, + "index out of range.\n"); + return FALSE; + } + + return insert_child (fragment, child, position, status); +} + +bool +SH_NodeFragment_prepend_child (struct SH_NodeFragment * fragment, + /*@only@*/ struct SH_Fragment * child, + /*@out@*/ /*@null@*/ + struct SH_Status * status) + /*@modifies fragment->childs@*/ + /*@modifies fragment->child_s@*/ + /*@modifies fragment->child_n@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/ +{ + return insert_child (fragment, child, 0, status); +} + +bool +SH_NodeFragment_append_child (struct SH_NodeFragment * fragment, + /*@only@*/ struct SH_Fragment * child, + /*@out@*/ /*@null@*/ + struct SH_Status * status) + /*@modifies fragment->childs@*/ + /*@modifies fragment->child_s@*/ + /*@modifies fragment->child_n@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/ +{ + return insert_child (fragment, child, fragment->child_n, status); +} + +bool +SH_NodeFragment_insert_child_before (struct SH_Fragment * fragment, + /*@only@*/ + struct SH_Fragment * child, + /*@out@*/ /*@null@*/ + struct SH_Status * status) + /*@modifies fragment->childs@*/ + /*@modifies fragment->child_s@*/ + /*@modifies fragment->child_n@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/ +{ + size_t index; + + #define parent get_parent (fragment) + if (NULL == parent) + { + set_status (status, E_STATE, 2, + "child is not linked, " + "can't insert before.\n"); + return FALSE; + } + + for (index = 0; index < parent->child_n; index++) + { + if (parent->childs[index] == fragment) + { + return insert_child (parent, child, + index, status); + } + } + #undef parent + + set_status (status, E_BUG, 10, + "fragment is both child and not child.\n"); + return FALSE; +} + +bool +SH_NodeFragment_insert_child_after (struct SH_Fragment * fragment, + /*@only@*/ + struct SH_Fragment * child, + /*@out@*/ /*@null@*/ + struct SH_Status * status) + /*@modifies fragment->childs@*/ + /*@modifies fragment->child_s@*/ + /*@modifies fragment->child_n@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/ +{ + size_t index; + + #define parent get_parent (fragment) + if (NULL == parent) + { + set_status (status, E_STATE, 2, + "child is not linked, " + "can't insert before.\n"); + return FALSE; + } + + for (index = 0; index < parent->child_n; index++) + { + if (parent->childs[index] == fragment) + { + return insert_child (parent, child, + index+1, status); + } + } + #undef parent + + set_status (status, E_BUG, 10, + "fragment is both child and not child.\n"); + return FALSE; +} + +static inline +/*@null@*/ +/*@only@*/ +struct SH_Fragment * +remove_child (struct SH_NodeFragment * fragment, size_t position, + /*@out@*/ /*@null@*/ struct SH_Status * status) +{ + size_t index; + size_t new_size; + typeof (fragment->childs) new_childs; + struct SH_Fragment * child; + + child = fragment->childs[position]; + + for (index = position+1; index < fragment->child_n; index++) + { + fragment->childs[index-1] = fragment->childs[index]; + } + + new_size = get_child_alloc_size (fragment->child_n - 1); + if (new_size < fragment->child_s) + { + new_childs = realloc (fragment->childs, new_size + * sizeof (*new_childs)); + if ((0 != new_size) && (NULL == new_childs)) + { + for (index = fragment->child_n-1; + index > position; + index--) + { + fragment->childs[index] = + fragment->childs[index-1]; + } + fragment->childs[position] = child; + + set_status (status, E_ALLOC, 4, + "realloc failed.\n"); + return NULL; + } + + fragment->childs = new_childs; + fragment->child_s = new_size; + } + + fragment->child_n--; + child->parent = NULL; + + set_success (status); + + return child; +} + +bool +SH_Fragment_remove (struct SH_Fragment * fragment, + /*@out@*/ /*@null@*/ struct SH_Status * status) +{ + size_t index; + + #define parent get_parent (fragment) + if (NULL == parent) + { + set_status (status, E_STATE, 2, + "fragment not linked, " + "can't remove it from parent"); + return FALSE; + } + + for (index = 0; index < parent->child_n; index++) + { + if (fragment == parent->childs[index]) + { + return NULL != remove_child (parent, index, + status); + } + } + #undef parent + + set_status (status, E_BUG, 10, + "fragment is both child and not child.\n"); + return FALSE; +} + +bool +SH_Fragment_delete (/*@only@*/ struct SH_Fragment * fragment, + /*@out@*/ /*@null@*/ struct SH_Status * status) +{ + size_t index; + + #define parent get_parent (fragment) + if (NULL == parent) + { + set_status (status, E_STATE, 2, + "fragment not linked, " + "can't remove it from parent"); + return FALSE; + } + + for (index = 0; index < parent->child_n; index++) + { + if (fragment == parent->childs[index]) + { + if (NULL == remove_child (parent, index, status)) + { + return FALSE; + } + + SH_Fragment_free (fragment); + return TRUE; + } + } + #undef parent + + set_status (status, E_BUG, 10, + "fragment is both child and not child.\n"); + return FALSE; +} + +bool +SH_NodeFragment_remove_child (struct SH_NodeFragment * fragment, + size_t position, + /*@out@*/ /*@null@*/ + struct SH_Status * status) +{ + if (position >= fragment->child_n) + { + set_status (status, E_VALUE, 2, + "index out of range.\n"); + return FALSE; + } + + return NULL != remove_child (fragment, position, status); +} + +bool +SH_NodeFragment_delete_child (struct SH_NodeFragment * fragment, + size_t position, + /*@out@*/ /*@null@*/ + struct SH_Status * status) +{ + struct SH_Fragment * child; + + if (position >= fragment->child_n) + { + set_status (status, E_VALUE, 2, + "index out of range.\n"); + return FALSE; + } + + child = remove_child (fragment, position, status); + if (NULL == child) + { + return FALSE; + } + + SH_Fragment_free (child); + return TRUE; +} + +/*@null@*/ +/*@only@*/ +struct SH_Fragment * +SH_NodeFragment_pop_child (struct SH_NodeFragment * fragment, + size_t position, + /*@out@*/ /*@null@*/ + struct SH_Status * status) +{ + if (position >= fragment->child_n) + { + set_status (status, E_VALUE, 2, + "index out of range.\n"); + return NULL; + } + + return remove_child (fragment, position, status); +} + /*@null@*/ /*@only@*/ struct SH_Text * diff --git a/src/lib/sefht/node_fragment.h b/src/lib/sefht/node_fragment.h index d9c540486fa3201a690e1432e9e58f81569a886b..eb07c6e711f93f152fa50e9b02fdf2ac51da3aa7 100644 --- a/src/lib/sefht/node_fragment.h +++ b/src/lib/sefht/node_fragment.h @@ -31,6 +31,7 @@ #include "status.h" +#include "attr.h" #include "data.h" #include "text.h" @@ -80,6 +81,122 @@ bool SH_Fragment_is_NodeFragment (const SH_Fragment * fragment) /*@*/; +/*@null@*/ +/*@dependent@*/ +SH_NodeFragment * +SH_Fragment_get_parent (const SH_Fragment * fragment) + /*@*/; + +size_t +SH_NodeFragment_count_attrs (const SH_NodeFragment * fragment) + /*@*/; + +/*@null@*/ +/*@observer@*/ +const SH_Attr * +SH_NodeFragment_get_attr (const SH_NodeFragment * fragment, + size_t index, + /*@out@*/ /*@null@*/ + struct SH_Status * status) + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/; + +bool +SH_NodeFragment_insert_attr (SH_NodeFragment * fragment, + /*@only@*/ SH_Attr * attr, + size_t position, + /*@out@*/ /*@null@*/ + struct SH_Status * status) + /*@modifies fragment@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/; + +bool +SH_NodeFragment_insert_attr_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, + size_t position, + /*@out@*/ /*@null@*/ + struct SH_Status * status) + /*@modifies fragment@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/; + +bool +SH_NodeFragment_prepend_attr (SH_NodeFragment * fragment, + /*@only@*/ SH_Attr * attr, + /*@out@*/ /*@null@*/ + struct SH_Status * status) + /*@modifies fragment@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/; + +bool +SH_NodeFragment_prepend_attr_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, + /*@out@*/ /*@null@*/ + struct SH_Status * status) + /*@modifies fragment@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/; + +bool +SH_NodeFragment_append_attr (SH_NodeFragment * fragment, + /*@only@*/ SH_Attr * attr, + /*@out@*/ /*@null@*/ + struct SH_Status * status) + /*@modifies fragment@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/; + +bool +SH_NodeFragment_append_attr_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, + /*@out@*/ /*@null@*/ + struct SH_Status * status) + /*@modifies fragment@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/; + /*@null@*/ /*@only@*/ char * @@ -106,13 +223,44 @@ SH_NodeFragment_is_child (const SH_NodeFragment * fragment, /*@*/; bool -SH_NodeFragment_is_descendant (const struct SH_NodeFragment * fragment, - const struct SH_Fragment * child) +SH_NodeFragment_is_descendant (const SH_NodeFragment * fragment, + const SH_Fragment * child) /*@*/; bool -SH_NodeFragment_append_child (struct SH_NodeFragment * fragment, - /*@only@*/ struct SH_Fragment * child, +SH_NodeFragment_is_parent (const SH_Fragment * fragment, + const SH_NodeFragment * parent) + /*@*/; + +bool +SH_NodeFragment_is_ancestor (const SH_Fragment * fragment, + const SH_NodeFragment * ancestor) + /*@*/; + +bool +SH_NodeFragment_insert_child (SH_NodeFragment * fragment, + /*@only@*/ SH_Fragment * child, + size_t position, + /*@out@*/ /*@null@*/ + struct SH_Status * status) + /*@modifies fragment@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/; + +bool +SH_NodeFragment_prepend_child (SH_NodeFragment * fragment, + /*@only@*/ SH_Fragment * child, + /*@out@*/ /*@null@*/ + struct SH_Status * status) + /*@modifies fragment@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/; + +bool +SH_NodeFragment_append_child (SH_NodeFragment * fragment, + /*@only@*/ SH_Fragment * child, /*@out@*/ /*@null@*/ struct SH_Status * status) /*@modifies fragment@*/ @@ -120,6 +268,54 @@ SH_NodeFragment_append_child (struct SH_NodeFragment * fragment, /*@modifies fileSystem@*/ /*@modifies status@*/; +bool +SH_NodeFragment_insert_child_before (SH_Fragment * fragment, + /*@only@*/ SH_Fragment * child, + /*@out@*/ /*@null@*/ + struct SH_Status * status) + /*@modifies fragment@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/; + +bool +SH_NodeFragment_insert_child_after (SH_Fragment * fragment, + /*@only@*/ SH_Fragment * child, + /*@out@*/ /*@null@*/ + struct SH_Status * status) + /*@modifies fragment@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/; + +bool +SH_Fragment_remove (SH_Fragment * fragment, + /*@out@*/ /*@null@*/ struct SH_Status * status); + +bool +SH_Fragment_delete (/*@only@*/ SH_Fragment * fragment, + /*@out@*/ /*@null@*/ struct SH_Status * status); + +bool +SH_NodeFragment_remove_child (SH_NodeFragment * fragment, + size_t position, + /*@out@*/ /*@null@*/ + struct SH_Status * status); + +bool +SH_NodeFragment_delete_child (SH_NodeFragment * fragment, + size_t position, + /*@out@*/ /*@null@*/ + struct SH_Status * status); + +/*@null@*/ +/*@only@*/ +SH_Fragment * +SH_NodeFragment_pop_child (SH_NodeFragment * fragment, + size_t position, + /*@out@*/ /*@null@*/ + struct SH_Status * status); + /*@null@*/ /*@only@*/ SH_Text * diff --git a/src/lib/sefht/status.h b/src/lib/sefht/status.h index 4b4b479ee2b7fb623f650127ab686e3b939f49ae..8ee1a364449c950c09bde844073b6ddbd8d69d90 100644 --- a/src/lib/sefht/status.h +++ b/src/lib/sefht/status.h @@ -112,7 +112,9 @@ struct SH_Status SUCCESS, E_ALLOC, E_DOMAIN, - E_VALUE + E_VALUE, + E_STATE, + E_BUG } status; int errno_; diff --git a/tests/Makefile.am b/tests/Makefile.am index 3053a22bd19ee3328a38ac7e9d429706061654b2..9c28186773ea6669c96f9261eaf5971394e6bb1d 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -3,6 +3,7 @@ AM_CFLAGS = -Wall -Wextra -Wno-nonnull $(CHECK_CFLAGS) TESTS = +TESTS += sefht_attr_test TESTS += sefht_cms_test TESTS += sefht_data_test TESTS += sefht_node_fragment_test @@ -18,6 +19,10 @@ LDADD = $(CHECK_LIBS) OBJECT_PREFIX = $(top_builddir)/src/lib/sefht/libsefht_la- +sefht_attr_test_SOURCES = test_attr.c +sefht_attr_test_LDADD = +sefht_attr_test_LDADD += $(LDADD) + sefht_cms_test_SOURCES = test_cms.c sefht_cms_test_LDADD = sefht_cms_test_LDADD += $(OBJECT_PREFIX)data.o @@ -31,6 +36,7 @@ sefht_data_test_LDADD += $(LDADD) sefht_node_fragment_test_SOURCES = test_node_fragment.c sefht_node_fragment_test_LDADD = +sefht_node_fragment_test_LDADD += $(OBJECT_PREFIX)attr.o sefht_node_fragment_test_LDADD += $(OBJECT_PREFIX)data.o sefht_node_fragment_test_LDADD += $(OBJECT_PREFIX)fragment.o sefht_node_fragment_test_LDADD += $(OBJECT_PREFIX)text.o diff --git a/tests/test_attr.c b/tests/test_attr.c new file mode 100644 index 0000000000000000000000000000000000000000..f4d20bad2e31d0ace2281c18fabf1dacf3dc07da --- /dev/null +++ b/tests/test_attr.c @@ -0,0 +1,634 @@ +/* + * test_attr.c + * + * Copyright 2022 Jonathan Schöbel <jonathan@Ubermos-2019> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * + */ + + +#include <check.h> +#include <stdlib.h> + +#include "status.h" + +#include "attr.c" + + +START_TEST(test_attr1_no_status) +{ + struct SH_Attr * attr; + const char * name = "name"; + + attr = SH_Attr_new (name, NULL, NULL); + ck_assert_ptr_ne (NULL, attr); + ck_assert_ptr_ne (name, attr->name); + ck_assert_str_eq (name, attr->name); + ck_assert_ptr_eq (NULL, attr->value); + + SH_Attr_free (attr); +} +END_TEST + +START_TEST(test_attr1_with_status) +{ + struct SH_Status status; + struct SH_Attr * attr; + const char * name = "name"; + + _status_preinit (status); + attr = SH_Attr_new (name, NULL, &status); + ck_assert_ptr_ne (NULL, attr); + ck_assert (succeed (&status)); + ck_assert_ptr_ne (name, attr->name); + ck_assert_str_eq (name, attr->name); + ck_assert_ptr_eq (NULL, attr->value); + + SH_Attr_free (attr); +} +END_TEST + +START_TEST(test_attr2_no_status) +{ + struct SH_Attr * attr; + const char * name = "name"; + const char * value = "value"; + + attr = SH_Attr_new (name, value, NULL); + ck_assert_ptr_ne (NULL, attr); + ck_assert_ptr_ne (name, attr->name); + ck_assert_str_eq (name, attr->name); + ck_assert_ptr_ne (value, attr->value); + ck_assert_str_eq (value, attr->value); + + SH_Attr_free (attr); +} +END_TEST + +START_TEST(test_attr2_with_status) +{ + struct SH_Status status; + struct SH_Attr * attr; + const char * name = "name"; + const char * value = "value"; + + _status_preinit (status); + attr = SH_Attr_new (name, value, &status); + ck_assert_ptr_ne (NULL, attr); + ck_assert (succeed (&status)); + ck_assert_ptr_ne (name, attr->name); + ck_assert_str_eq (name, attr->name); + ck_assert_ptr_ne (value, attr->value); + ck_assert_str_eq (value, attr->value); + + SH_Attr_free (attr); +} +END_TEST + +START_TEST(test_attr_raw1_no_status) +{ + struct SH_Attr * attr; + char * name = strdup ("name"); + + attr = SH_Attr_raw_new (name, NULL, NULL); + ck_assert_ptr_ne (NULL, attr); + ck_assert_ptr_eq (name, attr->name); + ck_assert_ptr_eq (NULL, attr->value); + + SH_Attr_free (attr); +} +END_TEST + +START_TEST(test_attr_raw1_with_status) +{ + struct SH_Status status; + struct SH_Attr * attr; + char * name = strdup ("name"); + + _status_preinit (status); + attr = SH_Attr_raw_new (name, NULL, &status); + ck_assert_ptr_ne (NULL, attr); + ck_assert (succeed (&status)); + ck_assert_ptr_eq (name, attr->name); + ck_assert_ptr_eq (NULL, attr->value); + + SH_Attr_free (attr); +} +END_TEST + +START_TEST(test_attr_raw2_no_status) +{ + struct SH_Attr * attr; + char * name = strdup ("name"); + char * value = strdup ("value"); + + attr = SH_Attr_raw_new (name, value, NULL); + ck_assert_ptr_ne (NULL, attr); + ck_assert_ptr_eq (name, attr->name); + ck_assert_ptr_eq (value, attr->value); + + SH_Attr_free (attr); +} +END_TEST + +START_TEST(test_attr_raw2_with_status) +{ + struct SH_Status status; + struct SH_Attr * attr; + char * name = strdup ("name"); + char * value = strdup ("value"); + + _status_preinit (status); + attr = SH_Attr_raw_new (name, value, &status); + ck_assert_ptr_ne (NULL, attr); + ck_assert (succeed (&status)); + ck_assert_ptr_eq (name, attr->name); + ck_assert_ptr_eq (value, attr->value); + + SH_Attr_free (attr); +} +END_TEST + +START_TEST(test_attr_copy1_no_status) +{ + struct SH_Attr * attr; + struct SH_Attr * copy; + const char * name = "name"; + + attr = SH_Attr_new (name, NULL, NULL); + + copy = SH_Attr_copy (attr, NULL); + ck_assert_ptr_ne (NULL, copy); + ck_assert_ptr_ne (attr->name, copy->name); + ck_assert_str_eq (attr->name, copy->name); + ck_assert_ptr_eq (NULL, copy->value); + + SH_Attr_free (attr); + SH_Attr_free (copy); +} +END_TEST + +START_TEST(test_attr_copy1_with_status) +{ + struct SH_Status status; + struct SH_Attr * attr; + struct SH_Attr * copy; + const char * name = "name"; + + attr = SH_Attr_new (name, NULL, NULL); + + _status_preinit (status); + copy = SH_Attr_copy (attr, &status); + ck_assert_ptr_ne (NULL, copy); + ck_assert (succeed (&status)); + ck_assert_ptr_ne (attr->name, copy->name); + ck_assert_str_eq (attr->name, copy->name); + ck_assert_ptr_eq (NULL, copy->value); + + SH_Attr_free (attr); + SH_Attr_free (copy); +} +END_TEST + +START_TEST(test_attr_copy2_no_status) +{ + struct SH_Attr * attr; + struct SH_Attr * copy; + const char * name = "name"; + const char * value = "value"; + + attr = SH_Attr_new (name, value, NULL); + + copy = SH_Attr_copy (attr, NULL); + ck_assert_ptr_ne (NULL, copy); + ck_assert_ptr_ne (attr->name, copy->name); + ck_assert_str_eq (attr->name, copy->name); + ck_assert_ptr_ne (attr->value, copy->value); + ck_assert_str_eq (attr->value, copy->value); + + SH_Attr_free (attr); + SH_Attr_free (copy); +} +END_TEST + +START_TEST(test_attr_copy2_with_status) +{ + struct SH_Status status; + struct SH_Attr * attr; + struct SH_Attr * copy; + const char * name = "name"; + const char * value = "value"; + + attr = SH_Attr_new (name, value, NULL); + + _status_preinit (status); + copy = SH_Attr_copy (attr, &status); + ck_assert_ptr_ne (NULL, copy); + ck_assert (succeed (&status)); + ck_assert_ptr_ne (attr->name, copy->name); + ck_assert_str_eq (attr->name, copy->name); + ck_assert_ptr_ne (attr->value, copy->value); + ck_assert_str_eq (attr->value, copy->value); + + SH_Attr_free (attr); + SH_Attr_free (copy); +} +END_TEST + +START_TEST(test_attr_name_no_status) +{ + struct SH_Attr * attr; + const char * name1 = "name1"; + const char * name2 = "name2"; + char * name; + bool result; + + attr = SH_Attr_new (name1, NULL, NULL); + ck_assert_ptr_ne (NULL, attr); + ck_assert_ptr_ne (name1, attr->name); + ck_assert_str_eq (name1, attr->name); + + name = SH_Attr_get_name (attr, NULL); + ck_assert_ptr_ne (NULL, name); + ck_assert_ptr_ne (name1, name); + ck_assert_str_eq (name1, name); + free (name); + + result = SH_Attr_set_name (attr, name2, NULL); + ck_assert_int_eq (TRUE, result); + ck_assert_ptr_ne (name2, attr->name); + ck_assert_str_eq (name2, attr->name); + + name = SH_Attr_get_name (attr, NULL); + ck_assert_ptr_ne (NULL, name); + ck_assert_ptr_ne (name2, name); + ck_assert_str_eq (name2, name); + free (name); + + SH_Attr_free (attr); +} +END_TEST + +START_TEST(test_attr_name_with_status) +{ + struct SH_Status status; + struct SH_Attr * attr; + const char * name1 = "name1"; + const char * name2 = "name2"; + char * name; + bool result; + + _status_preinit (status); + attr = SH_Attr_new (name1, NULL, &status); + ck_assert_ptr_ne (NULL, attr); + ck_assert (succeed (&status)); + ck_assert_ptr_ne (name1, attr->name); + ck_assert_str_eq (name1, attr->name); + + _status_preinit (status); + name = SH_Attr_get_name (attr, &status); + ck_assert_ptr_ne (NULL, name); + ck_assert (succeed (&status)); + ck_assert_ptr_ne (name1, name); + ck_assert_str_eq (name1, name); + free (name); + + _status_preinit (status); + result = SH_Attr_set_name (attr, name2, &status); + ck_assert_int_eq (TRUE, result); + ck_assert (succeed (&status)); + ck_assert_ptr_ne (name2, attr->name); + ck_assert_str_eq (name2, attr->name); + + _status_preinit (status); + name = SH_Attr_get_name (attr, &status); + ck_assert_ptr_ne (NULL, name); + ck_assert (succeed (&status)); + ck_assert_ptr_ne (name2, name); + ck_assert_str_eq (name2, name); + free (name); + + SH_Attr_free (attr); +} +END_TEST + +START_TEST(test_attr_name_raw) +{ + struct SH_Attr * attr; + char * name1 = strdup ("name1"); + char * name2 = strdup ("name2"); + const char * name; + + attr = SH_Attr_raw_new (name1, NULL, NULL); + ck_assert_ptr_ne (NULL, attr); + ck_assert_ptr_eq (name1, attr->name); + + name = SH_Attr_raw_get_name (attr); + ck_assert_ptr_ne (NULL, name); + ck_assert_ptr_eq (name1, name); + + SH_Attr_raw_set_name (attr, name2); + ck_assert_ptr_eq (name2, attr->name); + + name = SH_Attr_raw_get_name (attr); + ck_assert_ptr_ne (NULL, name); + ck_assert_ptr_eq (name2, name); + + SH_Attr_free (attr); +} +END_TEST + +START_TEST(test_attr_value_no_status) +{ + struct SH_Attr * attr; + const char * name = "name"; + const char * value1 = "value1"; + const char * value2 = "value2"; + char * value; + bool result; + + attr = SH_Attr_new (name, NULL, NULL); + ck_assert_ptr_ne (NULL, attr); + ck_assert_ptr_eq (NULL, attr->value); + + value = SH_Attr_get_value (attr, NULL); + ck_assert_ptr_eq (NULL, value); + + result = SH_Attr_set_value (attr, value1, NULL); + ck_assert_int_eq (TRUE, result); + ck_assert_ptr_ne (value1, attr->value); + ck_assert_str_eq (value1, attr->value); + + value = SH_Attr_get_value (attr, NULL); + ck_assert_ptr_ne (NULL, value); + ck_assert_ptr_ne (value1, value); + ck_assert_str_eq (value1, value); + free (value); + + result = SH_Attr_set_value (attr, value2, NULL); + ck_assert_int_eq (TRUE, result); + ck_assert_ptr_ne (value2, attr->value); + ck_assert_str_eq (value2, attr->value); + + SH_Attr_free (attr); +} +END_TEST + +START_TEST(test_attr_value_with_status) +{ + struct SH_Status status; + struct SH_Attr * attr; + const char * name = "name"; + const char * value1 = "value1"; + const char * value2 = "value2"; + char * value; + bool result; + + _status_preinit (status); + attr = SH_Attr_new (name, NULL, &status); + ck_assert_ptr_ne (NULL, attr); + ck_assert (succeed (&status)); + ck_assert_ptr_eq (NULL, attr->value); + + _status_preinit (status); + value = SH_Attr_get_value (attr, &status); + ck_assert_ptr_eq (NULL, value); + ck_assert (succeed (&status)); + + _status_preinit (status); + result = SH_Attr_set_value (attr, value1, &status); + ck_assert_int_eq (TRUE, result); + ck_assert (succeed (&status)); + ck_assert_ptr_ne (value1, attr->value); + ck_assert_str_eq (value1, attr->value); + + _status_preinit (status); + value = SH_Attr_get_value (attr, &status); + ck_assert_ptr_ne (NULL, value); + ck_assert (succeed (&status)); + ck_assert_ptr_ne (value1, value); + ck_assert_str_eq (value1, value); + free (value); + + _status_preinit (status); + result = SH_Attr_set_value (attr, value2, &status); + ck_assert_int_eq (TRUE, result); + ck_assert (succeed (&status)); + ck_assert_ptr_ne (value2, attr->value); + ck_assert_str_eq (value2, attr->value); + + SH_Attr_free (attr); +} +END_TEST + +START_TEST(test_attr_value_raw) +{ + struct SH_Attr * attr; + char * name = strdup ("name"); + char * value1 = strdup ("value1"); + char * value2 = strdup ("value2"); + const char * value; + + attr = SH_Attr_raw_new (name, NULL, NULL); + ck_assert_ptr_ne (NULL, attr); + ck_assert_ptr_eq (NULL, attr->value); + + value = SH_Attr_raw_get_value (attr); + ck_assert_ptr_eq (NULL, value); + + SH_Attr_raw_set_value (attr, value1); + ck_assert_ptr_eq (value1, attr->value); + + value = SH_Attr_raw_get_value (attr); + ck_assert_ptr_ne (NULL, value); + ck_assert_ptr_eq (value1, value); + + SH_Attr_raw_set_value (attr, value2); + ck_assert_ptr_eq (value2, attr->value); + + SH_Attr_free (attr); +} +END_TEST + +START_TEST(test_attr_equal) +{ + struct + { + struct + { + char * name; + char * value; + } _[2]; + bool result; + } tests[] = + { + {{{"name", NULL}, {"name", NULL}}, TRUE}, + {{{"name", "value"}, {"name", NULL}}, FALSE}, + {{{"name", "value"}, {"name", "value"}}, TRUE}, + {{{"name", "value1"}, {"name", "value2"}}, FALSE}, + {{{"name1", NULL}, {"name2", NULL}}, FALSE}, + {{{"name1", "value"}, {"name2", NULL}}, FALSE}, + {{{"name1", "value"}, {"name2", "value"}}, FALSE}, + {{{"name1", "value1"}, {"name2", "value2"}}, FALSE} + }; + const size_t size = sizeof (tests) / sizeof (tests[0]); + size_t index; + + for (index = 0; index < size; index++) + { + struct SH_Attr * attr1; + struct SH_Attr * attr2; + bool result; + + attr1 = SH_Attr_new (tests[index]._[0].name, + tests[index]._[0].value, NULL); + ck_assert_ptr_ne (NULL, attr1); + + attr2 = SH_Attr_new (tests[index]._[1].name, + tests[index]._[1].value, NULL); + ck_assert_ptr_ne (NULL, attr2); + + result = SH_Attr_is_equal (attr1, attr2); + ck_assert_int_eq (result, tests[index].result); + + result = SH_Attr_is_equal (attr2, attr1); + ck_assert_int_eq (result, tests[index].result); + + result = Attr_is_equal (attr1, attr2); + ck_assert_int_eq (result, tests[index].result); + + result = Attr_is_equal (attr2, attr1); + ck_assert_int_eq (result, tests[index].result); + + SH_Attr_free (attr1); + SH_Attr_free (attr2); + } +} + +START_TEST(test_attr_equal_name) +{ + struct + { + struct + { + char * name; + char * value; + } _[2]; + bool result; + } tests[] = + { + {{{"name", NULL}, {"name", NULL}}, TRUE}, + {{{"name", "value"}, {"name", NULL}}, TRUE}, + {{{"name", "value"}, {"name", "value"}}, TRUE}, + {{{"name", "value1"}, {"name", "value2"}}, TRUE}, + {{{"name1", NULL}, {"name2", NULL}}, FALSE}, + {{{"name1", "value"}, {"name2", NULL}}, FALSE}, + {{{"name1", "value"}, {"name2", "value"}}, FALSE}, + {{{"name1", "value1"}, {"name2", "value2"}}, FALSE} + }; + const size_t size = sizeof (tests) / sizeof (tests[0]); + size_t index; + + for (index = 0; index < size; index++) + { + struct SH_Attr * attr1; + struct SH_Attr * attr2; + bool result; + + attr1 = SH_Attr_new (tests[index]._[0].name, + tests[index]._[0].value, NULL); + ck_assert_ptr_ne (NULL, attr1); + + attr2 = SH_Attr_new (tests[index]._[1].name, + tests[index]._[1].value, NULL); + ck_assert_ptr_ne (NULL, attr2); + + result = SH_Attr_is_equal_name (attr1, attr2); + ck_assert_int_eq (result, tests[index].result); + + result = SH_Attr_is_equal_name (attr2, attr1); + ck_assert_int_eq (result, tests[index].result); + + result = Attr_is_equal_name (attr1, attr2); + ck_assert_int_eq (result, tests[index].result); + + result = Attr_is_equal_name (attr2, attr1); + ck_assert_int_eq (result, tests[index].result); + + SH_Attr_free (attr1); + SH_Attr_free (attr2); + } +} + +Suite * test_suite (void) +{ + Suite *s; + TCase *tc_core; + + s = suite_create ("Testsuite SeFHT Attr"); + + /* Core test case */ + tc_core = tcase_create ("Core"); + + tcase_add_test (tc_core, test_attr1_no_status); + tcase_add_test (tc_core, test_attr1_with_status); + tcase_add_test (tc_core, test_attr2_no_status); + tcase_add_test (tc_core, test_attr2_with_status); + + tcase_add_test (tc_core, test_attr_raw1_no_status); + tcase_add_test (tc_core, test_attr_raw1_with_status); + tcase_add_test (tc_core, test_attr_raw2_no_status); + tcase_add_test (tc_core, test_attr_raw2_with_status); + + tcase_add_test (tc_core, test_attr_copy1_no_status); + tcase_add_test (tc_core, test_attr_copy1_with_status); + tcase_add_test (tc_core, test_attr_copy2_no_status); + tcase_add_test (tc_core, test_attr_copy2_with_status); + + tcase_add_test (tc_core, test_attr_name_no_status); + tcase_add_test (tc_core, test_attr_name_with_status); + tcase_add_test (tc_core, test_attr_name_raw); + + tcase_add_test (tc_core, test_attr_value_no_status); + tcase_add_test (tc_core, test_attr_value_with_status); + tcase_add_test (tc_core, test_attr_value_raw); + + tcase_add_test (tc_core, test_attr_equal); + tcase_add_test (tc_core, test_attr_equal_name); + + suite_add_tcase (s, tc_core); + + return s; +} + +int main (void) +{ + int number_failed; + Suite *s; + SRunner *sr; + + s = test_suite (); + sr = srunner_create (s); + + srunner_run_all (sr, CK_NORMAL); + number_failed = srunner_ntests_failed (sr); + srunner_free (sr); + + return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} + diff --git a/tests/test_node_fragment.c b/tests/test_node_fragment.c index 95ce707330f77fa8c9622d9b19ab370715e9373d..43fd79f7f5ab5110c10e88009f83671e4c4ea931 100644 --- a/tests/test_node_fragment.c +++ b/tests/test_node_fragment.c @@ -32,213 +32,367 @@ #include "node_fragment.c" -START_TEST(test_node_fragment) +START_TEST(test_node_fragment_no_status) { - struct SH_Status status; - struct SH_Fragment * fragment; - struct SH_Data * data; + struct SH_NodeFragment * fragment; + SH_Data * data; const char * tag = "tag"; data = SH_Data_new (NULL); - /* valid tag - no error */ - fragment = SH_NodeFragment_new (tag, data, NULL); - ck_assert_int_ne ((long int) fragment, (long int) NULL); + fragment = (struct SH_NodeFragment *) + SH_NodeFragment_new (tag, data, NULL); - ck_assert_str_eq (((struct SH_NodeFragment *) fragment)->tag, tag); + ck_assert_ptr_ne (NULL, fragment); - SH_Fragment_free (fragment); + ck_assert_ptr_eq (NULL, fragment->base.parent); + ck_assert_str_eq (fragment->tag, tag); + + ck_assert_int_eq (0, fragment->attr_n); + ck_assert_int_eq (0, fragment->attr_s); + + ck_assert_int_eq (0, fragment->child_n); + ck_assert_int_eq (0, fragment->child_s); + + SH_NodeFragment_free (fragment); + + SH_Data_free (data); +} +END_TEST + +START_TEST(test_node_fragment_with_status) +{ + struct SH_Status status; + struct SH_NodeFragment * fragment; + SH_Data * data; + const char * tag = "tag"; + + data = SH_Data_new (NULL); - /* valid tag - error */ _status_preinit (status); - fragment = SH_NodeFragment_new (tag, data, &status); - ck_assert_int_ne ((long int) fragment, (long int) NULL); - ck_assert_int_eq (status.status, SUCCESS); + fragment = (struct SH_NodeFragment *) + SH_NodeFragment_new (tag, data, &status); - ck_assert_str_eq (((struct SH_NodeFragment *) fragment)->tag, tag); + ck_assert_ptr_ne (NULL, fragment); + ck_assert (succeed (&status)); - SH_Fragment_free (fragment); + ck_assert_ptr_eq (NULL, fragment->base.parent); + ck_assert_str_eq (fragment->tag, tag); + + ck_assert_int_eq (0, fragment->attr_n); + ck_assert_int_eq (0, fragment->attr_s); + + ck_assert_int_eq (0, fragment->child_n); + ck_assert_int_eq (0, fragment->child_s); + + SH_NodeFragment_free (fragment); + + SH_Data_free (data); +} +END_TEST + +START_TEST(test_node_fragment_raw_no_status) +{ + struct SH_NodeFragment * fragment; + SH_Data * data; + char * tag = strdup ("tag"); + + data = SH_Data_new (NULL); + + fragment = (struct SH_NodeFragment *) + SH_NodeFragment_raw_new (tag, data, NULL); + + ck_assert_ptr_ne (NULL, fragment); + + ck_assert_ptr_eq (NULL, fragment->base.parent); + ck_assert_ptr_eq (fragment->tag, tag); + + ck_assert_int_eq (0, fragment->attr_n); + ck_assert_int_eq (0, fragment->attr_s); + + ck_assert_int_eq (0, fragment->child_n); + ck_assert_int_eq (0, fragment->child_s); + + SH_NodeFragment_free (fragment); SH_Data_free (data); } END_TEST -START_TEST(test_node_fragment_copy) +START_TEST(test_node_fragment_raw_with_status) { struct SH_Status status; - struct SH_Fragment * fragment; - struct SH_Fragment * copy; - struct SH_Data * data; + struct SH_NodeFragment * fragment; + SH_Data * data; + char * tag = strdup ("tag"); data = SH_Data_new (NULL); - fragment = SH_NodeFragment_new ("html", data, NULL); + _status_preinit (status); + fragment = (struct SH_NodeFragment *) + SH_NodeFragment_raw_new (tag, data, &status); - /* without error */ - copy = SH_NodeFragment_copy (((struct SH_NodeFragment *) fragment), - NULL); + ck_assert_ptr_ne (NULL, fragment); + ck_assert (succeed (&status)); + + ck_assert_ptr_eq (NULL, fragment->base.parent); + ck_assert_ptr_eq (fragment->tag, tag); + + ck_assert_int_eq (0, fragment->attr_n); + ck_assert_int_eq (0, fragment->attr_s); + + ck_assert_int_eq (0, fragment->child_n); + ck_assert_int_eq (0, fragment->child_s); + + SH_NodeFragment_free (fragment); + + SH_Data_free (data); +} +END_TEST + +START_TEST(test_node_fragment_copy_no_status) +{ + struct SH_NodeFragment * fragment; + struct SH_NodeFragment * copy; + SH_Data * data; + + data = SH_Data_new (NULL); + + fragment = (struct SH_NodeFragment *) + SH_NodeFragment_new ("html", data, NULL); + + copy = (struct SH_NodeFragment *) + SH_NodeFragment_copy (fragment, NULL); ck_assert_ptr_ne (copy, NULL); ck_assert_ptr_ne (fragment, copy); - ck_assert_str_eq (((struct SH_NodeFragment *) fragment)->tag, - ((struct SH_NodeFragment *) copy)->tag); - ck_assert_int_eq (((struct SH_NodeFragment *) copy)->child_n, 0); - ck_assert_ptr_ne (((struct SH_NodeFragment *) fragment)->childs, - ((struct SH_NodeFragment *) copy)->childs); + ck_assert_ptr_eq (NULL, copy->base.parent); + ck_assert_str_eq (fragment->tag, copy->tag); + ck_assert_int_eq (0, copy->attr_n); + ck_assert_int_eq (0, copy->attr_s); + ck_assert_int_eq (0, copy->child_n); + ck_assert_int_eq (0, copy->child_s); + ck_assert_ptr_ne (NULL, copy->childs); - SH_Fragment_free (copy); + SH_NodeFragment_free (fragment); + SH_NodeFragment_free (copy); + + SH_Data_free (data); +} +END_TEST + +START_TEST(test_node_fragment_copy_with_status) +{ + struct SH_Status status; + struct SH_NodeFragment * fragment; + struct SH_NodeFragment * copy; + SH_Data * data; + + data = SH_Data_new (NULL); + + fragment = (struct SH_NodeFragment *) + SH_NodeFragment_new ("html", data, NULL); - /* with error */ _status_preinit (status); - copy = SH_NodeFragment_copy (((struct SH_NodeFragment *) fragment), - &status); - ck_assert_int_eq (status.status, SUCCESS); + copy = (struct SH_NodeFragment *) + SH_NodeFragment_copy (fragment, &status); + ck_assert (succeed (&status)); ck_assert_ptr_ne (copy, NULL); ck_assert_ptr_ne (fragment, copy); - ck_assert_str_eq (((struct SH_NodeFragment *) fragment)->tag, - ((struct SH_NodeFragment *) copy)->tag); - ck_assert_int_eq (((struct SH_NodeFragment *) copy)->child_n, 0); - ck_assert_ptr_ne (((struct SH_NodeFragment *) fragment)->childs, - ((struct SH_NodeFragment *) copy)->childs); + ck_assert_ptr_eq (NULL, copy->base.parent); + ck_assert_str_eq (fragment->tag, copy->tag); + ck_assert_int_eq (0, copy->attr_n); + ck_assert_int_eq (0, copy->attr_s); + ck_assert_int_eq (0, copy->child_n); + ck_assert_int_eq (0, copy->child_s); + ck_assert_ptr_ne (NULL, copy->childs); - SH_Fragment_free (fragment); - SH_Fragment_free (copy); + SH_NodeFragment_free (fragment); + SH_NodeFragment_free (copy); SH_Data_free (data); } END_TEST static void -check_childs (struct SH_NodeFragment * fragment, struct SH_NodeFragment * copy) +check_childs (struct SH_NodeFragment * fragment, + struct SH_NodeFragment * copy) { size_t index; + ck_assert_str_eq (fragment->tag, copy->tag); + ck_assert_int_eq (fragment->attr_n, copy->attr_n); + ck_assert_int_eq (fragment->attr_s, copy->attr_s); + ck_assert_int_eq (fragment->child_n, copy->child_n); + ck_assert_int_eq (fragment->child_s, copy->child_s); + ck_assert_ptr_ne (fragment->childs, copy->childs); + for (index = 0; index < copy->child_n; index++) { - ck_assert_ptr_ne (((struct SH_NodeFragment *) fragment->childs[index]), - ((struct SH_NodeFragment *) copy->childs[index])); - ck_assert_str_eq (((struct SH_NodeFragment *) fragment->childs[index])->tag, - ((struct SH_NodeFragment *) copy->childs[index])->tag); - ck_assert_int_eq (((struct SH_NodeFragment *) fragment->childs[index])->child_n, - ((struct SH_NodeFragment *) copy->childs[index])->child_n); - - check_childs (((struct SH_NodeFragment *) fragment->childs[index]), - ((struct SH_NodeFragment *) copy->childs[index])); + ck_assert_ptr_ne (fragment->childs[index], + copy->childs[index]); + ck_assert_ptr_eq (copy, get_parent (copy->childs[index])); + + check_childs (((struct SH_NodeFragment *) + fragment->childs[index]), + ((struct SH_NodeFragment *) + copy->childs[index])); } return; } -START_TEST(test_node_fragment_deepcopy) +START_TEST(test_node_fragment_deepcopy_no_status) { - struct SH_Status status; - struct SH_Fragment * fragment; + struct SH_NodeFragment * fragment; + struct SH_NodeFragment * copy; struct SH_Fragment * child1; struct SH_Fragment * child2; - struct SH_Fragment * copy; - struct SH_Data * data; + SH_Data * data; data = SH_Data_new (NULL); - fragment = SH_NodeFragment_new ("html", data, NULL); + fragment = (struct SH_NodeFragment *) + SH_NodeFragment_new ("html", data, NULL); child1 = SH_NodeFragment_new ("head", data, NULL); - SH_NodeFragment_append_child (((struct SH_NodeFragment *) fragment), - child1, NULL); + SH_NodeFragment_append_child (fragment, child1, NULL); child2 = SH_NodeFragment_new ("title", data, NULL); - SH_NodeFragment_append_child (((struct SH_NodeFragment *) child1), - child2, NULL); + SH_NodeFragment_append_child ((struct SH_NodeFragment *)child1, + child2, NULL); child1 = SH_NodeFragment_new ("body", data, NULL); - SH_NodeFragment_append_child (((struct SH_NodeFragment *) fragment), - child1, NULL); + SH_NodeFragment_append_child (fragment, child1, NULL); child2 = SH_NodeFragment_new ("header", data, NULL); - SH_NodeFragment_append_child (((struct SH_NodeFragment *) child1), - child2, NULL); + SH_NodeFragment_append_child ((struct SH_NodeFragment *)child1, + child2, NULL); child2 = SH_NodeFragment_new ("main", data, NULL); - SH_NodeFragment_append_child (((struct SH_NodeFragment *) child1), - child2, NULL); + SH_NodeFragment_append_child ((struct SH_NodeFragment *)child1, + child2, NULL); child2 = SH_NodeFragment_new ("footer", data, NULL); - SH_NodeFragment_append_child (((struct SH_NodeFragment *) child1), - child2, NULL); + SH_NodeFragment_append_child ((struct SH_NodeFragment *)child1, + child2, NULL); - /* without error */ - copy = SH_Fragment_copy (fragment, NULL); + copy = (struct SH_NodeFragment *) + SH_NodeFragment_deepcopy (fragment, NULL); - ck_assert_ptr_ne (copy, NULL); + ck_assert_ptr_ne (NULL, copy); ck_assert_ptr_ne (fragment, copy); - ck_assert_str_eq (((struct SH_NodeFragment *) fragment)->tag, - ((struct SH_NodeFragment *) copy)->tag); - ck_assert_int_eq (((struct SH_NodeFragment *) fragment)->child_n, - ((struct SH_NodeFragment *) copy)->child_n); - ck_assert_ptr_ne (((struct SH_NodeFragment *) fragment)->childs, - ((struct SH_NodeFragment *) copy)->childs); + ck_assert_ptr_eq (NULL, copy->base.parent); - check_childs (((struct SH_NodeFragment *) fragment), - ((struct SH_NodeFragment *) copy)); + check_childs (fragment, copy); + + SH_NodeFragment_free (fragment); + SH_NodeFragment_free (copy); + + SH_Data_free (data); +} +END_TEST + +START_TEST(test_node_fragment_deepcopy_with_status) +{ + struct SH_Status status; + struct SH_NodeFragment * fragment; + struct SH_NodeFragment * copy; + struct SH_Fragment * child1; + struct SH_Fragment * child2; + SH_Data * data; + + data = SH_Data_new (NULL); + + fragment = (struct SH_NodeFragment *) + SH_NodeFragment_new ("html", data, NULL); + + child1 = SH_NodeFragment_new ("head", data, NULL); + SH_NodeFragment_append_child (fragment, child1, NULL); + + child2 = SH_NodeFragment_new ("title", data, NULL); + SH_NodeFragment_append_child ((struct SH_NodeFragment *)child1, + child2, NULL); + + + child1 = SH_NodeFragment_new ("body", data, NULL); + SH_NodeFragment_append_child (fragment, child1, NULL); + + child2 = SH_NodeFragment_new ("header", data, NULL); + SH_NodeFragment_append_child ((struct SH_NodeFragment *)child1, + child2, NULL); + + child2 = SH_NodeFragment_new ("main", data, NULL); + SH_NodeFragment_append_child ((struct SH_NodeFragment *)child1, + child2, NULL); + + child2 = SH_NodeFragment_new ("footer", data, NULL); + SH_NodeFragment_append_child ((struct SH_NodeFragment *)child1, + child2, NULL); - SH_Fragment_free (copy); - /* with error */ _status_preinit (status); - copy = SH_Fragment_copy (fragment, &status); - ck_assert_int_eq (status.status, SUCCESS); + copy = (struct SH_NodeFragment *) + SH_NodeFragment_deepcopy (fragment, &status); + ck_assert (succeed (&status)); - ck_assert_ptr_ne (copy, NULL); + ck_assert_ptr_ne (NULL, copy); ck_assert_ptr_ne (fragment, copy); - ck_assert_str_eq (((struct SH_NodeFragment *) fragment)->tag, - ((struct SH_NodeFragment *) copy)->tag); - ck_assert_int_eq (((struct SH_NodeFragment *) fragment)->child_n, - ((struct SH_NodeFragment *) copy)->child_n); - ck_assert_ptr_ne (((struct SH_NodeFragment *) fragment)->childs, - ((struct SH_NodeFragment *) copy)->childs); + ck_assert_ptr_eq (NULL, copy->base.parent); - check_childs (((struct SH_NodeFragment *) fragment), - ((struct SH_NodeFragment *) copy)); + check_childs (fragment, copy); - SH_Fragment_free (fragment); - SH_Fragment_free (copy); + SH_NodeFragment_free (fragment); + SH_NodeFragment_free (copy); SH_Data_free (data); } END_TEST -START_TEST(test_node_fragment_tag) +START_TEST(test_node_fragment_tag_no_status) { - struct SH_Status status; struct SH_Fragment * fragment; - struct SH_Data * data; + SH_Data * data; char * tag; const char * tag1 = "html"; - const char * tag2 = "body"; data = SH_Data_new (NULL); /* no error */ fragment = SH_NodeFragment_new (tag1, data, NULL); - tag = SH_NodeFragment_get_tag (((struct SH_NodeFragment *) fragment), - NULL); + tag = SH_NodeFragment_get_tag ((struct SH_NodeFragment *) + fragment, + NULL); ck_assert_str_eq (tag, tag1); free (tag); SH_Fragment_free (fragment); + SH_Data_free (data); +} +END_TEST - /* error */ - fragment = SH_NodeFragment_new (tag2, data, NULL); +START_TEST(test_node_fragment_tag_with_status) +{ + struct SH_Status status; + struct SH_Fragment * fragment; + SH_Data * data; + char * tag; + const char * tag1 = "html"; + + data = SH_Data_new (NULL); + + fragment = SH_NodeFragment_new (tag1, data, NULL); _status_preinit (status); - tag = SH_NodeFragment_get_tag (((struct SH_NodeFragment *) fragment), - &status); - ck_assert_str_eq (tag, tag2); - ck_assert_int_eq (status.status, SUCCESS); + tag = SH_NodeFragment_get_tag ((struct SH_NodeFragment *) + fragment, + &status); + ck_assert_str_eq (tag, tag1); + ck_assert (succeed (&status)); free (tag); SH_Fragment_free (fragment); @@ -246,178 +400,2375 @@ START_TEST(test_node_fragment_tag) } END_TEST -START_TEST(test_node_fragment_child) +START_TEST(test_node_fragment_tag_raw) { - struct SH_Status status; - struct SH_Fragment * parent; - struct SH_Fragment * child1; - struct SH_Fragment * child2; - struct SH_Data * data; - bool boolean; + struct SH_Fragment * fragment; + SH_Data * data; + char * tag; + const char * tag1 = "html"; data = SH_Data_new (NULL); - parent = SH_NodeFragment_new ("html", data, NULL); - child1 = SH_NodeFragment_new ("head", data, NULL); - child2 = SH_NodeFragment_new ("body", data, NULL); - - /* no error */ - ck_assert_int_eq (((struct SH_NodeFragment *) parent)->child_n, 0); - - boolean = SH_NodeFragment_append_child (((struct SH_NodeFragment *) parent), - child1, NULL); - ck_assert_int_eq (boolean, TRUE); - ck_assert_int_eq (((struct SH_NodeFragment *) parent)->child_n, - 1); - ck_assert_ptr_eq (((struct SH_NodeFragment *) parent)->childs[0], - child1); - - /* with error */ - ck_assert_int_eq (((struct SH_NodeFragment *) parent)->child_n, 1); - - _status_preinit (status); - boolean = SH_NodeFragment_append_child (((struct SH_NodeFragment *) parent), - child2, &status); - ck_assert_int_eq (boolean, TRUE); - ck_assert_int_eq (status.status, SUCCESS); - ck_assert_int_eq (((struct SH_NodeFragment *) parent)->child_n, - 2); - ck_assert_ptr_eq (((struct SH_NodeFragment *) parent)->childs[1], - child2); + fragment = SH_NodeFragment_new (tag1, data, NULL); - SH_Fragment_free (parent); + tag = SH_NodeFragment_raw_get_tag (((struct SH_NodeFragment *) + fragment)); + ck_assert_str_eq (tag, tag1); + SH_Fragment_free (fragment); SH_Data_free (data); } END_TEST -START_TEST(test_node_fragment_get_child) +START_TEST(test_node_fragment_attr_alloc) { - struct SH_Status status; - struct SH_Fragment * parent; - struct SH_Fragment * child1; - const struct SH_Fragment * child2; - struct SH_Data * data; + #define alloc_size get_attr_alloc_size + ck_assert_int_eq (0, alloc_size (0)); + ck_assert_int_eq (CHILD_CHUNK, alloc_size (1)); + ck_assert_int_eq (CHILD_CHUNK, alloc_size (CHILD_CHUNK)); + ck_assert_int_eq (2*CHILD_CHUNK, alloc_size (CHILD_CHUNK+1)); + ck_assert_int_eq (SIZE_MAX, alloc_size (SIZE_MAX)); + for (size_t i = 0; i < CHILD_CHUNK; i++) + { + ck_assert_int_le (SIZE_MAX-i, alloc_size (SIZE_MAX-i)); + } + #undef alloc_size +} +END_TEST - data = SH_Data_new (NULL); +START_TEST(test_node_fragment_attr_get_no_status) +{ + SH_Attr * attr1; + const SH_Attr * attr2; + SH_Data * data; + SH_NodeFragment * fragment; + bool result; - parent = SH_NodeFragment_new ("html", data, NULL); - child1 = SH_NodeFragment_new ("body", data, NULL); + /* setup */ + attr1 = SH_Attr_new ("name", "value", NULL); + ck_assert_ptr_ne (NULL, attr1); - SH_NodeFragment_append_child (((struct SH_NodeFragment *) parent), - child1, NULL); + data = SH_Data_new (NULL); + ck_assert_ptr_ne (NULL, data); - /* without error */ - child2 = SH_NodeFragment_get_child (((struct SH_NodeFragment *) parent), - 0, NULL); - ck_assert_ptr_eq (child1, child2); + fragment = (SH_NodeFragment *)SH_NodeFragment_new ("html", data, + NULL); + ck_assert_ptr_ne (NULL, fragment); - child2 = SH_NodeFragment_get_child (((struct SH_NodeFragment *) parent), - 1, NULL); - ck_assert_ptr_eq (NULL, child2); + result = SH_NodeFragment_append_attr_copy (fragment, attr1, NULL); + ck_assert_int_eq (TRUE, result); - /* with error */ - _status_preinit (status); - child2 = SH_NodeFragment_get_child (((struct SH_NodeFragment *) parent), - 0, &status); - ck_assert_ptr_eq (child1, child2); - ck_assert_int_eq (status.status, SUCCESS); + /* test - success */ + attr2 = SH_NodeFragment_get_attr (fragment, 0, NULL); + ck_assert_ptr_ne (NULL, attr2); - _status_preinit (status); - child2 = SH_NodeFragment_get_child (((struct SH_NodeFragment *) parent), - 1, &status); - ck_assert_ptr_eq (NULL, child2); - ck_assert_int_eq (status.status, E_VALUE); + ck_assert (Attr_is_equal (attr1, attr2)); - SH_Fragment_free (parent); + /* test - fail */ + attr2 = SH_NodeFragment_get_attr (fragment, 1, NULL); + ck_assert_ptr_eq (NULL, attr2); + /* cleanup */ + SH_NodeFragment_free (fragment); SH_Data_free (data); + SH_Attr_free (attr1); } END_TEST -START_TEST(test_node_fragment_is_child) +START_TEST(test_node_fragment_attr_get_with_status) { - struct SH_Fragment * parent; - struct SH_Fragment * child1; - struct SH_Fragment * child2; - struct SH_Data * data; - bool boolean; + struct SH_Status status; + SH_Attr * attr1; + const SH_Attr * attr2; + SH_Data * data; + SH_NodeFragment * fragment; + bool result; - data = SH_Data_new (NULL); + /* setup */ + attr1 = SH_Attr_new ("name", "value", NULL); + ck_assert_ptr_ne (NULL, attr1); - parent = SH_NodeFragment_new ("html", data, NULL); - child1 = SH_NodeFragment_new ("head", data, NULL); - child2 = SH_NodeFragment_new ("title", data, NULL); + data = SH_Data_new (NULL); + ck_assert_ptr_ne (NULL, data); - SH_NodeFragment_append_child (((struct SH_NodeFragment *) parent), - child1, NULL); - SH_NodeFragment_append_child (((struct SH_NodeFragment *) child1), - child2, NULL); + fragment = (SH_NodeFragment *)SH_NodeFragment_new ("html", data, + NULL); + ck_assert_ptr_ne (NULL, fragment); - boolean = SH_NodeFragment_is_child (((struct SH_NodeFragment *) parent), - child1); - ck_assert_int_eq (boolean, TRUE); + result = SH_NodeFragment_append_attr_copy (fragment, attr1, NULL); + ck_assert_int_eq (TRUE, result); - boolean = SH_NodeFragment_is_child (((struct SH_NodeFragment *) parent), - child2); - ck_assert_int_eq (boolean, FALSE); + /* test - success */ + _status_preinit (status); + attr2 = SH_NodeFragment_get_attr (fragment, 0, &status); + ck_assert_ptr_ne (NULL, attr2); + ck_assert_int_eq (SUCCESS, status.status); - boolean = SH_NodeFragment_is_child (((struct SH_NodeFragment *) child1), - child2); - ck_assert_int_eq (boolean, TRUE); + ck_assert (Attr_is_equal (attr1, attr2)); - SH_Fragment_free (parent); + /* test - fail */ + _status_preinit (status); + attr2 = SH_NodeFragment_get_attr (fragment, 1, &status); + ck_assert_ptr_eq (NULL, attr2); + ck_assert_int_eq (E_VALUE, status.status); + /* cleanup */ + SH_NodeFragment_free (fragment); SH_Data_free (data); + SH_Attr_free (attr1); } END_TEST -START_TEST(test_node_fragment_is_descendant) +START_TEST(test_node_fragment_attr_insert_no_status) { - struct SH_Fragment * parent; - struct SH_Fragment * child1; - struct SH_Fragment * child2; - struct SH_Fragment * child3; - struct SH_Data * data; - bool boolean; + char * name; + char * value; + SH_Attr * attr; + 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); - parent = SH_NodeFragment_new ("html", data, NULL); - child1 = SH_NodeFragment_new ("head", data, NULL); - child2 = SH_NodeFragment_new ("body", data, NULL); - child3 = SH_NodeFragment_new ("title", data, NULL); + fragment = (SH_NodeFragment *)SH_NodeFragment_new ("html", data, + NULL); + ck_assert_ptr_ne (NULL, fragment); - SH_NodeFragment_append_child (((struct SH_NodeFragment *) parent), - child1, NULL); - SH_NodeFragment_append_child (((struct SH_NodeFragment *) parent), - child2, NULL); - SH_NodeFragment_append_child (((struct SH_NodeFragment *) child1), - child3, NULL); + /* test insert - success */ + attr = SH_Attr_copy (attr1, NULL); + ck_assert_ptr_ne (NULL, attr); - boolean = SH_NodeFragment_is_descendant (((struct SH_NodeFragment *) parent), - child1); - ck_assert_int_eq (boolean, TRUE); + name = Attr_get_name (attr); + value = Attr_get_value (attr); - boolean = SH_NodeFragment_is_descendant (((struct SH_NodeFragment *) parent), + result = insert_attr (fragment, attr, 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 (name, fragment->attrs[0].name); + ck_assert_ptr_eq (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 */ + attr = SH_Attr_copy (attr2, NULL); + ck_assert_ptr_ne (NULL, attr); + + name = Attr_get_name (attr); + value = Attr_get_value (attr); + + result = insert_attr (fragment, attr, 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_eq (name, fragment->attrs[0].name); + ck_assert_ptr_eq (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 */ + attr = SH_Attr_copy (attr3, NULL); + ck_assert_ptr_ne (NULL, attr); + + name = Attr_get_name (attr); + value = Attr_get_value (attr); + + result = insert_attr (fragment, attr, 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_eq (name, fragment->attrs[2].name); + ck_assert_ptr_eq (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_with_status) +{ + struct SH_Status status; + char * name; + char * value; + SH_Attr * attr; + 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 */ + attr = SH_Attr_copy (attr1, NULL); + ck_assert_ptr_ne (NULL, attr); + + name = Attr_get_name (attr); + value = Attr_get_value (attr); + + _status_preinit (status); + result = insert_attr (fragment, attr, 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_eq (name, fragment->attrs[0].name); + ck_assert_ptr_eq (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 */ + attr = SH_Attr_copy (attr2, NULL); + ck_assert_ptr_ne (NULL, attr); + + name = Attr_get_name (attr); + value = Attr_get_value (attr); + + _status_preinit (status); + result = insert_attr (fragment, attr, 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_eq (name, fragment->attrs[0].name); + ck_assert_ptr_eq (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 */ + attr = SH_Attr_copy (attr3, NULL); + ck_assert_ptr_ne (NULL, attr); + + name = Attr_get_name (attr); + value = Attr_get_value (attr); + + _status_preinit (status); + result = insert_attr (fragment, attr, 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_eq (name, fragment->attrs[2].name); + ck_assert_ptr_eq (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_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_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); + + /* 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_eq (attr2->name, fragment->attrs[0].name); + ck_assert_ptr_eq (attr2->value, fragment->attrs[0].value); + + ck_assert_ptr_eq (attr1->name, fragment->attrs[1].name); + ck_assert_ptr_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_eq (attr2->name, fragment->attrs[0].name); + ck_assert_ptr_eq (attr2->value, fragment->attrs[0].value); + + ck_assert_ptr_eq (attr1->name, fragment->attrs[1].name); + ck_assert_ptr_eq (attr1->value, fragment->attrs[1].value); + + ck_assert_ptr_eq (attr3->name, fragment->attrs[2].name); + ck_assert_ptr_eq (attr3->value, fragment->attrs[2].value); + + /* cleanup */ + SH_NodeFragment_free (fragment); + SH_Data_free (data); + free (attr1); + free (attr2); + 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_eq (attr1->name, fragment->attrs[0].name); + ck_assert_ptr_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_eq (attr2->name, fragment->attrs[0].name); + ck_assert_ptr_eq (attr2->value, fragment->attrs[0].value); + + ck_assert_ptr_eq (attr1->name, fragment->attrs[1].name); + ck_assert_ptr_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_eq (attr2->name, fragment->attrs[0].name); + ck_assert_ptr_eq (attr2->value, fragment->attrs[0].value); + + ck_assert_ptr_eq (attr1->name, fragment->attrs[1].name); + ck_assert_ptr_eq (attr1->value, fragment->attrs[1].value); + + ck_assert_ptr_eq (attr3->name, fragment->attrs[2].name); + ck_assert_ptr_eq (attr3->value, fragment->attrs[2].value); + + /* cleanup */ + SH_NodeFragment_free (fragment); + SH_Data_free (data); + free (attr1); + free (attr2); + free (attr3); +} +END_TEST + +START_TEST(test_node_fragment_attr_insert_copy_no_status) +{ + char * name; + char * value; + SH_Attr * attr; + 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 */ + attr = SH_Attr_copy (attr1, NULL); + ck_assert_ptr_ne (NULL, attr); + + name = Attr_get_name (attr); + value = Attr_get_value (attr); + + result = insert_attr_copy (fragment, attr, 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_ne (name, fragment->attrs[0].name); + ck_assert_ptr_ne (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 */ + attr = SH_Attr_copy (attr2, NULL); + ck_assert_ptr_ne (NULL, attr); + + name = Attr_get_name (attr); + value = Attr_get_value (attr); + + result = insert_attr_copy (fragment, attr, 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 (name, fragment->attrs[0].name); + ck_assert_ptr_ne (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 */ + attr = SH_Attr_copy (attr3, NULL); + ck_assert_ptr_ne (NULL, attr); + + name = Attr_get_name (attr); + value = Attr_get_value (attr); + + result = insert_attr_copy (fragment, attr, 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 (name, fragment->attrs[2].name); + ck_assert_ptr_ne (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_copy_with_status) +{ + struct SH_Status status; + char * name; + char * value; + SH_Attr * attr; + 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 */ + attr = SH_Attr_copy (attr1, NULL); + ck_assert_ptr_ne (NULL, attr); + + name = Attr_get_name (attr); + value = Attr_get_value (attr); + + _status_preinit (status); + result = insert_attr_copy (fragment, attr, 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 (name, fragment->attrs[0].name); + ck_assert_ptr_ne (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 */ + attr = SH_Attr_copy (attr2, NULL); + ck_assert_ptr_ne (NULL, attr); + + name = Attr_get_name (attr); + value = Attr_get_value (attr); + + _status_preinit (status); + result = insert_attr_copy (fragment, attr, 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 (name, fragment->attrs[0].name); + ck_assert_ptr_ne (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 */ + attr = SH_Attr_copy (attr3, NULL); + ck_assert_ptr_ne (NULL, attr); + + name = Attr_get_name (attr); + value = Attr_get_value (attr); + + _status_preinit (status); + result = insert_attr_copy (fragment, attr, 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 (name, fragment->attrs[2].name); + ck_assert_ptr_ne (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_insert_no_status) +{ + char * name; + char * value; + SH_Attr * attr; + 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 */ + result = SH_NodeFragment_insert_attr (fragment, attr1, 1, NULL); + ck_assert_int_eq (FALSE, result); + + /* test */ + attr = SH_Attr_copy (attr2, NULL); + ck_assert_ptr_ne (NULL, attr); + + name = Attr_get_name (attr); + value = Attr_get_value (attr); + + result = SH_NodeFragment_insert_attr (fragment, attr, 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 */ + attr = SH_Attr_copy (attr1, NULL); + ck_assert_ptr_ne (NULL, attr); + + name = Attr_get_name (attr); + value = Attr_get_value (attr); + + result = SH_NodeFragment_prepend_attr (fragment, attr, 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 */ + attr = SH_Attr_copy (attr3, NULL); + ck_assert_ptr_ne (NULL, attr); + + name = Attr_get_name (attr); + value = Attr_get_value (attr); + + result = SH_NodeFragment_append_attr (fragment, attr, 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); + SH_Attr_free (attr1); + SH_Attr_free (attr2); + SH_Attr_free (attr3); +} +END_TEST + +START_TEST(test_node_fragment_attr_insert_insert_with_status) +{ + struct SH_Status status; + char * name; + char * value; + SH_Attr * attr; + 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 */ + _status_preinit (status); + result = SH_NodeFragment_insert_attr (fragment, attr1, 1, &status); + ck_assert_int_eq (FALSE, result); + ck_assert_int_eq (E_VALUE, status.status); + + /* test */ + attr = SH_Attr_copy (attr2, NULL); + ck_assert_ptr_ne (NULL, attr); + + name = Attr_get_name (attr); + value = Attr_get_value (attr); + + _status_preinit (status); + result = SH_NodeFragment_insert_attr (fragment, attr, 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 */ + attr = SH_Attr_copy (attr1, NULL); + ck_assert_ptr_ne (NULL, attr); + + name = Attr_get_name (attr); + value = Attr_get_value (attr); + + _status_preinit (status); + result = SH_NodeFragment_prepend_attr (fragment, attr, &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 */ + attr = SH_Attr_copy (attr3, NULL); + ck_assert_ptr_ne (NULL, attr); + + name = Attr_get_name (attr); + value = Attr_get_value (attr); + + _status_preinit (status); + result = SH_NodeFragment_append_attr (fragment, attr, &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); + + 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_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_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_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_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_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_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_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_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_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_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); + + 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_copy_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 */ + result = SH_NodeFragment_insert_attr_copy (fragment, attr1, 1, + NULL); + ck_assert_int_eq (FALSE, result); + + /* test */ + name = Attr_get_name (attr2); + value = Attr_get_value (attr2); + + result = SH_NodeFragment_insert_attr_copy (fragment, attr2, 0, + NULL); + ck_assert_int_eq (TRUE, result); + + ck_assert_ptr_ne (name, fragment->attrs[0].name); + ck_assert_ptr_ne (value, fragment->attrs[0].value); + + /* test - insert before */ + name = Attr_get_name (attr1); + value = Attr_get_value (attr1); + + result = SH_NodeFragment_prepend_attr_copy (fragment, attr1, + NULL); + ck_assert_int_eq (TRUE, result); + + ck_assert_ptr_ne (name, fragment->attrs[0].name); + ck_assert_ptr_ne (value, fragment->attrs[0].value); + + /* test - insert after */ + name = Attr_get_name (attr3); + value = Attr_get_value (attr3); + + result = SH_NodeFragment_append_attr_copy (fragment, attr3, + NULL); + ck_assert_int_eq (TRUE, result); + + ck_assert_ptr_ne (name, fragment->attrs[2].name); + ck_assert_ptr_ne (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_copy_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 */ + _status_preinit (status); + result = SH_NodeFragment_insert_attr_copy (fragment, attr1, 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_copy (fragment, attr2, 0, + &status); + ck_assert_int_eq (TRUE, result); + ck_assert_int_eq (SUCCESS, status.status); + + ck_assert_ptr_ne (name, fragment->attrs[0].name); + ck_assert_ptr_ne (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_copy (fragment, attr1, + &status); + ck_assert_int_eq (TRUE, result); + ck_assert_int_eq (SUCCESS, status.status); + + ck_assert_ptr_ne (name, fragment->attrs[0].name); + ck_assert_ptr_ne (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_copy (fragment, attr3, + &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_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_child_alloc) +{ + #define alloc_size get_child_alloc_size + ck_assert_int_eq (0, alloc_size (0)); + ck_assert_int_eq (CHILD_CHUNK, alloc_size (1)); + ck_assert_int_eq (CHILD_CHUNK, alloc_size (CHILD_CHUNK)); + ck_assert_int_eq (2*CHILD_CHUNK, alloc_size (CHILD_CHUNK+1)); + ck_assert_int_eq (SIZE_MAX, alloc_size (SIZE_MAX)); + for (size_t i = 0; i < CHILD_CHUNK; i++) + { + ck_assert_int_le (SIZE_MAX-i, alloc_size (SIZE_MAX-i)); + } + #undef alloc_size +} +END_TEST + +START_TEST(test_node_fragment_child) +{ + struct SH_Status status; + struct SH_Fragment * parent; + struct SH_Fragment * child1; + struct SH_Fragment * child2; + struct SH_Data * data; + bool boolean; + + data = SH_Data_new (NULL); + + parent = SH_NodeFragment_new ("html", data, NULL); + child1 = SH_NodeFragment_new ("head", data, NULL); + child2 = SH_NodeFragment_new ("body", data, NULL); + + /* no error */ + ck_assert_int_eq (((struct SH_NodeFragment *) parent)->child_n, 0); + + boolean = SH_NodeFragment_append_child (((struct SH_NodeFragment *) parent), + child1, NULL); + ck_assert_int_eq (boolean, TRUE); + ck_assert_int_eq (((struct SH_NodeFragment *) parent)->child_n, + 1); + ck_assert_ptr_eq (((struct SH_NodeFragment *) parent)->childs[0], + child1); + + ck_assert_ptr_eq (parent, get_parent (child1)); + + /* with error */ + ck_assert_int_eq (((struct SH_NodeFragment *) parent)->child_n, 1); + + _status_preinit (status); + boolean = SH_NodeFragment_append_child (((struct SH_NodeFragment *) parent), + child2, &status); + ck_assert_int_eq (boolean, TRUE); + ck_assert_int_eq (status.status, SUCCESS); + ck_assert_int_eq (((struct SH_NodeFragment *) parent)->child_n, + 2); + ck_assert_ptr_eq (((struct SH_NodeFragment *) parent)->childs[1], + child2); + + ck_assert_ptr_eq (parent, get_parent (child2)); + + SH_Fragment_free (parent); + + SH_Data_free (data); +} +END_TEST + +START_TEST(test_node_fragment_get_child) +{ + struct SH_Status status; + struct SH_Fragment * parent; + struct SH_Fragment * child1; + const struct SH_Fragment * child2; + struct SH_Data * data; + + data = SH_Data_new (NULL); + + parent = SH_NodeFragment_new ("html", data, NULL); + child1 = SH_NodeFragment_new ("body", data, NULL); + + SH_NodeFragment_append_child (((struct SH_NodeFragment *) parent), + child1, NULL); + + /* without error */ + child2 = SH_NodeFragment_get_child (((struct SH_NodeFragment *) parent), + 0, NULL); + ck_assert_ptr_eq (child1, child2); + + child2 = SH_NodeFragment_get_child (((struct SH_NodeFragment *) parent), + 1, NULL); + ck_assert_ptr_eq (NULL, child2); + + /* with error */ + _status_preinit (status); + child2 = SH_NodeFragment_get_child (((struct SH_NodeFragment *) parent), + 0, &status); + ck_assert_ptr_eq (child1, child2); + ck_assert_int_eq (status.status, SUCCESS); + + _status_preinit (status); + child2 = SH_NodeFragment_get_child (((struct SH_NodeFragment *) parent), + 1, &status); + ck_assert_ptr_eq (NULL, child2); + ck_assert_int_eq (status.status, E_VALUE); + + SH_Fragment_free (parent); + + SH_Data_free (data); +} +END_TEST + +START_TEST(test_node_fragment_is_child) +{ + struct SH_Fragment * parent; + struct SH_Fragment * child1; + struct SH_Fragment * child2; + struct SH_Data * data; + bool boolean; + + data = SH_Data_new (NULL); + + parent = SH_NodeFragment_new ("html", data, NULL); + child1 = SH_NodeFragment_new ("head", data, NULL); + child2 = SH_NodeFragment_new ("title", data, NULL); + + SH_NodeFragment_append_child (((struct SH_NodeFragment *) parent), + child1, NULL); + SH_NodeFragment_append_child (((struct SH_NodeFragment *) child1), + child2, NULL); + + boolean = SH_NodeFragment_is_child (((struct SH_NodeFragment *) parent), + child1); + ck_assert_int_eq (boolean, TRUE); + + boolean = SH_NodeFragment_is_child (((struct SH_NodeFragment *) parent), + child2); + ck_assert_int_eq (boolean, FALSE); + + boolean = SH_NodeFragment_is_child (((struct SH_NodeFragment *) child1), + child2); + ck_assert_int_eq (boolean, TRUE); + + SH_Fragment_free (parent); + + SH_Data_free (data); +} +END_TEST + +START_TEST(test_node_fragment_is_descendant) +{ + struct SH_Fragment * parent; + struct SH_Fragment * child1; + struct SH_Fragment * child2; + struct SH_Fragment * child3; + struct SH_Data * data; + bool boolean; + + data = SH_Data_new (NULL); + + parent = SH_NodeFragment_new ("html", data, NULL); + child1 = SH_NodeFragment_new ("head", data, NULL); + child2 = SH_NodeFragment_new ("body", data, NULL); + child3 = SH_NodeFragment_new ("title", data, NULL); + + SH_NodeFragment_append_child (((struct SH_NodeFragment *) parent), + child1, NULL); + SH_NodeFragment_append_child (((struct SH_NodeFragment *) parent), + child2, NULL); + SH_NodeFragment_append_child (((struct SH_NodeFragment *) child1), + child3, NULL); + + boolean = SH_NodeFragment_is_descendant (((struct SH_NodeFragment *) parent), + child1); + ck_assert_int_eq (boolean, TRUE); + + boolean = SH_NodeFragment_is_descendant (((struct SH_NodeFragment *) parent), + child2); + ck_assert_int_eq (boolean, TRUE); + + boolean = SH_NodeFragment_is_descendant (((struct SH_NodeFragment *) parent), + child3); + ck_assert_int_eq (boolean, TRUE); + + boolean = SH_NodeFragment_is_descendant (((struct SH_NodeFragment *) child1), child2); + ck_assert_int_eq (boolean, FALSE); + + boolean = SH_NodeFragment_is_descendant (((struct SH_NodeFragment *) child1), + child3); + ck_assert_int_eq (boolean, TRUE); + + boolean = SH_NodeFragment_is_descendant (((struct SH_NodeFragment *) child2), + child3); + ck_assert_int_eq (boolean, FALSE); + + SH_Fragment_free (parent); + + SH_Data_free (data); +} +END_TEST + +START_TEST(test_node_fragment_is_parent) +{ + struct SH_Fragment * parent; + struct SH_Fragment * child1; + struct SH_Fragment * child2; + struct SH_Data * data; + bool boolean; + + data = SH_Data_new (NULL); + + parent = SH_NodeFragment_new ("html", data, NULL); + child1 = SH_NodeFragment_new ("head", data, NULL); + child2 = SH_NodeFragment_new ("title", data, NULL); + + SH_NodeFragment_append_child (((struct SH_NodeFragment *) parent), + child1, NULL); + SH_NodeFragment_append_child (((struct SH_NodeFragment *) child1), + child2, NULL); + + boolean = SH_NodeFragment_is_parent (child1, + (struct SH_NodeFragment *) + parent); + ck_assert_int_eq (boolean, TRUE); + + boolean = SH_NodeFragment_is_parent (child2, + (struct SH_NodeFragment *) + parent); + ck_assert_int_eq (boolean, FALSE); + + boolean = SH_NodeFragment_is_parent (child2, + (struct SH_NodeFragment *) + child1); + ck_assert_int_eq (boolean, TRUE); + + SH_Fragment_free (parent); + + SH_Data_free (data); +} +END_TEST + +START_TEST(test_node_fragment_is_ancestor) +{ + struct SH_Fragment * parent; + struct SH_Fragment * child1; + struct SH_Fragment * child2; + struct SH_Fragment * child3; + struct SH_Data * data; + bool boolean; + + data = SH_Data_new (NULL); + + parent = SH_NodeFragment_new ("html", data, NULL); + child1 = SH_NodeFragment_new ("head", data, NULL); + child2 = SH_NodeFragment_new ("body", data, NULL); + child3 = SH_NodeFragment_new ("title", data, NULL); + + SH_NodeFragment_append_child (((struct SH_NodeFragment *)parent), + child1, NULL); + SH_NodeFragment_append_child (((struct SH_NodeFragment *)parent), + child2, NULL); + SH_NodeFragment_append_child (((struct SH_NodeFragment *)child1), + child3, NULL); + + boolean = SH_NodeFragment_is_ancestor (child1, + ((struct SH_NodeFragment *) + parent)); + ck_assert_int_eq (boolean, TRUE); + + boolean = SH_NodeFragment_is_ancestor (child2, + ((struct SH_NodeFragment *) + parent)); + ck_assert_int_eq (boolean, TRUE); + + boolean = SH_NodeFragment_is_ancestor (child3, + ((struct SH_NodeFragment *) + parent)); + ck_assert_int_eq (boolean, TRUE); + + boolean = SH_NodeFragment_is_ancestor (child2, + ((struct SH_NodeFragment *) + child1)); + ck_assert_int_eq (boolean, FALSE); + + boolean = SH_NodeFragment_is_ancestor (child3, + ((struct SH_NodeFragment *) + child1)); ck_assert_int_eq (boolean, TRUE); - boolean = SH_NodeFragment_is_descendant (((struct SH_NodeFragment *) parent), - child3); - ck_assert_int_eq (boolean, TRUE); + boolean = SH_NodeFragment_is_ancestor (child3, + ((struct SH_NodeFragment *) + child2)); + ck_assert_int_eq (boolean, FALSE); + + SH_Fragment_free (parent); + + SH_Data_free (data); +} +END_TEST + +START_TEST(test_node_fragment_child_insert_no_status) +{ + SH_Data * data; + struct SH_NodeFragment * parent; + struct SH_Fragment * child; + struct SH_Fragment * child1; + struct SH_Fragment * child2; + struct SH_Fragment * child3; + bool result; + + data = SH_Data_new (NULL); + + parent = (struct SH_NodeFragment *) + SH_NodeFragment_new ("body", data, NULL); + child1 = SH_NodeFragment_new ("header", data, NULL); + child2 = SH_NodeFragment_new ("main", data, NULL); + child3 = SH_NodeFragment_new ("footer", data, NULL); + + /* insert - success */ + result = insert_child (parent, child1, 0, NULL); + ck_assert_int_eq (TRUE, result); + ck_assert_int_eq (1, parent->child_n); + ck_assert_int_le (1, parent->child_s); + ck_assert_int_eq (CHILD_CHUNK, parent->child_s); + ck_assert_ptr_eq (child1, parent->childs[0]); + ck_assert_ptr_eq (parent, child1->parent); + + /* reinsert - failing */ + result = insert_child (parent, child1, 0, NULL); + ck_assert_int_eq (FALSE, result); + + /* insert copy - success */ + child = SH_Fragment_copy (child1, NULL); + result = insert_child (parent, child, 0, NULL); + ck_assert_int_eq (TRUE, result); + ck_assert_int_eq (2, parent->child_n); + ck_assert_int_le (2, parent->child_s); + ck_assert_int_eq (CHILD_CHUNK, parent->child_s); + ck_assert_ptr_eq (child, parent->childs[0]); + ck_assert_ptr_eq (child1, parent->childs[1]); + ck_assert_ptr_eq (parent, child->parent); + ck_assert_ptr_eq (parent, child1->parent); + + /* insert parent into child - failing */ + result = insert_child ((struct SH_NodeFragment *)child1, + (struct SH_Fragment *)parent, + 0, NULL); + ck_assert_int_eq (FALSE, result); + + /* insert inbetween */ + result = insert_child (parent, child2, 1, NULL); + ck_assert_int_eq (TRUE, result); + ck_assert_int_eq (3, parent->child_n); + ck_assert_int_le (3, parent->child_s); + ck_assert_int_eq (CHILD_CHUNK, parent->child_s); + ck_assert_ptr_eq (child, parent->childs[0]); + ck_assert_ptr_eq (child1, parent->childs[2]); + ck_assert_ptr_eq (child2, parent->childs[1]); + ck_assert_ptr_eq (parent, child->parent); + ck_assert_ptr_eq (parent, child1->parent); + ck_assert_ptr_eq (parent, child2->parent); + + /* insert after */ + result = insert_child (parent, child3, 3, NULL); + ck_assert_int_eq (TRUE, result); + ck_assert_int_eq (4, parent->child_n); + ck_assert_int_le (4, parent->child_s); + ck_assert_int_eq (CHILD_CHUNK, parent->child_s); + ck_assert_ptr_eq (child, parent->childs[0]); + ck_assert_ptr_eq (child1, parent->childs[2]); + ck_assert_ptr_eq (child2, parent->childs[1]); + ck_assert_ptr_eq (child3, parent->childs[3]); + ck_assert_ptr_eq (parent, child->parent); + ck_assert_ptr_eq (parent, child1->parent); + ck_assert_ptr_eq (parent, child2->parent); + ck_assert_ptr_eq (parent, child3->parent); + + SH_NodeFragment_free (parent); + + SH_Data_free (data); +} +END_TEST + +START_TEST(test_node_fragment_child_insert_with_status) +{ + struct SH_Status status; + SH_Data * data; + struct SH_NodeFragment * parent; + struct SH_Fragment * child; + struct SH_Fragment * child1; + struct SH_Fragment * child2; + struct SH_Fragment * child3; + bool result; + + data = SH_Data_new (NULL); + + parent = (struct SH_NodeFragment *) + SH_NodeFragment_new ("body", data, NULL); + child1 = SH_NodeFragment_new ("header", data, NULL); + child2 = SH_NodeFragment_new ("main", data, NULL); + child3 = SH_NodeFragment_new ("footer", data, NULL); + + /* insert - success */ + _status_preinit (status); + result = insert_child (parent, child1, 0, &status); + ck_assert (succeed (&status)); + ck_assert_int_eq (TRUE, result); + ck_assert_int_eq (1, parent->child_n); + ck_assert_int_le (1, parent->child_s); + ck_assert_int_eq (CHILD_CHUNK, parent->child_s); + ck_assert_ptr_eq (child1, parent->childs[0]); + ck_assert_ptr_eq (parent, child1->parent); + + /* reinsert - failing */ + _status_preinit (status); + result = insert_child (parent, child1, 0, &status); + ck_assert (failed (&status)); + ck_assert_int_eq (FALSE, result); + ck_assert_int_eq (E_STATE, status.status); + + /* insert copy - success */ + child = SH_Fragment_copy (child1, NULL); + _status_preinit (status); + result = insert_child (parent, child, 0, &status); + ck_assert (succeed (&status)); + ck_assert_int_eq (TRUE, result); + ck_assert_int_eq (2, parent->child_n); + ck_assert_int_le (2, parent->child_s); + ck_assert_int_eq (CHILD_CHUNK, parent->child_s); + ck_assert_ptr_eq (child, parent->childs[0]); + ck_assert_ptr_eq (child1, parent->childs[1]); + ck_assert_ptr_eq (parent, child->parent); + ck_assert_ptr_eq (parent, child1->parent); + + /* insert parent into child - failing */ + _status_preinit (status); + result = insert_child ((struct SH_NodeFragment *)child1, + (struct SH_Fragment *)parent, + 0, &status); + ck_assert (failed (&status)); + ck_assert_int_eq (FALSE, result); + ck_assert_int_eq (E_STATE, status.status); + + /* insert inbetween */ + _status_preinit (status); + result = insert_child (parent, child2, 1, &status); + ck_assert (succeed (&status)); + ck_assert_int_eq (TRUE, result); + ck_assert_int_eq (3, parent->child_n); + ck_assert_int_le (3, parent->child_s); + ck_assert_int_eq (CHILD_CHUNK, parent->child_s); + ck_assert_ptr_eq (child, parent->childs[0]); + ck_assert_ptr_eq (child1, parent->childs[2]); + ck_assert_ptr_eq (child2, parent->childs[1]); + ck_assert_ptr_eq (parent, child->parent); + ck_assert_ptr_eq (parent, child1->parent); + ck_assert_ptr_eq (parent, child2->parent); + + /* insert after */ + _status_preinit (status); + result = insert_child (parent, child3, 3, &status); + ck_assert (succeed (&status)); + ck_assert_int_eq (TRUE, result); + ck_assert_int_eq (4, parent->child_n); + ck_assert_int_le (4, parent->child_s); + ck_assert_int_eq (CHILD_CHUNK, parent->child_s); + ck_assert_ptr_eq (child, parent->childs[0]); + ck_assert_ptr_eq (child1, parent->childs[2]); + ck_assert_ptr_eq (child2, parent->childs[1]); + ck_assert_ptr_eq (child3, parent->childs[3]); + ck_assert_ptr_eq (parent, child->parent); + ck_assert_ptr_eq (parent, child1->parent); + ck_assert_ptr_eq (parent, child2->parent); + ck_assert_ptr_eq (parent, child3->parent); + + SH_NodeFragment_free (parent); + + SH_Data_free (data); +} +END_TEST + +START_TEST(test_node_fragment_child_insert_insert_no_status) +{ + struct SH_NodeFragment * parent; + struct SH_Fragment * child1; + struct SH_Fragment * child2; + struct SH_Fragment * child3; + SH_Data * data; + bool result; + + data = SH_Data_new (NULL); + + parent = (struct SH_NodeFragment *)SH_NodeFragment_new ("body", + data, + NULL); + child1 = SH_NodeFragment_new ("header", data, NULL); + child2 = SH_NodeFragment_new ("main", data, NULL); + child3 = SH_NodeFragment_new ("footer", data, NULL); + + /* out of range - fail */ + result = SH_NodeFragment_insert_child (parent, child1, 1, NULL); + ck_assert_int_eq (FALSE, result); + + /* insert - success */ + result = SH_NodeFragment_insert_child (parent, child2, 0, NULL); + ck_assert_int_eq (TRUE, result); + + /* insert before - success */ + result = SH_NodeFragment_prepend_child (parent, child1, NULL); + ck_assert_int_eq (TRUE, result); + + /* insert after - success */ + result = SH_NodeFragment_append_child (parent, child3, NULL); + ck_assert_int_eq (TRUE, result); + + ck_assert_int_eq (3, parent->child_n); + ck_assert_ptr_eq (child1, parent->childs[0]); + ck_assert_ptr_eq (child2, parent->childs[1]); + ck_assert_ptr_eq (child3, parent->childs[2]); + + SH_NodeFragment_free (parent); + + SH_Data_free (data); +} +END_TEST + +START_TEST(test_node_fragment_child_insert_insert_with_status) +{ + struct SH_Status status; + struct SH_NodeFragment * parent; + struct SH_Fragment * child1; + struct SH_Fragment * child2; + struct SH_Fragment * child3; + SH_Data * data; + bool result; + + data = SH_Data_new (NULL); + + parent = (struct SH_NodeFragment *)SH_NodeFragment_new ("body", + data, + NULL); + child1 = SH_NodeFragment_new ("header", data, NULL); + child2 = SH_NodeFragment_new ("main", data, NULL); + child3 = SH_NodeFragment_new ("footer", data, NULL); + + /* out of range - fail */ + _status_preinit (status); + result = SH_NodeFragment_insert_child (parent, child1, 1, + &status); + ck_assert_int_eq (FALSE, result); + ck_assert_int_eq (E_VALUE, status.status); + ck_assert (failed (&status)); + + /* insert - success */ + _status_preinit (status); + result = SH_NodeFragment_insert_child (parent, child2, 0, + &status); + ck_assert_int_eq (TRUE, result); + ck_assert (succeed (&status)); + + /* insert before - success */ + _status_preinit (status); + result = SH_NodeFragment_prepend_child (parent, child1, + &status); + ck_assert_int_eq (TRUE, result); + ck_assert (succeed (&status)); + + /* insert after - success */ + _status_preinit (status); + result = SH_NodeFragment_append_child (parent, child3, + &status); + ck_assert_int_eq (TRUE, result); + ck_assert (succeed (&status)); + + ck_assert_int_eq (3, parent->child_n); + ck_assert_ptr_eq (child1, parent->childs[0]); + ck_assert_ptr_eq (child2, parent->childs[1]); + ck_assert_ptr_eq (child3, parent->childs[2]); + + SH_NodeFragment_free (parent); + + SH_Data_free (data); +} +END_TEST + +START_TEST(test_node_fragment_child_insert_relative_no_status) +{ + struct SH_NodeFragment * parent; + struct SH_Fragment * child1; + struct SH_Fragment * child2; + struct SH_Fragment * child3; + SH_Data * data; + bool result; + + data = SH_Data_new (NULL); + + parent = (struct SH_NodeFragment *)SH_NodeFragment_new ("body", + data, + NULL); + child1 = SH_NodeFragment_new ("header", data, NULL); + child2 = SH_NodeFragment_new ("main", data, NULL); + child3 = SH_NodeFragment_new ("footer", data, NULL); + + /* test erroneous call */ + result = SH_NodeFragment_insert_child_before (child2, child1, + NULL); + ck_assert_int_eq (FALSE, result); + + result = SH_NodeFragment_insert_child_after (child2, child3, + NULL); + ck_assert_int_eq (FALSE, result); + + /* test bug check */ + child2->parent = parent; + + result = SH_NodeFragment_insert_child_before (child2, child1, + NULL); + ck_assert_int_eq (FALSE, result); + + result = SH_NodeFragment_insert_child_after (child2, child3, + NULL); + ck_assert_int_eq (FALSE, result); + + child2->parent = NULL; + + /* test real */ + result = SH_NodeFragment_insert_child (parent, child2, 0, + NULL); + ck_assert_int_eq (TRUE, result); - boolean = SH_NodeFragment_is_descendant (((struct SH_NodeFragment *) child1), - child2); - ck_assert_int_eq (boolean, FALSE); + result = SH_NodeFragment_insert_child_before (child2, child1, + NULL); + ck_assert_int_eq (TRUE, result); - boolean = SH_NodeFragment_is_descendant (((struct SH_NodeFragment *) child1), - child3); - ck_assert_int_eq (boolean, TRUE); + result = SH_NodeFragment_insert_child_after (child2, child3, + NULL); + ck_assert_int_eq (TRUE, result); - boolean = SH_NodeFragment_is_descendant (((struct SH_NodeFragment *) child2), - child3); - ck_assert_int_eq (boolean, FALSE); + ck_assert_int_eq (3, parent->child_n); + ck_assert_ptr_eq (child1, parent->childs[0]); + ck_assert_ptr_eq (child2, parent->childs[1]); + ck_assert_ptr_eq (child3, parent->childs[2]); + + SH_NodeFragment_free (parent); + + SH_Data_free (data); +} +END_TEST + +START_TEST(test_node_fragment_child_insert_relative_with_status) +{ + struct SH_Status status; + struct SH_NodeFragment * parent; + struct SH_Fragment * child1; + struct SH_Fragment * child2; + struct SH_Fragment * child3; + SH_Data * data; + bool result; + + data = SH_Data_new (NULL); + + parent = (struct SH_NodeFragment *)SH_NodeFragment_new ("body", + data, + NULL); + child1 = SH_NodeFragment_new ("header", data, NULL); + child2 = SH_NodeFragment_new ("main", data, NULL); + child3 = SH_NodeFragment_new ("footer", data, NULL); + + /* test erroneous call */ + _status_preinit (status); + result = SH_NodeFragment_insert_child_before (child2, child1, + &status); + ck_assert_int_eq (FALSE, result); + ck_assert_int_eq (E_STATE, status.status); + ck_assert (failed (&status)); + + _status_preinit (status); + result = SH_NodeFragment_insert_child_after (child2, child3, + &status); + ck_assert_int_eq (FALSE, result); + ck_assert_int_eq (E_STATE, status.status); + ck_assert (failed (&status)); + + /* test bug check */ + child2->parent = parent; + + _status_preinit (status); + result = SH_NodeFragment_insert_child_before (child2, child1, + &status); + ck_assert_int_eq (FALSE, result); + ck_assert_int_eq (E_BUG, status.status); + ck_assert (failed (&status)); + + _status_preinit (status); + result = SH_NodeFragment_insert_child_after (child2, child3, + &status); + ck_assert_int_eq (FALSE, result); + ck_assert_int_eq (E_BUG, status.status); + ck_assert (failed (&status)); + + child2->parent = NULL; + + /* test real */ + _status_preinit (status); + result = SH_NodeFragment_insert_child (parent, child2, 0, + &status); + ck_assert_int_eq (TRUE, result); + ck_assert (succeed (&status)); + + _status_preinit (status); + result = SH_NodeFragment_insert_child_before (child2, child1, + &status); + ck_assert_int_eq (TRUE, result); + ck_assert (succeed (&status)); + + _status_preinit (status); + result = SH_NodeFragment_insert_child_after (child2, child3, + &status); + ck_assert_int_eq (TRUE, result); + ck_assert (succeed (&status)); + + ck_assert_int_eq (3, parent->child_n); + ck_assert_ptr_eq (child1, parent->childs[0]); + ck_assert_ptr_eq (child2, parent->childs[1]); + ck_assert_ptr_eq (child3, parent->childs[2]); + + SH_NodeFragment_free (parent); + + SH_Data_free (data); +} +END_TEST + +START_TEST(test_node_fragment_child_remove_no_status) +{ + struct SH_NodeFragment * parent; + struct SH_Fragment * child; + struct SH_Fragment * child1; + struct SH_Fragment * child2; + struct SH_Fragment * child3; + struct SH_Fragment * child4; + struct SH_Fragment * child5; + struct SH_Fragment * child6; + SH_Data * data; + bool result; + + data = SH_Data_new (NULL); + + parent = (struct SH_NodeFragment *)SH_NodeFragment_new ("body", + data, + NULL); + child1 = SH_NodeFragment_new ("p", data, NULL); + child2 = SH_NodeFragment_new ("p", data, NULL); + child3 = SH_NodeFragment_new ("p", data, NULL); + child4 = SH_NodeFragment_new ("p", data, NULL); + child5 = SH_NodeFragment_new ("p", data, NULL); + child6 = SH_NodeFragment_new ("p", data, NULL); + + result = SH_NodeFragment_append_child (parent, child1, NULL); + ck_assert_int_eq (TRUE, result); + + result = SH_NodeFragment_append_child (parent, child2, NULL); + ck_assert_int_eq (TRUE, result); + + result = SH_NodeFragment_append_child (parent, child3, NULL); + ck_assert_int_eq (TRUE, result); + + result = SH_NodeFragment_append_child (parent, child4, NULL); + ck_assert_int_eq (TRUE, result); + + result = SH_NodeFragment_append_child (parent, child5, NULL); + ck_assert_int_eq (TRUE, result); + + result = SH_NodeFragment_append_child (parent, child6, NULL); + ck_assert_int_eq (TRUE, result); + + + ck_assert_int_eq (10, parent->child_s); + ck_assert_int_eq (6, parent->child_n); + ck_assert_ptr_eq (child1, parent->childs[0]); + + child = remove_child (parent, 0, NULL); + ck_assert_ptr_eq (child, child1); + ck_assert_ptr_eq (NULL, child->parent); + SH_Fragment_free (child1); + ck_assert_int_eq (5, parent->child_s); + ck_assert_int_eq (5, parent->child_n); + ck_assert_ptr_eq (child2, parent->childs[0]); + + child = remove_child (parent, 0, NULL); + ck_assert_ptr_eq (child, child2); + ck_assert_ptr_eq (NULL, child->parent); + SH_Fragment_free (child2); + ck_assert_int_eq (5, parent->child_s); + ck_assert_int_eq (4, parent->child_n); + ck_assert_ptr_eq (child3, parent->childs[0]); + + child = remove_child (parent, 0, NULL); + ck_assert_ptr_eq (child, child3); + ck_assert_ptr_eq (NULL, child->parent); + SH_Fragment_free (child3); + ck_assert_int_eq (5, parent->child_s); + ck_assert_int_eq (3, parent->child_n); + ck_assert_ptr_eq (child4, parent->childs[0]); + + child = remove_child (parent, 0, NULL); + ck_assert_ptr_eq (child, child4); + ck_assert_ptr_eq (NULL, child->parent); + SH_Fragment_free (child4); + ck_assert_int_eq (5, parent->child_s); + ck_assert_int_eq (2, parent->child_n); + ck_assert_ptr_eq (child5, parent->childs[0]); + + child = remove_child (parent, 0, NULL); + ck_assert_ptr_eq (child, child5); + ck_assert_ptr_eq (NULL, child->parent); + SH_Fragment_free (child5); + ck_assert_int_eq (5, parent->child_s); + ck_assert_int_eq (1, parent->child_n); + ck_assert_ptr_eq (child6, parent->childs[0]); + + child = remove_child (parent, 0, NULL); + ck_assert_ptr_eq (child, child6); + ck_assert_ptr_eq (NULL, child->parent); + SH_Fragment_free (child6); + ck_assert_int_eq (0, parent->child_s); + ck_assert_int_eq (0, parent->child_n); + + SH_NodeFragment_free (parent); + + SH_Data_free (data); +} +END_TEST + +START_TEST(test_node_fragment_child_remove_with_status) +{ + struct SH_Status status; + struct SH_NodeFragment * parent; + struct SH_Fragment * child; + struct SH_Fragment * child1; + struct SH_Fragment * child2; + struct SH_Fragment * child3; + struct SH_Fragment * child4; + struct SH_Fragment * child5; + struct SH_Fragment * child6; + SH_Data * data; + bool result; + + data = SH_Data_new (NULL); + + parent = (struct SH_NodeFragment *)SH_NodeFragment_new ("body", + data, + NULL); + child1 = SH_NodeFragment_new ("p", data, NULL); + child2 = SH_NodeFragment_new ("p", data, NULL); + child3 = SH_NodeFragment_new ("p", data, NULL); + child4 = SH_NodeFragment_new ("p", data, NULL); + child5 = SH_NodeFragment_new ("p", data, NULL); + child6 = SH_NodeFragment_new ("p", data, NULL); + + result = SH_NodeFragment_append_child (parent, child1, NULL); + ck_assert_int_eq (TRUE, result); + + result = SH_NodeFragment_append_child (parent, child2, NULL); + ck_assert_int_eq (TRUE, result); + + result = SH_NodeFragment_append_child (parent, child3, NULL); + ck_assert_int_eq (TRUE, result); + + result = SH_NodeFragment_append_child (parent, child4, NULL); + ck_assert_int_eq (TRUE, result); + + result = SH_NodeFragment_append_child (parent, child5, NULL); + ck_assert_int_eq (TRUE, result); + + result = SH_NodeFragment_append_child (parent, child6, NULL); + ck_assert_int_eq (TRUE, result); + + + ck_assert_int_eq (10, parent->child_s); + ck_assert_int_eq (6, parent->child_n); + ck_assert_ptr_eq (child1, parent->childs[0]); + + _status_preinit (status); + child = remove_child (parent, 0, &status); + ck_assert_ptr_eq (child, child1); + ck_assert_ptr_eq (NULL, child->parent); + ck_assert (succeed (&status)); + SH_Fragment_free (child1); + ck_assert_int_eq (5, parent->child_s); + ck_assert_int_eq (5, parent->child_n); + ck_assert_ptr_eq (child2, parent->childs[0]); + + _status_preinit (status); + child = remove_child (parent, 0, &status); + ck_assert_ptr_eq (child, child2); + ck_assert_ptr_eq (NULL, child->parent); + ck_assert (succeed (&status)); + SH_Fragment_free (child2); + ck_assert_int_eq (5, parent->child_s); + ck_assert_int_eq (4, parent->child_n); + ck_assert_ptr_eq (child3, parent->childs[0]); + + _status_preinit (status); + child = remove_child (parent, 0, &status); + ck_assert_ptr_eq (child, child3); + ck_assert_ptr_eq (NULL, child->parent); + ck_assert (succeed (&status)); + SH_Fragment_free (child3); + ck_assert_int_eq (5, parent->child_s); + ck_assert_int_eq (3, parent->child_n); + ck_assert_ptr_eq (child4, parent->childs[0]); + + _status_preinit (status); + child = remove_child (parent, 0, &status); + ck_assert_ptr_eq (child, child4); + ck_assert_ptr_eq (NULL, child->parent); + ck_assert (succeed (&status)); + SH_Fragment_free (child4); + ck_assert_int_eq (5, parent->child_s); + ck_assert_int_eq (2, parent->child_n); + ck_assert_ptr_eq (child5, parent->childs[0]); + + _status_preinit (status); + child = remove_child (parent, 0, &status); + ck_assert_ptr_eq (child, child5); + ck_assert_ptr_eq (NULL, child->parent); + ck_assert (succeed (&status)); + SH_Fragment_free (child5); + ck_assert_int_eq (5, parent->child_s); + ck_assert_int_eq (1, parent->child_n); + ck_assert_ptr_eq (child6, parent->childs[0]); + + _status_preinit (status); + child = remove_child (parent, 0, &status); + ck_assert_ptr_eq (child, child6); + ck_assert_ptr_eq (NULL, child->parent); + ck_assert (succeed (&status)); + SH_Fragment_free (child6); + ck_assert_int_eq (0, parent->child_s); + ck_assert_int_eq (0, parent->child_n); + + SH_NodeFragment_free (parent); + + SH_Data_free (data); +} +END_TEST + +START_TEST(test_node_fragment_child_remove_remove_self_no_status) +{ + struct SH_Fragment * parent; + struct SH_Fragment * child; + SH_Data * data; + bool result; + + data = SH_Data_new (NULL); + + parent = SH_NodeFragment_new ("html", data, NULL); + child = SH_NodeFragment_new ("head", data, NULL); + + result = SH_NodeFragment_append_child ((struct SH_NodeFragment *) + parent, child, NULL); + ck_assert_int_eq (TRUE, result); + + /* test erroneous call */ + result = SH_Fragment_remove (parent, NULL); + ck_assert_int_eq (FALSE, result); + + /* test real */ + result = SH_Fragment_remove (child, NULL); + ck_assert_int_eq (TRUE, result); + + /* test bug check */ + child->parent = (struct SH_NodeFragment *)parent; + result = SH_Fragment_remove (child, NULL); + ck_assert_int_eq (FALSE, result); + + SH_Fragment_free (parent); + SH_Fragment_free (child); + + SH_Data_free (data); +} +END_TEST + +START_TEST(test_node_fragment_child_remove_remove_self_with_status) +{ + struct SH_Status status; + struct SH_Fragment * parent; + struct SH_Fragment * child; + SH_Data * data; + bool result; + + data = SH_Data_new (NULL); + + parent = SH_NodeFragment_new ("html", data, NULL); + child = SH_NodeFragment_new ("head", data, NULL); + + result = SH_NodeFragment_append_child ((struct SH_NodeFragment *) + parent, child, NULL); + ck_assert_int_eq (TRUE, result); + + /* test erroneous call */ + _status_preinit (status); + result = SH_Fragment_remove (parent, &status); + ck_assert_int_eq (FALSE, result); + ck_assert (failed (&status)); + ck_assert_int_eq (E_STATE, status.status); + + /* test real */ + _status_preinit (status); + result = SH_Fragment_remove (child, &status); + ck_assert_int_eq (TRUE, result); + ck_assert (succeed (&status)); + + /* test bug check */ + child->parent = (struct SH_NodeFragment *)parent; + _status_preinit (status); + result = SH_Fragment_remove (child, &status); + ck_assert_int_eq (FALSE, result); + ck_assert (failed (&status)); + ck_assert_int_eq (E_BUG, status.status); + + SH_Fragment_free (parent); + SH_Fragment_free (child); + + SH_Data_free (data); +} +END_TEST + +START_TEST(test_node_fragment_child_remove_delete_self_no_status) +{ + struct SH_Fragment * parent; + struct SH_Fragment * child; + SH_Data * data; + bool result; + + data = SH_Data_new (NULL); + + parent = SH_NodeFragment_new ("html", data, NULL); + child = SH_NodeFragment_new ("head", data, NULL); + + /* test erroneous call */ + result = SH_Fragment_delete (parent, NULL); + ck_assert_int_eq (FALSE, result); + + /* test bug check */ + child->parent = (struct SH_NodeFragment *)parent; + result = SH_Fragment_delete (child, NULL); + ck_assert_int_eq (FALSE, result); + child->parent = NULL; + + result = SH_NodeFragment_append_child ((struct SH_NodeFragment *) + parent, child, NULL); + ck_assert_int_eq (TRUE, result); + + /* test real */ + result = SH_Fragment_delete (child, NULL); + ck_assert_int_eq (TRUE, result); + + SH_Fragment_free (parent); + + SH_Data_free (data); +} +END_TEST + +START_TEST(test_node_fragment_child_remove_delete_self_with_status) +{ + struct SH_Status status; + struct SH_Fragment * parent; + struct SH_Fragment * child; + SH_Data * data; + bool result; + + data = SH_Data_new (NULL); + + parent = SH_NodeFragment_new ("html", data, NULL); + child = SH_NodeFragment_new ("head", data, NULL); + + /* test erroneous call */ + _status_preinit (status); + result = SH_Fragment_remove (parent, &status); + ck_assert_int_eq (FALSE, result); + ck_assert (failed (&status)); + ck_assert_int_eq (E_STATE, status.status); + + /* test bug check */ + child->parent = (struct SH_NodeFragment *)parent; + _status_preinit (status); + result = SH_Fragment_delete (child, &status); + ck_assert_int_eq (FALSE, result); + ck_assert (failed (&status)); + ck_assert_int_eq (E_BUG, status.status); + child->parent = NULL; + + result = SH_NodeFragment_append_child ((struct SH_NodeFragment *) + parent, child, NULL); + ck_assert_int_eq (TRUE, result); + + /* test real */ + _status_preinit (status); + result = SH_Fragment_delete (child, &status); + ck_assert_int_eq (TRUE, result); + ck_assert (succeed (&status)); SH_Fragment_free (parent); @@ -425,6 +2776,204 @@ START_TEST(test_node_fragment_is_descendant) } END_TEST +START_TEST(test_node_fragment_child_remove_remove_no_status) +{ + struct SH_NodeFragment * parent; + struct SH_Fragment * child; + SH_Data * data; + bool result; + + data = SH_Data_new (NULL); + + parent = (struct SH_NodeFragment *)SH_NodeFragment_new ("html", + data, + NULL); + child = SH_NodeFragment_new ("body", data, NULL); + + result = SH_NodeFragment_append_child (parent, child, NULL); + ck_assert_int_eq (TRUE, result); + + result = SH_NodeFragment_remove_child (parent, 1, NULL); + ck_assert_int_eq (FALSE, result); + + result = SH_NodeFragment_remove_child (parent, 0, NULL); + ck_assert_int_eq (TRUE, result); + + SH_NodeFragment_free (parent); + SH_Fragment_free (child); + + SH_Data_free (data); +} +END_TEST + +START_TEST(test_node_fragment_child_remove_remove_with_status) +{ + struct SH_Status status; + struct SH_NodeFragment * parent; + struct SH_Fragment * child; + SH_Data * data; + bool result; + + data = SH_Data_new (NULL); + + parent = (struct SH_NodeFragment *)SH_NodeFragment_new ("html", + data, + NULL); + child = SH_NodeFragment_new ("body", data, NULL); + + result = SH_NodeFragment_append_child (parent, child, NULL); + ck_assert_int_eq (TRUE, result); + + _status_preinit (status); + result = SH_NodeFragment_remove_child (parent, 1, &status); + ck_assert_int_eq (FALSE, result); + ck_assert (failed (&status)); + ck_assert_int_eq (E_VALUE, status.status); + + _status_preinit (status); + result = SH_NodeFragment_remove_child (parent, 0, &status); + ck_assert_int_eq (TRUE, result); + ck_assert (succeed (&status)); + + SH_NodeFragment_free (parent); + SH_Fragment_free (child); + + SH_Data_free (data); +} +END_TEST + +START_TEST(test_node_fragment_child_remove_delete_no_status) +{ + struct SH_NodeFragment * parent; + struct SH_Fragment * child; + SH_Data * data; + bool result; + + data = SH_Data_new (NULL); + + parent = (struct SH_NodeFragment *)SH_NodeFragment_new ("html", + data, + NULL); + child = SH_NodeFragment_new ("body", data, NULL); + + result = SH_NodeFragment_append_child (parent, child, NULL); + ck_assert_int_eq (TRUE, result); + + result = SH_NodeFragment_delete_child (parent, 1, NULL); + ck_assert_int_eq (FALSE, result); + + result = SH_NodeFragment_delete_child (parent, 0, NULL); + ck_assert_int_eq (TRUE, result); + + SH_NodeFragment_free (parent); + + SH_Data_free (data); +} +END_TEST + +START_TEST(test_node_fragment_child_remove_delete_with_status) +{ + struct SH_Status status; + struct SH_NodeFragment * parent; + struct SH_Fragment * child; + SH_Data * data; + bool result; + + data = SH_Data_new (NULL); + + parent = (struct SH_NodeFragment *)SH_NodeFragment_new ("html", + data, + NULL); + child = SH_NodeFragment_new ("body", data, NULL); + + result = SH_NodeFragment_append_child (parent, child, NULL); + ck_assert_int_eq (TRUE, result); + + _status_preinit (status); + result = SH_NodeFragment_delete_child (parent, 1, &status); + ck_assert_int_eq (FALSE, result); + ck_assert (failed (&status)); + ck_assert_int_eq (E_VALUE, status.status); + + _status_preinit (status); + result = SH_NodeFragment_delete_child (parent, 0, &status); + ck_assert_int_eq (TRUE, result); + ck_assert (succeed (&status)); + + SH_NodeFragment_free (parent); + + SH_Data_free (data); +} +END_TEST + +START_TEST(test_node_fragment_child_remove_pop_no_status) +{ + struct SH_NodeFragment * parent; + struct SH_Fragment * child; + struct SH_Fragment * child1; + SH_Data * data; + bool result; + + data = SH_Data_new (NULL); + + parent = (struct SH_NodeFragment *)SH_NodeFragment_new ("html", + data, + NULL); + child1 = SH_NodeFragment_new ("body", data, NULL); + + result = SH_NodeFragment_append_child (parent, child1, NULL); + ck_assert_int_eq (TRUE, result); + + child = SH_NodeFragment_pop_child (parent, 1, NULL); + ck_assert_ptr_eq (NULL, child); + + child = SH_NodeFragment_pop_child (parent, 0, NULL); + ck_assert_ptr_eq (child, child1); + + SH_NodeFragment_free (parent); + SH_Fragment_free (child); + + SH_Data_free (data); +} +END_TEST + +START_TEST(test_node_fragment_child_remove_pop_with_status) +{ + struct SH_Status status; + struct SH_NodeFragment * parent; + struct SH_Fragment * child; + struct SH_Fragment * child1; + SH_Data * data; + bool result; + + data = SH_Data_new (NULL); + + parent = (struct SH_NodeFragment *)SH_NodeFragment_new ("html", + data, + NULL); + child1 = SH_NodeFragment_new ("body", data, NULL); + + result = SH_NodeFragment_append_child (parent, child1, NULL); + ck_assert_int_eq (TRUE, result); + + _status_preinit (status); + child = SH_NodeFragment_pop_child (parent, 1, &status); + ck_assert_ptr_eq (NULL, child); + ck_assert (failed (&status)); + ck_assert_int_eq (E_VALUE, status.status); + + _status_preinit (status); + child = SH_NodeFragment_pop_child (parent, 0, &status); + ck_assert_ptr_eq (child, child1); + ck_assert (succeed (&status)); + + SH_NodeFragment_free (parent); + SH_Fragment_free (child); + + SH_Data_free (data); +} +END_TEST + START_TEST(test_node_fragment_html) { struct SH_Status status; @@ -448,6 +2997,7 @@ START_TEST(test_node_fragment_html) string = SH_Text_get_string (text, 0, SIZE_MAX, &length, NULL); ck_assert_str_eq (string, "<html><body></body></html>"); free (string); + SH_Text_free (text); text = SH_Fragment_to_html (fragment1, WRAP, 0, 1, INDENT_TEXT, NULL); @@ -455,6 +3005,7 @@ START_TEST(test_node_fragment_html) ck_assert_str_eq (string, "<html>\n\t<body>\n\t</body>\n</html>\n"); free (string); + SH_Text_free (text); SH_Fragment_free (fragment1); @@ -470,6 +3021,7 @@ START_TEST(test_node_fragment_html) string = SH_Text_get_string (text, 0, SIZE_MAX, &length, NULL); ck_assert_str_eq (string, "<html><body></body></html>"); free (string); + SH_Text_free (text); ck_assert_int_eq (status.status, SUCCESS); _status_preinit (status); @@ -479,6 +3031,7 @@ START_TEST(test_node_fragment_html) ck_assert_str_eq (string, "<html>\n\t<body>\n\t</body>\n</html>\n"); free (string); + SH_Text_free (text); ck_assert_int_eq (status.status, SUCCESS); SH_Fragment_free (fragment1); @@ -496,14 +3049,57 @@ Suite * fragment_suite (void) /* Core test case */ tc_core = tcase_create ("Core"); - tcase_add_test (tc_core, test_node_fragment); - tcase_add_test (tc_core, test_node_fragment_copy); - tcase_add_test (tc_core, test_node_fragment_deepcopy); - tcase_add_test (tc_core, test_node_fragment_tag); + tcase_add_test (tc_core, test_node_fragment_no_status); + tcase_add_test (tc_core, test_node_fragment_with_status); + tcase_add_test (tc_core, test_node_fragment_raw_no_status); + tcase_add_test (tc_core, test_node_fragment_raw_with_status); + tcase_add_test (tc_core, test_node_fragment_copy_no_status); + tcase_add_test (tc_core, test_node_fragment_copy_with_status); + tcase_add_test (tc_core, test_node_fragment_deepcopy_no_status); + tcase_add_test (tc_core, test_node_fragment_deepcopy_with_status); + tcase_add_test (tc_core, test_node_fragment_tag_no_status); + tcase_add_test (tc_core, test_node_fragment_tag_with_status); + tcase_add_test (tc_core, test_node_fragment_tag_raw); + tcase_add_test (tc_core, test_node_fragment_attr_alloc); + tcase_add_test (tc_core, test_node_fragment_attr_get_no_status); + tcase_add_test (tc_core, test_node_fragment_attr_get_with_status); + tcase_add_test (tc_core, test_node_fragment_attr_insert_no_status); + 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_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_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_child_alloc); tcase_add_test (tc_core, test_node_fragment_child); tcase_add_test (tc_core, test_node_fragment_get_child); tcase_add_test (tc_core, test_node_fragment_is_child); tcase_add_test (tc_core, test_node_fragment_is_descendant); + tcase_add_test (tc_core, test_node_fragment_is_parent); + tcase_add_test (tc_core, test_node_fragment_is_ancestor); + tcase_add_test (tc_core, test_node_fragment_child_insert_no_status); + tcase_add_test (tc_core, test_node_fragment_child_insert_with_status); + tcase_add_test (tc_core, test_node_fragment_child_insert_insert_no_status); + tcase_add_test (tc_core, test_node_fragment_child_insert_insert_with_status); + tcase_add_test (tc_core, test_node_fragment_child_insert_relative_no_status); + tcase_add_test (tc_core, test_node_fragment_child_insert_relative_with_status); + tcase_add_test (tc_core, test_node_fragment_child_remove_no_status); + tcase_add_test (tc_core, test_node_fragment_child_remove_with_status); + tcase_add_test (tc_core, test_node_fragment_child_remove_remove_self_no_status); + tcase_add_test (tc_core, test_node_fragment_child_remove_remove_self_with_status); + tcase_add_test (tc_core, test_node_fragment_child_remove_delete_self_no_status); + tcase_add_test (tc_core, test_node_fragment_child_remove_delete_self_with_status); + tcase_add_test (tc_core, test_node_fragment_child_remove_remove_no_status); + tcase_add_test (tc_core, test_node_fragment_child_remove_remove_with_status); + tcase_add_test (tc_core, test_node_fragment_child_remove_delete_no_status); + tcase_add_test (tc_core, test_node_fragment_child_remove_delete_with_status); + tcase_add_test (tc_core, test_node_fragment_child_remove_pop_no_status); + tcase_add_test (tc_core, test_node_fragment_child_remove_pop_with_status); tcase_add_test (tc_core, test_node_fragment_html); suite_add_tcase (s, tc_core);