diff --git a/.gitignore b/.gitignore index 0a526df..f8b849d 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,6 @@ include/version.h nbproject config.guess.dh-orig config.sub.dh-orig +debian/files +debian/tmp +debian/libtdata* diff --git a/configure.ac b/configure.ac index 9a13cc8..fa0228b 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. -AC_INIT(libtdata, 0.2.1) +AC_INIT(libtdata, 0.2.2) AC_CONFIG_HEADERS([config.h]) diff --git a/debian/changelog b/debian/changelog index 4c19afe..8ae8042 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,11 @@ +libtdata (0.2.2) stable; urgency=low + + * Release 0.2.2 Added simple list to the collection + + -- Alexander Vdolainen Wed, 20 May 2015 15:02:00 +0300 + libtdata (0.2.1) stable; urgency=low * Initial release (Closes: #nnnn) - -- Alexander Vdolainen Mon, 24 Nov 2014 00:34:00 +0200 + -- Alexander Vdolainen Mon, 24 Nov 2014 00:34:00 +0200 diff --git a/debian/shlibs.local.ex b/debian/shlibs.local.ex index 8fab807..21309f5 100644 --- a/debian/shlibs.local.ex +++ b/debian/shlibs.local.ex @@ -1 +1 @@ -liblibtdata 0.2.1 libtdata (>> 0.2.1-0), libtdata (<< 0.2.1-99) +liblibtdata 0.2.2 libtdata (>> 0.2.2-0), libtdata (<< 0.2.2-99) diff --git a/debian/source/format b/debian/source/format deleted file mode 100644 index 163aaf8..0000000 --- a/debian/source/format +++ /dev/null @@ -1 +0,0 @@ -3.0 (quilt) diff --git a/include/Makefile.am b/include/Makefile.am index ebbaf3d..f96454d 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1 +1 @@ -nobase_include_HEADERS = tdata/bitwise.h tdata/idx_allocator.h tdata/macro.h tdata/tree.h tdata/usrtc.h +nobase_include_HEADERS = tdata/bitwise.h tdata/idx_allocator.h tdata/macro.h tdata/tree.h tdata/usrtc.h tdata/list.h diff --git a/include/tdata/list.h b/include/tdata/list.h new file mode 100644 index 0000000..65f3f3d --- /dev/null +++ b/include/tdata/list.h @@ -0,0 +1,416 @@ +/* + * Typical data structures used. + * This is a proprietary software. See COPYING for further details. + * + * (c) 2013-2014, 2015 Copyright Askele, inc. + * (c) 2013-2014, 2015 Copyright Askele Ingria, inc. + */ + +#ifndef __TDATA_LIST_H__ +#define __TDATA_LIST_H__ + +#include +#include + +#define __MILESTONE ((unsigned long)0x123) + +/** + * @def MILESTONES_SEQ(num) ((void *)__MILESTONE##num) + * @brief Easy way to define next item in milestones sequence + * @pararm num - number of milestone in sequence + */ +#define MILESTONES_SEQ(num) ((void *)(__MILESTONE + (num))) + +/* milestones for list's next and prev pointers respectively */ +#define MLST_LIST_NEXT MILESTONES_SEQ(1) +#define MLST_LIST_PREV MILESTONES_SEQ(2) + +#ifndef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + +#ifndef container_of +#define container_of(PTR, TYPE, MEMBER) \ + ((TYPE *)((char *)(PTR) - offsetof(TYPE, MEMBER))) +#endif + +/* init root node of non containerized double linked non cyclic list */ +#define nclist_init_root(root) \ +do { \ + root->next = NULL; \ + root->prev = root; \ +} while (0) + +/* add to tail of non containerized double linked non cyclic list */ +#define nclist_add2tail(root,node) \ +do { \ + typeof(root) __tail = (root)->prev; \ + \ + __tail->next = node; \ + node->prev = __tail; \ + node->next = NULL; \ + (root)->prev = node; \ +} while (0) + +#define nclist_for_each(root, node) \ + for (node = root; node != NULL; node = node->next) + +/** + * @typedef struct __list_node list_node_t + * @struct __list_node + * @brief List node + */ +typedef struct __list_node { + struct __list_node *next; + struct __list_node *prev; +} list_node_t; + +/** + * @typedef struct __list_head list_head_t + * @struct __list_head + * @brief List head + * Actually list_head_t is the same as list_node_t, but + * they have different types though. That was done to prevent + * potentional errors(notice that list head is a stub, it's never + * tied with any real data and it's used only to determine where list + * starts and where it ends) + */ +typedef struct __list_head { + list_node_t head; /**< Head element of the list */ +} list_head_t; + +/** + * @def LIST_DEFINE(name) + * @brief Define and initialize list head with name @a name + * @param name - name of variable + */ +#define LIST_DEFINE(name) \ + list_head_t name = { .head = { &(name).head, &(name).head } } + +/** + * @fn static inline void list_init_head(list_head_t *lst) + * @brief Initialize list head + * @param lst - a pointer to list head. + */ +static inline void list_init_head(list_head_t *lst) +{ + lst->head.next = lst->head.prev = &lst->head; +} + +/** + * @fn static inline void list_init_node(list_node_t *node) + * @brief Initialize list node + * @param node - a pointer to free(unattached from list) node. + */ +static inline void list_init_node(list_node_t *node) +{ + node->next = MLST_LIST_NEXT; + node->prev = MLST_LIST_PREV; +} + +static inline bool list_node_next_isbound(list_node_t *node) +{ + return (node->next == MLST_LIST_NEXT); +} + +static inline bool list_node_prev_isbound(list_node_t *node) +{ + return (node->prev == MLST_LIST_PREV); +} + +/** + * @def list_entry(lst, nptr) + * @brief Get item that holds @a nptr node + * @param list - A pointer to the list + * @param nptr - A pointer to the node + * @return A pointer to the object given node contains + */ +#define list_entry(node, type, member) \ + container_of(node, type, member) + + + +/** + * @def list_head(lst) + * @brief Get head of the list + * @param lst - a pointer to list_head_t + * @return A pointer to header list_node_t + */ +#define list_head(lst) \ + (&(lst)->head) + +/** + * @def list_node_first(lst) + * @brief Get list's first node + * @param list - A pointer to the list_head_t + * @return A pointer to the list first node + */ +#define list_node_first(lst) \ + ((lst)->head.next) + +/** + * list_first_entry - get the first element from a list + * @lst: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + * + * Note, that list is expected to be not empty. + */ +#define list_first_entry(lst, type, member) \ + list_entry((lst)->head.next, type, member) + +/** + * @def list_node_last(lst) + * @brief Get list's last node + * @param list - A pointer to the list_head_t + * @return A pointer to the list last node + */ +#define list_node_last(lst) \ + ((lst)->head.prev) + +/** + * list_last_entry - get the last element from a list + * @lst: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + * + * Note, that list is expected to be not empty. + */ +#define list_last_entry(lst, type, member) \ + list_entry((lst)->head.prev, type, member) + +/** + * @def list_add2head(lst, new) + * @brief Add a node @a new to the head of the list + * @param lst - A pointer to the list + * @param new - A pointer to the list node + */ +#define list_add2head(lst, new) \ + list_add(list_node_first(lst), new) + +/** + * @def list_add2tail(lst, new) + * @brief Add a node @a new to the tail of the list + * @param lst - A pointer to the list + * @param new - A pointer to node to add + */ +#define list_add2tail(lst, new) \ + list_add(list_head(lst), new) + +/** + * @def list_delfromhead(lst) + * @brief Remove first element of the list + * @param lst - A pointer to the list + */ +#define list_delfromhead(lst) \ + list_del(list_node_first(lst)) + +/** + * @def list_delfromtail(lst) + * @brief Remove the last element of the list + * @param list - A pointer to the list + */ +#define list_delfromtail(lst) \ + list_del(list_node_last(lst)) + +/** + * @def list_del(del) + * @brief Remove node @a del from the list + * @param del - A node to remove + */ +#define list_del(del) \ + (list_del_range(del, del)) + +/** + * @def list_add(before, new, after) + * @param after - will be the next node after @a new + * @param new - node to insert + */ +#define list_add(after, new) \ + (list_add_range(new, new, (after)->prev, after)) + +/** + * @def list_move2head(to, from) + * @brief Move all nodes from list @a from to the head of list @a to + * @param to - destination list + * @param from - source list + */ +#define list_move2head(to, from) \ + (list_move(list_head(to), list_node_first(to), from)) + +/** + * @def list_move2tail(to, from) + * @brief Move all nodes from list @a from to the tail of list @a to + * @param to - destination list + * @param from - source list + */ +#define list_move2tail(to, from) \ + (list_move(list_node_last(to), list_head(to), from)) + + +/** + * @def list_for_each(lst, liter) + * @brief Iterate through each element of the list + * @param lst - A pointer to list head + * @param liter - A pointer to list which will be used for iteration + */ +#define list_for_each(lst, liter) \ + for (liter = list_node_first(lst); \ + (liter) != list_head(lst); (liter) = (liter)->next) + +/** + * @def list_for_each_safe(lst, liter, save) + * @brief Safe iteration through the list @a lst + * + * This iteration wouldn't be broken even if @a liter will be removed + * from the list + * + * @param lst - A pointer to the list head + * @param liter - A pointer to list node which will be used for iteration + * @param save - The same + */ +#define list_for_each_safe(lst, liter, save) \ + for (liter = list_node_first(lst), save = (liter)->next; \ + (liter) != list_head(lst); (liter) = (save), \ + (save) = (liter)->next) + +/** + * @def list_for_each_entry(lst, iter, member) + * @brief Iterate through each list node member + * @param lst - a pointer list head + * @param iter - a pointer to list entry using as iterator + * @param member - name of list node member in the parent structure + */ +#define list_for_each_entry(lst, iter, member) \ + for (iter = list_entry(list_node_first(lst), typeof(*iter), member); \ + &iter->member != list_head(lst); \ + iter = list_entry(iter->member.next, typeof(*iter), member)) + +/** + * @def list_for_each_entry(lst, iter, member) + * @brief Iterate through each list node member and calls specified function with argument + * pointing to a list entry + * + * @param lst - a pointer list head + * @param iter - a pointer to list entry using as iterator + * @param member - name of list node member in the parent structure + * @param fn - function doing some actins against each entry of the list + */ +#define list_do_for_each_entry(lst, type, member, fn) \ +{ \ + type *t; \ + list_node_t *node, *save; \ + \ + list_for_each_safe(lst, node, save) { \ + t = container_of(node, type, member); \ + fn(t); \ + } \ +} + +/** + * @fn static inline int list_is_empty(list_t *list) + * @brief Determines if list @a list is empty + * @param list - A pointer to list to test + * @return True if list is empty, false otherwise + */ +static inline int list_is_empty(list_head_t *list) +{ + return (list_node_first(list) == list_head(list)); +} + +/** + * @fn static inline void list_add_range(list_node_t *first, list_node_t *last, + * list_node_t *prev, list_node_t *next) + * @brief Insert a range of nodes from @a frist to @a last after @a prev and before @a last + * @param first - first node of range + * @param last - last node of range + * @param prev - after this node a range will be inserted + * @param next - before this node a range will be inserted + */ +static inline void list_add_range(list_node_t *first, list_node_t *last, + list_node_t *prev, list_node_t *next) +{ + next->prev = last; + last->next = next; + prev->next = first; + first->prev = prev; +} + +/* for internal usage */ +static inline void __list_del_range(list_node_t *first, list_node_t *last) +{ + first->prev->next = last->next; + last->next->prev = first->prev; +} + +/** + * @fn static inline list_del_range(list_node_t *first, list_node_t *last) + * @brief Delete nodes from @a first to @a last from list. + * @param fist - first node to delete + * @param last - last node to delete + */ +static inline void list_del_range(list_node_t *first, list_node_t *last) +{ + __list_del_range(first, last); + first->prev = MLST_LIST_PREV; + last->next = MLST_LIST_NEXT; +} + +/** + * @fn static inline void list_cut_sublist(list_node_t *first, list_node_t *last) + * @brief Cut a "sublist" started from @a first and ended with @a last + * + * A @e "sublist" is similar to ordinary list except it hasn't a head. + * In other words it's a cyclic list in which all nodes are equitable. + * + * @param first - From this node sublist will be cutted + * @param last - The last node in the cutted sequence + */ +static inline void list_cut_sublist(list_node_t *first, list_node_t *last) +{ + __list_del_range(first, last); + first->prev = last; + last->next = first; +} + +/** + * @fn static inline void list_cut_head(list_head_t *head) + * @brief Cut a head from the list and make a "sublist" + * @param head - List's head that will be cutted. + * @see list_cut_sublist + * @see list_set_head + */ +static inline void list_cut_head(list_head_t *head) +{ + list_cut_sublist(list_node_first(head), list_node_last(head)); +} + +/** + * @fn static inline void list_cut_head(list_head_t *head) + * @brief Attach a head to the sublist @a cyclist + * @param new_head - A head that will be attached + * @param cyclist - "sublist" + * @see list_cut_sublist + * @see list_set_head + */ +static inline void list_set_head(list_head_t *new_head, list_node_t *cyclist) +{ + list_add_range(cyclist, cyclist->prev, + list_node_first(new_head), list_node_last(new_head)); +} + +/** + * @fn static inline void list_move(list_node_t *prev, list_node_t *next, list_head_t *from) + * @brief Insert nodes of list @a from after @a prev and before @a next + * @param prev - a node after which nodes of @a from will be inserted + * @param next - a node before which nodes of @a from will be inserted + */ +static inline void list_move(list_node_t *prev, list_node_t *next, list_head_t *from) +{ + list_add_range(list_node_first(from), list_node_last(from), + prev, next); + list_init_head(from); +} + +#endif /* __TDATA_LIST_H__ */ +