Azure IoT common library
Fork of azure_c_shared_utility by
Diff: vector.c
- Revision:
- 19:2e0811512ceb
- Parent:
- 11:77df6d7e65ae
- Child:
- 21:b92006c5b9ff
--- a/vector.c Fri Jan 13 18:41:15 2017 -0800 +++ b/vector.c Sat Jan 28 09:35:22 2017 -0800 @@ -2,84 +2,118 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. #include <stdlib.h> -#ifdef _CRTDBG_MAP_ALLOC -#include <crtdbg.h> -#endif - #include "azure_c_shared_utility/gballoc.h" #include "azure_c_shared_utility/vector.h" - +#include "azure_c_shared_utility/xlogging.h" -typedef struct VECTOR_TAG -{ - void* storage; - size_t count; - size_t elementSize; -} VECTOR; +#include "azure_c_shared_utility/vector_types_internal.h" VECTOR_HANDLE VECTOR_create(size_t elementSize) { VECTOR_HANDLE result; - VECTOR* vec = (VECTOR*)malloc(sizeof(VECTOR)); - if (vec == NULL) + /* Codes_SRS_VECTOR_10_002: [VECTOR_create shall fail and return NULL if elementsize is 0.] */ + if (elementSize == 0) { + LogError("invalid elementSize(%zd).", elementSize); result = NULL; } else { - vec->storage = NULL; - vec->count = 0; - vec->elementSize = elementSize; - result = (VECTOR_HANDLE)vec; + result = (VECTOR*)malloc(sizeof(VECTOR)); + /* Codes_SRS_VECTOR_10_002 : [VECTOR_create shall fail and return NULL if malloc fails.] */ + if (result == NULL) + { + LogError("malloc failed."); + } + else + { + /* Codes_SRS_VECTOR_10_001: [VECTOR_create shall allocate a VECTOR_HANDLE that will contain an empty vector.The size of each element is given with the parameter elementSize.] */ + result->storage = NULL; + result->count = 0; + result->elementSize = elementSize; + } } return result; } -static void internal_VECTOR_clear(VECTOR* vec) -{ - if (vec->storage != NULL) - { - free(vec->storage); - vec->storage = NULL; - } - vec->count = 0; -} - void VECTOR_destroy(VECTOR_HANDLE handle) { - if (handle != NULL) + /* Codes_SRS_VECTOR_10_009: [VECTOR_destroy shall return if the given handle is NULL.] */ + if (handle == NULL) { - VECTOR* vec = (VECTOR*)handle; - internal_VECTOR_clear(vec); - free(vec); + LogError("invalid argument handle(NULL)."); + } + else + { + /* Codes_SRS_VECTOR_10_008: [VECTOR_destroy shall free the given handle and its internal storage.] */ + free(handle->storage); + free(handle); } } +VECTOR_HANDLE VECTOR_move(VECTOR_HANDLE handle) +{ + VECTOR_HANDLE result; + if (handle == NULL) + { + /* Codes_SRS_VECTOR_10_005: [VECTOR_move shall fail and return NULL if the given handle is NULL.] */ + LogError("invalid argument - handle(NULL)."); + result = NULL; + } + else + { + result = (VECTOR*)malloc(sizeof(VECTOR)); + if (result == NULL) + { + /* Codes_SRS_VECTOR_10_006: [VECTOR_move shall fail and return NULL if malloc fails.] */ + LogError("malloc failed."); + } + else + { + /* Codes_SRS_VECTOR_10_004: [VECTOR_move shall allocate a VECTOR_HANDLE and move the data to it from the given handle.] */ + result->count = handle->count; + result->elementSize = handle->elementSize; + result->storage = handle->storage; + + handle->storage = NULL; + handle->count = 0; + } + } + return result; +} + /* insertion */ + int VECTOR_push_back(VECTOR_HANDLE handle, const void* elements, size_t numElements) { int result; if (handle == NULL || elements == NULL || numElements == 0) { + /* Codes_SRS_VECTOR_10_011: [VECTOR_push_back shall fail and return non-zero if `handle` is NULL.] */ + /* Codes_SRS_VECTOR_10_034: [VECTOR_push_back shall fail and return non-zero if `elements` is NULL.] */ + /* Codes_SRS_VECTOR_10_035: [VECTOR_push_back shall fail and return non-zero if `numElements` is 0.] */ + LogError("invalid argument - handle(%p), elements(%p), numElements(%zd).", handle, elements, numElements); result = __LINE__; } else { - VECTOR* vec = (VECTOR*)handle; - const size_t curSize = vec->elementSize * vec->count; - const size_t appendSize = vec->elementSize * numElements; + size_t curSize = handle->elementSize * handle->count; + size_t appendSize = handle->elementSize * numElements; - void* temp = realloc(vec->storage, curSize + appendSize); + void* temp = realloc(handle->storage, curSize + appendSize); if (temp == NULL) { + /* Codes_SRS_VECTOR_10_012: [VECTOR_push_back shall fail and return non-zero if memory allocation fails.] */ + LogError("realloc failed."); result = __LINE__; } else { - memcpy((unsigned char*)temp + curSize, elements, appendSize); - vec->storage = temp; - vec->count += numElements; + /* Codes_SRS_VECTOR_10_013: [VECTOR_push_back shall append the given elements and return 0 indicating success.] */ + (void)memcpy((unsigned char*)temp + curSize, elements, appendSize); + handle->storage = temp; + handle->count += numElements; result = 0; } } @@ -87,103 +121,217 @@ } /* removal */ + void VECTOR_erase(VECTOR_HANDLE handle, void* elements, size_t numElements) { - if (handle != NULL && elements != NULL && numElements > 0) + if (handle == NULL || elements == NULL || numElements == 0) { - VECTOR* vec = (VECTOR*)handle; - unsigned char* src = (unsigned char*)elements + (vec->elementSize * numElements); - unsigned char* srcEnd = (unsigned char*)vec->storage + (vec->elementSize * vec->count); - (void)memmove(elements, src, srcEnd - src); - vec->count -= numElements; - if (vec->count == 0) + /* Codes_SRS_VECTOR_10_015: [VECTOR_erase shall return if `handle` is NULL.] */ + /* Codes_SRS_VECTOR_10_038: [VECTOR_erase shall return if `elements` is NULL.] */ + /* Codes_SRS_VECTOR_10_039: [VECTOR_erase shall return if `numElements` is 0.] */ + LogError("invalid argument - handle(%p), elements(%p), numElements(%zd).", handle, elements, numElements); + } + else + { + if (elements < handle->storage) { - free(vec->storage); - vec->storage = NULL; + /* Codes_SRS_VECTOR_10_040: [VECTOR_erase shall return if `elements` is out of bound.] */ + LogError("invalid argument elements(%p) is not a member of this object.", elements); } else { - vec->storage = realloc(vec->storage, (vec->elementSize * vec->count)); + ptrdiff_t diff = ((unsigned char*)elements) - ((unsigned char*)handle->storage); + if ((diff % handle->elementSize) != 0) + { + /* Codes_SRS_VECTOR_10_041: [VECTOR_erase shall return if elements is misaligned.] */ + LogError("invalid argument - elements(%p) is misaligned", elements); + } + else + { + /* Compute the arguments needed for memmove. */ + unsigned char* src = (unsigned char*)elements + (handle->elementSize * numElements); + unsigned char* srcEnd = (unsigned char*)handle->storage + (handle->elementSize * handle->count); + if (src > srcEnd) + { + /* Codes_SRS_VECTOR_10_040: [VECTOR_erase shall return if `elements` is out of bound.] */ + LogError("invalid argument - numElements(%zd) is out of bound.", numElements); + } + else + { + /* Codes_SRS_VECTOR_10_014: [VECTOR_erase shall remove the 'numElements' starting at 'elements' and reduce its internal storage.] */ + handle->count -= numElements; + if (handle->count == 0) + { + free(handle->storage); + handle->storage = NULL; + } + else + { + void* tmp; + (void)memmove(elements, src, srcEnd - src); + tmp = realloc(handle->storage, (handle->elementSize * handle->count)); + if (tmp == NULL) + { + LogInfo("realloc failed. Keeping original internal storage pointer."); + } + else + { + handle->storage = tmp; + } + } + } + } } } } void VECTOR_clear(VECTOR_HANDLE handle) { - if (handle != NULL) + /* Codes_SRS_VECTOR_10_017: [VECTOR_clear shall if the object is NULL or empty.] */ + if (handle == NULL) { - VECTOR* vec = (VECTOR*)handle; - internal_VECTOR_clear(vec); + LogError("invalid argument handle(NULL)."); + } + else + { + /* Codes_SRS_VECTOR_10_016: [VECTOR_clear shall remove all elements from the object and release internal storage.] */ + free(handle->storage); + handle->storage = NULL; + handle->count = 0; } } /* access */ -void* VECTOR_element(const VECTOR_HANDLE handle, size_t index) +void* VECTOR_element(VECTOR_HANDLE handle, size_t index) { - void* result = NULL; - if (handle != NULL) + void* result; + if (handle == NULL) + { + /* Codes_SRS_VECTOR_10_019: [VECTOR_element shall fail and return NULL if handle is NULL.] */ + LogError("invalid argument handle(NULL)."); + result = NULL; + } + else { - const VECTOR* vec = (const VECTOR*)handle; - if (index < vec->count) + if (index >= handle->count) { - result = (unsigned char*)vec->storage + (vec->elementSize * index); + /* Codes_SRS_VECTOR_10_020: [VECTOR_element shall fail and return NULL if the given index is out of range.] */ + LogError("invalid argument - index(%zd); should be >= 0 and < %zd.", index, handle->count); + result = NULL; + } + else + { + /* Codes_SRS_VECTOR_10_018: [VECTOR_element shall return the element at the given index.] */ + result = (unsigned char*)handle->storage + (handle->elementSize * index); } } return result; } -void* VECTOR_front(const VECTOR_HANDLE handle) +void* VECTOR_front(VECTOR_HANDLE handle) { - void* result = NULL; - if (handle != NULL) + void* result; + if (handle == NULL) + { + /* Codes_SRS_VECTOR_10_022: [VECTOR_front shall fail and return NULL if handle is NULL.] */ + LogError("invalid argument handle (NULL)."); + result = NULL; + } + else { - const VECTOR* vec = (const VECTOR*)handle; - result = vec->storage; + if (handle->count == 0) + { + /* Codes_SRS_VECTOR_10_028: [VECTOR_front shall return NULL if the vector is empty.] */ + LogError("vector is empty."); + result = NULL; + } + else + { + /* Codes_SRS_VECTOR_10_021: [VECTOR_front shall return a pointer to the element at index 0.] */ + result = handle->storage; + } } return result; } -void* VECTOR_back(const VECTOR_HANDLE handle) +void* VECTOR_back(VECTOR_HANDLE handle) { - void* result = NULL; - if (handle != NULL) + void* result; + if (handle == NULL) + { + /* Codes_SRS_VECTOR_10_024: [VECTOR_back shall fail and return NULL if handle is NULL.] */ + LogError("invalid argument handle (NULL)."); + result = NULL; + } + else { - const VECTOR* vec = (const VECTOR*)handle; - result = (unsigned char*)vec->storage + (vec->elementSize * (vec->count - 1)); + if (handle->count == 0) + { + /* Codes_SRS_VECTOR_10_029: [VECTOR_back shall return NULL if the vector is empty.] */ + LogError("vector is empty."); + result = NULL; + } + else + { + /* Codes_SRS_VECTOR_10_023: [VECTOR_front shall return the last element of the vector.] */ + result = (unsigned char*)handle->storage + (handle->elementSize * (handle->count - 1)); + } } return result; } -void* VECTOR_find_if(const VECTOR_HANDLE handle, PREDICATE_FUNCTION pred, const void* value) +void* VECTOR_find_if(VECTOR_HANDLE handle, PREDICATE_FUNCTION pred, const void* value) { - void* result = NULL; - size_t i; - VECTOR* handleData = (VECTOR*)handle; - if (handle != NULL && pred != NULL && value != NULL) + void* result; + if (handle == NULL || pred == NULL) { - for (i = 0; i < handleData->count; ++i) + /* Codes_SRS_VECTOR_10_030: [VECTOR_find_if shall fail and return NULL if `handle` is NULL.] */ + /* Codes_SRS_VECTOR_10_036: [VECTOR_find_if shall fail and return NULL if `pred` is NULL.] */ + LogError("invalid argument - handle(%p), pred(%p)", handle, pred); + result = NULL; + } + else + { + size_t i; + for (i = 0; i < handle->count; ++i) { - void* elem = (unsigned char*)handleData->storage + (handleData->elementSize * i); - if (!!pred(elem, value)) + if (true == pred((unsigned char*)handle->storage + (handle->elementSize * i), value)) { - result = elem; + /* Codes_SRS_VECTOR_10_031: [VECTOR_find_if shall return the first element in the vector that matches `pred`.] */ break; } } + + if (i == handle->count) + { + /* Codes_SRS_VECTOR_10_032: [VECTOR_find_if shall return NULL if no matching element is found.] */ + result = NULL; + } + else + { + /* Codes_SRS_VECTOR_10_031: [VECTOR_find_if shall return the first element in the vector that matches `pred`.]*/ + result = (unsigned char*)handle->storage + (handle->elementSize * i); + } } return result; } /* capacity */ -size_t VECTOR_size(const VECTOR_HANDLE handle) +size_t VECTOR_size(VECTOR_HANDLE handle) { - size_t result = 0; - if (handle != NULL) + size_t result; + if (handle == NULL) { - const VECTOR* vec = (const VECTOR*)handle; - result = vec->count; + /* Codes_SRS_VECTOR_10_026: [**VECTOR_size shall return 0 if the given handle is NULL.] */ + LogError("invalid argument handle(NULL)."); + result = 0; + } + else + { + /* Codes_SRS_VECTOR_10_025: [VECTOR_size shall return the number of elements stored with the given handle.] */ + result = handle->count; } return result; }