Skip to content
Snippets Groups Projects
Commit 13ac85b5 authored by Jonathan Schöbel's avatar Jonathan Schöbel
Browse files

NodeFragment: added getter & insert methods for attributes

The method SH_NodeFragment_get_attr provides a pointer to an Attr, by
its index. Note, that it directly points to the internal data, instead
of copying the data to a new Attr, which would be unneccessary overhead,
if only reading access is needed. That's why it is also a const pointer.
If the user intends to modify it, a copy should be taken via
SH_Attr_copy.

Multiple insert methods allow either to add an existing Attr, or to
create a new one implicitly. If the Attr is not already used beforehand,
it is more efficient to call the attr_new methods. Also an old Attr is
freed, after it was inserted, thus it can't be used afterwards. This is
neccessary, as for efficiency reasons an array of Attr is used directly,
instead of the indirect approach of storing a pointer of Attr. This
means, that the contents of the Attr has to be copied to the internal
structure. If the old Attr would be left unfreed, there would be two
Attrs, the original one and the implicit one, referring to the same
data, which would lead to at least data corruption, or undefined
behaviour like a double free, which would be a serious threat for a
library which is to be used on a webserver. ...
For each of the two insert modes, there is a method to prepend, append
or insert at a specific position. An incorrect position is handled
inside of the external method and an E_VALUE is thrown. The internal
method doesn't handle this, so special care must be taken to not make
undefined behaviour. However enforcing this check would be unneccessary
overhead for the prepend and append methods, which are known to have
correct indicies, as well for other internal methods, where the internal
method may be used.

The tests for the new methods are still missing, as well as the methods
to remove an Attr. As the implementation is already a bit dated, the
changes are commited now anyways.
parent a94eb0b6
No related branches found
No related tags found
No related merge requests found
......@@ -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=10722;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=2403;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=16481;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_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
......
......@@ -520,6 +520,262 @@ SH_NodeFragment_count_attrs (const struct SH_NodeFragment * fragment)
return fragment->attr_n;
}
/*@null@*/
/*@observer@*/
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->attr_n)
{
set_status (status, E_VALUE, 2,
"Fragment: Attr index out of range.\n");
return NULL;
}
set_success (status);
return &(fragment->attrs[index]);
}
static inline
bool
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;
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];
}
Attr_move (&(fragment->attrs[position]), attr);
fragment->attr_n++;
set_success (status);
return TRUE;
}
static inline
bool
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;
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];
}
Attr_raw_init (&(fragment->attrs[position]), name, value);
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_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_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);
}
size_t
SH_NodeFragment_count_childs (const struct SH_NodeFragment * fragment)
/*@*/
......
......@@ -31,6 +31,7 @@
#include "status.h"
#include "attr.h"
#include "data.h"
#include "text.h"
......@@ -90,6 +91,82 @@ 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_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_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@*/;
/*@null@*/
/*@only@*/
char *
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment