Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of azure_c_shared_utility by
vector.c
- Committer:
- AzureIoTClient
- Date:
- 2017-02-24
- Revision:
- 21:b92006c5b9ff
- Parent:
- 19:2e0811512ceb
File content as of revision 21:b92006c5b9ff:
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
#include <stdlib.h>
#include "azure_c_shared_utility/gballoc.h"
#include "azure_c_shared_utility/vector.h"
#include "azure_c_shared_utility/optimize_size.h"
#include "azure_c_shared_utility/xlogging.h"
#include "azure_c_shared_utility/vector_types_internal.h"
VECTOR_HANDLE VECTOR_create(size_t elementSize)
{
VECTOR_HANDLE result;
/* 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
{
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;
}
void VECTOR_destroy(VECTOR_HANDLE handle)
{
/* Codes_SRS_VECTOR_10_009: [VECTOR_destroy shall return if the given handle is NULL.] */
if (handle == NULL)
{
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 = __FAILURE__;
}
else
{
size_t curSize = handle->elementSize * handle->count;
size_t appendSize = handle->elementSize * numElements;
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 = __FAILURE__;
}
else
{
/* 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;
}
}
return result;
}
/* removal */
void VECTOR_erase(VECTOR_HANDLE handle, void* elements, size_t numElements)
{
if (handle == NULL || elements == NULL || numElements == 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)
{
/* 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
{
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)
{
/* Codes_SRS_VECTOR_10_017: [VECTOR_clear shall if the object is NULL or empty.] */
if (handle == NULL)
{
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(VECTOR_HANDLE handle, size_t index)
{
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
{
if (index >= handle->count)
{
/* 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(VECTOR_HANDLE handle)
{
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
{
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(VECTOR_HANDLE handle)
{
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
{
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(VECTOR_HANDLE handle, PREDICATE_FUNCTION pred, const void* value)
{
void* result;
if (handle == NULL || pred == NULL)
{
/* 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)
{
if (true == pred((unsigned char*)handle->storage + (handle->elementSize * i), value))
{
/* 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(VECTOR_HANDLE handle)
{
size_t result;
if (handle == NULL)
{
/* 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;
}
