Nigel Rantor / azure_c_shared_utility

Fork of azure_c_shared_utility by Azure IoT

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers vector.c Source File

vector.c

00001 // Copyright (c) Microsoft. All rights reserved.
00002 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
00003 
00004 #include <stdlib.h>
00005 #include "azure_c_shared_utility/gballoc.h"
00006 #include "azure_c_shared_utility/vector.h"
00007 #include "azure_c_shared_utility/optimize_size.h"
00008 #include "azure_c_shared_utility/xlogging.h"
00009 
00010 #include "azure_c_shared_utility/vector_types_internal.h"
00011 
00012 VECTOR_HANDLE VECTOR_create(size_t elementSize)
00013 {
00014     VECTOR_HANDLE result;
00015 
00016     /* Codes_SRS_VECTOR_10_002: [VECTOR_create shall fail and return NULL if elementsize is 0.] */
00017     if (elementSize == 0)
00018     {
00019         LogError("invalid elementSize(%zd).", elementSize);
00020         result = NULL;
00021     }
00022     else
00023     {
00024         result = (VECTOR*)malloc(sizeof(VECTOR));
00025         /* Codes_SRS_VECTOR_10_002 : [VECTOR_create shall fail and return NULL if malloc fails.] */
00026         if (result == NULL)
00027         {
00028             LogError("malloc failed.");
00029         }
00030         else
00031         {
00032             /* 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.] */
00033             result->storage = NULL;
00034             result->count = 0;
00035             result->elementSize = elementSize;
00036         }
00037     }
00038     return result;
00039 }
00040 
00041 void VECTOR_destroy(VECTOR_HANDLE handle)
00042 {
00043     /* Codes_SRS_VECTOR_10_009: [VECTOR_destroy shall return if the given handle is NULL.] */
00044     if (handle == NULL)
00045     {
00046         LogError("invalid argument handle(NULL).");
00047     }
00048     else
00049     {
00050         /* Codes_SRS_VECTOR_10_008: [VECTOR_destroy shall free the given handle and its internal storage.] */
00051         free(handle->storage);
00052         free(handle);
00053     }
00054 }
00055 
00056 VECTOR_HANDLE VECTOR_move(VECTOR_HANDLE handle)
00057 {
00058     VECTOR_HANDLE result;
00059     if (handle == NULL)
00060     {
00061         /* Codes_SRS_VECTOR_10_005: [VECTOR_move shall fail and return NULL if the given handle is NULL.] */
00062         LogError("invalid argument - handle(NULL).");
00063         result = NULL;
00064     }
00065     else
00066     {
00067         result = (VECTOR*)malloc(sizeof(VECTOR));
00068         if (result == NULL)
00069         {
00070             /* Codes_SRS_VECTOR_10_006: [VECTOR_move shall fail and return NULL if malloc fails.] */
00071             LogError("malloc failed.");
00072         }
00073         else
00074         {
00075             /* Codes_SRS_VECTOR_10_004: [VECTOR_move shall allocate a VECTOR_HANDLE and move the data to it from the given handle.] */
00076             result->count = handle->count;
00077             result->elementSize = handle->elementSize;
00078             result->storage = handle->storage;
00079 
00080             handle->storage = NULL;
00081             handle->count = 0;
00082         }
00083     }
00084     return result;
00085 }
00086 
00087 /* insertion */
00088 
00089 int VECTOR_push_back(VECTOR_HANDLE handle, const void* elements, size_t numElements)
00090 {
00091     int result;
00092     if (handle == NULL || elements == NULL || numElements == 0)
00093     {
00094        /* Codes_SRS_VECTOR_10_011: [VECTOR_push_back shall fail and return non-zero if `handle` is NULL.] */
00095        /* Codes_SRS_VECTOR_10_034: [VECTOR_push_back shall fail and return non-zero if `elements` is NULL.] */
00096        /* Codes_SRS_VECTOR_10_035: [VECTOR_push_back shall fail and return non-zero if `numElements` is 0.] */
00097         LogError("invalid argument - handle(%p), elements(%p), numElements(%zd).", handle, elements, numElements);
00098         result = __FAILURE__;
00099     }
00100     else
00101     {
00102         size_t curSize = handle->elementSize * handle->count;
00103         size_t appendSize = handle->elementSize * numElements;
00104 
00105         void* temp = realloc(handle->storage, curSize + appendSize);
00106         if (temp == NULL)
00107         {
00108            /* Codes_SRS_VECTOR_10_012: [VECTOR_push_back shall fail and return non-zero if memory allocation fails.] */
00109             LogError("realloc failed.");
00110             result = __FAILURE__;
00111         }
00112         else
00113         {
00114             /* Codes_SRS_VECTOR_10_013: [VECTOR_push_back shall append the given elements and return 0 indicating success.] */
00115             (void)memcpy((unsigned char*)temp + curSize, elements, appendSize);
00116             handle->storage = temp;
00117             handle->count += numElements;
00118             result = 0;
00119         }
00120     }
00121     return result;
00122 }
00123 
00124 /* removal */
00125 
00126 void VECTOR_erase(VECTOR_HANDLE handle, void* elements, size_t numElements)
00127 {
00128     if (handle == NULL || elements == NULL || numElements == 0)
00129     {
00130         /* Codes_SRS_VECTOR_10_015: [VECTOR_erase shall return if `handle` is NULL.] */
00131         /* Codes_SRS_VECTOR_10_038: [VECTOR_erase shall return if `elements` is NULL.] */
00132         /* Codes_SRS_VECTOR_10_039: [VECTOR_erase shall return if `numElements` is 0.] */
00133         LogError("invalid argument - handle(%p), elements(%p), numElements(%zd).", handle, elements, numElements);
00134     }
00135     else
00136     {
00137         if (elements < handle->storage)
00138         {
00139             /* Codes_SRS_VECTOR_10_040: [VECTOR_erase shall return if `elements` is out of bound.] */
00140             LogError("invalid argument elements(%p) is not a member of this object.", elements);
00141         }
00142         else
00143         {
00144             ptrdiff_t diff = ((unsigned char*)elements) - ((unsigned char*)handle->storage);
00145             if ((diff % handle->elementSize) != 0)
00146             {
00147                 /* Codes_SRS_VECTOR_10_041: [VECTOR_erase shall return if elements is misaligned.] */
00148                 LogError("invalid argument - elements(%p) is misaligned", elements);
00149             }
00150             else
00151             {
00152                 /* Compute the arguments needed for memmove. */
00153                 unsigned char* src = (unsigned char*)elements + (handle->elementSize * numElements);
00154                 unsigned char* srcEnd = (unsigned char*)handle->storage + (handle->elementSize * handle->count);
00155                 if (src > srcEnd)
00156                 {
00157                     /* Codes_SRS_VECTOR_10_040: [VECTOR_erase shall return if `elements` is out of bound.] */
00158                     LogError("invalid argument - numElements(%zd) is out of bound.", numElements);
00159                 }
00160                 else
00161                 {
00162                     /* Codes_SRS_VECTOR_10_014: [VECTOR_erase shall remove the 'numElements' starting at 'elements' and reduce its internal storage.] */
00163                     handle->count -= numElements;
00164                     if (handle->count == 0)
00165                     {
00166                         free(handle->storage);
00167                         handle->storage = NULL;
00168                     }
00169                     else
00170                     {
00171                         void* tmp;
00172                         (void)memmove(elements, src, srcEnd - src);
00173                         tmp = realloc(handle->storage, (handle->elementSize * handle->count));
00174                         if (tmp == NULL)
00175                         {
00176                             LogInfo("realloc failed. Keeping original internal storage pointer.");
00177                         }
00178                         else
00179                         {
00180                             handle->storage = tmp;
00181                         }
00182                     }
00183                 }
00184             }
00185         }
00186     }
00187 }
00188 
00189 void VECTOR_clear(VECTOR_HANDLE handle)
00190 {
00191     /* Codes_SRS_VECTOR_10_017: [VECTOR_clear shall if the object is NULL or empty.] */
00192     if (handle == NULL)
00193     {
00194         LogError("invalid argument handle(NULL).");
00195     }
00196     else
00197     {
00198         /* Codes_SRS_VECTOR_10_016: [VECTOR_clear shall remove all elements from the object and release internal storage.] */
00199         free(handle->storage);
00200         handle->storage = NULL;
00201         handle->count = 0;
00202     }
00203 }
00204 
00205 /* access */
00206 
00207 void* VECTOR_element(VECTOR_HANDLE handle, size_t index)
00208 {
00209     void* result;
00210     if (handle == NULL)
00211     {
00212         /* Codes_SRS_VECTOR_10_019: [VECTOR_element shall fail and return NULL if handle is NULL.] */
00213         LogError("invalid argument handle(NULL).");
00214         result = NULL;
00215     }
00216     else
00217     {
00218         if (index >= handle->count)
00219         {
00220             /* Codes_SRS_VECTOR_10_020: [VECTOR_element shall fail and return NULL if the given index is out of range.] */
00221             LogError("invalid argument - index(%zd); should be >= 0 and < %zd.", index, handle->count);
00222             result = NULL;
00223         }
00224         else
00225         {
00226             /* Codes_SRS_VECTOR_10_018: [VECTOR_element shall return the element at the given index.] */
00227             result = (unsigned char*)handle->storage + (handle->elementSize * index);
00228         }
00229     }
00230     return result;
00231 }
00232 
00233 void* VECTOR_front(VECTOR_HANDLE handle)
00234 {
00235     void* result;
00236     if (handle == NULL)
00237     {
00238         /* Codes_SRS_VECTOR_10_022: [VECTOR_front shall fail and return NULL if handle is NULL.] */
00239         LogError("invalid argument handle (NULL).");
00240         result = NULL;
00241     }
00242     else
00243     {
00244         if (handle->count == 0)
00245         {
00246             /* Codes_SRS_VECTOR_10_028: [VECTOR_front shall return NULL if the vector is empty.] */
00247             LogError("vector is empty.");
00248             result = NULL;
00249         }
00250         else
00251         {
00252             /* Codes_SRS_VECTOR_10_021: [VECTOR_front shall return a pointer to the element at index 0.] */
00253             result = handle->storage;
00254         }
00255     }
00256     return result;
00257 }
00258 
00259 void* VECTOR_back(VECTOR_HANDLE handle)
00260 {
00261     void* result;
00262     if (handle == NULL)
00263     {
00264         /* Codes_SRS_VECTOR_10_024: [VECTOR_back shall fail and return NULL if handle is NULL.] */
00265         LogError("invalid argument handle (NULL).");
00266         result = NULL;
00267     }
00268     else
00269     {
00270         if (handle->count == 0)
00271         {
00272             /* Codes_SRS_VECTOR_10_029: [VECTOR_back shall return NULL if the vector is empty.] */
00273             LogError("vector is empty.");
00274             result = NULL;
00275         }
00276         else
00277         {
00278             /* Codes_SRS_VECTOR_10_023: [VECTOR_front shall return the last element of the vector.] */
00279             result = (unsigned char*)handle->storage + (handle->elementSize * (handle->count - 1));
00280         }
00281     }
00282     return result;
00283 }
00284 
00285 void* VECTOR_find_if(VECTOR_HANDLE handle, PREDICATE_FUNCTION pred, const void* value)
00286 {
00287     void* result;
00288     if (handle == NULL || pred == NULL)
00289     {
00290         /* Codes_SRS_VECTOR_10_030: [VECTOR_find_if shall fail and return NULL if `handle` is NULL.] */
00291         /* Codes_SRS_VECTOR_10_036: [VECTOR_find_if shall fail and return NULL if `pred` is NULL.] */
00292         LogError("invalid argument - handle(%p), pred(%p)", handle, pred);
00293         result = NULL;
00294     }
00295     else
00296     {
00297         size_t i;
00298         for (i = 0; i < handle->count; ++i)
00299         {
00300             if (true == pred((unsigned char*)handle->storage + (handle->elementSize * i), value))
00301             {
00302                 /* Codes_SRS_VECTOR_10_031: [VECTOR_find_if shall return the first element in the vector that matches `pred`.] */
00303                 break;
00304             }
00305         }
00306 
00307         if (i == handle->count)
00308         {
00309             /* Codes_SRS_VECTOR_10_032: [VECTOR_find_if shall return NULL if no matching element is found.] */
00310             result = NULL;
00311         }
00312         else
00313         {
00314             /* Codes_SRS_VECTOR_10_031: [VECTOR_find_if shall return the first element in the vector that matches `pred`.]*/
00315             result = (unsigned char*)handle->storage + (handle->elementSize * i);
00316         }
00317     }
00318     return result;
00319 }
00320 
00321 /* capacity */
00322 
00323 size_t VECTOR_size(VECTOR_HANDLE handle)
00324 {
00325     size_t result;
00326     if (handle == NULL)
00327     {
00328         /* Codes_SRS_VECTOR_10_026: [**VECTOR_size shall return 0 if the given handle is NULL.] */
00329         LogError("invalid argument handle(NULL).");
00330         result = 0;
00331     }
00332     else
00333     {
00334         /* Codes_SRS_VECTOR_10_025: [VECTOR_size shall return the number of elements stored with the given handle.] */
00335         result = handle->count;
00336     }
00337     return result;
00338 }