qLibc
qtreetbl.c File Reference

Tree Table container that implements "Left-Leaning Red-Black" BST algorithm. More...

Go to the source code of this file.

Functions

qtreetbl_t * qtreetbl (int options)
 Initialize a tree table. More...
 
void qtreetbl_set_compare (qtreetbl_t *tbl, int(*cmp)(const void *name1, size_t namesize1, const void *name2, size_t namesize2))
 qtreetbl->set_compare(): Set user comparator. More...
 
bool qtreetbl_put (qtreetbl_t *tbl, const char *name, const void *data, size_t datasize)
 qtreetbl->put(): Put an object into this table with string type key. More...
 
bool qtreetbl_putstr (qtreetbl_t *tbl, const char *name, const char *str)
 qtreetbl->putstr(): Put a string into this table. More...
 
bool qtreetbl_putstrf (qtreetbl_t *tbl, const char *name, const char *format,...)
 qtreetbl->putstrf(): Put a formatted string into this table. More...
 
bool qtreetbl_put_by_obj (qtreetbl_t *tbl, const void *name, size_t namesize, const void *data, size_t datasize)
 qtreetbl->put_by_obj(): Put an object data into this table with an object name. More...
 
void * qtreetbl_get (qtreetbl_t *tbl, const char *name, size_t *datasize, bool newmem)
 qtreetbl->get(): Get an object from this table. More...
 
char * qtreetbl_getstr (qtreetbl_t *tbl, const char *name, const bool newmem)
 qtreetbl->getstr(): Finds an object and returns as string type. More...
 
void * qtreetbl_get_by_obj (qtreetbl_t *tbl, const char *name, size_t namesize, size_t *datasize, bool newmem)
 qtreetbl->get_by_obj(): Get an object from this table with an object name. More...
 
bool qtreetbl_remove (qtreetbl_t *tbl, const char *name)
 qtreetbl->remove(): Remove an object from this table. More...
 
bool qtreetbl_remove_by_obj (qtreetbl_t *tbl, const void *name, size_t namesize)
 qtreetbl->remove(): Remove an object from this table with an object name. More...
 
bool qtreetbl_getnext (qtreetbl_t *tbl, qtreetbl_obj_t *obj, const bool newmem)
 qhashtbl->getnext(): Get next element. More...
 
void * qtreetbl_find_min (qtreetbl_t *tbl, size_t *namesize)
 qtreetbl->find_min(): Find the name of very left object. More...
 
void * qtreetbl_find_max (qtreetbl_t *tbl, size_t *namesize)
 qtreetbl->find_max(): Find the name of very right object. More...
 
qtreetbl_obj_t qtreetbl_find_nearest (qtreetbl_t *tbl, const void *name, size_t namesize, bool newmem)
 qtreetbl->find_nearest(): Find equal or nearest object. More...
 
size_t qtreetbl_size (qtreetbl_t *tbl)
 qtreetbl->size(): Returns the number of keys in the table. More...
 
void qtreetbl_clear (qtreetbl_t *tbl)
 qtreetbl->clear(): Clears the table so that it contains no keys. More...
 
void qtreetbl_lock (qtreetbl_t *tbl)
 qtreetbl->lock(): Enter critical section. More...
 
void qtreetbl_unlock (qtreetbl_t *tbl)
 qtreetbl->unlock(): Leave critical section. More...
 
void qtreetbl_free (qtreetbl_t *tbl)
 qtreetbl->free(): De-allocate the table More...
 
int qtreetbl_byte_cmp (const void *name1, size_t namesize1, const void *name2, size_t namesize2)
 
bool qtreetbl_debug (qtreetbl_t *tbl, FILE *out)
 qtreetbl->debug(): Print hash table for debugging purpose More...
 

Detailed Description

Tree Table container that implements "Left-Leaning Red-Black" BST algorithm.

qtreetbl implements a binary search tree that allows efficient in-order traversal with O(log n) search time.

The algorithm qtreetbl specifically implements is left-leaning red-black tree algorithm invented in 2008 by Robert Sedgewick. A left-leaning red–black tree is a type of self-balancing binary search tree and it is a variant of the red–black tree which was invented in 1972 by Rudolf Bayer.

References:

Following example code will construct the data structure shown in below diagram. This example is quoted from the inventor's presentation slide p24-p25, http://www.cs.princeton.edu/~rs/talks/LLRB/RedBlack.pdf and used in unit tests for verification purpose.

                           (E)
              ______________|______________
             /                             \
            (C)                           (R)
           /   \                         /   \
       (A,B)   (D)                   (I,N)   (S,X)

              <2-3-4 Tree Data Structure>

                            E
              ______________|______________
             /                             \
            C                               R
     _______|_______                 _______|_______
    /               \               /               \
   B                 D             N                 X
 //                              //                //
A*                              I*                S*

       Tree Info : tot=10, red=3, black=-7, root=E
Nodes A, I and S are nodes with RED upper link. Others are BLACK

       <Left-Leaning Red-Black Tree Data Structure>

Red-Black BST algorithm has been one of the famous BST algorithm especially for in-memory operation. It's been using in all around the computing area. I was very impressed about this variant, Left-Leaning version of Red-Black about how it improves the performance and reduces the overall complexity. Since it's relatively new algorithm, there's not many of practically functional working codes yet other than proof of concept kinds. Here's one of fully functional codes and I, Seungyoung Kim, would like to dedicate this code to the genius inventor Robert Sedgewick and to all the great qLibc users. Cheers!

Unique features:

  • iterator. (have you ever seen iterator implementation in LLRB tree?)
  • find nearest key. (have you ever seen this as well? :)
  • iteration from given key.
  • find min/max key.
qtreetbl_t *tbl = qtreetbl(QTREETBL_THREADSAFE);
tbl->put(tbl, "key", "DATA", 4); // use put_by_obj() for binary keys.
void *data = tbl->get(tbl, "key", false); // use get_by_obj() for binary keys.
tbl->remove(tbl, "key"); // use remove_by_key() for binary keys.
// iteration example
tbl->lock(tbl);
qtreetbl_obj_t obj = tbl->find_nearest(tbl, "k", 2, false);
while (tbl->getnext(tbl, &obj, false) == true) {
...
}
tbl->unlock(tbl);
tbl->set_compare(tbl, my_compare_func);
size_t num = tbl->size(tbl);
void *min = tbl->find_min(tbl, &keysize);
qtree_clean();
tbl->free(tbl);

Definition in file qtreetbl.c.

Function Documentation

qtreetbl_t* qtreetbl ( int  options)

Initialize a tree table.

Parameters
optionscombination of initialization options.
Returns
a pointer of malloced qtreetbl_t, otherwise returns NULL.
Return values
errnowill be set in error condition.
  • ENOMEM : Memory allocation failure.
qtreetbl_t *tbl = qtreetbl(0);
Note
Available options:
  • QTREETBL_THREADSAFE - make it thread-safe.

Definition at line 171 of file qtreetbl.c.

void qtreetbl_set_compare ( qtreetbl_t *  tbl,
int(*)(const void *name1, size_t namesize1, const void *name2, size_t namesize2)  cmp 
)

qtreetbl->set_compare(): Set user comparator.

Parameters
tblqtreetbl_t container pointer.
cmpa pointer to the user comparator function.
Note
By default, qtreetbl uses byte comparator that works for both binary type key and string type key. Please refer qtreetbl_byte_cmp() for your idea to make your own comparator,

Definition at line 240 of file qtreetbl.c.

bool qtreetbl_put ( qtreetbl_t *  tbl,
const char *  name,
const void *  data,
size_t  datasize 
)

qtreetbl->put(): Put an object into this table with string type key.

Parameters
tblqtreetbl_t container pointer.
namekey name
datadata object
datasizesize of data object
Returns
true if successful, otherwise returns false
Return values
errnowill be set in error condition.
  • EINVAL : Invalid argument.
  • ENOMEM : Memory allocation failure.

Definition at line 260 of file qtreetbl.c.

bool qtreetbl_putstr ( qtreetbl_t *  tbl,
const char *  name,
const char *  str 
)

qtreetbl->putstr(): Put a string into this table.

Parameters
tblqtreetbl container pointer.
namekey name.
strstring data.
Returns
true if successful, otherwise returns false.
Return values
errnowill be set in error condition.
  • EINVAL : Invalid argument.
  • ENOMEM : Memory allocation failure.

Definition at line 279 of file qtreetbl.c.

bool qtreetbl_putstrf ( qtreetbl_t *  tbl,
const char *  name,
const char *  format,
  ... 
)

qtreetbl->putstrf(): Put a formatted string into this table.

Parameters
tblqtreetbl_t container pointer.
namekey name.
formatformatted string data.
Returns
true if successful, otherwise returns false.
Return values
errnowill be set in error condition.
  • EINVAL : Invalid argument.
  • ENOMEM : Memory allocation failure.

Definition at line 297 of file qtreetbl.c.

bool qtreetbl_put_by_obj ( qtreetbl_t *  tbl,
const void *  name,
size_t  namesize,
const void *  data,
size_t  datasize 
)

qtreetbl->put_by_obj(): Put an object data into this table with an object name.

Parameters
tblqtreetbl_t container pointer.
namekey name
namesizekey size
datadata object
datasizesize of data object
Returns
true if successful, otherwise returns false
Return values
errnowill be set in error condition.
  • EINVAL : Invalid argument.
  • ENOMEM : Memory allocation failure.
Note
This is the underlying put function which all other put methods use.

Definition at line 328 of file qtreetbl.c.

void* qtreetbl_get ( qtreetbl_t *  tbl,
const char *  name,
size_t *  datasize,
bool  newmem 
)

qtreetbl->get(): Get an object from this table.

Parameters
tblqtreetbl_t container pointer.
namekey name.
datasizeif not NULL, oject size will be stored.
newmemwhether or not to allocate memory for the data.
Returns
a pointer of data if the key is found, otherwise returns NULL.
Return values
errnowill be set in error condition.
  • ENOENT : No such key found.
  • EINVAL : Invalid argument.
  • ENOMEM : Memory allocation failure.
qtreetbl_t *tbl = qtreetbl(0);
(...codes...)
// with newmem flag unset
size_t size;
void *data = (struct myobj*)tbl->get(tbl, "key_name", &size, false);
// with newmem flag set
size_t size;
void *data = (struct myobj*)tbl->get(tbl, "key_name", &size, true);
free(data);
Note
If newmem flag is set, returned data will be malloced and should be deallocated by user. Otherwise returned pointer will point internal buffer directly and should not be de-allocated by user. In thread-safe mode, newmem flag must be set to true always.

Definition at line 384 of file qtreetbl.c.

char* qtreetbl_getstr ( qtreetbl_t *  tbl,
const char *  name,
const bool  newmem 
)

qtreetbl->getstr(): Finds an object and returns as string type.

Parameters
tblqtreetbl_t container pointer.
namekey name
newmemwhether or not to allocate memory for the data.
Returns
a pointer of data if the key is found, otherwise returns NULL.
Return values
errnowill be set in error condition.
  • ENOENT : No such key found.
  • EINVAL : Invalid argument.
  • ENOMEM : Memory allocation failure.
Note
If newmem flag is set, returned data will be malloced and should be deallocated by user. Otherwise returned pointer will point internal buffer directly and should not be de-allocated by user. In thread-safe mode, newmem flag must be set to true always.

Definition at line 410 of file qtreetbl.c.

void* qtreetbl_get_by_obj ( qtreetbl_t *  tbl,
const char *  name,
size_t  namesize,
size_t *  datasize,
bool  newmem 
)

qtreetbl->get_by_obj(): Get an object from this table with an object name.

Parameters
tblqtreetbl_t container pointer.
namekey name
namesizekey size
datasizeif not NULL, oject size will be stored.
newmemwhether or not to allocate memory for the data.
Returns
a pointer of data if the key is found, otherwise returns NULL.
Return values
errnowill be set in error condition.
  • ENOENT : No such key found.
  • EINVAL : Invalid argument.
  • ENOMEM : Memory allocation failure.
Note
If newmem flag is set, returned data will be malloced and should be deallocated by user. Otherwise returned pointer will point internal buffer directly and should not be de-allocated by user. In thread-safe mode, newmem flag must be set to true always.

Definition at line 437 of file qtreetbl.c.

bool qtreetbl_remove ( qtreetbl_t *  tbl,
const char *  name 
)

qtreetbl->remove(): Remove an object from this table.

Parameters
tblqtreetbl_t container pointer.
namekey name
Returns
true if successful, otherwise(not found) returns false
Return values
errnowill be set in error condition.
  • ENOENT : No such key found.
  • EINVAL : Invalid argument.

Definition at line 468 of file qtreetbl.c.

bool qtreetbl_remove_by_obj ( qtreetbl_t *  tbl,
const void *  name,
size_t  namesize 
)

qtreetbl->remove(): Remove an object from this table with an object name.

Parameters
tblqtreetbl_t container pointer.
namekey name
namekey size
Returns
true if successful, otherwise(not found) returns false
Return values
errnowill be set in error condition.
  • ENOENT : No such key found.
  • EINVAL : Invalid argument.

Definition at line 485 of file qtreetbl.c.

bool qtreetbl_getnext ( qtreetbl_t *  tbl,
qtreetbl_obj_t *  obj,
const bool  newmem 
)

qhashtbl->getnext(): Get next element.

Parameters
tblqhashtbl_t container pointer.
objfound data will be stored in this object
newmemwhether or not to allocate memory for the data.
Returns
true if found otherwise returns false
Return values
errnowill be set in error condition.
  • ENOENT : No next element.
  • EINVAL : Invalid argument.
  • ENOMEM : Memory allocation failure.
[Iteration example from the beginning]
qtreetbl_obj_t obj;
memset((void*)&obj, 0, sizeof(obj)); // must be cleared before call
tbl->lock(tbl); // lock it when thread condition is expected
while(tbl->getnext(tbl, &obj, false) == true) {
//
// obj.name : key data
// obj.namesize : key size
// obj.data : data
// obj.datasize : data size
//
// Do free obj.name and obj.data if newmem is set to true;
}
tbl->unlock(tbl);
[Iteration example from given point]
qtreetbl_obj_t obj;
memset((void*)&obj, 0, sizeof(obj));
tbl->lock(tbl); // lock must be raised before find_nearest() call.
qtreetbl_obj_t obj = tbl->find_nearest(tbl, "F", 2, false); // here we go!
while (tbl->getnext(tbl, &obj, false) == true) { // newmem is false
//If tree has 5 objects, A, C, E, G and I.
//Iteration sequence from nearest "F" will be: E->G->I->A->C
}
tbl->unlock(tbl);
[Removal example in iteration loop]
qtreetbl_obj_t obj;
memset((void*) &obj, 0, sizeof(obj)); // start from the minimum.
tbl->lock(tbl);
while (tbl->getnext(tbl, &obj, false) == true) {
if (...condition...) {
char *name = qmemdup(obj.name, obj.namesize); // keep the name
size_t namesize = obj.namesize; // for removal argument
tbl->remove_by_obj(tbl, obj.name, obj.namesize); // remove
obj = tbl->find_nearest(tbl, name, namesize, false); // rewind one step back
free(name); // clean up
}
}
tbl->unlock(tbl);
Note
  • locking must be provided on user code when thread condition is expected because entire traversal needs to be running under read-only mode.
  • Data insertion or deletion can be made during the traversal, but in that case iterator doesn't guarantee full sweep and possibly skip some visits. When deletion happens in getnext() loop, use find_nearest() to rewind the iterator one step back.
  • Object obj should be initialized with 0 by using memset() before first call.
  • If newmem flag is true, user should de-allocate obj.name and obj.data resources.

Definition at line 578 of file qtreetbl.c.

void* qtreetbl_find_min ( qtreetbl_t *  tbl,
size_t *  namesize 
)

qtreetbl->find_min(): Find the name of very left object.

Parameters
tblqtreetbl_t container pointer.
namesizeif not NULL, the size of key name will be stored.
Returns
malloced memory copying the key name.
Note
It's user's responsibility to free the return.

Definition at line 632 of file qtreetbl.c.

void* qtreetbl_find_max ( qtreetbl_t *  tbl,
size_t *  namesize 
)

qtreetbl->find_max(): Find the name of very right object.

Parameters
tblqtreetbl_t container pointer.
namesizeif not NULL, the size of key name will be stored.
Returns
malloced memory copying the key name.
Note
It's user's responsibility to free the return.

Definition at line 660 of file qtreetbl.c.

qtreetbl_obj_t qtreetbl_find_nearest ( qtreetbl_t *  tbl,
const void *  name,
size_t  namesize,
bool  newmem 
)

qtreetbl->find_nearest(): Find equal or nearest object.

find_nearest() returns matching key or nearest key. If there's no keys in the table. It'll return empty qtreetbl_obj_t object with errno ENOENT.

Parameters
tblqtreetbl_t container pointer.
namekey name
namesizekey size
newmemwhether or not to allocate memory for the data.
Returns
qtreetbl_obj_t object.
Return values
errnowill be set in error condition.
  • ENOENT : No next element.
  • EINVAL : Invalid argument.
  • ENOMEM : Memory allocation failure.
[Some examples here]
Data Set : A B C D E I N R S X
find_nearest("0") => "A" // no smaller key available, so "A"
find_nearest("C") => "C" // matching key found
find_nearest("F") => "E" // "E" is nearest smaller key from "F"
find_nearest("M") => "N" // "N" is nearest smaller key from "M"
find_nearest("Z") => "X" // "X" is nearest smaller key from "Z"
Note
When there's no matching key it look for closest smaller key in the neighbors. The only exception when it returns bigger key than given search key is that when there's no smaller keys available in the table. In such case, it'll return the nearest bigger key.

Definition at line 712 of file qtreetbl.c.

size_t qtreetbl_size ( qtreetbl_t *  tbl)

qtreetbl->size(): Returns the number of keys in the table.

Parameters
tblqtreetbl_t container pointer.
Returns
number of elements stored

Definition at line 777 of file qtreetbl.c.

void qtreetbl_clear ( qtreetbl_t *  tbl)

qtreetbl->clear(): Clears the table so that it contains no keys.

Parameters
tblqtreetbl_t container pointer.

Definition at line 786 of file qtreetbl.c.

void qtreetbl_lock ( qtreetbl_t *  tbl)

qtreetbl->lock(): Enter critical section.

Parameters
tblqtreetbl_t container pointer.
Note
From user side, normally locking operation is only needed when traverse all elements using qtreetbl->getnext().
This operation will do nothing if QTREETBL_THREADSAFE option was not given at the initialization time.

Definition at line 807 of file qtreetbl.c.

void qtreetbl_unlock ( qtreetbl_t *  tbl)

qtreetbl->unlock(): Leave critical section.

Parameters
tblqtreetbl_t container pointer.
Note
This operation will do nothing if QTREETBL_THREADSAFE option was not given at the initialization time.

Definition at line 820 of file qtreetbl.c.

void qtreetbl_free ( qtreetbl_t *  tbl)

qtreetbl->free(): De-allocate the table

Parameters
tblqtreetbl_t container pointer.

Definition at line 829 of file qtreetbl.c.

bool qtreetbl_debug ( qtreetbl_t *  tbl,
FILE *  out 
)

qtreetbl->debug(): Print hash table for debugging purpose

Parameters
tblqtreetbl_t container pointer.
outoutput stream
Returns
true if successful, otherwise returns false.
Return values
errnowill be set in error condition.
  • EIO : Invalid output stream.

Definition at line 854 of file qtreetbl.c.