/* * Lua RTOS, list data structure * * Copyright (C) 2015 - 2017 * IBEROXARXA SERVICIOS INTEGRALES, S.L. & CSS IBÉRICA, S.L. * * Author: Jaume Olivé (jolive@iberoxarxa.com / jolive@whitecatboard.org) * * All rights reserved. * * Permission to use, copy, modify, and distribute this software * and its documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice appear in all * copies and that both that the copyright notice and this * permission notice and warranty disclaimer appear in supporting * documentation, and that the name of the author not be used in * advertising or publicity pertaining to distribution of the * software without specific, written prior permission. * * The author disclaim all warranties with regard to this * software, including all implied warranties of merchantability * and fitness. In no event shall the author be liable for any * special, indirect or consequential damages or any damages * whatsoever resulting from loss of use, data or profits, whether * in an action of contract, negligence or other tortious action, * arising out of or in connection with the use or performance of * this software. */ #include "esp_attr.h" #include #include #include #include "list.h" #include "mutex.h" void list_init(struct list *list, int first_index) { // Create the mutex mtx_init(&list->mutex, NULL, NULL, 0); mtx_lock(&list->mutex); list->indexes = 0; list->free = NULL; list->index = NULL; list->first_index = first_index; mtx_unlock(&list->mutex); } int list_add(struct list *list, void *item, int *item_index) { struct list_index *index = NULL; struct list_index *indexa = NULL; int grow = 0; mtx_lock(&list->mutex); // 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 list_index *)malloc(sizeof(struct list_index) * 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 list_index) * (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 *item_index = index->index + list->first_index; mtx_unlock(&list->mutex); return 0; } int IRAM_ATTR list_get(struct list *list, int index, void **item) { struct list_index *cindex = NULL; int iindex; mtx_lock(&list->mutex); 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; } *item = cindex->item; mtx_unlock(&list->mutex); return 0; } int list_remove(struct list *list, int index, int destroy) { struct list_index *cindex = NULL; int iindex; mtx_lock(&list->mutex); // 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); } cindex->next = list->free; cindex->deleted = 1; list->free = cindex; mtx_unlock(&list->mutex); return 0; } int IRAM_ATTR list_first(struct list *list) { int index; int res = -1; mtx_lock(&list->mutex); for(index=0;index < list->indexes;index++) { if (!list->index[index].deleted) { res = index + list->first_index; break; } } mtx_unlock(&list->mutex); return res; } int IRAM_ATTR list_next(struct list *list, int index) { int res = -1; int iindex; mtx_lock(&list->mutex); // 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; } } mtx_unlock(&list->mutex); return res; } void list_destroy(struct list *list, int items) { int index; mtx_lock(&list->mutex); if (items) { for(index=0;index < list->indexes;index++) { if (!list->index[index].deleted) { free(list->index[index].item); } } } free(list->index); mtx_unlock(&list->mutex); mtx_destroy(&list->mutex); }