/* Yash: yet another shell */ /* plist.h: modifiable list of pointers */ /* (C) 2007-2010 magicant */ /* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef YASH_PLIST_H #define YASH_PLIST_H #include #define Size_max ((size_t) -1) // = SIZE_MAX extern size_t plcount(void *const *list) __attribute__((pure,nonnull)); static inline void **pldup(void *const *array, void *copy(const void *p)) __attribute__((malloc,warn_unused_result,nonnull(2))); extern void **plndup( void *const *array, size_t count, void *copy(const void *p)) __attribute__((malloc,warn_unused_result,nonnull(3))); extern void plfree(void **ary, void freer(void *elem)); typedef struct plist_T { void **contents; size_t length, maxlength; } plist_T; static inline plist_T *pl_init(plist_T *list) __attribute__((nonnull)); static inline plist_T *pl_initwith(plist_T *list, void **array, size_t length) __attribute__((nonnull)); extern plist_T *pl_initwithmax(plist_T *list, size_t max) __attribute__((nonnull)); static inline void pl_destroy(plist_T *list) __attribute__((nonnull)); static inline void **pl_toary(plist_T *list) __attribute__((nonnull)); extern plist_T *pl_setmax(plist_T *list, size_t newmax) __attribute__((nonnull)); extern plist_T *pl_ensuremax(plist_T *list, size_t max) __attribute__((nonnull)); extern plist_T *pl_clear(plist_T *list, void freer(void *elem)) __attribute__((nonnull(1))); extern plist_T *pl_replace( plist_T *restrict list, size_t i, size_t ln, void *const *restrict a, size_t an) __attribute__((nonnull)); static inline plist_T *pl_ninsert( plist_T *restrict list, size_t i, void *const *restrict a, size_t n) __attribute__((nonnull)); static inline plist_T *pl_insert( plist_T *restrict list, size_t i, void *const *restrict a) __attribute__((nonnull)); static inline plist_T *pl_ncat( plist_T *restrict list, void *const *restrict a, size_t n) __attribute__((nonnull)); static inline plist_T *pl_cat( plist_T *restrict list, void *const *restrict a) __attribute__((nonnull)); static inline plist_T *pl_remove(plist_T *list, size_t i, size_t n) __attribute__((nonnull)); extern plist_T *pl_add(plist_T *list, const void *p) __attribute__((nonnull(1))); #ifndef PLIST_DEFAULT_MAX #define PLIST_DEFAULT_MAX 7 #endif /* Clones the specified NULL-terminated array of pointers. * Each pointer element is passed to function `copy' and the return value is * assigned to a new array element. * If `array' is NULL, simply returns NULL. */ /* `xstrdup' and `copyaswcs' are suitable for `copy'. */ void **pldup(void *const *array, void *copy(const void *p)) { return plndup(array, Size_max, copy); } /* Initializes the specified pointer list as a new empty list. */ plist_T *pl_init(plist_T *list) { return pl_initwithmax(list, PLIST_DEFAULT_MAX); } /* Initializes the specified pointer list with the specified array. * `array' must be a NULL-terminated array of pointers to void containing * exactly `length' elements and must be allocated by malloc. * `array' must not be modified or freed after the call to this function. */ plist_T *pl_initwith(plist_T *list, void **array, size_t length) { list->contents = array; list->length = list->maxlength = length; #ifdef assert assert(list->contents[list->length] == NULL); #endif return list; } /* Frees the specified pointer list. * Note that the list elements are not `free'd in this function. */ void pl_destroy(plist_T *list) { free(list->contents); } /* Frees the specified pointer list and returns the contents. * The caller must `free' the return value and its elements if needed. * If all the elements are pointers to byte strings, the return value can be * safely cast to (char **). */ void **pl_toary(plist_T *list) { return list->contents; } /* Inserts the first `n' elements of array `a' at offset `i' in pointer list * `list'. * NULL elements in `a' are not treated specially. * If (list->length <= i), the array elements are appended to the list. * Array `a' must not be part of `list->contents'. */ plist_T *pl_ninsert( plist_T *restrict list, size_t i, void *const *restrict a, size_t n) { return pl_replace(list, i, 0, a, n); } /* Inserts the elements of array `a' at offset `i' in pointer list `list'. * Array `a' must be terminated by a NULL element, which is not inserted. * If (list->length <= i), the array elements are appended to the list. * Array `a' must not be a part of `list->contents'. */ plist_T *pl_insert(plist_T *restrict list, size_t i, void *const *restrict a) { return pl_replace(list, i, 0, a, plcount(a)); } /* Appends the first `n' elements of array `a' to pointer list `list'. * NULL elements in `a' are not treated specially. * Array `a' must not be a part of `list->contents'. */ plist_T *pl_ncat(plist_T *restrict list, void *const *restrict a, size_t n) { return pl_replace(list, Size_max, 0, a, n); } /* Inserts the elements of array `a' to pointer list `list'. * Array `a' must be terminated by a NULL element, which is not inserted. * Array `a' must not be a part of `list->contents'. */ plist_T *pl_cat(plist_T *restrict list, void *const *restrict a) { return pl_replace(list, Size_max, 0, a, plcount(a)); } /* Removes the `n' elements at offset `i' in pointer list `list'. * It's the caller's responsibility to free the objects pointed by the removed * pointers. */ plist_T *pl_remove(plist_T *list, size_t i, size_t n) { return pl_replace(list, i, n, (void *[]) { NULL, }, 0); } #undef Size_max #endif /* YASH_PLIST_H */ /* vim: set ts=8 sts=4 sw=4 noet tw=80: */