Defines | |
#define | sll_decllink(type, mlabel) type* mlabel |
Declare a singly linked list "next" member template. | |
#define | sll_initlink(type, mlabel, self) (self)->mlabel = NULL |
Initialize a link. | |
#define | sll_decllist(type, mlabel, ilabel) type* ilabel |
Declare a singly linked list template. | |
#define | sll_autolist(type, mlabel, ilabel) type* ilabel = NULL |
Make a linked list from auto variables for stack or global use Uses non-standard ANSI extension: non-const initializers. | |
#define | sll_autolist_static(type, mlabel, ilabel) static type* ilabel = NULL |
Make a static linked list from auto variables for stack or global use Uses non-standard ANSI extension: non-const initializers. | |
#define | sll_externlist(type, mlabel, ilabel) extern type* ilabel |
Declare an extern linked list for sll_autolist or sll_decllist. | |
#define | sll_initlist(type, mlabel, ilabel) (ilabel) = NULL |
Initialize an empty list. | |
#define | sll_initarray(type, mlabel, ilabel, array, count) |
Initialize a singly linked list from an array of objects. | |
#define | sll_reset(type, mlabel, ilabel) |
Unlink all members; ilabel will be empty. | |
#define | sll_next(type, mlabel, ilabel, curr) ((curr) = (curr) ? ((curr)->mlabel) : NULL) |
Iterate to next member. | |
#define | sll_foreach_const(type, mlabel, ilabel, iterator) |
Iterate through all members of a singly linked list with a const pointer. This is the simplest and fastest way to do it, but you can't modify the list while you do it. This will generally need to be wrapped in its own {} scope There is not enough state maintained here to remove a member, so don't try it. | |
#define | sll_foreach(type, mlabel, ilabel, iterator) |
Iterate through all members of a singly linked list with a writable pointer This is the simplest and fastest way to do it, but you can't modify the list while you do it. This will generally need to be wrapped in its own {} scope There is not enough state maintained here to remove a member, so don't try it. | |
#define | sll_foreach_deletable(type, mlabel, ilabel, iterator) |
Iterate through all members of a singly linked list, allowing deletions with 'sll_foreach_deletecurr' Deletion is possible, and iteration may continue after a deletion This will generally need to be wrapped in its own {} scope. | |
#define | sll_foreach_deletable_reverse(type, mlabel, ilabel, iterator) |
Iterate through all members of a singly linked list; LIST ORDER WILL BE REVERSED AFTER THIS IS DONE This will generally need to be wrapped in its own {} scope Why? It's often necessary during animation cycles to do a list forwards, then backwards. Do it twice to get original list. | |
#define | sll_foreach_deletecurr(type, mlabel, ilabel, iterator) |
ONLY in sll_foreach_deletable, or sll_foreach_deletable_reverse, safely remove current member during iteration. | |
#define | sll_push_front(type, mlabel, ilabel, item) |
Push a new item onto front of a singly linked list Preferred method. | |
#define | sll_push_back(type, mlabel, ilabel, item) |
Add a new item onto the FAR END of the list Use sll_push_front whenever possible: This has to iterate through the whole list! | |
#define | sll_front(type, mlabel, ilabel, get) {(get) = (ilabel);} |
Get first item in the list. | |
#define | sll_back(type, mlabel, ilabel, get) |
Get last item in the list (requires traversal of list!). | |
#define | sll_pop_front(type, mlabel, ilabel, get) |
Pop first item in list off; unlinks and returns first member. | |
#define | sll_pop_back(type, mlabel, ilabel, get) |
Pop LAST item in list off; unlinks and returns last member (requires traversal of list!). | |
#define | sll_erase(type, mlabel, ilabel, item) |
Seek a member and remove it (requires traversal of list!) I recommend you mark members for later deletion, or identify deleted items while traversing with 'deletable' iterator, instead. | |
#define | sll_remove_filter(type, mlabel, ilabel, criteria) |
Seek member(s) in the list and remove it(them) based on a callback. | |
#define | sll_move_filter(type, mlabel, ilabel, criteria, target) |
Seek member(s) in the list and move it(them) to "target" based on a callback. | |
#define | sll_size(type, mlabel, ilabel, count) |
Tally members and return total in 'count'. | |
#define | sll_assert_size(type, mlabel, ilabel, count) |
Tally members and compare to a count. | |
#define | sll_splice(type, mlabel, toFirst, fromFirst) |
Append members from one singly linked list (OF THE SAME KIND) to another. | |
#define | sll_bsort(type, mlabel, ilabel, compare) |
BUBBLE Sort members by some criteria. | |
#define | sll_decl_qsort(type, mlabel, ilabel, name) void name( type** front, type** back, int (*compare)(const void* p1, const void* p2) ) |
Declare a singly linked qsort. | |
#define | sll_qsort(type, mlabel, ilabel, name, compare) name( &(ilabel), NULL, (int (*)(const void*, const void*))(compare) );\ |
Invoke singly linked bubble sort. | |
#define | sll_mfg_qsort(type, mlabel, ilabel, deref, name) |
Manufacture a singly linked bubble sort. |
Basically a singly linked list is a handy, speedy little thing when used properly, and awful when used improperly. The two important bits are PUSH new members, and remove members while iterating, rather than forcing an iteration to remove them.
Any link in the singly linked list can be treated as a subset of the whole list. Changling the links is about as fast as doing the saimilar operations with an array of pointers, except they're scattered.
This implementation has only ONE pointer to the base of the list. Some sll implementations include a tail pointer. If you want a tail, just add it. I don't; it's usually extra stuff to keep track of and keep up to date. If you want to get at something from *either* end, and insert/remove links without, extra iteration, then use the doubly-linked list (below) instead.
#define sll_assert_size | ( | type, | |||
mlabel, | |||||
ilabel, | |||||
count | ) |
Value:
{\ size_t ppScr2(__sll_assert_size,tally) = 0;\ sll_size(type,mlabel, ilabel, ppScr2(__sll_assert_size,tally));\ assert( ppScr2(__sll_assert_size,tally) == (count) );\ }
type | Template: Structure type this link belongs to. | |
mlabel | Template: A unique label for this link | |
ilabel | Template/param: Whatever dereferencing is required + the base ilabel from sll_decllist | |
count | An expected count |
#define sll_autolist | ( | type, | |||
mlabel, | |||||
ilabel | ) | type* ilabel = NULL |
Make a linked list from auto variables for stack or global use Uses non-standard ANSI extension: non-const initializers.
type | Template: Structure type this link belongs to. | |
mlabel | Template: A unique label for this link | |
ilabel | Template/param: Whatever dereferencing is required + the base ilabel from sll_decllist |
#define sll_autolist_static | ( | type, | |||
mlabel, | |||||
ilabel | ) | static type* ilabel = NULL |
Make a static linked list from auto variables for stack or global use Uses non-standard ANSI extension: non-const initializers.
type | Template: Structure type this link belongs to. | |
mlabel | Template: A unique label for this link | |
ilabel | Template/param: Whatever dereferencing is required + the base ilabel from sll_decllist |
#define sll_back | ( | type, | |||
mlabel, | |||||
ilabel, | |||||
get | ) |
Value:
{\ type* __ll_iterate = (ilabel);\ if( __ll_iterate ) \ while( __ll_iterate->mlabel )\ __ll_iterate = __ll_iterate->mlabel;\ (get) = __ll_iterate;\ }
type | Template: Structure type this link belongs to. | |
mlabel | Template: A unique label for this link | |
ilabel | Template/param: Whatever dereferencing is required + the base ilabel from sll_decllist | |
get | type* Pointer to receive value |
#define sll_bsort | ( | type, | |||
mlabel, | |||||
ilabel, | |||||
compare | ) |
BUBBLE Sort members by some criteria.
type | Template: Structure type this link belongs to. | |
mlabel | Template: A unique label for this link | |
ilabel | Template/param: Whatever dereferencing is required + the base ilabel from sll_decllist | |
compare | Takes compare(prev,next), returns >0 if prev > next, < 0 if prev < next, or ==0 if prev == next. |
Bubble sort is GOOD for data that's nearly sorted, or small sets; it's basically what the last stages of qsort look like. GOOD for 2D animation where things stay around and are sorted (for instance) by "Y", but AWFUL if you keep inserting and deleting things BAD for accumulating hundreds or thousands of items and then applying this sort to: See sll_qsort for that! Push new things onto the front, and Sort will find its place Compare can be a macro or a function.
#define sll_decl_qsort | ( | type, | |||
mlabel, | |||||
ilabel, | |||||
name | ) | void name( type** front, type** back, int (*compare)(const void* p1, const void* p2) ) |
Declare a singly linked qsort.
type | Template: Structure type this link belongs to. | |
mlabel | Template: A unique label for this link | |
ilabel | Template/param: Whatever dereferencing is required + the base ilabel from sll_decllist | |
name | What to call the resulting function |
#define sll_decllink | ( | type, | |||
mlabel | ) | type* mlabel |
#define sll_decllist | ( | type, | |||
mlabel, | |||||
ilabel | ) | type* ilabel |
#define sll_erase | ( | type, | |||
mlabel, | |||||
ilabel, | |||||
item | ) |
Value:
{\ type* ppConcat(__ll_iterate_remove,_prev) = NULL; \ type* __ll_iterate_remove = (ilabel); \ while( __ll_iterate_remove )\ {\ if ( __ll_iterate_remove == (item) )\ {\ if ( ppConcat(__ll_iterate_remove,_prev) )\ {\ ppConcat(__ll_iterate_remove,_prev)->mlabel = __ll_iterate_remove->mlabel;\ }\ else\ {\ ilabel = __ll_iterate_remove->mlabel;\ }\ break;\ }\ ppConcat(__ll_iterate_remove,_prev) = __ll_iterate_remove;\ __ll_iterate_remove = __ll_iterate_remove->mlabel;\ }\ }
type | Template: Structure type this link belongs to. | |
mlabel | Template: A unique label for this link | |
ilabel | Template/param: Whatever dereferencing is required + the base ilabel from sll_decllist | |
item | Item to remove |
Definition at line 464 of file ll.h.
Referenced by ctl_pool_base_alloc(), and ctl_pool_base_destroy().
#define sll_externlist | ( | type, | |||
mlabel, | |||||
ilabel | ) | extern type* ilabel |
Declare an extern linked list for sll_autolist or sll_decllist.
type | Template: Structure type this link belongs to. | |
mlabel | Template: A unique label for this link | |
ilabel | Template/param: Whatever dereferencing is required + the base ilabel from sll_decllist |
#define sll_foreach | ( | type, | |||
mlabel, | |||||
ilabel, | |||||
iterator | ) |
Value:
type* iterator = (ilabel); \
for ( ; iterator; iterator = iterator->mlabel )
type | Template: Structure type this link belongs to. | |
mlabel | Template: A unique label for this link | |
ilabel | Template/param: Whatever dereferencing is required + the base ilabel from sll_decllist | |
iterator | What to call the iterator; you'll be referencing the individual members with it |
#define sll_foreach_const | ( | type, | |||
mlabel, | |||||
ilabel, | |||||
iterator | ) |
Value:
const type* iterator = (ilabel); \ for ( ; iterator; iterator = iterator->mlabel )
type | Template: Structure type this link belongs to. | |
mlabel | Template: A unique label for this link | |
ilabel | Template/param: Whatever dereferencing is required + the base ilabel from sll_decllist | |
iterator | What to call the iterator; you'll be referencing the individual members with it |
Definition at line 269 of file ll.h.
Referenced by ctl_pool_dump().
#define sll_foreach_deletable | ( | type, | |||
mlabel, | |||||
ilabel, | |||||
iterator | ) |
Value:
type* ppConcat3(__ll_,iterator,_prev) = NULL; \ type* iterator = (ilabel);\ type* ppConcat3(__ll_,iterator,_next) = iterator?iterator->mlabel:NULL; \ for ( ; iterator; ppConcat3(__ll_,iterator,_prev) = iterator, iterator = ppConcat3(__ll_,iterator,_next), sll_next(type,mlabel, ilabel, ppConcat3(__ll_,iterator,_next) ) )
type | Template: Structure type this link belongs to. | |
mlabel | Template: A unique label for this link | |
ilabel | Template/param: Whatever dereferencing is required + the base ilabel from sll_decllist | |
iterator | What to call the iterator; you'll be referencing the individual members with it |
#define sll_foreach_deletable_reverse | ( | type, | |||
mlabel, | |||||
ilabel, | |||||
iterator | ) |
Value:
type* ppConcat3(__ll_,iterator,_prev) = NULL; \ type* iterator = (ilabel);\ type* ppConcat3(__ll_,iterator,_next) = iterator?iterator->mlabel:NULL; \ for ( ; iterator; iterator->mlabel = ppConcat3(__ll_,iterator,_prev), ppConcat3(__ll_,iterator,_prev) = (ilabel) = iterator, iterator = ppConcat3(__ll_,iterator,_next), sll_next(type,mlabel, ilabel, ppConcat3(__ll_,iterator,_next) ) )
type | Template: Structure type this link belongs to. | |
mlabel | Template: A unique label for this link | |
ilabel | Template/param: Whatever dereferencing is required + the base ilabel from sll_decllist | |
iterator | What to call the iterator; you'll be referencing the individual members with it |
#define sll_foreach_deletecurr | ( | type, | |||
mlabel, | |||||
ilabel, | |||||
iterator | ) |
Value:
if( iterator )\ {\ if ( ppConcat3(__ll_,iterator,_prev) )\ {\ ppConcat3(__ll_,iterator,_prev)->mlabel = ppConcat3(__ll_,iterator,_next);\ }\ else\ {\ ilabel = ppConcat3(__ll_,iterator,_next);\ }\ iterator->mlabel = NULL;\ }
type | Template: Structure type this link belongs to. | |
mlabel | Template: A unique label for this link | |
ilabel | Template/param: Whatever dereferencing is required + the base ilabel from sll_decllist | |
iterator | Iterator from sll_foreach_deletable |
#define sll_front | ( | type, | |||
mlabel, | |||||
ilabel, | |||||
get | ) | {(get) = (ilabel);} |
Get first item in the list.
type | Template: Structure type this link belongs to. | |
mlabel | Template: A unique label for this link | |
ilabel | Template/param: Whatever dereferencing is required + the base ilabel from sll_decllist | |
get | type* Pointer to receive value |
#define sll_initarray | ( | type, | |||
mlabel, | |||||
ilabel, | |||||
array, | |||||
count | ) |
Value:
{\
type* ppScr2(sllInit,array) = (array);\
type* ppScr2(sllInit,last) = ppScr2(sllInit,array) + (count) - 1;\
type* ppScr2(sllInit,curr) = ppScr2(sllInit,last);\
ppScr2(sllInit,last)->mlabel = NULL;\
while( ppScr2(sllInit,curr)-- > ppScr2(sllInit,array) )\
ppScr2(sllInit,curr)->mlabel = ppScr2(sllInit,last)--;\
(ilabel) = ppScr2(sllInit,array);\
}
type | Template: Structure type this link belongs to. | |
mlabel | Template: A unique label for this link | |
ilabel | Template/param: Whatever dereferencing is required + the base ilabel from sll_decllist | |
array | Pointer to start of array of members | |
count | Count of members in array |
#define sll_initlink | ( | type, | |||
mlabel, | |||||
self | ) | (self)->mlabel = NULL |
#define sll_initlist | ( | type, | |||
mlabel, | |||||
ilabel | ) | (ilabel) = NULL |
#define sll_mfg_qsort | ( | type, | |||
mlabel, | |||||
ilabel, | |||||
deref, | |||||
name | ) |
Manufacture a singly linked bubble sort.
type | Template: Structure type this link belongs to. | |
mlabel | Template: A unique label for this link | |
ilabel | Template/param: Whatever dereferencing is required + the base ilabel from sll_decllist | |
deref | What part of what you find to pass through to comparison | |
name | What to call the sorting function |
If it needs to be accessible by other code, you may generate the function declaration with sll_decl_qsort(type,mlabel, ilabel, name )
Then invoke the sort with sll_qsort(type,mlabel, ilabel, name )
This qsort is reasonably fast compared to a bubble sort when the data is NOT nearly sorted, and there is a lot of it.
#define sll_move_filter | ( | type, | |||
mlabel, | |||||
ilabel, | |||||
criteria, | |||||
target | ) |
Value:
{\ sll_foreach_deletable(type,mlabel, ilabel, __ll_iterate_move )\ {\ if ( criteria(__ll_iterate_move) ) \ {\ sll_foreach_deletecurr(type,mlabel, ilabel, __ll_iterate_move ); \ sll_push_front(type,mlabel, target, __ll_iterate_move );\ }\ }\ }
type | Template: Structure type this link belongs to. | |
mlabel | Template: A unique label for this link | |
ilabel | Template/param: Whatever dereferencing is required + the base ilabel from sll_decllist | |
criteria | A boolean macro or function that takes a list member pointer and returns non-zero if it should be removed | |
target | List to receive removed items (such as a "free" list) |
#define sll_next | ( | type, | |||
mlabel, | |||||
ilabel, | |||||
curr | ) | ((curr) = (curr) ? ((curr)->mlabel) : NULL) |
Iterate to next member.
type | Template: Structure type this link belongs to. | |
mlabel | Template: A unique label for this link | |
ilabel | Template/param: Whatever dereferencing is required + the base ilabel from sll_decllist | |
curr | Pointer to current, to be modified to next link |
#define sll_pop_back | ( | type, | |||
mlabel, | |||||
ilabel, | |||||
get | ) |
Value:
{\ type* __ll_iterate = (ilabel);\ type* __ll_iterate_prev = NULL;\ if( __ll_iterate ) \ {\ while( __ll_iterate->mlabel )\ {\ __ll_iterate_prev = __ll_iterate->mlabel;\ __ll_iterate = __ll_iterate->mlabel;\ }\ if( __ll_iterate_prev )\ {\ __ll_iterate_prev = NULL;\ }\ else\ {\ (ilabel) = NULL;\ }\ }\ (get) = __ll_iterate;\ }
type | Template: Structure type this link belongs to. | |
mlabel | Template: A unique label for this link | |
ilabel | Template/param: Whatever dereferencing is required + the base ilabel from sll_decllist | |
get | type* Pointer to receive value |
#define sll_pop_front | ( | type, | |||
mlabel, | |||||
ilabel, | |||||
get | ) |
Value:
{\ (get) = (ilabel);\ (ilabel) = (get)->mlabel;\ (get)->mlabel = NULL;\ }
type | Template: Structure type this link belongs to. | |
mlabel | Template: A unique label for this link | |
ilabel | Template/param: Whatever dereferencing is required + the base ilabel from sll_decllist | |
get | type* Pointer to receive value |
Definition at line 417 of file ll.h.
Referenced by ctl_destroy_all_pools().
#define sll_push_back | ( | type, | |||
mlabel, | |||||
ilabel, | |||||
item | ) |
Value:
{\ type* __ll_iterate_add;\ sll_back(type,mlabel, ilabel, __ll_iterate_add );\ if( __ll_iterate_add ) \ { \ __ll_iterate_add->mlabel = (item);\ } \ else \ { \ (ilabel) = (item);\ } \ (item)->mlabel = NULL;\ }
type | Template: Structure type this link belongs to. | |
mlabel | Template: A unique label for this link | |
ilabel | Template/param: Whatever dereferencing is required + the base ilabel from sll_decllist | |
item | type*, Item to add; THIS MUST NOT BE PART OF ANOTHER LIST |
#define sll_push_front | ( | type, | |||
mlabel, | |||||
ilabel, | |||||
item | ) |
Value:
{\ (item)->mlabel = (ilabel);\ (ilabel) = (item);\ }
type | Template: Structure type this link belongs to. | |
mlabel | Template: A unique label for this link | |
ilabel | Template/param: Whatever dereferencing is required + the base ilabel from sll_decllist | |
item | Item to add; THIS MUST NOT BE PART OF ANOTHER LIST |
Definition at line 351 of file ll.h.
Referenced by ctl_pool_base_free(), and ctl_pool_base_grow().
#define sll_qsort | ( | type, | |||
mlabel, | |||||
ilabel, | |||||
name, | |||||
compare | ) | name( &(ilabel), NULL, (int (*)(const void*, const void*))(compare) );\ |
Invoke singly linked bubble sort.
type | Template: Structure type this link belongs to. | |
mlabel | Template: A unique label for this link | |
ilabel | Template/param: Whatever dereferencing is required + the base ilabel from sll_decllist | |
name | The name of the sorting function | |
compare | Like qsort comparison function |
#define sll_remove_filter | ( | type, | |||
mlabel, | |||||
ilabel, | |||||
criteria | ) |
Value:
{\ sll_foreach_deletable(type,mlabel, ilabel, __ll_iterate_delete )\ {\ if ( criteria(__ll_iterate_delete) ) \ sll_foreach_deletecurr(type,mlabel, ilabel, __ll_iterate_delete ); \ }\ }
type | Template: Structure type this link belongs to. | |
mlabel | Template: A unique label for this link | |
ilabel | Template/param: Whatever dereferencing is required + the base ilabel from sll_decllist | |
criteria | A boolean macro or function that takes a list member pointer and returns non-zero if it should be removed |
#define sll_reset | ( | type, | |||
mlabel, | |||||
ilabel | ) |
Value:
{\
type* __ll_curr = (array);\
type* __ll_next;\
while( __ll_curr ) \
{\
__ll_next = __ll_curr->mlabel;\
__ll_curr->mlabel = NULL;\
__ll_curr = __ll_next;\
}\
(ilabel) = NULL;\
}
type | Template: Structure type this link belongs to. | |
mlabel | Template: A unique label for this link | |
ilabel | Template/param: Whatever dereferencing is required + the base ilabel from sll_decllist |
#define sll_size | ( | type, | |||
mlabel, | |||||
ilabel, | |||||
count | ) |
Value:
{\ size_t ppScr2(__sll_size_,tally) = 0;\ type* ppScr2(__sll_size_,iterator);\ for ( ppScr2(__sll_size_,iterator) = (ilabel); ppScr2(__sll_size_,iterator); ppScr2(__sll_size_,iterator) = ppScr2(__sll_size_,iterator)->mlabel, ppScr2(__sll_size_,tally)++ )\ ;\ (count) = ppScr2(__sll_size_,tally);\ }
type | Template: Structure type this link belongs to. | |
mlabel | Template: A unique label for this link | |
ilabel | Template/param: Whatever dereferencing is required + the base ilabel from sll_decllist | |
count | A size_t type variable to receive member count |
#define sll_splice | ( | type, | |||
mlabel, | |||||
toFirst, | |||||
fromFirst | ) |
Value:
{\ if( toFirst ) \ {\ type* sllTail;\ sll_back(type,mlabel, toFirst, sllTail );\ sllTail->mlabel = (fromFirst);\ }\ else\ {\ (toFirst) = (fromFirst);\ }\ (fromFirst) = NULL;\ }
type | Template: Structure type this link belongs to. | |
mlabel | Template: A unique label for this link | |
toFirst | Template/param: Pointer to head of the list that will contain both lists | |
fromFirst | Template/param: Pointer to the head of the list that will be empty after this |