set(UDPConnection_SOURCES
src/UDPConnection.c
- src/Deque.c
+ src/UDPC_Deque.c
)
set(CMAKE_C_FLAGS "-Wall -Wno-missing-braces")
add_library(UDPConnection ${UDPConnection_SOURCES})
target_compile_features(UDPConnection PUBLIC c_std_11)
+target_link_libraries(UDPConnection PUBLIC pthread)
+
+if(CMAKE_BUILD_TYPE MATCHES "Debug")
+ set(UDPC_UnitTest_SOURCES
+ src/test/UDPC_UnitTest.c)
+ add_executable(UnitTest ${UDPC_UnitTest_SOURCES})
+ target_link_libraries(UnitTest PUBLIC UDPConnection)
+ target_include_directories(UnitTest PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src)
+endif()
-#include "Deque.h"
+#include "UDPC_Deque.h"
#include <stdlib.h>
#include <string.h>
free(deque->buf);
deque->buf = buf;
deque->alloc_size = new_size;
+ deque->head = 0;
+ deque->tail = deque->size;
+ if(deque->tail == deque->alloc_size)
+ {
+ deque->tail = 0;
+ }
return 1;
}
else
}
}
-int UDPC_Deque_push_back(UDPC_Deque *deque, const char *data, uint32_t size)
+int UDPC_Deque_push_back(UDPC_Deque *deque, const void *data, uint32_t size)
{
if(deque->size + size > deque->alloc_size)
{
}
if(size > 0)
{
- memcpy(&deque->buf[deque->tail], &data[temp], size);
+ memcpy(&deque->buf[deque->tail], &((const char*)data)[temp], size);
deque->tail += size;
deque->size += size;
}
return 1;
}
-int UDPC_Deque_push_front(UDPC_Deque *deque, const char *data, uint32_t size)
+int UDPC_Deque_push_front(UDPC_Deque *deque, const void *data, uint32_t size)
{
if(deque->size + size > deque->alloc_size)
{
if(deque->head > 0)
{
- memcpy(deque->buf, &data[size - deque->head], deque->head);
+ memcpy(deque->buf, &((const char*)data)[size - deque->head], deque->head);
deque->size += deque->head;
size -= deque->head;
deque->head = 0;
return deque->size;
}
-int UDPC_Deque_get_back(UDPC_Deque *deque, char **data, uint32_t *size)
+int UDPC_Deque_get_back(UDPC_Deque *deque, void **data, uint32_t *size)
{
int returnValue = 1;
if(deque->size == 0)
return returnValue;
}
-int UDPC_Deque_get_front(UDPC_Deque *deque, char **data, uint32_t *size)
+int UDPC_Deque_get_front(UDPC_Deque *deque, void **data, uint32_t *size)
{
int returnValue = 1;
if(deque->size == 0)
}
}
-int UDPC_Deque_index(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, char **out)
+int UDPC_Deque_index(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, void **out)
{
uint32_t pos = unitSize * index;
uint32_t abspos;
- if(pos >= deque->alloc_size)
+ if(pos >= deque->size)
{
*out = NULL;
return 0;
return 1;
}
-int UDPC_Deque_index_rev(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, char **out)
+int UDPC_Deque_index_rev(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, void **out)
{
uint32_t pos = unitSize * (index + 1);
uint32_t abspos;
- if(pos >= deque->alloc_size)
+ if(pos >= deque->size + unitSize)
{
*out = NULL;
return 0;
* If there was not enough space in the Deque, then no data is inserted at all.
* \return non-zero on success (there was enough size to insert data)
*/
-int UDPC_Deque_push_back(UDPC_Deque *deque, const char *data, uint32_t size);
+int UDPC_Deque_push_back(UDPC_Deque *deque, const void *data, uint32_t size);
/*!
* If there was not enough space in the Deque, then no data is inserted at all.
* \return non-zero on success (there was enough size to insert data)
*/
-int UDPC_Deque_push_front(UDPC_Deque *deque, const char *data, uint32_t size);
+int UDPC_Deque_push_front(UDPC_Deque *deque, const void *data, uint32_t size);
/*!
* \return size in bytes of available data
* updated to allocated amount. If deque is empty, no data is allocated.
* \return non-zero if full requested size was returned
*/
-int UDPC_Deque_get_back(UDPC_Deque *deque, char **data, uint32_t *size);
+int UDPC_Deque_get_back(UDPC_Deque *deque, void **data, uint32_t *size);
/*!
* \brief Get data from front of deque
* updated to allocated amount. If deque is empty, no data is allocated.
* \return non-zero if full requested size was returned
*/
-int UDPC_Deque_get_front(UDPC_Deque *deque, char **data, uint32_t *size);
+int UDPC_Deque_get_front(UDPC_Deque *deque, void **data, uint32_t *size);
/*!
* \brief "free" data from the back of the deque
* The data will be indexed relative to the head of the Deque.
* The out pointer will be malloc'd with size unitSize and will have a copy of
* the data at the specified unitSize * index.
- * Note that the out data must be free'd, but nothing will be malloc'd on fail
+ * Note that the out data must be free'd, but on fail nothing will be malloc'd
* and *out will be set to NULL.
- * \return non-zero if unitSize * index < allocated_size_of_Deque
+ * \return non-zero if unitSize * index < size
*/
-int UDPC_Deque_index(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, char **out);
+int UDPC_Deque_index(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, void **out);
/*!
* \brief Get a unitSize sized chunk of data at position relative to tail
* The out pointer will be malloc'd with size unitSize and will have a copy of
- * the data at the specified unitSize * (index + 1) relative to tail in reverse
+ * the data at the specified unitSize * index relative to tail in reverse
* direction.
- * Note that the out data must be free'd, but nothing will be malloc'd on fail
+ * Note that the out data must be free'd, but on fail nothing will be malloc'd
* and *out will be set to NULL.
- * \return non-zero if unitSize * (index + 1) < allocated_size_of_Deque
+ * \return non-zero if unitSize * index < size
*/
-int UDPC_Deque_index_rev(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, char **out);
+int UDPC_Deque_index_rev(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, void **out);
void UDPC_Deque_clear(UDPC_Deque *deque);
--- /dev/null
+#include "UDPC_UnitTest.h"
+
+#include <stdlib.h>
+#include <UDPC_Deque.h>
+
+static UnitTestState UDPC_uts = {0, 0};
+
+int main()
+{
+ int arr[32];
+ char *temp = NULL;
+ uint32_t size;
+ for(int x = 0; x < 32; ++x)
+ {
+ arr[x] = x;
+ }
+ UDPC_Deque deque;
+
+ // init
+ ASSERT_TRUE(UDPC_Deque_init(&deque, sizeof(int) * 32));
+ ASSERT_TRUE(deque.buf);
+ ASSERT_EQ(deque.head, 0);
+ ASSERT_EQ(deque.tail, 0);
+ ASSERT_EQ(deque.size, 0);
+ ASSERT_EQ(deque.alloc_size, sizeof(int) * 32);
+
+ // realloc smaller success
+ ASSERT_TRUE(UDPC_Deque_realloc(&deque, sizeof(int) * 16));
+ ASSERT_TRUE(deque.buf);
+ ASSERT_EQ(deque.head, 0);
+ ASSERT_EQ(deque.tail, 0);
+ ASSERT_EQ(deque.size, 0);
+ ASSERT_EQ(deque.alloc_size, sizeof(int) * 16);
+
+ // push back success
+ ASSERT_TRUE(UDPC_Deque_push_back(&deque, arr, sizeof(int) * 4));
+ ASSERT_EQ_MEM(arr, deque.buf, sizeof(int) * 4);
+ ASSERT_EQ(deque.size, sizeof(int) * 4);
+
+ // push front success
+ ASSERT_TRUE(UDPC_Deque_push_front(&deque, &arr[4], sizeof(int) * 4));
+ ASSERT_EQ_MEM(&arr[4], &deque.buf[sizeof(int) * 12], sizeof(int) * 4);
+ ASSERT_EQ(deque.size, sizeof(int) * 8);
+
+ // realloc bigger success
+ ASSERT_TRUE(UDPC_Deque_realloc(&deque, sizeof(int) * 32));
+ ASSERT_EQ_MEM(&arr[4], deque.buf, sizeof(int) * 4);
+ ASSERT_EQ_MEM(arr, &deque.buf[sizeof(int) * 4], sizeof(int) * 4);
+ ASSERT_EQ(deque.alloc_size, sizeof(int) * 32);
+
+ // pop front success
+ UDPC_Deque_pop_front(&deque, sizeof(int) * 4);
+ ASSERT_EQ(deque.size, sizeof(int) * 4);
+
+ // get front success
+ size = sizeof(int) * 4;
+ ASSERT_TRUE(UDPC_Deque_get_front(&deque, (void**)&temp, &size));
+ ASSERT_EQ(size, sizeof(int) * 4);
+ ASSERT_EQ_MEM(arr, temp, size);
+ free(temp);
+
+ // pop back success
+ UDPC_Deque_pop_back(&deque, sizeof(int) * 4);
+ ASSERT_EQ(deque.size, 0);
+
+ // push front success
+ ASSERT_TRUE(UDPC_Deque_push_front(&deque, arr, sizeof(int) * 16));
+ ASSERT_EQ(deque.size, sizeof(int) * 16);
+
+ // get front success
+ size = sizeof(int) * 16;
+ ASSERT_TRUE(UDPC_Deque_get_front(&deque, (void**)&temp, &size));
+ ASSERT_EQ(size, sizeof(int) * 16);
+ ASSERT_EQ_MEM(arr, temp, size);
+ free(temp);
+
+ // get back success
+ size = sizeof(int) * 16;
+ ASSERT_TRUE(UDPC_Deque_get_back(&deque, (void**)&temp, &size));
+ ASSERT_EQ(size, sizeof(int) * 16);
+ ASSERT_EQ_MEM(arr, temp, size);
+ free(temp);
+
+ // realloc smaller fail
+ ASSERT_FALSE(UDPC_Deque_realloc(&deque, sizeof(int) * 8));
+ ASSERT_EQ(deque.size, sizeof(int) * 16);
+ ASSERT_EQ(deque.alloc_size, sizeof(int) * 32);
+
+ // realloc smaller success
+ ASSERT_TRUE(UDPC_Deque_realloc(&deque, sizeof(int) * 16));
+ ASSERT_EQ(deque.size, sizeof(int) * 16);
+ ASSERT_EQ(deque.alloc_size, sizeof(int) * 16);
+ ASSERT_EQ_MEM(deque.buf, arr, sizeof(int) * 16);
+
+ // push back fail
+ ASSERT_FALSE(UDPC_Deque_push_back(&deque, arr, sizeof(int) * 16));
+ ASSERT_EQ(deque.size, sizeof(int) * 16);
+ ASSERT_EQ(deque.alloc_size, sizeof(int) * 16);
+ ASSERT_EQ_MEM(deque.buf, arr, sizeof(int) * 16);
+
+ // push front fail
+ ASSERT_FALSE(UDPC_Deque_push_back(&deque, arr, sizeof(int) * 16));
+ ASSERT_EQ(deque.size, sizeof(int) * 16);
+ ASSERT_EQ(deque.alloc_size, sizeof(int) * 16);
+ ASSERT_EQ_MEM(deque.buf, arr, sizeof(int) * 16);
+
+ // pop back
+ UDPC_Deque_pop_back(&deque, sizeof(int) * 8);
+
+ // get front success
+ size = sizeof(int) * 8;
+ ASSERT_TRUE(UDPC_Deque_get_front(&deque, (void**)&temp, &size));
+ ASSERT_EQ(size, sizeof(int) * 8);
+ ASSERT_EQ_MEM(temp, arr, sizeof(int) * 8);
+ free(temp);
+
+ // get front fail
+ size = sizeof(int) * 16;
+ ASSERT_FALSE(UDPC_Deque_get_front(&deque, (void**)&temp, &size));
+ ASSERT_EQ(size, sizeof(int) * 8);
+ ASSERT_EQ_MEM(temp, arr, sizeof(int) * 8);
+ free(temp);
+
+ // get back success
+ size = sizeof(int) * 8;
+ ASSERT_TRUE(UDPC_Deque_get_back(&deque, (void**)&temp, &size));
+ ASSERT_EQ(size, sizeof(int) * 8);
+ ASSERT_EQ_MEM(temp, arr, sizeof(int) * 8);
+ free(temp);
+
+ // get back fail
+ size = sizeof(int) * 16;
+ ASSERT_FALSE(UDPC_Deque_get_back(&deque, (void**)&temp, &size));
+ ASSERT_EQ(size, sizeof(int) * 8);
+ ASSERT_EQ_MEM(temp, arr, sizeof(int) * 8);
+ free(temp);
+
+ // index success
+ for(int x = 0; x < 8; ++x)
+ {
+ ASSERT_TRUE(UDPC_Deque_index(&deque, sizeof(int), x, (void**)&temp));
+ if(temp)
+ {
+ ASSERT_EQ_MEM(temp, &arr[x], sizeof(int));
+ free(temp);
+ }
+ }
+
+ // index fail
+ ASSERT_FALSE(UDPC_Deque_index(&deque, sizeof(int), 8, (void**)&temp));
+ ASSERT_FALSE(temp);
+
+ // index_rev success
+ for(int x = 0; x < 8; ++x)
+ {
+ ASSERT_TRUE(UDPC_Deque_index_rev(&deque, sizeof(int), x, (void**)&temp));
+ if(temp)
+ {
+ ASSERT_EQ_MEM(temp, &arr[7 - x], sizeof(int));
+ free(temp);
+ }
+ }
+
+ // index_rev fail
+ ASSERT_FALSE(UDPC_Deque_index_rev(&deque, sizeof(int), 8, (void**)&temp));
+ ASSERT_FALSE(temp);
+
+ /*
+ printf("asize %d, size %d, head %d, tail %d\n",
+ deque.alloc_size, deque.size, deque.head, deque.tail);
+ */
+
+ UDPC_Deque_destroy(&deque);
+ UNITTEST_REPORT()
+ return 0;
+}
--- /dev/null
+#ifndef UDPC_UNIT_TEST_H
+#define UDPC_UNIT_TEST_H
+
+#include <stdio.h>
+#include <string.h>
+
+/*
+#include <UDPC_Deque.h>
+*/
+
+#define ASSERT_TRUE(x) \
+ if(!x) { printf("%d: ASSERT_TRUE(%s) FAILED\n", __LINE__, #x); \
+ ++UDPC_uts.failed; } ++UDPC_uts.total;
+#define ASSERT_FALSE(x) \
+ if(x) { printf("%d: ASSERT_FALSE(%s) FAILED\n", __LINE__, #x); \
+ ++UDPC_uts.failed; } ++UDPC_uts.total;
+#define ASSERT_EQ(x, y) \
+ if(x != y) { printf("%d: ASSERT_EQ(%s, %s) FAILED\n", __LINE__, #x, #y); \
+ ++UDPC_uts.failed; } ++UDPC_uts.total;
+#define ASSERT_NEQ(x, y) \
+ if(x == y) { printf("%d: ASSERT_NEQ(%s, %s) FAILED\n", __LINE__, #x, #y); \
+ ++UDPC_uts.failed; } ++UDPC_uts.total;
+#define ASSERT_EQ_MEM(x, y, size) \
+ if(memcmp(x, y, size) != 0) { printf("%d: ASSERT_EQ_MEM(%s, %s, %s) FAILED\n", \
+ __LINE__, #x, #y, #size); ++UDPC_uts.failed; } ++UDPC_uts.total;
+#define ASSERT_NEQ_MEM(x, y, size) \
+ if(memcmp(x, y, size) == 0) { printf("%d: ASSERT_NEQ_MEM(%s, %s, %s) FAILED\n", \
+ __LINE__, #x, #y, #size); ++UDPC_uts.failed; } ++UDPC_uts.total;
+
+#define UNITTEST_REPORT() printf("%d/%d tests failed\n", UDPC_uts.failed, UDPC_uts.total);
+
+
+typedef struct
+{
+ int result;
+} UnitTest_Test;
+
+typedef struct
+{
+ int failed;
+ int total;
+} UnitTestState;
+
+static UnitTestState UDPC_uts;
+
+#endif