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 a string.
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 the given name and returns an 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(): Prints stored elements for debugging purposes.
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 that maps keys to values. Keys are strings, and values are any non-null objects. These elements are stored sequentially in a 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:149

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
allocated qlisttbl_t pointer on success, or NULL on failure.
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 - replace entries with the same key
  • QLISTTBL_CASEINSENSITIVE - treat keys as case-insensitive
  • QLISTTBL_INSERTTOP - insert a new key at the top
  • QLISTTBL_LOOKUPFORWARD - search from the top

Definition at line 149 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 on success, otherwise 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 247 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 on success, otherwise false.
Return values
errnowill be set in error condition.
  • ENOMEM : Memory allocation failure.
  • EINVAL : Invalid argument.

Definition at line 293 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 on success, otherwise false.
Return values
errnowill be set in error condition.
  • ENOMEM : Memory allocation failure.
  • EINVAL : Invalid argument.

Definition at line 310 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 a string.

Parameters
tblqlisttbl container pointer.
nameelement name.
numnumber data.
Returns
true on success, otherwise 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 340 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
pointer to the data if the key is found on success, or NULL on failure.
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 is set, the returned data is newly allocated and must be freed by the caller. Otherwise, the returned pointer refers to the internal data buffer and must not be freed. In thread-safe mode, always set newmem to true to avoid race-condition issues.

Definition at line 385 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
pointer to the data if the key is found on success, or NULL on failure.
Return values
errnowill be set in error condition.
  • ENOENT : No such key found.
  • EINVAL : Invalid argument.
  • ENOMEM : Memory allocation failure.

Definition at line 434 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 451 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 the given name and returns an array of objects.

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

Parameters
tblqlisttbl container pointer.
nameelement name.
newmemwhether or not to allocate memory for the data.
numobjsthe number of returned objects will be stored here. (can be NULL)
Returns
pointer to the data array if the key is found, or NULL on failure.
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 calling freemulti() after use. Even if getmulti() is called with newmem set to false, freemulti() should still be called 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 496 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 564 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 583 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(). The address pointed to by obj may be different from the actual object in the table, but that is OK because we will recalculate the actual object address by following its links.

Parameters
tblqlisttbl container pointer.
objobject to remove.
Returns
true if deletion succeeds, otherwise false.
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 625 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 the key name is NULL, search all objects in the table.
newmemwhether or not to allocate memory for the data.
Returns
true if found otherwise 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 free obj.name and obj.data resources.
qlisttbl_t *tbl = qlisttbl();
(...add data into table...)
// single-threaded usage
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 715 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 786 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 812 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 847 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 on success, otherwise false.

Definition at line 879 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 924 of file qlisttbl.c.

◆ qlisttbl_debug()

bool qlisttbl_debug ( qlisttbl_t * tbl,
FILE * out )

qlisttbl->debug(): Prints stored elements for debugging purposes.

Parameters
tblqlisttbl container pointer.
outoutput stream such as stdout or stderr.
Returns
true on success, otherwise false.
Return values
errnowill be set in error condition.
  • EIO : Invalid output stream.

Definition at line 975 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 1002 of file qlisttbl.c.

◆ qlisttbl_unlock()

void qlisttbl_unlock ( qlisttbl_t * tbl)

qlisttbl->unlock(): Leave critical section.

Parameters
tblqlisttbl container pointer.

Definition at line 1011 of file qlisttbl.c.

◆ qlisttbl_free()

void qlisttbl_free ( qlisttbl_t * tbl)

qlisttbl->free(): Free qlisttbl_t

Parameters
tblqlisttbl container pointer.

Definition at line 1020 of file qlisttbl.c.