519 lines
16 KiB
C
519 lines
16 KiB
C
/* Copyright (c) 1997 Microsoft Corporation */
|
|
/* See the .C test code at the end of this file for examples of how to use
|
|
this stuff.
|
|
*/
|
|
#ifndef _LISTS_H
|
|
#define _LISTS_H
|
|
|
|
#if __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#define LIST_ROOT(name, type) struct name {struct type *Root;}
|
|
|
|
#define LIST_MEMBER(type) struct { struct type **Prev; struct type *Next;}
|
|
/* Note! Prev is the ADDRESS of the previous next element ptr */
|
|
|
|
#define LIST_INSERT_ROOT(root,element,field)\
|
|
{ if(((element)->field.Next = (root)->Root) != 0)\
|
|
(root)->Root->field.Prev = &(element)->field.Next;\
|
|
(root)->Root = (element);\
|
|
(element)->field.Prev = &(root)->Root;\
|
|
}
|
|
|
|
#define LIST_DELETE(element,field)\
|
|
{\
|
|
if((element)->field.Next)\
|
|
(element)->field.Next->field.Prev = (element)->field.Prev;\
|
|
*(element)->field.Prev = (element)->field.Next;\
|
|
(element)->field.Next = 0;\
|
|
(element)->field.Prev = 0;\
|
|
}
|
|
|
|
#define LIST_INITIALIZE(root)\
|
|
{\
|
|
(root)->Root = 0;\
|
|
}
|
|
|
|
#define LIST_INITIALIZE_MEMBER(element,field)\
|
|
{ (element)->field.Next = 0;\
|
|
(element)->field.Prev = 0;\
|
|
}
|
|
|
|
#define LIST_ORPHAN_MEMBER(element,field) (!((element)->field.Prev))
|
|
|
|
#define LIST_FIRST(root) (root)->Root
|
|
#define LIST_NEXT(element,field) (element)->field.Next
|
|
|
|
|
|
|
|
#define TAIL_QUEUE_INITIALIZE(root)\
|
|
{\
|
|
(root)->First = NULL;\
|
|
(root)->Last = &(root)->First;\
|
|
}
|
|
|
|
#define TAIL_QUEUE_ROOT(name,type)\
|
|
struct name\
|
|
{ struct type *First;\
|
|
struct type **Last;\
|
|
}/* NOTE! This is the address of the last Next pointer. */
|
|
|
|
|
|
#define TAIL_QUEUE_MEMBER(type)\
|
|
struct\
|
|
{ struct type *Next;\
|
|
struct type **Prev; /* NOTE! Address of previous Next element ptr */\
|
|
}
|
|
|
|
#define TAIL_QUEUE_INSERT_END(root,element,field)\
|
|
{ (element)->field.Prev = (root)->Last;\
|
|
(element)->field.Next = 0;\
|
|
*(root)->Last = (element);\
|
|
(root)->Last = &(element)->field.Next;\
|
|
}
|
|
|
|
#define TAIL_QUEUE_DELETE(root,element,field)\
|
|
{\
|
|
if (((element)->field.Next) != NULL)\
|
|
(element)->field.Next->field.Prev = (element)->field.Prev;\
|
|
else\
|
|
(root)->Last = (element)->field.Prev;\
|
|
*(element)->field.Prev = (element)->field.Next;\
|
|
(element)->field.Next = 0;\
|
|
(element)->field.Prev = 0;\
|
|
}
|
|
|
|
#define TAIL_QUEUE_FIRST(root) (root)->First
|
|
#define TAIL_QUEUE_NEXT(element,field) (element)->field.Next
|
|
|
|
|
|
|
|
#define CIRCLE_QUEUE_ROOT(name,type)\
|
|
struct name\
|
|
{ struct type *Last;\
|
|
struct type *First;\
|
|
}
|
|
|
|
#define CIRCLE_QUEUE_MEMBER(type)\
|
|
struct\
|
|
{ struct type *Prev;\
|
|
struct type *Next;\
|
|
}
|
|
|
|
#define CIRCLE_QUEUE_INITIALIZE(root,type)\
|
|
{ (root)->Last = (type *)(root);\
|
|
(root)->First = (type *)(root);\
|
|
}
|
|
|
|
#define CIRCLE_QUEUE_INITIALIZE_MEMBER(element,field)\
|
|
{ (element)->field.Next = (element)->field.Prev = 0;\
|
|
}
|
|
|
|
#define CIRCLE_QUEUE_INSERT_END(root,type,element,field)\
|
|
{ (element)->field.Prev = (root)->Last;\
|
|
(element)->field.Next = (type *)(root);\
|
|
if((root)->First != (type *)(root))\
|
|
(root)->Last->field.Next = (element);\
|
|
else\
|
|
(root)->First = (element);\
|
|
(root)->Last = (element);\
|
|
}
|
|
|
|
#define CIRCLE_QUEUE_INSERT_ROOT(root,type,element,field)\
|
|
{ (element)->field.Prev = (type *)(root);\
|
|
(element)->field.Next = (root)->First;\
|
|
if ((root)->Last != (void *)(root))\
|
|
(root)->First->field.Prev = (element);\
|
|
else\
|
|
(root)->Last = (element);\
|
|
(root)->First = (element);\
|
|
}
|
|
|
|
#define CIRCLE_QUEUE_INSERT_PREVIOUS(root,current_element,element,field)\
|
|
{ (element)->field.Prev = (current_element)->field.Prev;\
|
|
(element)->field.Next = (current_element);\
|
|
if ((current_element)->field.Prev != (void *)(root))\
|
|
(current_element)->field.Prev->field.Next = (element);\
|
|
else\
|
|
(root)->First = (element);\
|
|
(current_element)->field.Prev = (element);\
|
|
}
|
|
|
|
#define CIRCLE_QUEUE_DELETE(root,element,field)\
|
|
{ if((element)->field.Next != (void *)(root))\
|
|
(element)->field.Next->field.Prev = (element)->field.Prev;\
|
|
else\
|
|
(root)->Last = (element)->field.Prev;\
|
|
if((element)->field.Prev != (void *)(root))\
|
|
(element)->field.Prev->field.Next = (element)->field.Next;\
|
|
else\
|
|
(root)->First = (element)->field.Next;\
|
|
(element)->field.Next = 0;\
|
|
(element)->field.Prev = 0;\
|
|
}
|
|
|
|
#define CIRCLE_QUEUE_FIRST(root)\
|
|
((root)->First == (void *) (root)? 0: (root)->First)
|
|
|
|
#define CIRCLE_QUEUE_LAST(root)\
|
|
((root)->Last == (void *) (root)? 0: (root)->Last)
|
|
|
|
#define CIRCLE_QUEUE_NEXT(root,element,field)\
|
|
((void *) (element)->field.Next == (void *) (root)? 0: (element)->field.Next)
|
|
|
|
#define CIRCLE_QUEUE_PREVIOUS(root,element,field)\
|
|
((element)->field.Prev == (void *) (root)? 0: (element)->field.Prev)
|
|
|
|
#if 0
|
|
/*
|
|
Test code. Strip it out, put it in a .C (or .CPP) file and compile it as a
|
|
console app to test this stuff. It should run without any assertion failures.
|
|
|
|
Also, use this as example code.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
|
|
#include "lists.h"
|
|
|
|
void TestList(void)
|
|
{
|
|
struct Foo
|
|
{
|
|
int a;
|
|
LIST_MEMBER(Foo) ListStuff;
|
|
int b;
|
|
};
|
|
struct Foo MyFoo1, MyFoo2, MyFoo3, *pFoo = 0;
|
|
LIST_ROOT(sRoot, Foo) MyListRoot;
|
|
|
|
fputs("Testing LIST.\n",stdout);
|
|
|
|
LIST_INITIALIZE(&MyListRoot);
|
|
|
|
LIST_INITIALIZE_MEMBER(&MyFoo1,ListStuff);
|
|
MyFoo1.a = 0x1A; MyFoo1.b = 0x1B;
|
|
|
|
LIST_INITIALIZE_MEMBER(&MyFoo2,ListStuff);
|
|
MyFoo2.a = 0x2A; MyFoo2.b = 0x2B;
|
|
|
|
LIST_INITIALIZE_MEMBER(&MyFoo3,ListStuff);
|
|
MyFoo3.a = 0x3A; MyFoo3.b = 0x3B;
|
|
assert(LIST_ORPHAN_MEMBER(&MyFoo3,ListStuff));
|
|
|
|
LIST_INSERT_ROOT(&MyListRoot,&MyFoo3,ListStuff);
|
|
assert(!LIST_ORPHAN_MEMBER(&MyFoo3,ListStuff));
|
|
LIST_INSERT_ROOT(&MyListRoot,&MyFoo2,ListStuff);
|
|
LIST_INSERT_ROOT(&MyListRoot,&MyFoo1,ListStuff);
|
|
|
|
assert(!LIST_ORPHAN_MEMBER(&MyFoo1,ListStuff));
|
|
assert(!LIST_ORPHAN_MEMBER(&MyFoo2,ListStuff));
|
|
assert(!LIST_ORPHAN_MEMBER(&MyFoo3,ListStuff));
|
|
|
|
pFoo = LIST_FIRST(&MyListRoot);
|
|
assert(pFoo);
|
|
assert(pFoo->a == 0x1A);
|
|
assert(pFoo->b == 0x1B);
|
|
|
|
pFoo = LIST_NEXT(pFoo,ListStuff);
|
|
assert(pFoo);
|
|
assert(pFoo->a == 0x2A);
|
|
assert(pFoo->b == 0x2B);
|
|
|
|
pFoo = LIST_NEXT(pFoo,ListStuff);
|
|
assert(pFoo);
|
|
assert(pFoo->a == 0x3A);
|
|
assert(pFoo->b == 0x3B);
|
|
|
|
pFoo = LIST_NEXT(pFoo,ListStuff);
|
|
assert(pFoo == 0);
|
|
|
|
/* Delete member 2. */
|
|
pFoo = LIST_FIRST(&MyListRoot);
|
|
pFoo = LIST_NEXT(pFoo,ListStuff);
|
|
LIST_DELETE(pFoo,ListStuff);
|
|
assert(pFoo->a == 0x2A);/* Make sure we have the right member. */
|
|
assert(pFoo->b == 0x2B);/* And the data is intact. */
|
|
assert(LIST_NEXT(pFoo,ListStuff) == 0);
|
|
|
|
/* Make sure that there are only members 1 and 3 in the list now. */
|
|
pFoo = LIST_FIRST(&MyListRoot);
|
|
assert(pFoo);
|
|
assert(pFoo->a == 0x1A);
|
|
assert(pFoo->b == 0x1B);
|
|
pFoo = LIST_NEXT(pFoo,ListStuff);
|
|
assert(pFoo);
|
|
assert(pFoo->a == 0x3A);
|
|
assert(pFoo->b == 0x3B);
|
|
assert(LIST_NEXT(pFoo,ListStuff) == 0);
|
|
|
|
/* Delete member 3. */
|
|
pFoo = LIST_FIRST(&MyListRoot);
|
|
pFoo = LIST_NEXT(pFoo,ListStuff);
|
|
LIST_DELETE(pFoo,ListStuff);
|
|
assert(pFoo->a == 0x3A);/* Make sure we have the right member. */
|
|
assert(pFoo->b == 0x3B);/* And the data is intact. */
|
|
assert(LIST_NEXT(pFoo,ListStuff) == 0);
|
|
|
|
/* Delete member 1. */
|
|
pFoo = LIST_FIRST(&MyListRoot);
|
|
LIST_DELETE(pFoo,ListStuff);
|
|
assert(pFoo->a == 0x1A);/* Make sure we have the right member. */
|
|
assert(pFoo->b == 0x1B);/* And the data is intact. */
|
|
assert(LIST_NEXT(pFoo,ListStuff) == 0);
|
|
assert(LIST_FIRST(&MyListRoot) == 0);
|
|
|
|
LIST_INSERT_ROOT(&MyListRoot,&MyFoo2,ListStuff);
|
|
LIST_INSERT_ROOT(&MyListRoot,&MyFoo1,ListStuff);
|
|
|
|
/* Delete member 1 while there are other members in the list. */
|
|
pFoo = LIST_FIRST(&MyListRoot);
|
|
LIST_DELETE(pFoo,ListStuff);
|
|
assert(pFoo->a == 0x1A);/* Make sure we have the right member. */
|
|
assert(pFoo->b == 0x1B);/* And the data is intact. */
|
|
assert(LIST_NEXT(pFoo,ListStuff) == 0);
|
|
assert(LIST_FIRST(&MyListRoot) == &MyFoo2);
|
|
|
|
assert(MyFoo1.a == 0x1A); assert(MyFoo1.b == 0x1B);
|
|
assert(MyFoo2.a == 0x2A); assert(MyFoo2.b == 0x2B);
|
|
assert(MyFoo3.a == 0x3A); assert(MyFoo3.b == 0x3B);
|
|
|
|
fputs("List passed.\n", stdout);
|
|
}
|
|
|
|
void TestTailQueue(void)
|
|
{
|
|
struct Foo
|
|
{
|
|
int a;
|
|
TAIL_QUEUE_MEMBER(Foo) TQStuff;
|
|
int b;
|
|
};
|
|
struct Foo MyFoo1, MyFoo2, MyFoo3, *pFoo = 0;
|
|
TAIL_QUEUE_ROOT(sRoot, Foo) MyTQRoot;
|
|
|
|
fputs("Testing TAIL_QUEUE.\n",stdout);
|
|
|
|
TAIL_QUEUE_INITIALIZE(&MyTQRoot);
|
|
MyFoo1.a = 0x1A; MyFoo1.b = 0x1B;
|
|
MyFoo2.a = 0x2A; MyFoo2.b = 0x2B;
|
|
MyFoo3.a = 0x3A; MyFoo3.b = 0x3B;
|
|
|
|
TAIL_QUEUE_INSERT_END(&MyTQRoot,&MyFoo1,TQStuff);
|
|
TAIL_QUEUE_INSERT_END(&MyTQRoot,&MyFoo2,TQStuff);
|
|
TAIL_QUEUE_INSERT_END(&MyTQRoot,&MyFoo3,TQStuff);
|
|
|
|
pFoo = TAIL_QUEUE_FIRST(&MyTQRoot);
|
|
assert(pFoo);
|
|
assert(pFoo->a == 0x1A);
|
|
assert(pFoo->b == 0x1B);
|
|
|
|
pFoo = TAIL_QUEUE_NEXT(pFoo,TQStuff);
|
|
assert(pFoo);
|
|
assert(pFoo->a == 0x2A);
|
|
assert(pFoo->b == 0x2B);
|
|
|
|
pFoo = TAIL_QUEUE_NEXT(pFoo,TQStuff);
|
|
assert(pFoo);
|
|
assert(pFoo->a == 0x3A);
|
|
assert(pFoo->b == 0x3B);
|
|
|
|
pFoo = TAIL_QUEUE_NEXT(pFoo,TQStuff);
|
|
assert(pFoo == 0);
|
|
|
|
/* Delete member 2. */
|
|
pFoo = TAIL_QUEUE_FIRST(&MyTQRoot);
|
|
pFoo = TAIL_QUEUE_NEXT(pFoo,TQStuff);
|
|
TAIL_QUEUE_DELETE(&MyTQRoot,pFoo,TQStuff);
|
|
assert(pFoo->a == 0x2A);/* Make sure we have the right member. */
|
|
assert(pFoo->b == 0x2B);/* And the data is intact. */
|
|
assert(TAIL_QUEUE_NEXT(pFoo,TQStuff) == 0);
|
|
|
|
/* Make sure that there are only members 1 and 3 in the list now. */
|
|
pFoo = TAIL_QUEUE_FIRST(&MyTQRoot);
|
|
assert(pFoo);
|
|
assert(pFoo->a == 0x1A);
|
|
assert(pFoo->b == 0x1B);
|
|
pFoo = TAIL_QUEUE_NEXT(pFoo,TQStuff);
|
|
assert(pFoo);
|
|
assert(pFoo->a == 0x3A);
|
|
assert(pFoo->b == 0x3B);
|
|
assert(TAIL_QUEUE_NEXT(pFoo,TQStuff) == 0);
|
|
|
|
/* Delete member 3. */
|
|
pFoo = TAIL_QUEUE_FIRST(&MyTQRoot);
|
|
pFoo = TAIL_QUEUE_NEXT(pFoo,TQStuff);
|
|
TAIL_QUEUE_DELETE(&MyTQRoot,pFoo,TQStuff);
|
|
assert(pFoo->a == 0x3A);/* Make sure we have the right member. */
|
|
assert(pFoo->b == 0x3B);/* And the data is intact. */
|
|
assert(TAIL_QUEUE_NEXT(pFoo,TQStuff) == 0);
|
|
|
|
/* Delete member 1. */
|
|
pFoo = TAIL_QUEUE_FIRST(&MyTQRoot);
|
|
TAIL_QUEUE_DELETE(&MyTQRoot,pFoo,TQStuff);
|
|
assert(pFoo->a == 0x1A);/* Make sure we have the right member. */
|
|
assert(pFoo->b == 0x1B);/* And the data is intact. */
|
|
assert(TAIL_QUEUE_NEXT(pFoo,TQStuff) == 0);
|
|
assert(TAIL_QUEUE_FIRST(&MyTQRoot) == 0);
|
|
|
|
TAIL_QUEUE_INSERT_END(&MyTQRoot,&MyFoo1,TQStuff);
|
|
TAIL_QUEUE_INSERT_END(&MyTQRoot,&MyFoo2,TQStuff);
|
|
|
|
/* Delete member 1 while there are other members in the list. */
|
|
pFoo = TAIL_QUEUE_FIRST(&MyTQRoot);
|
|
TAIL_QUEUE_DELETE(&MyTQRoot,pFoo,TQStuff);
|
|
assert(pFoo->a == 0x1A);/* Make sure we have the right member. */
|
|
assert(pFoo->b == 0x1B);/* And the data is intact. */
|
|
assert(TAIL_QUEUE_NEXT(pFoo,TQStuff) == 0);
|
|
assert(TAIL_QUEUE_FIRST(&MyTQRoot) == &MyFoo2);
|
|
|
|
assert(MyFoo1.a == 0x1A); assert(MyFoo1.b == 0x1B);
|
|
assert(MyFoo2.a == 0x2A); assert(MyFoo2.b == 0x2B);
|
|
assert(MyFoo3.a == 0x3A); assert(MyFoo3.b == 0x3B);
|
|
|
|
fputs("Tail Queue passed.\n", stdout);
|
|
}
|
|
void TestCircleQueue(void)
|
|
{
|
|
enum {END,ROOT,PREVIOUS,DONE} WhichInsert = END;
|
|
int i;
|
|
struct Foo
|
|
{
|
|
int a;
|
|
CIRCLE_QUEUE_MEMBER(Foo) CQStuff;
|
|
int b;
|
|
};
|
|
struct Foo MyFoo1, MyFoo2, MyFoo3, *pFoo = 0;
|
|
CIRCLE_QUEUE_ROOT(sRoot, Foo) MyCQRoot;
|
|
|
|
fputs("Testing CIRCLE_QUEUE.\n",stdout);
|
|
|
|
while(WhichInsert != DONE)
|
|
{
|
|
CIRCLE_QUEUE_INITIALIZE(&MyCQRoot,Foo);
|
|
MyFoo1.a = 0x1A; MyFoo1.b = 0x1B;
|
|
MyFoo2.a = 0x2A; MyFoo2.b = 0x2B;
|
|
MyFoo3.a = 0x3A; MyFoo3.b = 0x3B;
|
|
|
|
switch(WhichInsert)
|
|
{
|
|
case END:
|
|
CIRCLE_QUEUE_INSERT_END(&MyCQRoot,Foo,&MyFoo1,CQStuff);
|
|
CIRCLE_QUEUE_INSERT_END(&MyCQRoot,Foo,&MyFoo2,CQStuff);
|
|
CIRCLE_QUEUE_INSERT_END(&MyCQRoot,Foo,&MyFoo3,CQStuff);
|
|
WhichInsert = ROOT;
|
|
break;
|
|
case ROOT:
|
|
CIRCLE_QUEUE_INSERT_ROOT(&MyCQRoot,Foo,&MyFoo3,CQStuff);
|
|
CIRCLE_QUEUE_INSERT_ROOT(&MyCQRoot,Foo,&MyFoo2,CQStuff);
|
|
CIRCLE_QUEUE_INSERT_ROOT(&MyCQRoot,Foo,&MyFoo1,CQStuff);
|
|
WhichInsert = PREVIOUS;
|
|
break;
|
|
case PREVIOUS:
|
|
CIRCLE_QUEUE_INSERT_ROOT(&MyCQRoot,Foo,&MyFoo3,CQStuff);
|
|
CIRCLE_QUEUE_INSERT_PREVIOUS(&MyCQRoot,&MyFoo3,&MyFoo2,CQStuff);
|
|
CIRCLE_QUEUE_INSERT_PREVIOUS(&MyCQRoot,&MyFoo2,&MyFoo1,CQStuff);
|
|
WhichInsert = DONE;
|
|
break;
|
|
default:
|
|
assert(0);
|
|
}
|
|
|
|
pFoo = CIRCLE_QUEUE_FIRST(&MyCQRoot);
|
|
assert(pFoo);
|
|
assert(pFoo->a == 0x1A);
|
|
assert(pFoo->b == 0x1B);
|
|
|
|
pFoo = CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff);
|
|
assert(pFoo);
|
|
assert(pFoo->a == 0x2A);
|
|
assert(pFoo->b == 0x2B);
|
|
|
|
pFoo = CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff);
|
|
assert(pFoo);
|
|
assert(pFoo->a == 0x3A);
|
|
assert(pFoo->b == 0x3B);
|
|
|
|
pFoo = CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff);
|
|
assert(pFoo == 0);
|
|
|
|
pFoo = CIRCLE_QUEUE_FIRST(&MyCQRoot);
|
|
assert(CIRCLE_QUEUE_PREVIOUS(&MyCQRoot,pFoo,CQStuff) == 0);
|
|
pFoo = CIRCLE_QUEUE_LAST(&MyCQRoot);
|
|
assert(pFoo == &MyFoo3);
|
|
assert(CIRCLE_QUEUE_PREVIOUS(&MyCQRoot,pFoo,CQStuff) == &MyFoo2);
|
|
assert(CIRCLE_QUEUE_PREVIOUS(&MyCQRoot,&MyFoo2,CQStuff) == &MyFoo1);
|
|
|
|
/* Delete member 2. */
|
|
pFoo = CIRCLE_QUEUE_FIRST(&MyCQRoot);
|
|
pFoo = CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff);
|
|
CIRCLE_QUEUE_DELETE(&MyCQRoot,pFoo,CQStuff);
|
|
assert(pFoo->a == 0x2A);/* Make sure we have the right member. */
|
|
assert(pFoo->b == 0x2B);/* And the data is intact. */
|
|
assert(CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff) == 0);
|
|
|
|
/* Make sure that there are only members 1 and 3 in the list now. */
|
|
pFoo = CIRCLE_QUEUE_FIRST(&MyCQRoot);
|
|
assert(pFoo);
|
|
assert(pFoo->a == 0x1A);
|
|
assert(pFoo->b == 0x1B);
|
|
pFoo = CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff);
|
|
assert(pFoo);
|
|
assert(pFoo->a == 0x3A);
|
|
assert(pFoo->b == 0x3B);
|
|
assert(CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff) == 0);
|
|
|
|
/* Delete member 3. */
|
|
pFoo = CIRCLE_QUEUE_FIRST(&MyCQRoot);
|
|
pFoo = CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff);
|
|
CIRCLE_QUEUE_DELETE(&MyCQRoot,pFoo,CQStuff);
|
|
assert(pFoo->a == 0x3A);/* Make sure we have the right member. */
|
|
assert(pFoo->b == 0x3B);/* And the data is intact. */
|
|
assert(CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff) == 0);
|
|
|
|
/* Delete member 1. */
|
|
pFoo = CIRCLE_QUEUE_FIRST(&MyCQRoot);
|
|
CIRCLE_QUEUE_DELETE(&MyCQRoot,pFoo,CQStuff);
|
|
assert(pFoo->a == 0x1A);/* Make sure we have the right member. */
|
|
assert(pFoo->b == 0x1B);/* And the data is intact. */
|
|
assert(CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff) == 0);
|
|
assert(CIRCLE_QUEUE_FIRST(&MyCQRoot) == 0);
|
|
|
|
CIRCLE_QUEUE_INSERT_END(&MyCQRoot,Foo,&MyFoo1,CQStuff);
|
|
CIRCLE_QUEUE_INSERT_END(&MyCQRoot,Foo,&MyFoo2,CQStuff);
|
|
|
|
/* Delete member 1 while there are other members in the list. */
|
|
pFoo = CIRCLE_QUEUE_FIRST(&MyCQRoot);
|
|
CIRCLE_QUEUE_DELETE(&MyCQRoot,pFoo,CQStuff);
|
|
assert(pFoo->a == 0x1A);/* Make sure we have the right member. */
|
|
assert(pFoo->b == 0x1B);/* And the data is intact. */
|
|
assert(CIRCLE_QUEUE_NEXT(&MyCQRoot,pFoo,CQStuff) == 0);
|
|
assert(CIRCLE_QUEUE_FIRST(&MyCQRoot) == &MyFoo2);
|
|
|
|
assert(MyFoo1.a == 0x1A); assert(MyFoo1.b == 0x1B);
|
|
assert(MyFoo2.a == 0x2A); assert(MyFoo2.b == 0x2B);
|
|
assert(MyFoo3.a == 0x3A); assert(MyFoo3.b == 0x3B);
|
|
}
|
|
|
|
fputs("Circle Queue passed.\n", stdout);
|
|
}
|
|
|
|
int main()
|
|
{
|
|
TestList();
|
|
TestTailQueue();
|
|
TestCircleQueue();
|
|
fputs("All tests passed.", stdout);
|
|
return EXIT_SUCCESS;
|
|
}
|
|
#endif /* End of test code. */
|
|
|
|
#if __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif // !_LISTS_H
|