qLibc

Functions
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
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

  options | combination of initialization options.

Returns
  a pointer of malloced qlisttbl_t structure in case of successful, otherwise returns NULL.

Return values

  errno | will 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

  tbl | qlisttbl container pointer.
  name | element name.
  data | a pointer which points data memory.
  size | size of the data.

Returns
  true if successful, otherwise returns false.

Return values

  errno | will 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

  tbl | qlisttbl container pointer.
  name | element name.
  str | string data.

Returns
  true if successful, otherwise returns false.

Return values

  errno | will 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

  tbl | qlisttbl container pointer.
  name | element name.
  format | formatted value string.

Returns
  true if successful, otherwise returns false.

Return values

  errno | will 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

  tbl | qlisttbl container pointer.
  name | element name.
  num | number data.

Returns
  true if successful, otherwise returns false.

Return values

  errno | will 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

  tbl | qlisttbl container pointer.
  name | element name.
  size | if size is not NULL, data size will be stored.
  newmem | whether or not to allocate memory for the data.

Returns
  a pointer of data if key is found, otherwise returns NULL.

Return values

  errno | will 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

  tbl | qlisttbl container pointer.
  name | element name.
  newmem | whether or not to allocate memory for the data.

Returns
  a pointer of data if key is found, otherwise returns NULL.

Return values

  errno | will 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

  tbl | qlisttbl container pointer.
  name | element name.

Returns
  an integer value of the integer object, otherwise returns 0.

Return values

  errno | will 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

  tbl | qlisttbl container pointer.
  name | element name.
  newmem | whether or not to allocate memory for the data.
  numobjs | the nuber of objects returned will be stored. (can be NULL)

Returns
  a pointer of data if key is found, otherwise returns NULL.

Return values

  errno | will 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

  objs | pointer 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

  tbl | qlisttbl container pointer.
  name | element 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

  tbl | qlisttbl container pointer.
  name | element name.

Returns
  true if succeed on deletion, false if failed.

Return values

  errno | will 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

  tbl | qlisttbl container pointer.
  obj | found data will be stored in this object
  name | element name., if key name is NULL search every objects in the table.
  newmem | whether or not to allocate memory for the data.

Returns
  true if found otherwise returns false

Return values

  errno | will 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

  tbl | qlisttbl 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

  tbl | qlisttbl 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

  tbl | qlisttbl 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

  tbl | qlisttbl container pointer.
  filepath | save file path
  sepchar | separator character between name and value. normally '=' is used.
  encode | flag 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

  tbl | qlisttbl container pointer.
  filepath | save file path
  sepchar | separator character between name and value. normally '=' is used
  decode | flag 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

  tbl | qlisttbl container pointer.
  out | output stream FILE descriptor such like stdout, stderr.

Returns
  true if successful, otherwise returns false.

Return values

  errno | will 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

  tbl | qlisttbl 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

  tbl | qlisttbl container pointer.

Definition at line 1031 of file qlisttbl.c.

## ◆ qlisttbl_free()

void qlisttbl_free | ( | qlisttbl_t * | tbl | ) |

qlisttbl->free(): Free qlisttbl_t

Parameters

  tbl | qlisttbl container pointer.

Definition at line 1041 of file qlisttbl.c.