Browse Source

Initial commit.

master
Tetsumi 3 weeks ago
parent
commit
43620c6a00
  1. 97
      list.h
  2. 38
      list_build.c
  3. 39
      list_create.c
  4. 29
      list_dequeue.c
  5. 20
      list_destroy.c
  6. 31
      list_enqueue.c
  7. 27
      list_equal.c
  8. 21
      list_equalfast.c
  9. 51
      list_filter.c
  10. 10
      list_foreach.c
  11. 24
      list_initialize.c
  12. 24
      list_last.c
  13. 16
      list_length.c
  14. 50
      list_map.c
  15. 16
      list_newtag.c
  16. 17
      list_pop.c
  17. 42
      list_print.c
  18. 16
      list_push.c
  19. 22
      list_reduce.c
  20. 29
      list_ref.c
  21. 20
      list_reverse.c
  22. 34
      list_take.c
  23. 1
      readme.md
  24. 631
      tests.c

97
list.h

@ -0,0 +1,97 @@ @@ -0,0 +1,97 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
typedef enum
{
ListTag_NONE,
ListTag_U8,
ListTag_U16,
ListTag_U32,
ListTag_U64,
ListTag_S8,
ListTag_S16,
ListTag_S32,
ListTag_S64,
ListTag_F32,
ListTag_F64,
ListTag_P,
ListTag_MAXTAG = 0x1FFFF
} ListTag;
typedef union
{
uint8_t u8;
uint16_t u16;
uint32_t u32;
uint64_t u64;
int8_t s8;
int16_t s16;
int32_t s32;
int64_t s64;
float f32;
void *p;
} ListData;
typedef struct
{
ListData data;
uint64_t rest : 47;
ListTag tag : 17;
} List;
#define List_emptyList ((List*)0x1)
#define List_rest(list) (List*)(uint64_t)(list)->rest
#define List_tag(list) (list)->tag
#define List_empty(list) ((list) == List_emptyList)
#define List_notEmpty(list) ((list) != List_emptyList)
typedef void List_CallbackProc(ListTag tag,
ListData data,
ListTag *outTag,
ListData *outData);
uint64_t List_length(List const *l);
uint64_t List_initialize(List *l, size_t length);
List *List_create(size_t length);
ListTag List_newTag (void);
List *List_map(List const *l, List_CallbackProc *callback);
void List_map$(List *l, List_CallbackProc *callback);
void List_print(List const *list);
int64_t List_ref(List const *list,
size_t pos,
ListTag *outTag,
ListData *outData);
void List_foreach(List const *list, void (*proc)(ListTag tag, ListData data));
void List_destroy(List *l);
List *List_build(bool proc(uint64_t pos, ListData *data, ListTag *tag));
List *List_filter(List const *list, bool proc(ListTag tag, ListData data));
int64_t List_last(List const *list, ListTag *tag, ListData *data);
List *List_take(List const *list, size_t amount);
List *List_reverse(List const *list);
bool List_equal(List const *listA,
List const *listB,
bool (*proc)(ListTag tagA,
ListData dataA,
ListTag tagB,
ListData dataB));
bool List_equalFast64(List const *listA, List const *listB);
List *List_enqueue(List *list, ListTag tag, ListData data);
List *List_dequeue(List *list, ListTag *tag, ListData *data);
List *List_push(List *list, ListTag tag, ListData data);
List *List_pop(List *list, ListTag *tag, ListData *data);
int64_t List_reduce(List const *list,
ListTag *tag,
ListData *data,
List_CallbackProc *reducer);

38
list_build.c

@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
#include "list.h"
#include <stdlib.h>
#include <stdio.h>
/*
* Build a list calling proc for each element until proc return false.
* pos is the current element position and starts at zero.
* NULL is returned if malloc failed.
*/
List *List_build(bool proc(uint64_t pos, ListData *data, ListTag *tag))
{
uint64_t pos = 0;
ListTag tag;
ListData data;
List *head = List_emptyList;
List *cl;
bool re;
while (re = proc(pos++, &data, &tag))
{
if (List_empty(head))
{
head = malloc(sizeof(List));
cl = head;
}
else
{
cl->rest = (uint64_t)malloc(sizeof(List));
cl = List_rest(cl);
}
cl->data = data;
cl->tag = tag;
cl->rest = (uint64_t)List_emptyList;
}
return head;
}

39
list_create.c

@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
#include "list.h"
#include <stdlib.h>
/*
* Create a list with length elements allocated on the heap.
*/
List *List_create(size_t length)
{
if (0 == length)
return List_emptyList;
List* head = malloc(sizeof(List));
if (!head)
return NULL;
--length;
List* cl = head;
for (size_t i = 0; i < length; ++i)
{
cl->rest = (uint64_t)malloc(sizeof(List));
if (!cl->rest)
{
List_destroy(head);
return NULL;
}
cl = List_rest(cl);
}
cl->rest = (uint64_t)List_emptyList;
return head;
}

29
list_dequeue.c

@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
#include "list.h"
#include <stdlib.h>
List *List_dequeue(List *list, ListTag *tag, ListData *data)
{
if (List_empty(list))
return NULL;
List *ll = list;
List *lll = list;
while (List_notEmpty(List_rest(ll)))
{
lll = ll;
ll = List_rest(ll);
}
*tag = ll->tag;
*data = ll->data;
if (list == ll)
list = List_emptyList;
else
lll->rest = (uint64_t)List_emptyList;
free(ll);
return list;
}

20
list_destroy.c

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
#include "list.h"
#include <stdlib.h>
void List_destroy(List *l)
{
if (List_empty(l))
return;
List *nl = NULL;
do
{
nl = List_rest(l);
free(l);
l = nl;
}
while (List_notEmpty(l));
}

31
list_enqueue.c

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
#include "list.h"
#include <stdlib.h>
/*
* add a new element at the end of the passed list.
* if the passed list is empty, a new list is returned.
* return NULL on error (eg: malloc failed).
*/
List *List_enqueue(List *list, ListTag tag, ListData data)
{
List *ne = malloc(sizeof(List));
if (!ne)
return NULL;
ne->data.u64 = data.u64;
ne->tag = tag;
ne->rest = (uint64_t)List_emptyList;
if (List_empty(list))
return ne;
List *ll = list;
while(List_notEmpty(List_rest(ll)))
ll = List_rest(ll);
ll->rest = (uint64_t)ne;
return list;
}

27
list_equal.c

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
#include "list.h"
bool List_equal(List const *listA,
List const *listB,
bool (*proc)(ListTag tagA,
ListData dataA,
ListTag tagB,
ListData dataB))
{
if (List_length(listA) != List_length(listB))
return false;
if (List_empty(listA))
return true;
while (List_notEmpty(listA))
{
if (!proc(listA->tag, listA->data, listB->tag, listB->data))
return false;
listA = List_rest(listA);
listB = List_rest(listB);
}
return true;
}

21
list_equalfast.c

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
#include "list.h"
bool List_equalFast64(List const *listA, List const *listB)
{
if (List_length(listA) != List_length(listB))
return false;
if (List_empty(listA))
return true;
while (List_notEmpty(listA))
{
if (listA->data.u64 != listB->data.u64)
return false;
listA = List_rest(listA);
listB = List_rest(listB);
}
return true;
}

51
list_filter.c

@ -0,0 +1,51 @@ @@ -0,0 +1,51 @@
#include "list.h"
#include <stdlib.h>
/*
* filter a list using proc as a predicate.
* return a new list.
*/
List *List_filter(List const *list, bool proc(ListTag tag, ListData data))
{
List *flistHead = List_emptyList;
List *cflist = NULL;
while (List_notEmpty(list))
{
bool keep = proc(list->tag, list->data);
if (!keep)
{
list = List_rest(list);
continue;
}
List *nList = malloc(sizeof(List));
if (!nList)
{
List_destroy(flistHead);
return NULL;
}
nList->data = list->data;
nList->tag = list->tag;
nList->rest = (uint64_t)List_emptyList;
list = List_rest(list);
if (cflist)
{
cflist->rest = (uint64_t)nList;
cflist = nList;
}
else
{
flistHead = nList;
cflist = nList;
}
}
return flistHead;
}

10
list_foreach.c

@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
#include "list.h"
void List_foreach(List const *list, void (*proc)(ListTag tag, ListData data))
{
while (List_notEmpty(list))
{
proc(list->tag, list->data);
list = List_rest(list);
}
}

24
list_initialize.c

@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
#include "list.h"
/**
* Helper procedure to initialize the nodes of a list that
* has been allocated on the stack.
*
* EG:
* List list[100];
* List_initialize(list, 100); // links the nodes
*/
uint64_t List_initialize(List *l, size_t length)
{
if (List_empty(l) || 0 == length)
return 0;
for (size_t index = 0; index < length; ++index)
{
l[index].rest = (uint64_t)&l[index + 1];
}
l[length-1].rest = (uint64_t)List_emptyList;
return 0;
}

24
list_last.c

@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
#include "list.h"
/*
* returns last element of a list.
* if list is empty, tag is set to LastTag_NONE.
*/
int64_t List_last(List const *list, ListTag *tag, ListData *data)
{
if (List_empty(list))
{
*tag = ListTag_NONE;
return 0;
}
while(List_notEmpty(List_rest(list)))
{
list = List_rest(list);
}
*tag = list->tag;
*data = list->data;
return 0;
}

16
list_length.c

@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
#include "list.h"
uint64_t List_length(List const *list)
{
uint64_t length = 0;
while (List_notEmpty(list))
{
++length;
list = List_rest(list);
}
return length;
}

50
list_map.c

@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
#include "list.h"
/*
* apply proc() on each element of a list to a new list.
* outTag initialized with the position of the element.
*
*/
List *List_map(List const *list , List_CallbackProc *callback)
{
if (List_empty(list))
return List_emptyList;
size_t length = List_length(list);
List *newl = List_create(length);
List *n = newl;
if (NULL == newl)
return NULL;
for (size_t i = 0; i < length; ++i)
{
ListTag tag = i;
ListData data;
callback(List_tag(list), list->data, &tag, &n->data);
n->tag = tag;
n = List_rest(n);
list = List_rest(list);
}
return newl;
}
/*
* in-place version.
*/
void List_map$(List *list, List_CallbackProc *callback)
{
uint32_t pos = 0;
while (List_notEmpty(list))
{
ListTag newTag = pos++;
callback(list->tag, list->data, &newTag, &list->data);
list->tag = newTag;
list = List_rest(list);
}
}

16
list_newtag.c

@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
#include "list.h"
/*
* return a new unique tag.
* return ListTag_None when no more tag is available.
* tags limit is ListTag_MAXTAG
*/
ListTag List_newTag (void)
{
static ListTag current_lt = ListTag_P + 1;
if (ListTag_MAXTAG == current_lt)
return ListTag_NONE;
return current_lt++;
}

17
list_pop.c

@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
#include "list.h"
#include <stdlib.h>
List *List_pop(List *list, ListTag *tag, ListData *data)
{
if (List_empty(list))
return NULL;
List *nl = List_rest(list);
*tag = list->tag;
*data = list->data;
free(list);
return nl;
}

42
list_print.c

@ -0,0 +1,42 @@ @@ -0,0 +1,42 @@
#include "list.h"
#include <stdio.h>
/*
* print list's elements to stdout.
* for debugging.
*/
void List_print(List const *list)
{
char *fstr(ListTag tag)
{
if (ListTag_NONE == tag)
return "<None>%s";
if (ListTag_U8 <= tag && ListTag_U64 >= tag)
return "%llu%s";
if (ListTag_S8 <= tag && ListTag_S64 >= tag)
return "%lli%s";
if (ListTag_F32 == tag || ListTag_F64 == tag)
return "%f%s";
return "*%p%s";
}
printf("List @%p:\n", list);
uint64_t elcount = 0;
while (List_notEmpty(list))
{
printf(fstr(list->tag),
list->data.p,
(++elcount & 0x7) == 0 ? "\n" : " ");
list = List_rest(list);
}
if (elcount & 0x7)
putchar('\n');
}

16
list_push.c

@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
#include "list.h"
#include <stdlib.h>
List *List_push(List *list, ListTag tag, ListData data)
{
List *n = malloc(sizeof(List));
if (!n)
return NULL;
n->tag = tag;
n->data = data;
n->rest = (uint64_t)list;
return n;
}

22
list_reduce.c

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
#include "list.h"
/*
* reduce a list to one value.
* the current calue is passed to the callback through outdData
* if list is empty, tag is set to LastTag_NONE.
*/
int64_t List_reduce(List const *list,
ListTag *tag,
ListData *data,
List_CallbackProc *reducer)
{
*tag = ListTag_NONE;
while (List_notEmpty(list))
{
reducer(list->tag, list->data, tag, data);
list = List_rest(list);
}
return 0;
}

29
list_ref.c

@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
#include "list.h"
/*
* get nth tag and element of list.
* element data and tag returned as outData and outTag.
* return -1 if pos is equal or greater than list's length.
*/
int64_t List_ref(List const *list,
size_t pos,
ListTag *outTag,
ListData *outData)
{
size_t i = 0;
for (; i < pos; ++i)
{
if (List_empty(list))
return -1;
list = List_rest(list);
}
if (List_empty(list))
return -1;
*outData = list->data;
*outTag = list->tag;
return 0;
}

20
list_reverse.c

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
#include "list.h"
#include <stdlib.h>
List *List_reverse(List const *list)
{
List *rl = List_emptyList;
while (List_notEmpty(list))
{
List *node = malloc(sizeof(List));
node->rest = (uint64_t)rl;
node->tag = list->tag;
node->data = list->data;
rl = node;
list = List_rest(list);
}
return rl;
}

34
list_take.c

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
#include "list.h"
#include <stdlib.h>
/*
* return a new list with the specified
* amount of elements starting from the first
* element.
*/
List *List_take(List const *list, size_t amount)
{
List *head = List_emptyList;
List *cl;
while (List_notEmpty(list) && amount--)
{
if (List_empty(head))
{
head = malloc(sizeof(List));
cl = head;
}
else
{
cl->rest = (uint64_t)malloc(sizeof(List));
cl = List_rest(cl);
}
cl->data = list->data;
cl->tag = list->tag;
cl->rest = (uint64_t)List_emptyList;
list = List_rest(list);
}
return head;
}

1
readme.md

@ -0,0 +1 @@ @@ -0,0 +1 @@
an old tagged linked list implementation for x64 that i used for Lisp like programming language.

631
tests.c

@ -0,0 +1,631 @@ @@ -0,0 +1,631 @@
// unit tests
#include <stdio.h>
#include "list.h"
bool test_list_empty(void)
{
List *list = List_create(1);
bool r = List_notEmpty(list) && !List_empty(list);
List_destroy(list);
return r && List_empty(List_emptyList) && !List_notEmpty(List_emptyList);
}
bool test_list_create(void)
{
List *list = List_create(0);
if(List_notEmpty(list) || List_length(list) != 0)
return false;
list = List_create(1);
bool r1 = List_notEmpty(list) && List_length(list) == 1;
List_destroy(list);
list = List_create(300);
bool r2 = List_notEmpty(list) && List_length(list) == 300;
List_destroy(list);
return r1 && r2;
}
bool test_list_destroy(void)
{
List_destroy(List_emptyList);
List_destroy(List_create(300));
return true;
}
bool buildproc (uint64_t pos, ListData *data, ListTag *tag)
{
if (100 <= pos)
return false;
data->u64 = pos;
*tag = ListTag_U64;
return true;
}
bool test_list_last(void)
{
List *l = List_build(buildproc);
ListTag tag;
ListData data;
List_last(l, &tag, &data);
List_destroy(l);
return ListTag_U64 == tag && 99 == data.u64;
}
bool test_list_initialize(void)
{
List list[100];
ListTag tag;
ListData data;
list[99].data.u64 = 0x123456;
list[99].tag = ListTag_U64;
List_initialize(list, 100);
List_last(list, &tag, &data);
return ListTag_U64 == tag && 0x123456 == data.u64;
}
bool test_list_length(void)
{
List *l = List_build(buildproc);
bool r = List_length(l) == 100;
List_destroy(l);
l = List_create(100);
bool r2 = List_length(l) == 100;
List_destroy(l);
return r && r2 && List_length(List_emptyList) == 0;
}
bool test_list_newtag(void)
{
return List_newTag() != List_newTag();
}
bool test_list_ref(void)
{
ListTag tag;
ListData data;
List *l = List_build(buildproc);
bool r1 = -1 != List_ref(l, 0, &tag, &data);
bool r2 = ListTag_U64 == tag && 0 == data.u64;
bool r3 = -1 != List_ref(l, 99, &tag, &data);
bool r4 = ListTag_U64 == tag && 99 == data.u64;
bool r5 = -1 == List_ref(List_emptyList, 99, &tag, &data);
List_destroy(l);
return r1 && r2 && r3 && r4 && r5;
}
bool test_buildproc1(uint64_t pos, ListData *data, ListTag *tag)
{
if (10 <= pos)
return false;
data->u64 = pos;
*tag = ListTag_U64;
return true;
}
bool test_buildproc2(uint64_t pos, ListData *data, ListTag *tag)
{
return 0 > pos;
}
bool test_list_build(void)
{
List *l = List_build(test_buildproc1);
List *ll = l;
for (size_t i = 0; i < 10; ++i)
{
if (ll->data.u64 != i && ll->tag != ListTag_U64)
{
List_destroy(l);
return false;
}
ll = List_rest(ll);
}
List_destroy(l);
if (List_notEmpty(ll))
return false;
l = List_build(test_buildproc2);
return List_empty(l);
}
bool test_list_take(void)
{
List *l = List_build(test_buildproc1);
List *l2 = List_take(l, 5);
if (5 != List_length(l2))
return false;
List *ll2 = l2;
for (size_t i = 0; i < 5; ++i)
{
if (ll2->data.u64 != i)
{
List_destroy(l);
List_destroy(l2);
return false;
}
ll2 = List_rest(ll2);
}
List_destroy(l2);
if (List_notEmpty(ll2))
{
List_destroy(l);
return false;
}
l2 = List_take(l, 0);
List_destroy(l);
return List_empty(l2) && List_empty(List_take(List_emptyList, 10));
}
bool test_filteroddproc(ListTag tag, ListData data)
{
return data.u64 & 1;
}
bool test_filterevenproc(ListTag tag, ListData data)
{
return 0 == (data.u64 & 1);
}
bool test_filterabove(ListTag tag, ListData data)
{
return data.u64 > 100;
}
bool test_list_filter(void)
{
List *l = List_build(test_buildproc1);
List *l2 = List_filter(l, test_filteroddproc);
List *l3 = List_filter(l, test_filterevenproc);
List *l4 = List_filter(l, test_filterabove);
List_destroy(l);
if (5 != List_length(l2) || 5 != List_length(l3) || List_notEmpty(l4))
{
List_destroy(l2);
List_destroy(l3);
List_destroy(l4);
return false;
}
List *ll2 = l2;
List *ll3 = l3;
for (size_t i = 0; i < 10; ++i)
{
if (i & 1)
{
if (ll2->data.u64 != i)
{
List_destroy(l2);
List_destroy(l3);
return false;
}
ll2 = List_rest(ll2);
}
else
{
if (ll3->data.u64 != i)
{
List_destroy(l2);
List_destroy(l3);
return false;
}
ll3 = List_rest(ll3);
}
}
List_destroy(l2);
List_destroy(l3);
return List_empty(ll2) && List_empty(ll3);
}
uint64_t foreach_incrementor(void)
{
static uint64_t i = 0;
return i++;
}
void foreachproc(ListTag tag, ListData data)
{
foreach_incrementor();
}
bool test_list_foreach(void)
{
List *l = List_build(test_buildproc1);
List_foreach(l, foreachproc);
List_destroy(l);
List_foreach(List_emptyList, foreachproc);
return 10 == foreach_incrementor();
}
void mapproc(ListTag tag,
ListData data,
ListTag *outTag,
ListData *outData)
{
*outTag = tag;
outData->u64 = data.u64 * 2;
}
bool test_list_map$(void)
{
List *l = List_build(test_buildproc1);
List *ll = l;
List_map$(l, mapproc);
if (List_length(l) != 10)
{
List_destroy(l);
return false;
}
for (size_t i = 0; i < 10; ++i)
{
if (ll->data.u64 != i * 2)
{
List_destroy(l);
return false;
}
ll = List_rest(ll);
}
List_destroy(l);
return true;
}
bool test_list_map(void)
{
List *l = List_build(test_buildproc1);
List *l2 = List_map(l, mapproc);
List *ll = l2;
List_destroy(l);
if (List_length(l2) != 10)
{
List_destroy(l2);
return false;
}
for (size_t i = 0; i < 10; ++i)
{
if (ll->data.u64 != i * 2)
{
List_destroy(l2);
return false;
}
ll = List_rest(ll);
}
List_destroy(l2);
return true;
}
bool test_list_reverse(void)
{
List *l = List_build(test_buildproc1);
List *rl = List_reverse(l);
List_destroy(l);
if (List_empty(rl) || List_length(rl) != 10)
{
List_destroy(rl);
return false;
}
List *rll = rl;
for (int64_t i = 9; i >= 0; --i)
{
if (rll->data.u64 != i)
{
List_destroy(rl);
return false;
}
rll = List_rest(rll);
}
List_destroy(rl);
return List_empty(List_reverse(List_emptyList));
}
bool equalproc(ListTag tagA, ListData dataA, ListTag tagB, ListData dataB)
{
return dataA.u64 == dataB.u64;
}
bool test_list_equal(void)
{
List *l = List_build(test_buildproc1);
List *lb = List_build(test_buildproc1);
if (!List_equal(l, lb, equalproc))
{
List_destroy(l);
List_destroy(lb);
return false;
}
lb->data.u64 = 123465;
bool res = List_equal(l, lb, equalproc);
List_destroy(l);
List_destroy(lb);
if (res)
return false;
l = List_create(1);
lb = List_create(2);
res = List_equal(l, lb, equalproc);
List_destroy(l);
List_destroy(lb);
if (res)
return false;
return List_equal(List_emptyList, List_emptyList, equalproc);
}
bool test_list_enqueue(void)
{
List *l = List_build(test_buildproc1);
for (size_t i = 10; i < 20; ++i)
List_enqueue(l, ListTag_U64, (ListData){.u64 = i});
if (20 != List_length(l))
{
List_destroy(l);
return false;
}
List *ll = l;
for (size_t i = 0; i < 20; ++i)
{
if (ll->data.u64 != i)
{
List_destroy(l);
return false;
}
ll = List_rest(ll);
}
List_destroy(l);
l = List_enqueue(List_emptyList, ListTag_U64, (ListData){.u64 = 123});
bool res = 1 == List_length(l) && 123 == l->data.u64;
List_destroy(l);
return res;
}
bool test_list_dequeue(void)
{
List *l = List_build(test_buildproc1);
ListTag tag;
ListData data;
l = List_dequeue(l, &tag, &data);
if (9 != List_length(l) || 9 != data.u64)
{
List_destroy(l);
return false;
}
for (size_t i = 0; i < 9; ++i)
l = List_dequeue(l, &tag, &data);
if (List_notEmpty(l))
{
List_destroy(l);
return false;
}
return NULL == List_dequeue(l, &tag, &data);
}
bool test_list_push(void)
{
List *l = List_push(List_emptyList, ListTag_U64, (ListData){.u64 = 123});
if (1 != List_length(l) || 123 != l->data.u64)
{
List_destroy(l);
return false;
}
l = List_push(l, ListTag_U64, (ListData){.u64 = 456});
bool res = 2 == List_length(l) || 456 == l->data.u64;
List_destroy(l);
return res;
}
bool test_list_pop(void)
{
List *l = List_build(test_buildproc1);
ListTag tag;
ListData data;
l = List_pop(l, &tag, &data);
if (9 != List_length(l) || 0 != data.u64)
{
List_destroy(l);
return false;
}
for (size_t i = 0; i < 9; ++i)
l = List_pop(l, &tag, &data);
if (List_notEmpty(l))
{
List_destroy(l);
return false;
}
return NULL == List_pop(l, &tag, &data);
}
void reducer(ListTag tag,
ListData data,
ListTag *outTag,
ListData *outData)
{
*outTag = tag;
outData->u64 += data.u64;
}
bool test_list_reduce(void)
{
List *l = List_build(test_buildproc1);
ListTag tag;
ListData data = {.u64 = 0};
List_reduce(l, &tag, &data, reducer);
return data.u64 == 45;
}
struct
{
bool (*proc)(void);
char *caption;
} tests[] = {
{test_list_empty, "List_empty"},
{test_list_create, "List_create"},
{test_list_destroy, "List_destroy"},
{test_list_last, "List_last"},
{test_list_initialize, "List_initialize"},
{test_list_length, "List_length"},
{test_list_newtag, "List_newTag"},
{test_list_ref, "List_ref"},
{test_list_build, "List_build"},
{test_list_take, "List_take"},
{test_list_filter, "List_filter"},
{test_list_foreach, "List_foreach"},
{test_list_map$, "List_map$"},
{test_list_map, "List_map"},
{test_list_reverse, "List_reverse"},
{test_list_equal, "List_equal"},
{test_list_enqueue, "List_enqueue"},
{test_list_dequeue, "List_dequeue"},
{test_list_push, "List_push()"},
{test_list_pop, "List_pop()"},
{test_list_reduce, "List_reduce()"},
{NULL, NULL}
};
/*
* TODO:
*
*
* TODO tests:
*
*
*/
#define TERMRED "\033[0;31m"
#define TERMGREEN "\033[0;32m"
#define TERMNOCOLOR "\033[0m"
int main(void)
{
puts("Tests:");
for (size_t i = 0; tests[i].proc; ++i)
{
printf(TERMNOCOLOR "%s...%s\n",
tests[i].caption,
tests[i].proc()
? TERMGREEN "passed."
: TERMRED "failed!!");
}
return 0;
}
Loading…
Cancel
Save