About Sglib

SGLIB stands for Simple Generic Library and it
consists of single header file
written in C programming language.
The header file sglib.h provides generic implementation of most
common algorithms for arrays, lists, sorted lists and red-black trees.
Implementation of double linked lists and hashed tables is envisaged.
Also suggestions for new useful functionalities are welcomed.
The library is generic and it does not define its own data
structures. Rather it acts on existing user defined data structures
via a generic interface. It also does not allocate or deallocate any
memory and does not depend on any particular memory management. In
case od several datatypes, sglib even does not impose its own data
representation. For example, sglib list routines can be applied to any
user defined structure containing a pointer to the same
structure as its field.

All algorithms are implemented in form of macros parametrized by the
type of data structure and comparator function (or comparator
macro). Several further generic parameters such as the name of 'next'
field for linked lists may be required for some algorithms and data
structures.

Sglib offers access to algorithms in two level user interface. A
level - 0 interface is simply a collection of useful macros.
If you do not like large macros or you afraid introduction of symbol
clashes after macro expansions you can use a level - 1
interface. This interface generates legal C functions for each particular
type. Those functions can be called from the main program without
worrying about unwanted effects due to macro expansions.

You can always use level - 0 interface. You can use level - 1 interface
only if your base type is named by a single identifier, or if you have
defined a typedef for it. It is a question of taste whether you decide
to use one of two interfaces. It seems that you get the most
advantages by using both interfaces in the same time. You can do this
without worrying about implementation clashes, the level - 1
inplementation are just wrappers to level - 0 interface. However, few
functions using recursion (red-black trees for example) are
implemented exclusively in level - 1 interface.

During the design and implementation of sglib we have followed following rules:

Efficiency. Resulting code must be as efficient as if it was
specialized code

Simplicity. No special tool is needed for generic constructions.

In order to avoid conflicts with user symbols, each defined macro and
function starts by 'SGLIB_' and 'sglib_' prefix respectively.

In order to avoid situation when actual macro parameter conflicts with
symbol defined within macro, all names defined within macros start and
finish with underscore character.

Each occurence of macro parameter giving an expression is always used
enclosed into supplementary parentheses.

Sglib - Concepts

Comparator

A comparator is a function (or macro)
taking two elements and returning an integer value, the value is
respectively a negative number, zero or a positive number for cases
when the first parameter is less than, equal, or greater than the second.
For example the standard C function strcmp is a string
comparator which can be directly
used in sglib. Also a macro

#define SGLIB_NUMERIC_COMPARATOR(x, y) ((int)((x) - (y)))

is a comparator for integers numbers. By the way, the macro
SGLIB_NUMERIC_COMPARATOR with this definition
is predefined in sglib
and you can use it withount need of your own redefinitions.

Subcomparator

A comparator which is induced from
another comparator in a way that it
makes several elements equal while otherwise preserving the original
ordering is called a subcomparator. More formally, if cmp
is a comparator and subcmp is its subcomparator, then:

Subcomparators are used in iterators to iterate over such part
of a container which is equal to a given element. For example, let's take that we have a red black tree
of strings ordered lexicographically.
We can define a subcomparator comparing only the first letter
of strings:

#define strsubcmp(x, y) (x[0] - y[0])

Using this subcomparator we can iterate over all strings
starting with the same letter.

Array elem_exchanger and simultaneous sorting of multiple arrays

An elem_exchanger is a function (or macro) performing
exchange of two elements in an array.
It takes following four parameters: the type of array elements,
the array on which it operates, and two indexes of elements to exchange.
For example the following macro:

is an elem_exchanger usable by sglib. By the way, the macro
SGLIB_ARRAY_ELEMENTS_EXCHANGER with this definition
is predefined in the sglib and you can use in implementations of your own
elem_exchangers.
An elem_exchanger can be used to parametrize sorting
algorithms. The motivation is that
in many projects, several arrays keep related informations.
Elemens of different arrays having the same index are related to each other
and they form a single record. For example, one can represent a phone annuary by
keeping person names in one array (say name) and corresponding phone
numbers in another array (say phoneNumbers). In this representation the person
name[i]
has the phone number phoneNumber[i].
If you decide to sort your annuary alphabetically by names,
you have to make corresponding reordering also on numbers.

Sglib modifies arrays exclusively by
using an elem_exchanger.
You can use your own elem_exchanger as parameter for sorting
algorithms. Your implementation can
simultaneously exchange elements in several arrays,
and hence make sorting to act on multiple related arrays.
For example, continuing the annuary example, we can define the following
elem_exchanger:

and use it as parameter of a sorting macro. For example we can sort the first 1000 elements
of the annuary by the following command:

SGLIB_ARRAY_QUICK_SORT(char*, name, 1000, strcmp, ANNUARY_EXCHANGER);

Container

A container data structure is any data structure containing
elements. This is for example an array, list, sorted list, red-black tree, etc.

Linked lists

A linked list is any C structure containing a pointer to the next
element. The structure is entirely defined by the user,
sglib does not provide any default implementation.
Following code defines several lists on which sglib can operate:

Sglib does not contain
any allocation or freeing of memory, so your program is responsible
for allocating/freeing of each element of the list.
Sglib provides macros for ordering and
maintaining such lists. Macros, such
as insert and delete only affect the next field of elements, so that the element is correctly
inserted/deleted into/from the list.

Linked list next element parameter

The next parameter of sglib macros is the name of the field
pointing to the next element of the list.
For example for structures defined in the previous section
this parameter will be respectively words:
next, previous and subtrees[1].

Pointer equality versus comparator equality

Sglib distinguishes two notions of equality. Two elements are said pointer equal if they
are the same object in the memory and hence they are referenced by the same pointer.
Two elements are said comparator equal if the
comparator applied on those elements returns zero.
In other words, the comparator equality tests the equality of keys. You can have several
elements with the same key (hence comparator equal) in a data structure such as list, but only
one occurence of each element with the same pointer (otherwise a cyclic data structure occurs).

The difference between pointer and comparator equality remains the
difference between == and equals operators in Java language (with
the difference that in sglib user has to implement its own comparator).

Pointer and comparator equal membership

Distinction between pointer and comparator equality
generates two notions of membership in a container data structure.
We say that an element E
is a pointer equal member of a container if it is physically
part of the data structure, i.e. if the container contains the pointer to E.
We say that an element E
is a comparator equal member, if the container contains
an element which is comparator equal to E.
In other words, an element is a comparator equal member of a container
if the container contains an element with the same key. Note that if an element
is a pointer equal member then it is also a comparator equal member.

Double Linked lists

A double linked list is any C structure containing two pointers interpreted respectively as the previous and the next
elements of the list. The structure is entirely defined by the user,
sglib does not provide any default implementation.
Following code defines several double linked lists on which sglib can operate:

Sglib provides macros for ordering and
maintaining such lists. The list is passed to sglib using a pointer to any of its member.
Sglib than operates on the whole list accessible via
previous and next
fields.
Macros, such
as insert and delete only affect the previous and next
fields of elements, the rest of the structure is kept intact.

Previous and next parameters of macros for double linked lists

The previous and next parameters of sglib macros are names of fields
pointing respectively to the previous and to the next elements of a double linked list.
For example, in the case of the first structure defined in the previous section
those parameters will be previous and next. For the second structure
those parameters will be up and down.

Binary trees

A binary tree is any structure type containing two pointers to subtrees.
The structure is entirely defined by the user,
sglib does not provide any default implementation.
Following code defines several implementations of binary trees on which sglib can operate:

Left and right parameters of tree macros

The left and right parameters of sglib macros are the names of fields
pointing respectively to the left and right subtrees of the given tree node.
For example for structures defined in the previous section
those parameter will be respectively pairs of words:
left, right then subtrees[0], subtrees[1] and finally
left_ptr, right_ptr.

Red-Black Trees

A red-black tree is a balanced binary tree with (at least) one
bit of additional information storing the color of each node. Nodes in red-black trees
can be colored either red or black. Usualy those two colors are represented by 0 and 1
respectively. The structure defining a node in red-black tree is entirely defined by the user,
sglib does not provide any default implementation.
Our implementation of red-black trees uses recursion,
this is why red-black trees are available only in level-1 interface.
Following code defines several examples of structures which can be organized
as red-black trees:

API: level 0

The level 0 application interface is simply a collection of useful
generic macros. Those macros are in general parametrized by some kind
of C type (probably a C structure) and this is why they can not be
implemented by C functions.

By convention, names of all macros start by SGLIB_ prefix. Then
goes the identification of the data structure on which the macro
operates and finaly the action performed by the macro.

In the design of macros we tried to make macros as generic as
possible. This sometimes leads to parameters which may seems useless.
However, because macro expansion is done in compile time and the
number of macro parameters does not affect the efficiency of the code,
we thing that additional parameters do not matter.

found - (output) is set to non-zero if the key was found, to zero otherwise.

result_index - (output) is set to the index of the element equal to the key. If there is no such element, than result_index is set to the index where the key can be inserted while preserving the array ordering.

Lists API: level 0

SGLIB_LIST_ADD

macro

SGLIB_LIST_ADD(type, list, elem, next)

add an element to a list.

Parameters:

type - the type of list elements.

list - the list.

elem - the element to add.

next - the name of the field pointing to the next element of the list.

next - the name of the field pointing to the next element of the list.

comparator_result - (output) the last comparator result. This is zero if the element was present in the list, non-zero otherwise.

member_ptr - (output) the place where to insert elem. It is the pointer to the pointer which will be set to elem by insertion. If comparator_result is zero, then this is the pointer to the pointer to the element equal to elem.

SGLIB_SORTED_LIST_LEN

macro

SGLIB_SORTED_LIST_LEN(type, list, next, result)

compute the length of a list.

Parameters:

type - the type of list elements.

list - the list.

next - the name of the field pointing to the next element of the list.

result - (output) variable set to the length of the list.

SGLIB_SORTED_LIST_MAP_ON_ELEMENTS

macro

SGLIB_SORTED_LIST_MAP_ON_ELEMENTS(type, list, var, next, command)

apply a command on all elements of a list.

Parameters:

type - the type of list elements.

list - the list.

var - the variable which will run through each element of the list.

next - the name of the field pointing to the next element of the list.

command - any (possibly composed) statement of the C language. In the statement you can use the variable var (third parameter of the macro) going through all elements of the list.

Double Linked Lists API: level 0

SGLIB_DL_LIST_ADD

macro

SGLIB_DL_LIST_ADD(type, list, elem, previous, next)

add an element to a list.

Parameters:

type - the type of list elements.

list - the list.

elem - the element to add.

previous - the name of the field pointing to the previous element of the list.

next - the name of the field pointing to the next element of the list.

SGLIB_DL_LIST_ADD_BEFORE

macro

SGLIB_DL_LIST_ADD_BEFORE(type, list, elem, previous, next)

add an element to a list. Elem will be inserted before the element pointed by list.

Parameters:

type - the type of list elements.

list - the list (also specifying the place where to insert the new element).

elem - the element to add.

previous - the name of the field pointing to the previous element of the list.

next - the name of the field pointing to the next element of the list.

SGLIB_DL_LIST_ADD_AFTER

macro

SGLIB_DL_LIST_ADD_AFTER(type, list, elem, previous, next)

add an element to a list. Elem will be inserted after the element pointed by list.

Parameters:

type - the type of list elements.

list - the list (also specifying the place where to insert the new element).

elem - the element to add.

previous - the name of the field pointing to the previous element of the list.

next - the name of the field pointing to the next element of the list.

apply a command on all elements of a list. Command will be repeatedly executed for each element of the list accessible via the previous field and then via the next field. The current element of the list is stored in the
variable var.

Parameters:

type - the type of list elements.

list - the list.

var - the variable which will run through each element of the list.

previous - the name of the field pointing to the previous element of the list.

next - the name of the field pointing to the next element of the list.

command - any (possibly composed) statement of the C language. In the statement you can use the variable var (third parameter of the macro) going through all
elements of the list.

SGLIB_DL_LIST_REVERSE

macro

SGLIB_DL_LIST_REVERSE(type, list, previous, next)

reverse a list.

Parameters:

type - the type of list elements.

list - the list to reverse.

previous - the name of the field pointing to the previous element of the list.

next - the name of the field pointing to the next element of the list.

SGLIB_DL_LIST_SORT

macro

SGLIB_DL_LIST_SORT(type, list, comparator, previous, next)

sort a list using mergesort. As a side effect the list is set to the first element of the list.

previous - the name of the field pointing to the previous element of the list.

next - the name of the field pointing to the next element of the list.

Binary Trees API: level 0

SGLIB_BIN_TREE_MAP_ON_ELEMENTS

macro

SGLIB_BIN_TREE_MAP_ON_ELEMENTS(type, tree, var, left, right, command)

traverse a binary tree and apply command on each element. This is non-recursive implementation of tree traversal. It maintains the path to the current node in the array _path_, the _path_[0] contains the root of the tree. The _path_[_pathi_-1] contains the parent of the var. The maximal deep of the tree is limited by SGLIB_MAX_TREE_DEEP macro.

Parameters:

type - the type of the tree data structure.

tree - the tree.

var - the variable which will run through each element of the tree.

left - the name of the field pointing to the left subtree of the tree.

right - the name of the field pointing to the right subtree of the tree.

command - any (possibly composed) statement of the C language. In the statement you can use the variable var (third parameter of the macro) going through all
elements of the tree.

API: level 1

The level - 1 application interface consists of two stages. First you need to
invoke a generic macro for given data type and then you can use a collection
of functions generated by the macro (see also our samples
for the difference between the two interfaces).
Function names
are composed from the name of the base type given by the user.

Hashed Containers API: level 1

Usually, in libraries similar to sglib, a hashed container is an array
where each cell contains a (possibly empty) list of elements.
In sglib we use a more abstract notion of hashed container. A hashed
container is a table of fixed size containing another (we say
base) container in each cell. Once an object is going to be
inserted into the hashed container, the hash function is used to
determine the cell where it belongs and then the object is inserted
into the base container stored in this cell. The base container is
usualy a list, however it can be a sorted list, double linked list or
a red-black tree as well. Sglib's hashed container is parametrized by
the name of the base container.

Hashed containers are provided only in level-1 interface because they
require a uniform interface for operations applied on the base container.

initialize an iterator it to run over those elements of table which are
equal to equalto. The equality is considered with respect to the
subcomparator which must be a subcomparator
of the base container comparator.

Parameters:

it - the iterator.

table - the hashed container.

subcomparator - the comparator used to find equal elements.

equalto - the element used as filter.

Returns:

The first iterated element or NULL if there is no element equal to equalto.

next - the name of the field pointing to the next element of the list.

sglib_type_sort

function

void sglib_type_sort(type **list)

sort the list according to comparator. This function does not logically
belong to this datatype as it is supposed that lists are kept sorted. However, it can be used
to initial sorting, when the list was created by other than sglib functions.

initialize an iterator it to run over those elements of the tree which are
equal to equalto. The equality is considered with respect to the
subcomparator which must be a subcomparator
of the comparator.

Parameters:

it - the iterator.

tree - the tree.

subcomparator - the comparator used to find equal elements.

equalto - the element used as filter.

Returns:

The first iterated element or NULL if there is no element equal to equalto.