diff options
Diffstat (limited to 'util/src/array_list.c')
-rw-r--r-- | util/src/array_list.c | 304 |
1 files changed, 304 insertions, 0 deletions
diff --git a/util/src/array_list.c b/util/src/array_list.c new file mode 100644 index 0000000..a40ecf9 --- /dev/null +++ b/util/src/array_list.c @@ -0,0 +1,304 @@ +/* + * 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. + */ + +#include <axutil_array_list.h> +#include <axutil_utils.h> +#include <string.h> + +struct axutil_array_list +{ + + /**The number of elements in this list. */ + int size; + + /**Current capacity of this list. */ + int capacity; + + /** Where the data is stored. */ + void **data; +}; + +AXIS2_EXTERN struct axutil_array_list *AXIS2_CALL +axutil_array_list_create( + const axutil_env_t * env, + int capacity) +{ + axutil_array_list_t *array_list = NULL; + + array_list = AXIS2_MALLOC(env->allocator, sizeof(axutil_array_list_t)); + if(!array_list) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory"); + return NULL; + } + + array_list->size = 0; + array_list->capacity = 0; + array_list->data = NULL; + + /* Check capacity, and set the default if error */ + if(capacity <= 0) + capacity = AXIS2_ARRAY_LIST_DEFAULT_CAPACITY; + array_list->data = AXIS2_MALLOC(env->allocator, sizeof(void *) * capacity); + if(!array_list->data) + { + axutil_array_list_free(array_list, env); + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory"); + return NULL; + } + array_list->capacity = capacity; + + return array_list; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axutil_array_list_ensure_capacity( + struct axutil_array_list * array_list, + const axutil_env_t * env, + int min_capacity) +{ + AXIS2_PARAM_CHECK(env->error, array_list, AXIS2_FAILURE); + if(min_capacity > array_list->capacity) + { + int new_capacity = (array_list->capacity * 2 > min_capacity) ? (array_list->capacity * 2) + : min_capacity; + void **data = (void **)AXIS2_MALLOC(env->allocator, sizeof(void *) * new_capacity); + if(!data) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory"); + return AXIS2_FAILURE; + } + memcpy(data, array_list->data, sizeof(void *) * array_list->capacity); + + AXIS2_FREE(env->allocator, array_list->data); + + array_list->data = data; + array_list->capacity = new_capacity; + } + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN int AXIS2_CALL +axutil_array_list_size( + struct axutil_array_list *array_list, + const axutil_env_t * env) +{ + /* Don't use AXIS2_PARAM_CHECK to verify array_list, as it clobbers + env->error->status_code on no error destroying the information + therein that an error has already occurred. */ + if(!array_list) + return 0; + return array_list->size; +} + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axutil_array_list_is_empty( + struct axutil_array_list * array_list, + const axutil_env_t * env) +{ + AXIS2_PARAM_CHECK(env->error, array_list, AXIS2_FAILURE); + return array_list->size == 0; +} + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axutil_array_list_contains( + struct axutil_array_list * array_list, + const axutil_env_t * env, + void *e) +{ + AXIS2_PARAM_CHECK(env->error, array_list, AXIS2_FAILURE); + return axutil_array_list_index_of(array_list, env, e) != -1; +} + +AXIS2_EXTERN int AXIS2_CALL +axutil_array_list_index_of( + struct axutil_array_list *array_list, + const axutil_env_t * env, + void *e) +{ + int i = 0; + + AXIS2_PARAM_CHECK(env->error, array_list, AXIS2_FAILURE); + for(i = 0; i < array_list->size; i++) + if(e == array_list->data[i]) + return i; + return -1; +} + +AXIS2_EXTERN void *AXIS2_CALL +axutil_array_list_get( + struct axutil_array_list *array_list, + const axutil_env_t * env, + int index) +{ + /* Don't use AXIS2_PARAM_CHECK to verify array_list, as it clobbers + env->error->status_code on no error destroying the information + therein that an error has already occurred. */ + if(axutil_array_list_check_bound_exclusive(array_list, env, index)) + return array_list->data[index]; + else + return NULL; +} + +AXIS2_EXTERN void *AXIS2_CALL +axutil_array_list_set( + struct axutil_array_list *array_list, + const axutil_env_t * env, + int index, + void *e) +{ + void *result = NULL; + + AXIS2_PARAM_CHECK(env->error, array_list, NULL); + if(axutil_array_list_check_bound_exclusive(array_list, env, index)) + { + result = array_list->data[index]; + array_list->data[index] = e; + } + return result; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axutil_array_list_add( + struct axutil_array_list * array_list, + const axutil_env_t * env, + const void *e) +{ + AXIS2_PARAM_CHECK(env->error, array_list, AXIS2_FAILURE); + if(array_list->size == array_list->capacity) + if(axutil_array_list_ensure_capacity(array_list, env, array_list->size + 1) + != AXIS2_SUCCESS) + return AXIS2_FAILURE; + array_list->data[array_list->size++] = (void *)e; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axutil_array_list_add_at( + struct axutil_array_list * array_list, + const axutil_env_t * env, + const int index, + const void *e) +{ + int i = 0; + AXIS2_PARAM_CHECK(env->error, array_list, AXIS2_FAILURE); + + if(!axutil_array_list_check_bound_inclusive(array_list, env, index)) + return AXIS2_FAILURE; + if(array_list->size == array_list->capacity) + { + if(axutil_array_list_ensure_capacity(array_list, env, array_list->size + 1) + != AXIS2_SUCCESS) + return AXIS2_FAILURE; + } + if(index != array_list->size) + { + for(i = array_list->size; i > index; i--) + array_list->data[i] = array_list->data[i - 1]; + } + array_list->data[index] = (void *)e; + array_list->size++; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN void *AXIS2_CALL +axutil_array_list_remove( + struct axutil_array_list *array_list, + const axutil_env_t * env, + int index) +{ + void *result = NULL; + int i = 0; + AXIS2_PARAM_CHECK(env->error, array_list, NULL); + + if(axutil_array_list_check_bound_exclusive(array_list, env, index)) + { + result = array_list->data[index]; + for(i = index; i < array_list->size - 1; i++) + array_list->data[i] = array_list->data[i + 1]; + array_list->size--; + } + + return result; +} + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axutil_array_list_check_bound_inclusive( + struct axutil_array_list * array_list, + const axutil_env_t * env, + int index) +{ + /* Don't use AXIS2_PARAM_CHECK to verify array_list, as it clobbers + env->error->status_code on no error destroying the information + therein that an error has already occurred. */ + if(!array_list || index < 0 || index > array_list->size) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INDEX_OUT_OF_BOUNDS, AXIS2_FAILURE); + return AXIS2_FALSE; + } + return AXIS2_TRUE; +} + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axutil_array_list_check_bound_exclusive( + struct axutil_array_list * array_list, + const axutil_env_t * env, + int index) +{ + /* Don't use AXIS2_PARAM_CHECK to verify array_list, as it clobbers + env->error->status_code on no error destroying the information + therein that an error has already occurred. */ + if(!array_list || index < 0 || index >= array_list->size) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INDEX_OUT_OF_BOUNDS, AXIS2_FAILURE); + return AXIS2_FALSE; + } + return AXIS2_TRUE; +} + +AXIS2_EXTERN void AXIS2_CALL +axutil_array_list_free( + struct axutil_array_list *array_list, + const axutil_env_t * env) +{ + AXIS2_PARAM_CHECK_VOID(env->error, array_list); + + if(array_list->data) + { + AXIS2_FREE(env->allocator, array_list->data); + } + AXIS2_FREE(env->allocator, array_list); + return; +} + +AXIS2_EXTERN void AXIS2_CALL +axutil_array_list_free_void_arg( + void *array_list, + const axutil_env_t * env) +{ + axutil_array_list_t *array_list_l = NULL; + + AXIS2_PARAM_CHECK_VOID(env->error, array_list); + + array_list_l = (axutil_array_list_t *)array_list; + axutil_array_list_free(array_list_l, env); + return; +} + |