#include "logger.h"
#include "oic_malloc.h"
-#define TAG PCF("UARRAYLIST")
+#define TAG "UARRAYLIST"
+
+/**
+ * Use this default capacity when initialized
+ */
+#define U_ARRAYLIST_DEFAULT_CAPACITY 1
u_arraylist_t *u_arraylist_create()
{
- u_arraylist_t *list = NULL;
-
- if (!(list = (u_arraylist_t*) OICMalloc(sizeof(u_arraylist_t))))
+ u_arraylist_t *list = (u_arraylist_t *) OICCalloc(1, sizeof(u_arraylist_t));
+ if (!list)
{
+ OIC_LOG(DEBUG, TAG, "Out of memory");
return NULL;
}
- list->size = U_ARRAYLIST_DEFAULT_SIZE;
+ list->capacity = U_ARRAYLIST_DEFAULT_CAPACITY;
list->length = 0;
- if (!(list->data = (void*) OICMalloc(list->size * sizeof(void*))))
+ list->data = (void **) OICMalloc(list->capacity * sizeof(list->data[0]));
+ if (!list->data)
{
+ OIC_LOG(DEBUG, TAG, "Out of memory");
OICFree(list);
return NULL;
}
-
return list;
}
-CAResult_t u_arraylist_free(u_arraylist_t *list)
+void u_arraylist_free(u_arraylist_t **list)
{
- OICFree(list->data);
- OICFree(list);
+ if (!list || !(*list))
+ {
+ return;
+ }
+
+ OICFree((*list)->data);
+ OICFree(*list);
- list = NULL;
+ *list = NULL;
+}
- return CA_STATUS_OK;
+bool u_arraylist_reserve(u_arraylist_t *list, size_t count)
+{
+ if (list && (count > list->capacity))
+ {
+ void *tmp = OICRealloc(list->data, count * sizeof(list->data[0]));
+ if (!tmp)
+ {
+ OIC_LOG(DEBUG, TAG, "Memory reallocation failed.");
+ return false;
+ }
+ else
+ {
+ list->data = (void **) tmp;
+ list->capacity = count;
+ }
+ }
+ return true;
+}
+
+void u_arraylist_shrink_to_fit(u_arraylist_t *list)
+{
+ if (!list)
+ {
+ return;
+ }
+
+ if ((list->capacity > list->length)
+ && (list->length >= U_ARRAYLIST_DEFAULT_CAPACITY))
+ {
+ void *tmp = OICRealloc(list->data,
+ list->length * sizeof(list->data[0]));
+ if (!tmp)
+ {
+ OIC_LOG(DEBUG, TAG, "Memory reallocation failed.");
+ // Considered non-fatal as this call is non-binding.
+ }
+ else
+ {
+ list->data = (void **) tmp;
+ list->capacity = list->length;
+ }
+ }
}
void *u_arraylist_get(const u_arraylist_t *list, uint32_t index)
{
- if (index >= list->length)
+ if (!list )
{
return NULL;
}
- if (list->data)
+ if ((index < list->length) && (list->data))
{
return list->data[index];
}
return NULL;
}
-CAResult_t u_arraylist_add(u_arraylist_t *list, void *data)
+bool u_arraylist_get_index(const u_arraylist_t *list, const void *data, uint32_t *index)
{
- uint32_t new_size = 0;
-
- if (list->size <= list->length)
+ if (!list || !data)
{
+ return false;
+ }
- new_size = list->size + 1;
- if (!(list->data = (void **) realloc(list->data, new_size * sizeof(void *))))
+ for (uint32_t i = 0; i < list->length; i++)
+ {
+ if (data == list->data[i])
{
- return -1;
+ *index = i;
+ return true;
}
+ }
+
+ return false;
+}
- (void) memset(list->data + list->size, 0, (new_size - list->size) * sizeof(void *));
- list->size = new_size;
+bool u_arraylist_add(u_arraylist_t *list, void *data)
+{
+ if (!list)
+ {
+ return false;
+ }
+
+ if (list->capacity <= list->length)
+ {
+ // Does a non-FP calcuation of the 1.5 growth factor. Helpful for
+ // certain limited platforms.
+ size_t new_capacity = ((list->capacity * 3) + 1) / 2;
+
+ // In case the re-alloc returns null, use a local variable to avoid
+ // losing the current block of memory.
+ void *tmp = OICRealloc(list->data,
+ new_capacity * sizeof(list->data[0]));
+ if (!tmp)
+ {
+ OIC_LOG(DEBUG, TAG, "Memory reallocation failed.");
+ return false;
+ }
+ list->data = (void **) tmp;
+ memset(list->data + list->capacity, 0,
+ (new_capacity - list->capacity) * sizeof(list->data[0]));
+ list->capacity = (uint32_t)new_capacity;
}
list->data[list->length] = data;
list->length++;
- return 0;
+ return true;
}
void *u_arraylist_remove(u_arraylist_t *list, uint32_t index)
{
void *removed = NULL;
- if (index >= list->length)
+ if (!list || (index >= list->length))
{
return NULL;
}
if (index < list->length - 1)
{
- memmove(&list->data[index], &list->data[index + 1],
- (list->length - index - 1) * sizeof(void *));
+ memmove(&list->data[index],
+ &list->data[index + 1],
+ (list->length - index - 1) * sizeof(list->data[0]));
}
- list->size--;
list->length--;
- if (!(list->data = (void **) realloc(list->data, list->size * sizeof(void *))))
- {
- return NULL;
- }
-
return removed;
}
uint32_t u_arraylist_length(const u_arraylist_t *list)
{
+ if (!list)
+ {
+ OIC_LOG(DEBUG, TAG, "Invalid Parameter");
+ return 0;
+ }
return list->length;
}
-uint8_t u_arraylist_contains(const u_arraylist_t *list, void *data)
+bool u_arraylist_contains(const u_arraylist_t *list, const void *data)
{
- uint32_t i = 0;
+ if (!list)
+ {
+ return false;
+ }
- for (i = 0; i < u_arraylist_length(list); i++)
+ for (uint32_t i = 0; i < list->length; i++)
{
- if (data == u_arraylist_get(list, i))
- {
- return 1;
- }
- else
+ if (data == list->data[i])
{
- continue;
+ return true;
}
}
- return 0;
+ return false;
}
+// Assumes elements are shallow (have no pointers to allocated memory)
+void u_arraylist_destroy(u_arraylist_t *list)
+{
+ if (!list)
+ {
+ return;
+ }
+ for (uint32_t i = 0; i < list->length; i++)
+ {
+ OICFree(list->data[i]);
+ }
+ (void)u_arraylist_free(&list);
+}