diff options
Diffstat (limited to 'libiot/sys/list.c')
| -rw-r--r-- | libiot/sys/list.c | 429 |
1 files changed, 429 insertions, 0 deletions
diff --git a/libiot/sys/list.c b/libiot/sys/list.c new file mode 100644 index 0000000..ef965c8 --- /dev/null +++ b/libiot/sys/list.c @@ -0,0 +1,429 @@ +/* + * Copyright (C) 2015 - 2018, IBEROXARXA SERVICIOS INTEGRALES, S.L. + * Copyright (C) 2015 - 2018, Jaume Olivé Petrus (jolive@whitecatboard.org) + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, 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 the <organization> nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * * The WHITECAT logotype cannot be changed, you can remove it, but you + * cannot change it in any way. The WHITECAT logotype is: + * + * /\ /\ + * / \_____/ \ + * /_____________\ + * W H I T E C A T + * + * * Redistributions in binary form must retain all copyright notices printed + * to any local or remote output device. This include any reference to + * Lua RTOS, whitecatboard.org, Lua, and other copyright notices that may + * appear in the future. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 <COPYRIGHT HOLDER> 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. + * + * Lua RTOS list data structure + * + */ + +//#include "esp_attr.h" + +#include <errno.h> +#include <string.h> +#include <stdlib.h> + +#include <assert.h> + +#include "list.h" +#include "mutex.h" + +void lstinit(struct list *list, int first_index, uint8_t flags) { + // Create the mutex + mtx_init(&list->mutex, NULL, NULL, 0); + + mtx_lock(&list->mutex); + + list->indexes = 0; + list->free = NULL; + list->index = NULL; + list->last = NULL; + list->first_index = first_index; + list->flags = flags; + list->init = 1; + + mtx_unlock(&list->mutex); +} + +int lstadd(struct list *list, void *item, long *item_index) { + struct lstindex *index = NULL; + struct lstindex *indexa = NULL; + int grow = 0; + + mtx_lock(&list->mutex); + + if (list->flags & LIST_DEFAULT) { + // Get an index + if (list->free) { + // Get first free element + index = list->free; + list->free = index->next; + } else { + // Must grow index array + grow = 1; + } + + if (grow) { + // Increment index count + list->indexes++; + + // Create a new index array for allocate new index + indexa = (struct lstindex *)malloc(sizeof(struct lstindex) * list->indexes); + if (!indexa) { + mtx_unlock(&list->mutex); + return ENOMEM; + } + + if (list->index) { + // Copy current index array to new created + bcopy(list->index, indexa, sizeof(struct lstindex) * (list->indexes - 1)); + + // Free current index array + free(list->index); + } + + // Store new index array + list->index = indexa; + + // Current index + index = list->index + list->indexes - 1; + + // Initialize new index + index->index = list->indexes - 1; + } + + index->next = NULL; + index->item = item; + index->deleted = 0; + + // Return index + if (item_index) { + *item_index = index->index + list->first_index; + } + } else if (list->flags & LIST_NOT_INDEXED) { + // Create a new element + index = (struct lstindex *)calloc(1, sizeof(struct lstindex)); + if (!index) { + return ENOMEM; + } + + index->item = item; + + if ((list->index == NULL) && (list->last == NULL)) { + // First element + list->index = index; + } else { + // Almost there is one element in list + assert(list->last != NULL); + + list->last->next = index; + index->previous = list->last; + } + + list->last = index; + + if (item_index) { + *item_index = (long)item; + } + } + + mtx_unlock(&list->mutex); + + return 0; +} + +int lstget(struct list *list, long index, void **item) { + struct lstindex *cindex = NULL; + long iindex; + + mtx_lock(&list->mutex); + + if (list->flags & LIST_DEFAULT) { + if (!list->indexes) { + mtx_unlock(&list->mutex); + return EINVAL; + } + + // Check index + if (index < list->first_index) { + mtx_unlock(&list->mutex); + return EINVAL; + } + + // Get new internal index + iindex = index - list->first_index; + + // Test for a valid index + if (iindex > list->indexes) { + mtx_unlock(&list->mutex); + return EINVAL; + } + + cindex = list->index + iindex; + + if (cindex->deleted) { + mtx_unlock(&list->mutex); + return EINVAL; + } + } else if (list->flags & LIST_NOT_INDEXED) { + cindex = list->index; + + while (cindex) { + if (cindex->item == (void *)index) { + *item = cindex->item; + break; + } + + cindex = cindex->next; + } + + if (!cindex) { + mtx_unlock(&list->mutex); + return EINVAL; + } + } + + *item = cindex->item; + + mtx_unlock(&list->mutex); + + return 0; +} + +int lstremovec(struct list *list, long index, int destroy, bool compact) { + struct lstindex *cindex = NULL; + long iindex; + + mtx_lock(&list->mutex); + + if (list->flags & LIST_DEFAULT) { + // Check index + if (index < list->first_index) { + mtx_unlock(&list->mutex); + return EINVAL; + } + + // Get new internal index + iindex = index - list->first_index; + + // Test for a valid index + if ((iindex < 0) || (iindex > list->indexes)) { + mtx_unlock(&list->mutex); + return EINVAL; + } + + cindex = &list->index[iindex]; + + if (destroy) { + free(cindex->item); + } + + if (compact) { + bcopy(&list->index[iindex+1], &list->index[iindex], sizeof(struct lstindex) * (list->indexes - iindex - 1)); + iindex = list->indexes-1; + cindex = &list->index[iindex]; + } + + cindex->next = list->free; + cindex->deleted = 1; + list->free = cindex; + } else if (list->flags & LIST_NOT_INDEXED) { + cindex = list->index; + + while (cindex) { + if (cindex->item == (void *)index) { + if (cindex->next) { + cindex->next->previous = cindex->previous; + } else { + list->last = cindex->previous; + } + + if (cindex->previous) { + cindex->previous->next = cindex->next; + } else { + list->index = cindex->next; + } + + if (destroy) { + free(cindex->item); + } + + free(cindex); + + break; + } + + cindex = cindex->next; + } + + } + + mtx_unlock(&list->mutex); + + return 0; +} + +int lstremove(struct list *list, long index, int destroy) { + return lstremovec(list, index, destroy, false); +} + +int lstfirst(struct list *list) { + long index; + long res = -1; + + mtx_lock(&list->mutex); + + if (list->flags & LIST_DEFAULT) { + for(index=0;index < list->indexes;index++) { + if (!list->index[index].deleted) { + res = index + list->first_index; + break; + } + } + } else if (list->flags & LIST_NOT_INDEXED) { + if ((list->index != NULL) && (list->last != NULL)) { + res = (long)list->index; + } + } + + mtx_unlock(&list->mutex); + + return res; +} + +int lstlast(struct list *list) { + long index; + long res = -1; + + mtx_lock(&list->mutex); + + if (list->flags & LIST_DEFAULT) { + for(index = list->indexes - 1;index >= 0;index--) { + if (!list->index[index].deleted) { + res = index + list->first_index; + break; + } + } + } else if (list->flags & LIST_NOT_INDEXED) { + if ((list->index != NULL) && (list->last != NULL)) { + res = (long)list->last; + } + } + + mtx_unlock(&list->mutex); + + return res; +} + +int lstnext(struct list *list, long index) { + long res = -1; + long iindex; + + mtx_lock(&list->mutex); + + if (list->flags & LIST_DEFAULT) { + // Check index + if (index < list->first_index) { + mtx_unlock(&list->mutex); + return -1; + } + + // Get new internal index + iindex = index - list->first_index + 1; + + // Get next non deleted item on list + for(;iindex < list->indexes;iindex++) { + if (!list->index[iindex].deleted) { + res = iindex + list->first_index; + break; + } + } + } else if (list->flags & LIST_NOT_INDEXED) { + struct lstindex *cindex = NULL; + + cindex = list->index; + + while (cindex) { + if (cindex->item == (void *)index) { + if (cindex->next) { + res = (long)cindex->next; + } + + break; + } + + cindex = cindex->next; + } + } + + mtx_unlock(&list->mutex); + + return res; +} + +void lstdestroy(struct list *list, int items) { + long index; + + if (!list->init) return; + + mtx_lock(&list->mutex); + + if (list->flags & LIST_DEFAULT) { + if (items) { + for(index=0;index < list->indexes;index++) { + if (!list->index[index].deleted) { + free(list->index[index].item); + } + } + } + + if (0 != list->index) { + free(list->index); + list->index = 0; + } + + } else if (list->flags & LIST_NOT_INDEXED) { + struct lstindex *cindex = NULL; + struct lstindex *pindex = NULL; + + cindex = list->index; + + while (cindex) { + pindex = cindex; + cindex = cindex->next; + + free(pindex); + } + } + + list->init = 0; + + mtx_unlock(&list->mutex); + mtx_destroy(&list->mutex); +} |
