| /** |
| *Licensed to the Apache Software Foundation (ASF) under one |
| *or more contributor license agreements. See the NOTICE file |
| *distributed with this work for additional information |
| *regarding copyright ownership. The ASF licenses this file |
| *to you 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. |
| */ |
| /* |
| * array_list.c |
| * |
| * \date Aug 4, 2010 |
| * \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a> |
| * \copyright Apache License, Version 2.0 |
| */ |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <string.h> |
| |
| #include "array_list.h" |
| #include "array_list_private.h" |
| |
| static celix_status_t arrayList_elementEquals(void *a, void *b, bool *equals); |
| |
| celix_status_t arrayList_create(array_list_pt *list) { |
| return arrayList_createWithEquals(arrayList_elementEquals, list); |
| } |
| |
| celix_status_t arrayList_createWithEquals(array_list_element_equals_pt equals, array_list_pt *list) { |
| *list = (array_list_pt) malloc(sizeof(**list)); |
| |
| (*list)->equals = equals; |
| (*list)->size = 0; |
| (*list)->capacity = 10; |
| (*list)->modCount = 0; |
| (*list)->elementData = (void **) malloc(sizeof(void*) * (*list)->capacity); |
| |
| return CELIX_SUCCESS; |
| } |
| |
| void arrayList_destroy(array_list_pt list) { |
| list->size = 0; |
| free(list->elementData); |
| list->elementData = NULL; |
| free(list); |
| } |
| |
| static celix_status_t arrayList_elementEquals(void *a, void *b, bool *equals) { |
| *equals = (a == b); |
| return CELIX_SUCCESS; |
| } |
| |
| void arrayList_trimToSize(array_list_pt list) { |
| unsigned int oldCapacity; |
| list->modCount++; |
| oldCapacity = list->capacity; |
| if (list->size < oldCapacity) { |
| void ** newList = (void **) realloc(list->elementData, sizeof(void *) * list->size); |
| list->capacity = list->size; |
| list->elementData = newList; |
| } |
| } |
| |
| void arrayList_ensureCapacity(array_list_pt list, int capacity) { |
| void ** newList; |
| unsigned int oldCapacity; |
| list->modCount++; |
| oldCapacity = list->capacity; |
| if (capacity > oldCapacity) { |
| unsigned int newCapacity = (oldCapacity * 3) / 2 + 1; |
| if (newCapacity < capacity) { |
| newCapacity = capacity; |
| } |
| newList = (void **) realloc(list->elementData, sizeof(void *) * newCapacity); |
| list->capacity = newCapacity; |
| list->elementData = newList; |
| } |
| } |
| |
| unsigned int arrayList_size(array_list_pt list) { |
| return list->size; |
| } |
| |
| bool arrayList_isEmpty(array_list_pt list) { |
| return list->size == 0; |
| } |
| |
| bool arrayList_contains(array_list_pt list, void * element) { |
| int index = arrayList_indexOf(list, element); |
| return index >= 0; |
| } |
| |
| int arrayList_indexOf(array_list_pt list, void * element) { |
| if (element == NULL) { |
| unsigned int i = 0; |
| for (i = 0; i < list->size; i++) { |
| if (list->elementData[i] == NULL) { |
| return i; |
| } |
| } |
| } else { |
| unsigned int i = 0; |
| for (i = 0; i < list->size; i++) { |
| bool equals = false; |
| list->equals(element, list->elementData[i], &equals); |
| if (equals) { |
| return i; |
| } |
| } |
| } |
| return -1; |
| } |
| |
| int arrayList_lastIndexOf(array_list_pt list, void * element) { |
| if (element == NULL) { |
| int i = 0; |
| for (i = list->size - 1; i >= 0; i--) { |
| if (list->elementData[i] == NULL) { |
| return i; |
| } |
| } |
| } else { |
| int i = 0; |
| for (i = list->size - 1; i >= 0; i--) { |
| bool equals = false; |
| list->equals(element, list->elementData[i], &equals); |
| if (equals) { |
| return i; |
| } |
| } |
| } |
| return -1; |
| } |
| |
| void * arrayList_get(array_list_pt list, unsigned int index) { |
| if (index >= list->size) { |
| return NULL; |
| } |
| |
| return list->elementData[index]; |
| } |
| |
| void * arrayList_set(array_list_pt list, unsigned int index, void * element) { |
| void * oldElement; |
| if (index >= list->size) { |
| return NULL; |
| } |
| |
| oldElement = list->elementData[index]; |
| list->elementData[index] = element; |
| return oldElement; |
| } |
| |
| bool arrayList_add(array_list_pt list, void * element) { |
| arrayList_ensureCapacity(list, list->size + 1); |
| list->elementData[list->size++] = element; |
| return true; |
| } |
| |
| int arrayList_addIndex(array_list_pt list, unsigned int index, void * element) { |
| unsigned int numMoved; |
| if (index > list->size) { |
| return -1; |
| } |
| arrayList_ensureCapacity(list, list->size+1); |
| numMoved = list->size - index; |
| memmove(list->elementData+(index+1), list->elementData+index, sizeof(void *) * numMoved); |
| |
| list->elementData[index] = element; |
| list->size++; |
| return 0; |
| } |
| |
| void * arrayList_remove(array_list_pt list, unsigned int index) { |
| void * oldElement; |
| unsigned int numMoved; |
| if (index >= list->size) { |
| return NULL; |
| } |
| |
| list->modCount++; |
| oldElement = list->elementData[index]; |
| numMoved = list->size - index - 1; |
| memmove(list->elementData+index, list->elementData+index+1, sizeof(void *) * numMoved); |
| list->elementData[--list->size] = NULL; |
| |
| return oldElement; |
| } |
| |
| void arrayList_fastRemove(array_list_pt list, unsigned int index) { |
| unsigned int numMoved; |
| list->modCount++; |
| |
| numMoved = list->size - index - 1; |
| memmove(list->elementData+index, list->elementData+index+1, sizeof(void *) * numMoved); |
| list->elementData[--list->size] = NULL; |
| } |
| |
| bool arrayList_removeElement(array_list_pt list, void * element) { |
| if (element == NULL) { |
| unsigned int i = 0; |
| for (i = 0; i < list->size; i++) { |
| if (list->elementData[i] == NULL) { |
| arrayList_fastRemove(list, i); |
| return true; |
| } |
| } |
| } else { |
| unsigned int i = 0; |
| for (i = 0; i < list->size; i++) { |
| bool equals = false; |
| list->equals(element, list->elementData[i], &equals); |
| if (equals) { |
| arrayList_fastRemove(list, i); |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| void arrayList_clear(array_list_pt list) { |
| unsigned int i; |
| list->modCount++; |
| |
| for (i = 0; i < list->size; i++) { |
| // free(list->elementData[i]); |
| list->elementData[i] = NULL; |
| } |
| list->size = 0; |
| } |
| |
| bool arrayList_addAll(array_list_pt list, array_list_pt toAdd) { |
| unsigned int i; |
| unsigned int size = arrayList_size(toAdd); |
| arrayList_ensureCapacity(list, list->size + size); |
| // memcpy(list->elementData+list->size, *toAdd->elementData, size); |
| // list->size += size; |
| for (i = 0; i < arrayList_size(toAdd); i++) { |
| arrayList_add(list, arrayList_get(toAdd, i)); |
| } |
| return size != 0; |
| } |
| |
| array_list_pt arrayList_clone(array_list_pt list) { |
| unsigned int i; |
| array_list_pt new = NULL; |
| arrayList_create(&new); |
| // arrayList_ensureCapacity(new, list->size); |
| // memcpy(new->elementData, list->elementData, list->size); |
| // new->size = list->size; |
| |
| for (i = 0; i < arrayList_size(list); i++) { |
| arrayList_add(new, arrayList_get(list, i)); |
| } |
| new->modCount = 0; |
| return new; |
| } |
| |
| array_list_iterator_pt arrayListIterator_create(array_list_pt list) { |
| array_list_iterator_pt iterator = (array_list_iterator_pt) malloc(sizeof(*iterator)); |
| |
| iterator->lastReturned = -1; |
| iterator->cursor = 0; |
| iterator->list = list; |
| iterator->expectedModificationCount = list->modCount; |
| |
| return iterator; |
| } |
| |
| void arrayListIterator_destroy(array_list_iterator_pt iterator) { |
| iterator->lastReturned = -1; |
| iterator->cursor = 0; |
| iterator->expectedModificationCount = 0; |
| iterator->list = NULL; |
| free(iterator); |
| } |
| |
| bool arrayListIterator_hasNext(array_list_iterator_pt iterator) { |
| return iterator->cursor != iterator->list->size; |
| } |
| |
| void * arrayListIterator_next(array_list_iterator_pt iterator) { |
| void * next; |
| if (iterator->expectedModificationCount != iterator->list->modCount) { |
| return NULL; |
| } |
| next = arrayList_get(iterator->list, iterator->cursor); |
| iterator->lastReturned = iterator->cursor++; |
| return next; |
| } |
| |
| bool arrayListIterator_hasPrevious(array_list_iterator_pt iterator) { |
| return iterator->cursor != 0; |
| } |
| |
| void * arrayListIterator_previous(array_list_iterator_pt iterator) { |
| int i; |
| void * previous; |
| if (iterator->expectedModificationCount != iterator->list->modCount) { |
| return NULL; |
| } |
| i = iterator->cursor - 1; |
| previous = arrayList_get(iterator->list, i); |
| iterator->lastReturned = iterator->cursor = i; |
| return previous; |
| } |
| |
| void arrayListIterator_remove(array_list_iterator_pt iterator) { |
| if (iterator->lastReturned == -1) { |
| return; |
| } |
| if (iterator->expectedModificationCount != iterator->list->modCount) { |
| return; |
| } |
| if (arrayList_remove(iterator->list, iterator->lastReturned) != NULL) { |
| if (iterator->lastReturned < iterator->cursor) { |
| iterator->cursor--; |
| } |
| iterator->lastReturned = -1; |
| iterator->expectedModificationCount = iterator->list->modCount; |
| } |
| } |
| |
| |
| |
| |