summaryrefslogtreecommitdiff
path: root/src/list.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/list.c')
-rw-r--r--src/list.c534
1 files changed, 534 insertions, 0 deletions
diff --git a/src/list.c b/src/list.c
new file mode 100644
index 00000000..d1a00533
--- /dev/null
+++ b/src/list.c
@@ -0,0 +1,534 @@
+/**
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * List of pointers.
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include "globals.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <libxml/tree.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/list.h>
+#include <xmlsec/errors.h>
+
+
+static int xmlSecPtrListEnsureSize (xmlSecPtrListPtr list,
+ xmlSecSize size);
+
+static xmlSecAllocMode gAllocMode = xmlSecAllocModeDouble;
+static xmlSecSize gInitialSize = 64;
+
+/**
+ * xmlSecPtrListSetDefaultAllocMode:
+ * @defAllocMode: the new default memory allocation mode.
+ * @defInitialSize: the new default minimal initial size.
+ *
+ * Sets new default allocation mode and minimal initial list size.
+ */
+void
+xmlSecPtrListSetDefaultAllocMode(xmlSecAllocMode defAllocMode, xmlSecSize defInitialSize) {
+ xmlSecAssert(defInitialSize > 0);
+
+ gAllocMode = defAllocMode;
+ gInitialSize = defInitialSize;
+}
+
+/**
+ * xmlSecPtrListCreate:
+ * @id: the list klass.
+ *
+ * Creates new list object. Caller is responsible for freeing returned list
+ * by calling #xmlSecPtrListDestroy function.
+ *
+ * Returns: pointer to newly allocated list or NULL if an error occurs.
+ */
+xmlSecPtrListPtr
+xmlSecPtrListCreate(xmlSecPtrListId id) {
+ xmlSecPtrListPtr list;
+ int ret;
+
+ xmlSecAssert2(id != xmlSecPtrListIdUnknown, NULL);
+
+ /* Allocate a new xmlSecPtrList and fill the fields. */
+ list = (xmlSecPtrListPtr)xmlMalloc(sizeof(xmlSecPtrList));
+ if(list == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecPtrListKlassGetName(id)),
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "sizeof(xmlSecPtrList)=%d",
+ sizeof(xmlSecPtrList));
+ return(NULL);
+ }
+
+ ret = xmlSecPtrListInitialize(list, id);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecPtrListKlassGetName(id)),
+ "xmlSecPtrListInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(list);
+ return(NULL);
+ }
+
+ return(list);
+}
+
+/**
+ * xmlSecPtrListDestroy:
+ * @list: the pointer to list.
+ *
+ * Destroys @list created with #xmlSecPtrListCreate function.
+ */
+void
+xmlSecPtrListDestroy(xmlSecPtrListPtr list) {
+ xmlSecAssert(xmlSecPtrListIsValid(list));
+ xmlSecPtrListFinalize(list);
+ xmlFree(list);
+}
+
+/**
+ * xmlSecPtrListInitialize:
+ * @list: the pointer to list.
+ * @id: the list klass.
+ *
+ * Initializes the list of given klass. Caller is responsible
+ * for cleaning up by calling #xmlSecPtrListFinalize function.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecPtrListInitialize(xmlSecPtrListPtr list, xmlSecPtrListId id) {
+ xmlSecAssert2(id != xmlSecPtrListIdUnknown, -1);
+ xmlSecAssert2(list != NULL, -1);
+
+ memset(list, 0, sizeof(xmlSecPtrList));
+ list->id = id;
+ list->allocMode = gAllocMode;
+
+ return(0);
+}
+
+/**
+ * xmlSecPtrListFinalize:
+ * @list: the pointer to list.
+ *
+ * Cleans up the list initialized with #xmlSecPtrListInitialize
+ * function.
+ */
+void
+xmlSecPtrListFinalize(xmlSecPtrListPtr list) {
+ xmlSecAssert(xmlSecPtrListIsValid(list));
+
+ xmlSecPtrListEmpty(list);
+ memset(list, 0, sizeof(xmlSecPtrList));
+}
+
+/**
+ * xmlSecPtrListEmpty:
+ * @list: the pointer to list.
+ *
+ * Remove all items from @list (if any).
+ */
+void
+xmlSecPtrListEmpty(xmlSecPtrListPtr list) {
+ xmlSecAssert(xmlSecPtrListIsValid(list));
+
+ if(list->id->destroyItem != NULL) {
+ xmlSecSize pos;
+
+ for(pos = 0; pos < list->use; ++pos) {
+ xmlSecAssert(list->data != NULL);
+ if(list->data[pos] != NULL) {
+ list->id->destroyItem(list->data[pos]);
+ }
+ }
+ }
+ if(list->max > 0) {
+ xmlSecAssert(list->data != NULL);
+
+ memset(list->data, 0, sizeof(xmlSecPtr) * list->use);
+ xmlFree(list->data);
+ }
+ list->max = list->use = 0;
+ list->data = NULL;
+}
+
+/**
+ * xmlSecPtrListCopy:
+ * @dst: the pointer to destination list.
+ * @src: the pointer to source list.
+ *
+ * Copies @src list items to @dst list using #duplicateItem method
+ * of the list klass. If #duplicateItem method is NULL then
+ * we jsut copy pointers to items.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecPtrListCopy(xmlSecPtrListPtr dst, xmlSecPtrListPtr src) {
+ xmlSecSize i;
+ int ret;
+
+ xmlSecAssert2(xmlSecPtrListIsValid(dst), -1);
+ xmlSecAssert2(xmlSecPtrListIsValid(src), -1);
+ xmlSecAssert2(dst->id == src->id, -1);
+
+ /* allocate memory */
+ ret = xmlSecPtrListEnsureSize(dst, dst->use + src->use);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecPtrListGetName(src)),
+ "xmlSecPtrListEnsureSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", src->use);
+ return(-1);
+ }
+
+ /* copy one item after another */
+ for(i = 0; i < src->use; ++i, ++dst->use) {
+ xmlSecAssert2(src->data != NULL, -1);
+ xmlSecAssert2(dst->data != NULL, -1);
+
+ if((dst->id->duplicateItem != NULL) && (src->data[i] != NULL)) {
+ dst->data[dst->use] = dst->id->duplicateItem(src->data[i]);
+ if(dst->data[dst->use] == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecPtrListGetName(src)),
+ "duplicateItem",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ } else {
+ dst->data[dst->use] = src->data[i];
+ }
+ }
+
+ return(0);
+}
+
+/**
+ * xmlSecPtrListDuplicate:
+ * @list: the pointer to list.
+ *
+ * Creates a new copy of @list and all its items.
+ *
+ * Returns: pointer to newly allocated list or NULL if an error occurs.
+ */
+xmlSecPtrListPtr
+xmlSecPtrListDuplicate(xmlSecPtrListPtr list) {
+ xmlSecPtrListPtr newList;
+ int ret;
+
+ xmlSecAssert2(xmlSecPtrListIsValid(list), NULL);
+
+ newList = xmlSecPtrListCreate(list->id);
+ if(newList == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecPtrListGetName(list)),
+ "xmlSecPtrListCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(NULL);
+ }
+
+ ret = xmlSecPtrListCopy(newList, list);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecPtrListGetName(list)),
+ "xmlSecPtrListCopy",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecPtrListDestroy(newList);
+ return(NULL);
+ }
+ return(newList);
+}
+
+/**
+ * xmlSecPtrListGetSize:
+ * @list: the pointer to list.
+ *
+ * Gets list size.
+ *
+ * Returns: the number of itmes in @list.
+ */
+xmlSecSize
+xmlSecPtrListGetSize(xmlSecPtrListPtr list) {
+ xmlSecAssert2(xmlSecPtrListIsValid(list), 0);
+
+ return(list->use);
+}
+
+/**
+ * xmlSecPtrListGetItem:
+ * @list: the pointer to list.
+ * @pos: the item position.
+ *
+ * Gets item from the list.
+ *
+ * Returns: the list item at position @pos or NULL if @pos is greater
+ * than the number of items in the list or an error occurs.
+ */
+xmlSecPtr
+xmlSecPtrListGetItem(xmlSecPtrListPtr list, xmlSecSize pos) {
+ xmlSecAssert2(xmlSecPtrListIsValid(list), NULL);
+ xmlSecAssert2(list->data != NULL, NULL);
+ xmlSecAssert2(pos < list->use, NULL);
+
+ return(list->data[pos]);
+}
+
+/**
+ * xmlSecPtrListAdd:
+ * @list: the pointer to list.
+ * @item: the item.
+ *
+ * Adds @item to the end of the @list.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecPtrListAdd(xmlSecPtrListPtr list, xmlSecPtr item) {
+ int ret;
+
+ xmlSecAssert2(xmlSecPtrListIsValid(list), -1);
+
+ ret = xmlSecPtrListEnsureSize(list, list->use + 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecPtrListGetName(list)),
+ "xmlSecPtrListAdd",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", list->use + 1);
+ return(-1);
+ }
+
+ list->data[list->use++] = item;
+ return(0);
+}
+
+/**
+ * xmlSecPtrListSet:
+ * @list: the pointer to list.
+ * @item: the item.
+ * @pos: the pos.
+ *
+ * Sets the value of list item at position @pos. The old value
+ * is destroyed.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecPtrListSet(xmlSecPtrListPtr list, xmlSecPtr item, xmlSecSize pos) {
+ xmlSecAssert2(xmlSecPtrListIsValid(list), -1);
+ xmlSecAssert2(list->data != NULL, -1);
+ xmlSecAssert2(pos < list->use, -1);
+
+ if((list->id->destroyItem != NULL) && (list->data[pos] != NULL)) {
+ list->id->destroyItem(list->data[pos]);
+ }
+ list->data[pos] = item;
+ return(0);
+}
+
+/**
+ * xmlSecPtrListRemove:
+ * @list: the pointer to list.
+ * @pos: the position.
+ *
+ * Destroys list item at the position @pos and sets it value to NULL.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecPtrListRemove(xmlSecPtrListPtr list, xmlSecSize pos) {
+ xmlSecAssert2(xmlSecPtrListIsValid(list), -1);
+ xmlSecAssert2(list->data != NULL, -1);
+ xmlSecAssert2(pos < list->use, -1);
+
+ if((list->id->destroyItem != NULL) && (list->data[pos] != NULL)) {
+ list->id->destroyItem(list->data[pos]);
+ }
+ list->data[pos] = NULL;
+ if(pos == list->use - 1) {
+ --list->use;
+ }
+ return(0);
+}
+
+/**
+ * xmlSecPtrListRemoveAndReturn:
+ * @list: the pointer to list.
+ * @pos: the position.
+ *
+ * Remove the list item at the position @pos and return it back.
+ *
+ * Returns: the pointer to the list item.
+ */
+xmlSecPtr
+xmlSecPtrListRemoveAndReturn(xmlSecPtrListPtr list, xmlSecSize pos) {
+ xmlSecPtr res;
+
+ xmlSecAssert2(xmlSecPtrListIsValid(list), NULL);
+ xmlSecAssert2(list->data != NULL, NULL);
+ xmlSecAssert2(pos < list->use, NULL);
+
+ res = list->data[pos];
+ list->data[pos] = NULL;
+ if(pos == list->use - 1) {
+ --list->use;
+ }
+ return(res);
+}
+
+
+/**
+ * xmlSecPtrListDebugDump:
+ * @list: the pointer to list.
+ * @output: the pointer to output FILE.
+ *
+ * Prints debug information about @list to the @output.
+ */
+void
+xmlSecPtrListDebugDump(xmlSecPtrListPtr list, FILE* output) {
+ xmlSecAssert(xmlSecPtrListIsValid(list));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "=== list size: %d\n", list->use);
+ if(list->id->debugDumpItem != NULL) {
+ xmlSecSize pos;
+
+ for(pos = 0; pos < list->use; ++pos) {
+ xmlSecAssert(list->data != NULL);
+ if(list->data[pos] != NULL) {
+ list->id->debugDumpItem(list->data[pos], output);
+ }
+ }
+ }
+}
+
+/**
+ * xmlSecPtrListDebugXmlDump:
+ * @list: the pointer to list.
+ * @output: the pointer to output FILE.
+ *
+ * Prints debug information about @list to the @output in XML format.
+ */
+void
+xmlSecPtrListDebugXmlDump(xmlSecPtrListPtr list, FILE* output) {
+ xmlSecAssert(xmlSecPtrListIsValid(list));
+ xmlSecAssert(output != NULL);
+
+ fprintf(output, "<List size=\"%d\">\n", list->use);
+ if(list->id->debugXmlDumpItem != NULL) {
+ xmlSecSize pos;
+
+ for(pos = 0; pos < list->use; ++pos) {
+ xmlSecAssert(list->data != NULL);
+ if(list->data[pos] != NULL) {
+ list->id->debugXmlDumpItem(list->data[pos], output);
+ }
+ }
+ }
+ fprintf(output, "</List>\n");
+}
+
+static int
+xmlSecPtrListEnsureSize(xmlSecPtrListPtr list, xmlSecSize size) {
+ xmlSecPtr* newData;
+ xmlSecSize newSize = 0;
+
+ xmlSecAssert2(xmlSecPtrListIsValid(list), -1);
+
+ if(size < list->max) {
+ return(0);
+ }
+
+ switch(list->allocMode) {
+ case xmlSecAllocModeExact:
+ newSize = size + 8;
+ break;
+ case xmlSecAllocModeDouble:
+ newSize = 2 * size + 32;
+ break;
+ }
+
+ if(newSize < gInitialSize) {
+ newSize = gInitialSize;
+ }
+
+ if(list->data != NULL) {
+ newData = (xmlSecPtr*)xmlRealloc(list->data, sizeof(xmlSecPtr) * newSize);
+ } else {
+ newData = (xmlSecPtr*)xmlMalloc(sizeof(xmlSecPtr) * newSize);
+ }
+ if(newData == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecPtrListGetName(list)),
+ NULL,
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ "sizeof(xmlSecPtr)*%d=%d",
+ newSize, sizeof(xmlSecPtr) * newSize);
+ return(-1);
+ }
+
+ list->data = newData;
+ list->max = newSize;
+
+ return(0);
+}
+
+/***********************************************************************
+ *
+ * strings list
+ *
+ **********************************************************************/
+static xmlSecPtr xmlSecStringListDuplicateItem (xmlSecPtr ptr);
+static void xmlSecStringListDestroyItem (xmlSecPtr ptr);
+
+static xmlSecPtrListKlass xmlSecStringListKlass = {
+ BAD_CAST "strings-list",
+ xmlSecStringListDuplicateItem, /* xmlSecPtrDuplicateItemMethod duplicateItem; */
+ xmlSecStringListDestroyItem, /* xmlSecPtrDestroyItemMethod destroyItem; */
+ NULL, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
+ NULL, /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
+};
+
+/**
+ * xmlSecStringListGetKlass:
+ *
+ * The strins list class.
+ *
+ * Returns: strings list klass.
+ */
+xmlSecPtrListId
+xmlSecStringListGetKlass(void) {
+ return(&xmlSecStringListKlass);
+}
+
+static xmlSecPtr
+xmlSecStringListDuplicateItem(xmlSecPtr ptr) {
+ xmlSecAssert2(ptr != NULL, NULL);
+
+ return(xmlStrdup((xmlChar*)ptr));
+}
+
+static void
+xmlSecStringListDestroyItem(xmlSecPtr ptr) {
+ xmlSecAssert(ptr != NULL);
+
+ xmlFree(ptr);
+}
+
+