Recently i added such generic list in github and i would like to get some feedback.
Here is a link to the code in github:
https://github.com/MartinChekurov/Generic-Linked-List
GenericList.c
#include "GenericList.h"
typedef struct GenListNode_t {
void* data;
struct GenListNode_t* pNext;
}GenListNode;
struct GenList_t {
GenListNode* head;
Compare cmp;
unsigned int dataSize;
unsigned int count;
};
static GenListError genListCopyNodeData(void* data, unsigned int dataSize, void* buf, unsigned int bufSize)
{
unsigned int cSize = 0;
if (!data || !buf) {
return GEN_LIST_WRONG_PAR;
}
cSize = bufSize < dataSize ? bufSize : dataSize;
memcpy(buf, data, cSize);
return GEN_LIST_NO_ERR;
}
static GenListNode* genLisNewNode(void* data, unsigned int dataSize)
{
GenListNode* node = NULL;
if (!data) {
return NULL;
}
node = malloc(sizeof(*node));
if (!node) {
return NULL;
}
memset(node, 0, sizeof(*node));
node->data = malloc(dataSize);
if (!node->data) {
return NULL;
}
memcpy(node->data, data, dataSize);
return node;
}
static GenListError genListDestroyNode(GenListNode* node)
{
if (!node) {
return GEN_LIST_WRONG_PAR;
}
free(node->data);
free(node);
return GEN_LIST_NO_ERR;
}
GenList* genListNew(unsigned int dataSize, Compare cmp)
{
GenList* list = NULL;
list = malloc(sizeof(*list));
if (!list) {
return NULL;
}
memset(list, 0, sizeof(*list));
list->dataSize = dataSize;
if (cmp) {
list->cmp = cmp;
}
return list;
}
GenListError genListPushHead(GenList* list, void* data)
{
GenListNode* node = NULL;
if (!list || !data) {
return GEN_LIST_WRONG_PAR;
}
if (list->count == UINT_MAX) {
return GEN_LIST_FULL;
}
node = genLisNewNode(data, list->dataSize);
if (!node) {
return GEN_LIST_NO_MEMORY;
}
node->pNext = list->head;
list->head = node;
list->count++;
return GEN_LIST_NO_ERR;
}
GenListError genListPopHead(GenList* list, void* buf, unsigned int size)
{
GenListNode* node = NULL;
GenListError status = GEN_LIST_NO_ERR;
if (!list) {
return GEN_LIST_WRONG_PAR;
}
if (list->head) {
node = list->head;
list->head = node->pNext;
status = genListCopyNodeData(node->data, list->dataSize, buf, size);
if (status != GEN_LIST_NO_ERR) {
return status;
}
genListDestroyNode(node);
if (list->count)
list->count--;
}
return GEN_LIST_NO_ERR;
}
GenListError genListGetIndex(GenList* list, unsigned int index, void* buf, unsigned int size)
{
GenListNode* node = NULL;
unsigned int count = 0;
if (!list) {
return GEN_LIST_WRONG_PAR;
}
node = list->head;
while(node && count < list->count) {
if (count == index) {
return genListCopyNodeData(node->data, list->dataSize, buf, size);
}
node = node->pNext;
count++;
}
return GEN_LIST_ERROR;
}
GenListError genListSearchNode(GenList* list, void* data, void* buf, unsigned int size)
{
GenListNode* node = NULL;
GenListError status = GEN_LIST_NO_ERR;
if (!list || !data || !buf) {
return GEN_LIST_WRONG_PAR;
}
node = list->head;
while(node) {
if (list->cmp) {
status = list->cmp(node->data, data);
if (status == GEN_LIST_MATCH) {
return genListCopyNodeData(node->data, list->dataSize, buf, size);
}
}
node = node->pNext;
}
return GEN_LIST_ERROR;
}
GenListError genListDestroy(GenList* list)
{
GenListNode* node = NULL;
GenListError status = GEN_LIST_NO_ERR;
if (!list) {
return GEN_LIST_WRONG_PAR;
}
while(list->head) {
node = list->head;
list->head = node->pNext;
status = genListDestroyNode(node);
if (status != GEN_LIST_NO_ERR) {
return status;
}
}
free(list);
return GEN_LIST_NO_ERR;
}
GenListError genListGetSize(GenList* list, unsigned int *size)
{
if (!list || !size) {
return GEN_LIST_WRONG_PAR;
}
*size = list->count;
return GEN_LIST_NO_ERR;
}
GenericList.h
/*
* Author: Martin Chekurov
*/
#ifndef GEN_LIST_H_
#define GEN_LIST_H_
#include <stdlib.h>
#include <string.h>
#include <limits.h>
typedef enum {
GEN_LIST_NO_ERR,
GEN_LIST_WRONG_PAR,
GEN_LIST_NO_MEMORY,
GEN_LIST_MATCH,
GEN_LIST_NO_MATCH,
GEN_LIST_FULL,
GEN_LIST_ERROR
}GenListError;
typedef GenListError (*Compare)(void*, void*);
typedef struct GenList_t GenList;
GenList* genListNew (unsigned int dataSize, Compare cmp);
GenListError genListDestroy (GenList* list);
GenListError genListPushHead (GenList* list, void* data);
GenListError genListPopHead (GenList* list, void* buf, unsigned int size);
GenListError genListSearchNode(GenList* list, void* data, void* buf, unsigned int size);
GenListError genListGetSize (GenList* list, unsigned int *size);
GenListError genListGetIndex (GenList* list, unsigned int index, void* buf, unsigned int size);
#endif
Test.c
#include"GenericList.h"
#include<stdio.h>
#define MAX_NODES (5)
GenListError compare(void* dataIn, void* dataOut)
{
return *(int*)dataIn == *(int*)dataOut ? GEN_LIST_MATCH : GEN_LIST_NO_MATCH;
}
int main(void)
{
GenListError status = GEN_LIST_NO_ERR;
GenList* list = NULL;
unsigned int buf[MAX_NODES] = {1, 2, 3, 4, 5};
unsigned int i = 0, size = 0, value = 0;
printf("\nInitialize the list.");
list = genListNew(sizeof(int), compare);
if (!list) {
printf("\ngenListNew failed.");
return 1;
}
printf("\nPush %d nodes:", MAX_NODES);
for (i = 0 ; i < MAX_NODES ; i++) {
printf("\nPush value: %d.", buf[i]);
status = genListPushHead(list, &buf[i]);
if (status != GEN_LIST_NO_ERR) {
printf("\ngenListPushHead() error: %d", (int)status);
return 1;
}
}
for (i = 0 ; i < MAX_NODES ; i++) {
printf("\nGet value on index %d.", i);
status = genListGetIndex(list, i, &value, sizeof(int));
if (status != GEN_LIST_NO_ERR) {
printf("\ngenListGetIndex() error: %d", (int)status);
return 1;
}
printf("\nGot value: %d.", value);
}
status = genListGetSize(list, &size);
if (status != GEN_LIST_NO_ERR) {
printf("\ngenListGetSize() error: %d", (int)status);
return 1;
}
printf("\nPushed %d nodes.", size);
for (i = 0 ; i < MAX_NODES ; i++) {
printf("\nFind value: %d.", buf[i]);
status = genListSearchNode(list, &buf[i], &value, sizeof(int));
if (status != GEN_LIST_NO_ERR) {
printf("\ngenListSearchNode() error: %d", (int)status);
return 1;
}
printf("\nFound value: %d.", value);
}
for (i = 0 ; i < MAX_NODES ; i++) {
printf("\nPop a value from the list.");
status = genListPopHead(list, &value, sizeof(int));
if (status != GEN_LIST_NO_ERR) {
printf("\ngenListPopHead() error: %d", (int)status);
return 1;
}
printf("\nPoped value: %d.", value);
status = genListGetSize(list, &size);
if (status != GEN_LIST_NO_ERR) {
printf("\ngenListGetSize() error: %d", (int)status);
return 1;
}
printf("\nValues left: %d.", size);
}
printf("\nDestroy the list.");
status = genListDestroy(list);
if (status != GEN_LIST_NO_ERR) {
printf("\ngenListDestroy() error: %d", (int)status);
return 1;
}
printf("\nDone.");
getchar();
}