diff array.c @ 136:c6d9eb5702e8

array: o add ARRAY_FASTREMOVE, use last object when removing, o add ARRAY_CLEARBITS, set to 0 the bytes when removing parray: o add PARRAY_FASTREMOVE, use last object when removing, o add PARRAY_NULLEND, always has a last NULL entry
author David Demelier <markand@malikania.fr>
date Mon, 26 Mar 2012 10:24:49 +0200
parents 5917096facb9
children e3cf5ac9a5aa
line wrap: on
line diff
--- a/array.c	Tue Mar 20 22:49:37 2012 +0100
+++ b/array.c	Mon Mar 26 10:24:49 2012 +0200
@@ -43,6 +43,9 @@
 	if ((arr->data = arr->malloc(arr->size)) == NULL)
 		return -1;
 
+	if (arr->flags & ARRAY_CLEARBITS)
+		memset(arr->data, 0, arr->size);
+
 	return 0;
 }
 
@@ -51,7 +54,7 @@
  * l -> optional array block size of type int
  * m -> malloc function that must matches void * (*malloc)(size_t)
  * r -> realloc function that must matches void * (*realloc)(void *, size_t)
- * t -> type of array of type int
+ * f -> array flags of type int
  */
 
 void
@@ -72,8 +75,8 @@
 		case 'r':
 			arr->realloc = va_arg(ap, void *(*)(void *, size_t));
 			break;
-		case 't':
-			arr->type = va_arg(ap, int);
+		case 'f':
+			arr->flags = va_arg(ap, int);
 			break;
 		default:
 			break;
@@ -141,11 +144,7 @@
 void
 array_pop(struct array *arr)
 {
-	if (arr->length > 0) {
-		memmove((char *)arr->data, (char *)arr->data + OFFSET(1),
-		    OFFSET(--arr->length));
-		memset((char *)arr->data + OFFSET(arr->length), 0, arr->unit);
-	}
+	array_iremove(arr, 0);
 }
 
 /*
@@ -155,8 +154,7 @@
 void
 array_unqueue(struct array *arr)
 {
-	if (arr->length > 0)
-		memset((char *)arr->data + OFFSET(--arr->length), 0, arr->unit);
+	array_iremove(arr, arr->length - 1);
 }
 
 /*
@@ -167,11 +165,18 @@
 array_iremove(struct array *arr, int index)
 {
 	if (arr->length > 0 && index >= 0 && index < arr->length) {
-		memmove((char *)arr->data + OFFSET(index),
-		    (char *)arr->data + OFFSET(index + 1),
-		    OFFSET(arr->length - index - 1));
-		memset((char *)arr->data + OFFSET(--arr->length), 0, arr->unit);
+		if (arr->flags & ARRAY_FASTREMOVE)
+			memmove((char *)arr->data + OFFSET(index),
+			    (char *)arr->data + OFFSET(--arr->length),
+			    arr->unit);
+		else
+			memmove((char *)arr->data + OFFSET(index),
+			    (char *)arr->data + OFFSET(index + 1),
+			    OFFSET(arr->length-- - index - 1));
 	}
+
+	if (arr->flags & ARRAY_CLEARBITS)
+		memset((char *)arr->data + OFFSET(arr->length), 0, arr->unit);
 }
 
 /*
@@ -188,8 +193,10 @@
 	for (i = 0; i < arr->length; ++i) {
 		elm = (char *)arr->data + OFFSET(i);
 
-		if (memcmp(elm, data, arr->unit) == 0)
+		if (memcmp(elm, data, arr->unit) == 0) {
 			array_iremove(arr, i);
+			break;
+		}
 	}
 }
 
@@ -208,11 +215,6 @@
 	if (i1 >= arr->length || i1 < 0 || i2 >= arr->length || i2 < 0)
 		return -1;
 
-	/*
-	 * Only allocate at this time, the user may do not want to use this
-	 * function.
-	 */
-
 	if ((tmp = arr->malloc(arr->unit)) == NULL)
 		return -1;
 
@@ -226,7 +228,8 @@
 	 * secure data to be left somewhere in the memory.
 	 */
 
-	memset(tmp, 0, arr->unit);
+	if (arr->flags & ARRAY_CLEARBITS)
+		memset(tmp, 0, arr->unit);
 	free(tmp);
 
 	return 0;
@@ -292,6 +295,33 @@
 	return (st) ? i - 1 : -1;
 }
 
+void *
+array_first(const struct array *arr)
+{
+	return arr->data;
+}
+
+void *
+array_last(const struct array *arr)
+{
+	if (arr->length == 0)
+		return array_first(arr);
+
+	return (char *)arr->data + OFFSET(arr->length - 1);
+
+}
+
+void *
+array_index(const struct array *arr, int idx)
+{
+	if (idx < 0)
+		return array_first(arr);
+	if (idx >= arr->length)
+		return array_last(arr);
+
+	return (char *)arr->data + OFFSET(idx);
+}
+
 /*
  * Erase every bytes and set the length to 0.
  */
@@ -299,7 +329,9 @@
 void
 array_clear(struct array *arr)
 {
-	memset(arr->data, 0, arr->size);
+	if (arr->flags & ARRAY_CLEARBITS)
+		memset(arr->data, 0, arr->size);
+
 	arr->length = 0;
 }
 
@@ -310,7 +342,11 @@
 void
 array_free(struct array *arr)
 {
+	array_clear(arr);
 	free(arr->data);
+
+	arr->data	= NULL;
+	arr->size	= 0;
 }
 
 /*
@@ -322,13 +358,15 @@
 static int
 grow(struct array *arr)
 {
-	if ((arr->size / arr->unit) > (size_t) arr->length)
+	if ((arr->size / arr->unit) > (size_t)arr->length)
 		return 0;
 
-	if (arr->type == ARRAY_AUTO) {
+	if (!(arr->flags & ARRAY_FIXED)) {
 		if ((arr->data = arr->realloc(arr->data, arr->size +
-		    OFFSET(arr->bsize))) == NULL)
+		    OFFSET(arr->bsize))) == NULL) {
+			arr->size = arr->length = 0;
 			return -1;
+		}
 
 		arr->size += OFFSET(arr->bsize);
 	} else