/* * Copyright (C) 2013-2017 Tobias Brunner * Copyright (C) 2007 Martin Willi * HSR Hochschule fuer Technik Rapperswil * * 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. See . * * 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. */ /** * @defgroup enumerator enumerator * @{ @ingroup collections */ #ifndef ENUMERATOR_H_ #define ENUMERATOR_H_ typedef struct enumerator_t enumerator_t; #include /** * Enumerator interface, allows enumeration over collections. */ struct enumerator_t { /** * Enumerate collection. * * The enumerate() method takes a variable number of pointer arguments * where the enumerated values get written to. * * @note Just assigning the generic enumerator_enumerate_default() function * that calls the enumerator's venumerate() method is usually enough. * * @param ... variable list of enumerated items, implementation dependent * @return TRUE if pointers returned */ bool (*enumerate)(enumerator_t *this, ...); /** * Enumerate collection. * * The venumerate() method takes a variable argument list containing * pointers where the enumerated values get written to. * * To simplify the implementation the VA_ARGS_VGET() macro may be used. * * @param args variable list of enumerated items, implementation dependent * @return TRUE if pointers returned */ bool (*venumerate)(enumerator_t *this, va_list args); /** * Destroy an enumerator_t instance. */ void (*destroy)(enumerator_t *this); }; /** * Generic implementation of enumerator_t::enumerate() that simply calls * the enumerator's venumerate() method. * * @param enumerator the enumerator * @param ... arguments passed to enumerate() */ bool enumerator_enumerate_default(enumerator_t *enumerator, ...); /** * Create an enumerator which enumerates over nothing * * @return an enumerator over no values */ enumerator_t* enumerator_create_empty(); /** * Create an enumerator which enumerates over a single item * * @param item item to enumerate * @param cleanup cleanup function called on destroy with the item * @return an enumerator over a single value */ enumerator_t *enumerator_create_single(void *item, void (*cleanup)(void *item)); /** * Create an enumerator over files/subdirectories in a directory. * * This enumerator_t.enumerate() function returns a (to the directory) relative * filename (as a char*), an absolute filename (as a char*) and a file status * (to a struct stat), which all may be NULL. "." and ".." entries are * skipped. * * Example: * * @code char *rel, *abs; struct stat st; enumerator_t *e; e = enumerator_create_directory("/tmp"); if (e) { while (e->enumerate(e, &rel, &abs, &st)) { if (S_ISDIR(st.st_mode) && *rel != '.') { printf("%s\n", abs); } } e->destroy(e); } @endcode * * @param path path of the directory * @return the directory enumerator, NULL on failure */ enumerator_t* enumerator_create_directory(const char *path); /** * Create an enumerator over files/directories matching a file pattern. * * This enumerator_t.enumerate() function returns the filename (as a char*), * and a file status (to a struct stat), which both may be NULL. * * Example: * * @code char *file; struct stat st; enumerator_t *e; e = enumerator_create_glob("/etc/ipsec.*.conf"); if (e) { while (e->enumerate(e, &file, &st)) { if (S_ISREG(st.st_mode)) { printf("%s\n", file); } } e->destroy(e); } @endcode * * @param pattern file pattern to match * @return the enumerator, NULL if not supported */ enumerator_t* enumerator_create_glob(const char *pattern); /** * Create an enumerator over tokens of a string. * * Tokens are separated by one of the characters in sep and trimmed by the * characters in trim. * * @param string string to parse * @param sep separator characters * @param trim characters to trim from tokens * @return enumerator over char* tokens */ enumerator_t* enumerator_create_token(const char *string, const char *sep, const char *trim); /** * Creates an enumerator which enumerates over enumerated enumerators :-). * * The outer enumerator is expected to return objects that, when passed to * inner_constructor, will create a new enumerator that will be enumerated until * completion (to this enumerator will the pointer arguments that are passed to * this enumerator be forwarded) at which point a new element from the outer * enumerator is requested to create a new inner enumerator. * * @param outer outer enumerator * @param inner_constructor constructor to create inner enumerator * @param data data to pass to each inner_constructor call * @param destructor destructor function to clean up data after use * @return the nested enumerator */ enumerator_t *enumerator_create_nested(enumerator_t *outer, enumerator_t *(*inner_constructor)(void *outer, void *data), void *data, void (*destructor)(void *data)); /** * Creates an enumerator which filters/maps output of another enumerator. * * The filter function receives the user supplied "data" followed by the * original enumerator, followed by the arguments passed to the outer * enumerator. It returns TRUE to deliver the values assigned to these * arguments to the caller of enumerate() and FALSE to end the enumeration. * Filtering items is simple as the filter function may just skip enumerated * items from the original enumerator. * * @param orig original enumerator to wrap, gets destroyed * @param filter filter function * @param data user data to supply to filter * @param destructor destructor function to clean up data after use * @return the filtered enumerator */ enumerator_t *enumerator_create_filter(enumerator_t *orig, bool (*filter)(void *data, enumerator_t *orig, va_list args), void *data, void (*destructor)(void *data)); /** * Create an enumerator wrapper which does a cleanup on destroy. * * @param wrapped wrapped enumerator * @param cleanup cleanup function called on destroy * @param data user data to supply to cleanup * @return the enumerator with cleanup */ enumerator_t *enumerator_create_cleaner(enumerator_t *wrapped, void (*cleanup)(void *data), void *data); #endif /** ENUMERATOR_H_ @}*/