summaryrefslogtreecommitdiffstats
path: root/libcutils/array.c
diff options
context:
space:
mode:
Diffstat (limited to 'libcutils/array.c')
-rw-r--r--libcutils/array.c155
1 files changed, 155 insertions, 0 deletions
diff --git a/libcutils/array.c b/libcutils/array.c
new file mode 100644
index 0000000..ff2c8ff
--- /dev/null
+++ b/libcutils/array.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cutils/array.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define INITIAL_CAPACITY (4)
+
+struct Array {
+ void** contents;
+ int size;
+ int capacity;
+};
+
+Array* arrayCreate() {
+ return calloc(1, sizeof(struct Array));
+}
+
+void arrayFree(Array* array) {
+ assert(array != NULL);
+
+ // Free internal array.
+ free(array->contents);
+
+ // Free the Array itself.
+ free(array);
+}
+
+/** Returns 0 if successful, < 0 otherwise.. */
+static int ensureCapacity(Array* array, int capacity) {
+ int oldCapacity = array->capacity;
+ if (capacity > oldCapacity) {
+ int newCapacity = (oldCapacity == 0) ? INITIAL_CAPACITY : oldCapacity * 2;
+
+ // Keep doubling capacity until we surpass necessary capacity.
+ while (newCapacity < capacity) {
+ newCapacity *= 2;
+ }
+
+ void** newContents;
+ if (array->contents == NULL) {
+ // Allocate new array.
+ newContents = malloc(newCapacity * sizeof(void*));
+ if (newContents == NULL) {
+ return -1;
+ }
+ } else {
+ // Expand existing array.
+ newContents = realloc(array->contents, sizeof(void*) * newCapacity);
+ if (newContents == NULL) {
+ return -1;
+ }
+ }
+
+ array->capacity = newCapacity;
+ array->contents = newContents;
+ }
+
+ return 0;
+}
+
+int arrayAdd(Array* array, void* pointer) {
+ assert(array != NULL);
+ int size = array->size;
+ int result = ensureCapacity(array, size + 1);
+ if (result < 0) {
+ return result;
+ }
+ array->contents[size] = pointer;
+ array->size++;
+ return 0;
+}
+
+static inline void checkBounds(Array* array, int index) {
+ assert(array != NULL);
+ assert(index < array->size);
+ assert(index >= 0);
+}
+
+void* arrayGet(Array* array, int index) {
+ checkBounds(array, index);
+ return array->contents[index];
+}
+
+void* arrayRemove(Array* array, int index) {
+ checkBounds(array, index);
+
+ void* pointer = array->contents[index];
+
+ int newSize = array->size - 1;
+
+ // Shift entries left.
+ if (index != newSize) {
+ memmove(array->contents + index, array->contents + index + 1,
+ (sizeof(void*)) * (newSize - index));
+ }
+
+ array->size = newSize;
+
+ return pointer;
+}
+
+void* arraySet(Array* array, int index, void* pointer) {
+ checkBounds(array, index);
+ void* old = array->contents[index];
+ array->contents[index] = pointer;
+ return old;
+}
+
+int arraySetSize(Array* array, int newSize) {
+ assert(array != NULL);
+ assert(newSize >= 0);
+
+ int oldSize = array->size;
+
+ if (newSize > oldSize) {
+ // Expand.
+ int result = ensureCapacity(array, newSize);
+ if (result < 0) {
+ return result;
+ }
+
+ // Zero out new entries.
+ memset(array->contents + sizeof(void*) * oldSize, 0,
+ sizeof(void*) * (newSize - oldSize));
+ }
+
+ array->size = newSize;
+
+ return 0;
+}
+
+int arraySize(Array* array) {
+ assert(array != NULL);
+ return array->size;
+}
+
+const void** arrayUnwrap(Array* array) {
+ return array->contents;
+}