Azure IoT common library

Fork of azure_c_shared_utility by Azure IoT

Revision:
19:2e0811512ceb
Parent:
11:77df6d7e65ae
Child:
21:b92006c5b9ff
diff -r 6d8a413a4d9a -r 2e0811512ceb vector.c
--- 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;
 }