From 7ccc8bee02991f3044884492b0881e9270e4c97a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonathan=20Sch=C3=B6bel?= <jonathan@xn--schbel-yxa.info>
Date: Thu, 1 Jun 2023 23:47:20 +0200
Subject: [PATCH] NodeFragment: added insert_copy methods for attributes

Sometimes you want to reuse an Attr after adding it, this is done via
the insert_copy methods.
---
 sefht.geany                   |   6 +-
 src/lib/sefht/node_fragment.c | 122 ++++++++++++++++++++++++++++++++++
 src/lib/sefht/node_fragment.h |  30 +++++++++
 3 files changed, 155 insertions(+), 3 deletions(-)

diff --git a/sefht.geany b/sefht.geany
index 35460a1..1f7d93b 100644
--- a/sefht.geany
+++ b/sefht.geany
@@ -28,7 +28,7 @@ long_line_behaviour=1
 long_line_column=72
 
 [files]
-current_page=12
+current_page=13
 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
@@ -41,8 +41,8 @@ FILE_NAME_8=1550;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fpr
 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=26203;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=4703;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_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=1393;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=2924;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=2603;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fattr_static.c;0;8
diff --git a/src/lib/sefht/node_fragment.c b/src/lib/sefht/node_fragment.c
index b274bdd..e380b30 100644
--- a/src/lib/sefht/node_fragment.c
+++ b/src/lib/sefht/node_fragment.c
@@ -666,6 +666,74 @@ insert_attr_new (struct SH_NodeFragment * fragment,
 	return TRUE;
 }
 
+static inline
+bool
+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@*/
+{
+	size_t new_size;
+	size_t index;
+	typeof (fragment->attrs) new_attrs;
+
+	new_size = get_attr_alloc_size (fragment->attr_n + 1);
+	if (new_size > fragment->attr_s)
+	{
+		if ((SIZE_MAX / sizeof (*new_attrs)) < new_size)
+		{
+			set_status (status, E_DOMAIN, -6,
+			            "maximum number of "
+			            "attrs reached.\n");
+			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;
+	}
+
+	for (index = fragment->attr_n; index > position; index--)
+	{
+		fragment->attrs[index] = fragment->attrs[index-1];
+	}
+
+	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,
@@ -713,6 +781,29 @@ SH_NodeFragment_insert_attr_new (struct SH_NodeFragment * fragment,
 	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,
@@ -744,6 +835,21 @@ SH_NodeFragment_prepend_attr_new (struct SH_NodeFragment * fragment,
 	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,
@@ -776,6 +882,22 @@ SH_NodeFragment_append_attr_new (struct SH_NodeFragment * fragment,
 	                        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)
 	/*@*/
diff --git a/src/lib/sefht/node_fragment.h b/src/lib/sefht/node_fragment.h
index f10dede..521b1a1 100644
--- a/src/lib/sefht/node_fragment.h
+++ b/src/lib/sefht/node_fragment.h
@@ -125,6 +125,17 @@ SH_NodeFragment_insert_attr_new (SH_NodeFragment * fragment,
 	/*@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,
@@ -146,6 +157,16 @@ SH_NodeFragment_prepend_attr_new (SH_NodeFragment * fragment,
 	/*@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,
@@ -166,6 +187,15 @@ SH_NodeFragment_append_attr_new (SH_NodeFragment * 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@*/
-- 
GitLab