qLibc
qlisttbl.c File Reference

Linked-list-table implementation. More...

Go to the source code of this file.

Functions

qlisttbl_t * qlisttbl (int options)
 Create a new Q_LIST linked-list container.
 
bool qlisttbl_put (qlisttbl_t *tbl, const char *name, const void *data, size_t size)
 qlisttbl->put(): Put an element to this table.
 
bool qlisttbl_putstr (qlisttbl_t *tbl, const char *name, const char *str)
 qlisttbl->putstr(): Put a string into this table.
 
bool qlisttbl_putstrf (qlisttbl_t *tbl, const char *name, const char *format,...)
 qlisttbl->putstrf(): Put a formatted string into this table.
 
bool qlisttbl_putint (qlisttbl_t *tbl, const char *name, int64_t num)
 qlisttbl->putInt(): Put an integer into this table as string type.
 
void * qlisttbl_get (qlisttbl_t *tbl, const char *name, size_t *size, bool newmem)
 qlisttbl->get(): Finds an object with given name.
 
char * qlisttbl_getstr (qlisttbl_t *tbl, const char *name, bool newmem)
 qlisttbl->getstr(): Finds an object with given name and returns as string type.
 
int64_t qlisttbl_getint (qlisttbl_t *tbl, const char *name)
 qlisttbl->getint(): Finds an object with given name and returns as integer type.
 
qlisttbl_data_t * qlisttbl_getmulti (qlisttbl_t *tbl, const char *name, bool newmem, size_t *numobjs)
 qlisttbl->getmulti(): Finds all objects with given name and return a array of objects.
 
void qlisttbl_freemulti (qlisttbl_data_t *objs)
 qlisttbl->freemulti(): Deallocate object array returned by getmulti().
 
size_t qlisttbl_remove (qlisttbl_t *tbl, const char *name)
 qlisttbl->remove(): Remove matched objects with given name.
 
bool qlisttbl_removeobj (qlisttbl_t *tbl, const qlisttbl_obj_t *obj)
 qlisttbl->removeobj(): Remove objects with given object pointer.
 
bool qlisttbl_getnext (qlisttbl_t *tbl, qlisttbl_obj_t *obj, const char *name, bool newmem)
 qlisttbl->getnext(): Get next element.
 
size_t qlisttbl_size (qlisttbl_t *tbl)
 qlisttbl->size(): Returns the number of elements in this table.
 
void qlisttbl_sort (qlisttbl_t *tbl)
 qlisttbl->sort(): Sort keys in this table.
 
void qlisttbl_clear (qlisttbl_t *tbl)
 qlisttbl->clear(): Removes all of the elements from this table.
 
bool qlisttbl_save (qlisttbl_t *tbl, const char *filepath, char sepchar, bool encode)
 qlisttbl->save(): Save qlisttbl as plain text format Dumping direction is always forward(from the top to the bottom) to preserve the order when we load the file again.
 
ssize_t qlisttbl_load (qlisttbl_t *tbl, const char *filepath, char sepchar, bool decode)
 qlisttbl->load(): Load and append entries from given filepath Loading direction is always appending at the bottom of the table to preserve the order as it was.
 
bool qlisttbl_debug (qlisttbl_t *tbl, FILE *out)
 qlisttbl->debug(): Print out stored elements for debugging purpose.
 
void qlisttbl_lock (qlisttbl_t *tbl)
 qlisttbl->lock(): Enter critical section.
 
void qlisttbl_unlock (qlisttbl_t *tbl)
 qlisttbl->unlock(): Leave critical section.
 
void qlisttbl_free (qlisttbl_t *tbl)
 qlisttbl->free(): Free qlisttbl_t
 

Detailed Description

Linked-list-table implementation.

qlisttbl container is a Linked-List-Table implementation. Which maps keys to values. Key is a string and value is any non-null object. These elements are stored sequentially in Doubly-Linked-List data structure.

Compared to Hash-Table, List-Table is efficient when you need to keep duplicated keys since Hash-Table only keep unique keys. Of course, qlisttbl supports both unique keys and key duplication.

[Conceptional Data Structure Diagram]
last~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
|
+-----------+ doubly +-----------+ doubly +-v---------+
first~~~|~> 0 <~|~~~~~~~~~~|~> 1 <~|~~~~~~~~~~|~> N |
+--|-----|--+ linked +--|-----|--+ linked +--|-----|--+
| | | | | |
+-----v-+ +-v-------+ | | +-----v-+ +-v-------+
| KEY A | | VALUE A | | | | KEY N | | VALUE N |
+-------+ +---------+ | | +-------+ +---------+
+-----v-+ +-v-------+
| KEY B | | VALUE B |
+-------+ +---------+
// create a list table.
qlisttbl_t *tbl = qlisttbl(QLISTTBL_THREADSAFE);
// insert elements (key duplication allowed)
tbl->put(tbl, "e1", "a", strlen("e1")+1); // equal to putstr();
tbl->putstr(tbl, "e2", "b");
tbl->putstr(tbl, "e2", "c");
tbl->putstr(tbl, "e3", "d");
// debug output
tbl->debug(tbl, stdout, true);
// get element
printf("get('e2') : %s\n", (char*)tbl->get(tbl, "e2", NULL, false));
printf("getstr('e2') : %s\n", tbl->getstr(tbl, "e2", false));
// get all matching elements
qlisttbl_data_t *objs = tbl->getmulti(tbl, "e2", true, NULL);
for (i = 0; objs[i].data != NULL; i++) {
printf("getmulti('e2')[%d] : %s (size=%d)\n",
i, (char *)objs[i].data, (int)objs[i].size);
}
tbl->freemulti(objs);
// find every 'e2' elements
qlisttbl_obj_t obj;
memset((void*)&obj, 0, sizeof(obj)); // must be cleared before call
while(tbl->getnext(tbl, &obj, "e2", false) == true) {
printf("NAME=%s, DATA=%s, SIZE=%zu\n",
obj.name, (char*)obj.data, obj.size);
}
// free object
tbl->free(tbl);
qlisttbl_t * qlisttbl(int options)
Create a new Q_LIST linked-list container.
Definition qlisttbl.c:150

Definition in file qlisttbl.c.

Function Documentation

◆ qlisttbl()

qlisttbl_t * qlisttbl ( int  options)

Create a new Q_LIST linked-list container.

Parameters
optionscombination of initialization options.
Returns
a pointer of malloced qlisttbl_t structure in case of successful, otherwise returns NULL.
Return values
errnowill be set in error condition.
  • ENOMEM : Memory allocation failure.
qlisttbl_t *tbl = qlisttbl(0);
qlisttbl_t *threadsafe_tbl = qlisttbl(QLISTTBL_THREADSAFE);
Note
Available options:
  • QLISTTBL_THREADSAFE - make it thread-safe.
  • QLISTTBL_UNIQUE - keys are all unique. replace same key
  • QLISTTBL_CASEINSENSITIVE - key is case insensitive
  • QLISTTBL_INSERTTOP - insert new key at the top
  • QLISTTBL_LOOKUPFORWARD - find key from the top

Definition at line 150 of file qlisttbl.c.

◆ qlisttbl_put()

bool qlisttbl_put ( qlisttbl_t *  tbl,
const char *  name,
const void *  data,
size_t  size 
)

qlisttbl->put(): Put an element to this table.

Parameters
tblqlisttbl container pointer.
nameelement name.
dataa pointer which points data memory.
sizesize of the data.
Returns
true if successful, otherwise returns false.
Return values
errnowill be set in error condition.
  • ENOMEM : Memory allocation failure.
  • EINVAL : Invalid argument.
struct my_obj {
int a, b, c;
};
// create a sample object.
struct my_obj obj;
// create a table and add a sample object.
qlisttbl_t *tbl = qlisttbl();
tbl->put(tbl, "obj1", &obj, sizeof(struct my_obj));
Note
The default behavior is adding an object at the end of this table unless QLISTTBL_INSERTTOP option was given.

Definition at line 249 of file qlisttbl.c.

◆ qlisttbl_putstr()

bool qlisttbl_putstr ( qlisttbl_t *  tbl,
const char *  name,
const char *  str 
)

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

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

Definition at line 296 of file qlisttbl.c.

◆ qlisttbl_putstrf()

bool qlisttbl_putstrf ( qlisttbl_t *  tbl,
const char *  name,
const char *  format,
  ... 
)

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

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

Definition at line 314 of file qlisttbl.c.

◆ qlisttbl_putint()

bool qlisttbl_putint ( qlisttbl_t *  tbl,
const char *  name,
int64_t  num 
)

qlisttbl->putInt(): Put an integer into this table as string type.

Parameters
tblqlisttbl container pointer.
nameelement name.
numnumber data.
Returns
true if successful, otherwise returns false.
Return values
errnowill be set in error condition.
  • ENOMEM : Memory allocation failure.
  • EINVAL : Invalid argument.
Note
The integer will be converted to a string object and stored as a string object.

Definition at line 345 of file qlisttbl.c.

◆ qlisttbl_get()

void * qlisttbl_get ( qlisttbl_t *  tbl,
const char *  name,
size_t *  size,
bool  newmem 
)

qlisttbl->get(): Finds an object with given name.

If there are duplicate keys in the table, this will return the first matched one from the bottom (or the top if QLISTTBL_LOOKUPFORWARD option was given). So if there are duplicated keys, it'll return recently inserted one.

Parameters
tblqlisttbl container pointer.
nameelement name.
sizeif size is not NULL, data size will be stored.
newmemwhether or not to allocate memory for the data.
Returns
a pointer of data if 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.
qlisttbl_t *tbl = qlisttbl();
(...codes...)
// with newmem flag unset
size_t size;
void *data = tbl->get(tbl, "key_name", &size, false);
// with newmem flag set
size_t size;
void *data = tbl->get(tbl, "key_name", &size, true);
(...does something with data...)
if(data != NULL) 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 data buffer directly and should not be de-allocated by user. In thread-safe mode, always set newmem flag as true to make sure it works in race condition situation.

Definition at line 392 of file qlisttbl.c.

◆ qlisttbl_getstr()

char * qlisttbl_getstr ( qlisttbl_t *  tbl,
const char *  name,
bool  newmem 
)

qlisttbl->getstr(): Finds an object with given name and returns as string type.

Parameters
tblqlisttbl container pointer.
nameelement name.
newmemwhether or not to allocate memory for the data.
Returns
a pointer of data if 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.

Definition at line 442 of file qlisttbl.c.

◆ qlisttbl_getint()

int64_t qlisttbl_getint ( qlisttbl_t *  tbl,
const char *  name 
)

qlisttbl->getint(): Finds an object with given name and returns as integer type.

Parameters
tblqlisttbl container pointer.
nameelement name.
Returns
an integer value of the integer object, otherwise returns 0.
Return values
errnowill be set in error condition.
  • ENOENT : No such key found.
  • EINVAL : Invalid argument.
  • ENOMEM : Memory allocation failure.

Definition at line 460 of file qlisttbl.c.

◆ qlisttbl_getmulti()

qlisttbl_data_t * qlisttbl_getmulti ( qlisttbl_t *  tbl,
const char *  name,
bool  newmem,
size_t *  numobjs 
)

qlisttbl->getmulti(): Finds all objects with given name and return a array of objects.

If there are duplicate keys in the table, this will return all the matched ones. The order of objects in return depends on setnextdir() setting. By default, the order is same(forward) as listed in the table.

Parameters
tblqlisttbl container pointer.
nameelement name.
newmemwhether or not to allocate memory for the data.
numobjsthe nuber of objects returned will be stored. (can be NULL)
Returns
a pointer of data if 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
The returned array of qlisttbl_data_t should be released by freemulti() call after use. Even you call getmulti() with newmem set false, freemulti() should be called all the times, so the object array itself can be released.
size_t numobjs = 0;
qlisttbl_data_t *objs = tbl->getmulti(tbl, "e2", true, &numobjs);
for (i = 0; objs[i].data != NULL; i++) {
printf("DATA=%s, SIZE=%zu\n", i, (char *)objs[i].data, objs[i].size);
}
tbl->freemulti(objs);

Definition at line 504 of file qlisttbl.c.

◆ qlisttbl_freemulti()

void qlisttbl_freemulti ( qlisttbl_data_t *  objs)

qlisttbl->freemulti(): Deallocate object array returned by getmulti().

Parameters
objspointer of array of qlisttbl_data_t.
qlisttbl_data_t *objs = tbl->getmulti(tbl, "newmem is true", true, &numobjs);
tbl->freemulti(objs); // frees allocated objects and object array itself.
qlisttbl_data_t *objs = tbl->getmulti(tbl, "even newmem is false", false, &numobjs);
tbl->freemulti(objs); // frees object array itself.

Definition at line 573 of file qlisttbl.c.

◆ qlisttbl_remove()

size_t qlisttbl_remove ( qlisttbl_t *  tbl,
const char *  name 
)

qlisttbl->remove(): Remove matched objects with given name.

Parameters
tblqlisttbl container pointer.
nameelement name.
Returns
a number of removed objects.

Definition at line 593 of file qlisttbl.c.

◆ qlisttbl_removeobj()

bool qlisttbl_removeobj ( qlisttbl_t *  tbl,
const qlisttbl_obj_t *  obj 
)

qlisttbl->removeobj(): Remove objects with given object pointer.

This call is useful when you want to remove an element while traversing a table using getnext(). So the address pointed by obj maybe different than the actual object in a table, but it's ok because we'll recalculate the actual object address by referring it's links.

Parameters
tblqlisttbl container pointer.
nameelement name.
Returns
true if succeed on deletion, false if failed.
Return values
errnowill be set in error condition.
  • ENOENT : No such key found.
qlisttbl_obj_t obj;
memset((void*)&obj, 0, sizeof(obj)); // must be cleared before call
tbl->lock(tbl);
while(tbl->getnext(tbl, &obj, NULL, true) == true) {
tbl->removeobj(tbl, &obj); // this will remove all entries in the table
}
tbl->unlock(tbl);

Definition at line 636 of file qlisttbl.c.

◆ qlisttbl_getnext()

bool qlisttbl_getnext ( qlisttbl_t *  tbl,
qlisttbl_obj_t *  obj,
const char *  name,
bool  newmem 
)

qlisttbl->getnext(): Get next element.

Default searching direction is backward, from the bottom to top unless QLISTTBL_LOOKUPFORWARD option was specified.

Parameters
tblqlisttbl container pointer.
objfound data will be stored in this object
nameelement name., if key name is NULL search every objects in the table.
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.
  • ENOMEM : Memory allocation failure.
Note
The 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.
qlisttbl_t *tbl = qlisttbl();
(...add data into table...)
// non-thread usages
qlisttbl_obj_t obj;
memset((void*)&obj, 0, sizeof(obj)); // must be cleared before call
while(tbl->getnext(tbl, &obj, NULL, false) == true) {
printf("NAME=%s, DATA=%s, SIZE=%zu\n",
obj.name, (char*)obj.data, obj.size);
}
// thread model with particular key search
qlisttbl_obj_t obj;
memset((void*)&obj, 0, sizeof(obj)); // must be cleared before call
tbl->lock(tbl);
while(tbl->getnext(tbl, &obj, "key_name", true) == true) {
printf("NAME=%s, DATA=%s, SIZE=%zu\n",
obj.name, (char*)obj.data, obj.size);
free(obj.name);
free(obj.data);
}
tbl->unlock(tbl);

Definition at line 727 of file qlisttbl.c.

◆ qlisttbl_size()

size_t qlisttbl_size ( qlisttbl_t *  tbl)

qlisttbl->size(): Returns the number of elements in this table.

Parameters
tblqlisttbl container pointer.
Returns
the number of elements in this table.

Definition at line 799 of file qlisttbl.c.

◆ qlisttbl_sort()

void qlisttbl_sort ( qlisttbl_t *  tbl)

qlisttbl->sort(): Sort keys in this table.

Parameters
tblqlisttbl container pointer.
Note
It will sort the table in ascending manner, if you need descending order somehow, lookup-backword option will do the job without changing the order in the table.
The appearence order of duplicated keys will be preserved in a sored table.
See how duplicated key 'b' is ordered in below example
[Unsorted] [sorted ASC] [sorted DES]
d = 1 a = 2 d = 1
a = 2 b = 3 c = 5
b = 3 b = 4 b = 3
b = 4 b = 6 b = 4
c = 5 c = 5 b = 6
b = 6 d = 1 a = 2

Definition at line 826 of file qlisttbl.c.

◆ qlisttbl_clear()

void qlisttbl_clear ( qlisttbl_t *  tbl)

qlisttbl->clear(): Removes all of the elements from this table.

Parameters
tblqlisttbl container pointer.

Definition at line 862 of file qlisttbl.c.

◆ qlisttbl_save()

bool qlisttbl_save ( qlisttbl_t *  tbl,
const char *  filepath,
char  sepchar,
bool  encode 
)

qlisttbl->save(): Save qlisttbl as plain text format Dumping direction is always forward(from the top to the bottom) to preserve the order when we load the file again.

Parameters
tblqlisttbl container pointer.
filepathsave file path
sepcharseparator character between name and value. normally '=' is used.
encodeflag for encoding data . false can be used if the all data are string or integer type and has no new line. otherwise true must be set.
Returns
true if successful, otherwise returns false.

Definition at line 895 of file qlisttbl.c.

◆ qlisttbl_load()

ssize_t qlisttbl_load ( qlisttbl_t *  tbl,
const char *  filepath,
char  sepchar,
bool  decode 
)

qlisttbl->load(): Load and append entries from given filepath Loading direction is always appending at the bottom of the table to preserve the order as it was.

Parameters
tblqlisttbl container pointer.
filepathsave file path
sepcharseparator character between name and value. normally '=' is used
decodeflag for decoding data
Returns
the number of loaded entries, otherwise returns -1.

Definition at line 941 of file qlisttbl.c.

◆ qlisttbl_debug()

bool qlisttbl_debug ( qlisttbl_t *  tbl,
FILE *  out 
)

qlisttbl->debug(): Print out stored elements for debugging purpose.

Parameters
tblqlisttbl container pointer.
outoutput stream FILE descriptor such like stdout, stderr.
Returns
true if successful, otherwise returns false.
Return values
errnowill be set in error condition.
  • EIO : Invalid output stream.

Definition at line 993 of file qlisttbl.c.

◆ qlisttbl_lock()

void qlisttbl_lock ( qlisttbl_t *  tbl)

qlisttbl->lock(): Enter critical section.

Parameters
tblqlisttbl container pointer.
Note
Normally explicit locking is only needed when traverse all the elements with qlisttbl->getnext().

Definition at line 1021 of file qlisttbl.c.

◆ qlisttbl_unlock()

void qlisttbl_unlock ( qlisttbl_t *  tbl)

qlisttbl->unlock(): Leave critical section.

Parameters
tblqlisttbl container pointer.

Definition at line 1031 of file qlisttbl.c.

◆ qlisttbl_free()

void qlisttbl_free ( qlisttbl_t *  tbl)

qlisttbl->free(): Free qlisttbl_t

Parameters
tblqlisttbl container pointer.

Definition at line 1041 of file qlisttbl.c.