diff options
Diffstat (limited to 'src/data/list.c')
| -rw-r--r-- | src/data/list.c | 458 |
1 files changed, 458 insertions, 0 deletions
diff --git a/src/data/list.c b/src/data/list.c new file mode 100644 index 0000000..00e5a72 --- /dev/null +++ b/src/data/list.c @@ -0,0 +1,458 @@ +/*:* + *: File: ./src/data/list.c + *: A simple interpreter + *: + *: WWW : http://fype.buetow.org + *: E-Mail : fype@dev.buetow.org + *: + *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net) + *: All rights reserved. + *: + *: Redistribution and use in source and binary forms, with or without modi- + *: fication, are permitted provided that the following conditions are met: + *: * Redistributions of source code must retain the above copyright + *: notice, this list of conditions and the following disclaimer. + *: * Redistributions in binary form must reproduce the above copyright + *: notice, this list of conditions and the following disclaimer in the + *: documentation and/or other materials provided with the distribution. + *: * Neither the name of P. B. Labs nor the names of its contributors may + *: be used to endorse or promote products derived from this software + *: without specific prior written permission. + *: + *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR + *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT, + *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + *: POSSIBILITY OF SUCH DAMAGE. + *:*/ + +#include "list.h" + +List* +list_new() { + List *p_list = malloc(sizeof(List)); + + p_list->p_first = NULL; + p_list->p_last = NULL; + p_list->i_size = 0; + + return p_list; +} + +void +_list_copy_cb(void *p_void1, void *p_cpy) { + ListElem *p_elem = p_void1; + list_add_back(p_cpy, p_elem->p_val); +} + +List* +list_copy(List *p_list) { + List *p_list_cpy = list_new(); + list_iterate2(p_list, _list_copy_cb, p_list_cpy); + return (p_list_cpy); +} + +List* +list_copy2(List *p_list, void* (*func)(void *)) { + List *p_list_cpy = list_new(); + ListIterator *p_iter = listiterator_new(p_list); + + while (listiterator_has_next(p_iter)) + list_add_back(p_list_cpy, (*func) (listiterator_next(p_iter))); + + listiterator_delete(p_iter); + + return (p_list_cpy); +} + +ListElem* +listelem_new() { + ListElem *p_elem = malloc(sizeof(ListElem)); + + p_elem->p_next = NULL; + p_elem->p_prev = NULL; + p_elem->p_val = NULL; + return p_elem; +} + +_Bool +list_empty(List *p_list) { + return p_list->i_size == 0; +} + +void +list_concat_front(List *p_list1, List *p_list2) { + if (!p_list1 || !p_list2 || !p_list2->p_last) + return; + + ListElem *p_first = p_list1->p_first; + + if (!p_first) { + p_list1->p_first = p_list2->p_first; + p_list1->p_last = p_list2->p_last; + + } else { + p_list2->p_last->p_next = p_list1->p_first; + p_list1->p_first->p_prev = p_list2->p_last; + p_list1->p_first = p_list2->p_first; + } + + p_list1->i_size += p_list2->i_size; + p_list2->i_size = 0; + p_list2->p_first = NULL; + p_list2->p_last = NULL; +} + +void +list_concat_back(List *p_list1, List *p_list2) { + if (!p_list1 || !p_list2 || !p_list2->p_first) + return; + + ListElem *p_last = p_list1->p_last; + + if (!p_last) { + p_list1->p_first = p_list2->p_first; + p_list1->p_last = p_list2->p_last; + + } else { + p_last->p_next = p_list2->p_first; + p_list2->p_first->p_prev = p_last; + p_list1->p_last = p_list2->p_last; + } + + p_list1->i_size += p_list2->i_size; + p_list2->i_size = 0; + p_list2->p_first = NULL; + p_list2->p_last = NULL; + +} + +void +list_add_front(List *p_list, void *p_val) { + ListElem *p_elem = listelem_new(); + + p_elem->p_val = p_val; + if (p_list->p_first == NULL) { + p_list->p_first = p_elem; + p_list->p_last = p_elem; + + } else { + p_elem->p_next = p_list->p_first; + p_list->p_first->p_prev = p_elem; + p_list->p_first = p_elem; + } + + ++p_list->i_size; +} + +void +list_add_back(List *p_list, void *p_val) { + ListElem *p_elem = listelem_new(); + + p_elem->p_val = p_val; + if (p_list->p_last == NULL) { + p_list->p_first = p_elem; + p_list->p_last = p_elem; + + } else { + p_elem->p_prev = p_list->p_last; + p_list->p_last->p_next = p_elem; + p_list->p_last = p_elem; + } + + ++p_list->i_size; +} + +void* +list_remove_front(List *p_list) { + if (list_empty(p_list)) + return NULL; + + ListElem *p_elem = p_list->p_first; + p_list->p_first = p_elem->p_next; + + if (p_list->p_first) + p_list->p_first->p_prev = NULL; + + void *p_val = p_elem->p_val; + free(p_elem); + + --p_list->i_size; + + return p_val; +} + +void* +list_remove_back(List *p_list) { + if (list_empty(p_list)) + return NULL; + + ListElem *p_elem = p_list->p_last; + p_list->p_last = p_elem->p_prev; + p_list->p_last->p_next = NULL; + + void *p_val = p_elem->p_val; + free(p_elem); + + --p_list->i_size; + + return p_val; +} + +void +list_clear(List *p_list) { + for (;!list_empty(p_list); list_remove_front(p_list)); +} + +void +list_clear_and_free_vals(List *p_list) { + void *p_void = NULL; + for (;!list_empty(p_list); p_void = list_remove_front(p_list)) + if (p_void) + free(p_void); +} + +void +list_delete(List *p_list) { + list_clear(p_list); + free(p_list); +} + +void +list_delete_cb(void *p_list) { + list_delete(p_list); +} + +void +list_delete_and_free_vals(List *p_list) { + list_clear_and_free_vals(p_list); + free(p_list); +} + +unsigned +list_size(List *p_list) { + return p_list->i_size; +} + +void +list_iterate(List *p_list, void (*func)(void *)) { + ListElem *p_elem = p_list->p_first; + + while (p_elem) { + (*func) (p_elem->p_val); + p_elem = p_elem->p_next; + } +} + +void +list_iterate2(List *p_list, void (*func)(void *, void *), void *p_void) { + ListElem *p_elem = p_list->p_first; + + while (p_elem) { + (*func) (p_elem->p_val, p_void); + p_elem = p_elem->p_next; + } +} + +void +list_iterate2_ptr(List *p_list, void (*func)(void *, void *), void *p_void) { + ListElem *p_elem = p_list->p_first; + + while (p_elem) { + (*func) (&p_elem->p_val, p_void); + p_elem = p_elem->p_next; + } +} + +void +list_iterate3(List *p_list, void (*func)(void *, void *, void *), void *p_void1, void *p_void2) { + ListElem *p_elem = p_list->p_first; + + while (p_elem) { + (*func) (p_elem->p_val, p_void1, p_void2); + p_elem = p_elem->p_next; + } +} + +void +list_iterate3_ptr(List *p_list, void (*func)(void *, void *, void *), + void *p_void1, void *p_void2) { + ListElem *p_elem = p_list->p_first; + + while (p_elem) { + (*func) (&p_elem->p_val, p_void1, p_void2); + p_elem = p_elem->p_next; + } +} + +void +list_remove_elem(List *p_list, ListElem *p_elem_remove) { + ListElem *p_elem = p_list->p_first; + + if (p_elem == p_elem_remove) { + p_list->p_first = p_elem->p_next; + p_list->p_first->p_prev = NULL; + --p_list->i_size; + return; + } + + while ((p_elem = p_elem->p_next)) { + if (p_elem == p_elem_remove) { + ListElem *p_prev = p_elem->p_prev; + ListElem *p_next = p_elem->p_next; + + if (p_next) { + p_prev->p_next = p_next; + p_next->p_prev = p_prev; + + } else { + p_prev->p_next = NULL; + p_list->p_last = p_prev; + } + + --p_list->i_size; + free(p_elem_remove); + return; + } + } +} + +ListIterator* +listiterator_new(List *p_list) { + if (!p_list) + return NULL; + + ListIterator *p_iter = malloc(sizeof(ListIterator)); + + p_iter->p_cur = p_list->p_first; + p_iter->b_reverse = false; + p_iter->func = NULL; + + return p_iter; +} + +ListIterator* +listiterator_new_reverse(List *p_list) { + if (!p_list) + return NULL; + + ListIterator *p_iter = listiterator_new(p_list); + + p_iter->p_cur = p_list->p_last; + p_iter->b_reverse = true; + + return p_iter; +} + +void +listiterator_delete(ListIterator *p_iter) { + if (p_iter) + free(p_iter); +} + +void* +listiterator_next(ListIterator *p_iter) { + if (p_iter->p_cur) { + void *p_ret = p_iter->p_cur->p_val; + + if (p_iter->b_reverse) + p_iter->p_cur = p_iter->p_cur->p_prev; + + else + p_iter->p_cur = p_iter->p_cur->p_next; + + if (p_iter->func) + return ((*p_iter->func) (p_ret)); + + else + return (p_ret); + } + + return (NULL); +} + +void* +listiterator_prev(ListIterator *p_iter) { + if (p_iter->p_cur) { + void *p_ret = p_iter->p_cur->p_val; + + if (!p_iter->b_reverse) + p_iter->p_cur = p_iter->p_cur->p_prev; + + else + p_iter->p_cur = p_iter->p_cur->p_next; + + if (p_iter->func) + return ((*p_iter->func) (p_ret)); + + else + return (p_ret); + } + + return (NULL); +} + +void* +listiterator_current(ListIterator *p_iter) { + if (p_iter->p_cur) + return (p_iter->p_cur->p_val); + + return (NULL); +} + +void* +listiterator_end(ListIterator *p_iter) { + void *p_ret = NULL; + + while (listiterator_has_next(p_iter)) + p_ret = listiterator_next(p_iter); + + return (p_ret); +} + +ListElem* +listiterator_next_elem(ListIterator *p_iter) { + if (p_iter->p_cur) { + ListElem *p_ret = p_iter->p_cur; + + p_iter->p_cur = p_iter->b_reverse ? + p_iter->p_cur->p_prev : p_iter->p_cur->p_next; + + return (p_ret); + } + + return (NULL); +} + +_Bool +listiterator_has_next(ListIterator *p_iter) { + return (p_iter->p_cur != NULL ? true : false); +} + + +ListIteratorState* +listiterator_get_state(ListIterator *p_iter) { + ListIteratorState *p_state = malloc(sizeof(ListIteratorState)); + + p_state->p_cur = p_iter->p_cur; + p_state->b_reverse = p_iter->b_reverse; + + return (p_state); +} + +void +listiterator_set_state(ListIterator *p_iter, ListIteratorState *p_state) { + p_iter->p_cur = p_state->p_cur; + p_iter->b_reverse = p_state->b_reverse; +} + +void +listiteratorstate_delete(ListIteratorState *p_state) { + free(p_state); +} |
