/*
- * Copyright (c) 2007,2008 Mij <mij@bitchx.it>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS 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, DIRECT, 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.
- */
+* Copyright (c) 2007,2008 Mij <mij@bitchx.it>
+*
+* Permission to use, copy, modify, and distribute this software for any
+* purpose with or without fee is hereby granted, provided that the above
+* copyright notice and this permission notice appear in all copies.
+*
+* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS 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, DIRECT, 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.
+*/
/*
- * SimCList library. See http://mij.oltrelinux.com/devel/simclist
- */
+* SimCList library. See http://mij.oltrelinux.com/devel/simclist
+*/
#ifndef SIMCLIST_H
#include <sys/types.h>
#ifndef SIMCLIST_NO_DUMPRESTORE
-#ifndef _WIN32
-#include <sys/time.h> /* list_dump_info_t's struct timeval */
-#else
-#include <time.h>
-#endif
+# ifndef _WIN32
+# include <sys/time.h> /* list_dump_info_t's struct timeval */
+# else
+# include <time.h>
+# endif
#endif
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
/* "inline" and "restrict" are keywords */
#else
-#define inline /* inline */
-#define restrict /* restrict */
+# define inline /* inline */
+# define restrict /* restrict */
#endif
/**
- * Type representing list hashes.
- *
- * This is a signed integer value.
- */
+ * Type representing list hashes.
+ *
+ * This is a signed integer value.
+ */
typedef int32_t list_hash_t;
#ifndef SIMCLIST_NO_DUMPRESTORE
typedef struct {
- uint16_t version; /* dump version */
- struct timeval timestamp; /* when the list has been dumped, seconds since UNIX epoch */
+ uint16_t version; /* dump version */
+ struct timeval timestamp; /* when the list has been dumped, seconds since UNIX epoch */
uint32_t list_size;
uint32_t list_numels;
- list_hash_t list_hash; /* hash of the list when dumped, or 0 if invalid */
+ list_hash_t list_hash; /* hash of the list when dumped, or 0 if invalid */
uint32_t dumpsize;
- int consistent; /* 1 if the dump is verified complete/consistent; 0 otherwise */
+ int consistent; /* 1 if the dump is verified complete/consistent; 0 otherwise */
} list_dump_info_t;
#endif
/**
- * a comparator of elements.
- *
- * A comparator of elements is a function that:
- * -# receives two references to elements a and b
- * -# returns {<0, 0, >0} if (a > b), (a == b), (a < b) respectively
- *
- * It is responsability of the function to handle possible NULL values.
- */
- typedef int (*element_comparator) (const void *a, const void *b);
-
- /**
- * a seeker of elements.
- *
- * An element seeker is a function that:
- * -# receives a reference to an element el
- * -# receives a reference to some indicator data
- * -# returns non-0 if the element matches the indicator, 0 otherwise
- *
- * It is responsability of the function to handle possible NULL values in any
- * argument.
- */
- typedef int (*element_seeker) (const void *el, const void *indicator);
-
- /**
- * an element lenght meter.
- *
- * An element meter is a function that:
- * -# receives the reference to an element el
- * -# returns its size in bytes
- *
- * It is responsability of the function to handle possible NULL values.
- */
- typedef size_t (*element_meter) (const void *el);
-
- /**
- * a function computing the hash of elements.
- *
- * An hash computing function is a function that:
- * -# receives the reference to an element el
- * -# returns a hash value for el
- *
- * It is responsability of the function to handle possible NULL values.
- */
- typedef list_hash_t (*element_hash_computer) (const void *el);
-
- /**
- * a function for serializing an element.
- *
- * A serializer function is one that gets a reference to an element,
- * and returns a reference to a buffer that contains its serialization
- * along with the length of this buffer.
- * It is responsability of the function to handle possible NULL values,
- * returning a NULL buffer and a 0 buffer length.
- *
- * These functions have 3 goals:
- * -# "freeze" and "flatten" the memory representation of the element
- * -# provide a portable (wrt byte order, or type size) representation of the element, if the dump can be used on different sw/hw combinations
- * -# possibly extract a compressed representation of the element
- *
- * @param el reference to the element data
- * @param serialize_buffer reference to fill with the length of the buffer
- * @return reference to the buffer with the serialized data
- */
- typedef void *(*element_serializer) (const void *restrict el, uint32_t *restrict serializ_len);
-
- /**
- * a function for un-serializing an element.
- *
- * An unserializer function accomplishes the inverse operation of the
- * serializer function. An unserializer function is one that gets a
- * serialized representation of an element and turns it backe to the original
- * element. The serialized representation is passed as a reference to a buffer
- * with its data, and the function allocates and returns the buffer containing
- * the original element, and it sets the length of this buffer into the
- * integer passed by reference.
- *
- * @param data reference to the buffer with the serialized representation of the element
- * @param data_len reference to the location where to store the length of the data in the buffer returned
- * @return reference to a buffer with the original, unserialized representation of the element
- */
- typedef void *(*element_unserializer) (const void *restrict data, uint32_t *restrict data_len);
+ * a comparator of elements.
+ *
+ * A comparator of elements is a function that:
+ * -# receives two references to elements a and b
+ * -# returns {<0, 0, >0} if (a > b), (a == b), (a < b) respectively
+ *
+ * It is responsability of the function to handle possible NULL values.
+ */
+ typedef int(*element_comparator)(const void *a, const void *b);
+
+ /**
+ * a seeker of elements.
+ *
+ * An element seeker is a function that:
+ * -# receives a reference to an element el
+ * -# receives a reference to some indicator data
+ * -# returns non-0 if the element matches the indicator, 0 otherwise
+ *
+ * It is responsability of the function to handle possible NULL values in any
+ * argument.
+ */
+ typedef int(*element_seeker)(const void *el, const void *indicator);
+
+ /**
+ * an element lenght meter.
+ *
+ * An element meter is a function that:
+ * -# receives the reference to an element el
+ * -# returns its size in bytes
+ *
+ * It is responsability of the function to handle possible NULL values.
+ */
+ typedef size_t(*element_meter)(const void *el);
+
+ /**
+ * a function computing the hash of elements.
+ *
+ * An hash computing function is a function that:
+ * -# receives the reference to an element el
+ * -# returns a hash value for el
+ *
+ * It is responsability of the function to handle possible NULL values.
+ */
+ typedef list_hash_t(*element_hash_computer)(const void *el);
+
+ /**
+ * a function for serializing an element.
+ *
+ * A serializer function is one that gets a reference to an element,
+ * and returns a reference to a buffer that contains its serialization
+ * along with the length of this buffer.
+ * It is responsability of the function to handle possible NULL values,
+ * returning a NULL buffer and a 0 buffer length.
+ *
+ * These functions have 3 goals:
+ * -# "freeze" and "flatten" the memory representation of the element
+ * -# provide a portable (wrt byte order, or type size) representation of the element, if the dump can be used on different sw/hw combinations
+ * -# possibly extract a compressed representation of the element
+ *
+ * @param el reference to the element data
+ * @param serialize_buffer reference to fill with the length of the buffer
+ * @return reference to the buffer with the serialized data
+ */
+ typedef void *(*element_serializer)(const void *restrict el, uint32_t *restrict serializ_len);
+
+ /**
+ * a function for un-serializing an element.
+ *
+ * An unserializer function accomplishes the inverse operation of the
+ * serializer function. An unserializer function is one that gets a
+ * serialized representation of an element and turns it backe to the original
+ * element. The serialized representation is passed as a reference to a buffer
+ * with its data, and the function allocates and returns the buffer containing
+ * the original element, and it sets the length of this buffer into the
+ * integer passed by reference.
+ *
+ * @param data reference to the buffer with the serialized representation of the element
+ * @param data_len reference to the location where to store the length of the data in the buffer returned
+ * @return reference to a buffer with the original, unserialized representation of the element
+ */
+ typedef void *(*element_unserializer)(const void *restrict data, uint32_t *restrict data_len);
/* [private-use] list entry -- olds actual user datum */
struct list_entry_s {
} list_t;
/**
- * initialize a list object for use.
- *
- * @param l must point to a user-provided memory location
- * @return 0 for success. -1 for failure
- */
- KS_DECLARE(int) list_init(list_t *restrict l);
-
- /**
- * completely remove the list from memory.
- *
- * This function is the inverse of list_init(). It is meant to be called when
- * the list is no longer going to be used. Elements and possible memory taken
- * for internal use are freed.
- *
- * @param l list to destroy
- */
- KS_DECLARE(void) list_destroy(list_t *restrict l);
-
- /**
- * set the comparator function for list elements.
- *
- * Comparator functions are used for searching and sorting. If NULL is passed
- * as reference to the function, the comparator is disabled.
- *
- * @param l list to operate
- * @param comparator_fun pointer to the actual comparator function
- * @return 0 if the attribute was successfully set; -1 otherwise
- *
- * @see element_comparator()
- */
- KS_DECLARE(int) list_attributes_comparator(list_t *restrict l, element_comparator comparator_fun);
-
- /**
- * set a seeker function for list elements.
- *
- * Seeker functions are used for finding elements. If NULL is passed as reference
- * to the function, the seeker is disabled.
- *
- * @param l list to operate
- * @param seeker_fun pointer to the actual seeker function
- * @return 0 if the attribute was successfully set; -1 otherwise
- *
- * @see element_seeker()
- */
- KS_DECLARE(int) list_attributes_seeker(list_t *restrict l, element_seeker seeker_fun);
-
- /**
- * require to free element data when list entry is removed (default: don't free).
- *
- * [ advanced preference ]
- *
- * By default, when an element is removed from the list, it disappears from
- * the list by its actual data is not free()d. With this option, every
- * deletion causes element data to be freed.
- *
- * It is responsability of this function to correctly handle NULL values, if
- * NULL elements are inserted into the list.
- *
- * @param l list to operate
- * @param metric_fun pointer to the actual metric function
- * @param copy_data 0: do not free element data (default); non-0: do free
- * @return 0 if the attribute was successfully set; -1 otherwise
- *
- * @see element_meter()
- * @see list_meter_int8_t()
- * @see list_meter_int16_t()
- * @see list_meter_int32_t()
- * @see list_meter_int64_t()
- * @see list_meter_uint8_t()
- * @see list_meter_uint16_t()
- * @see list_meter_uint32_t()
- * @see list_meter_uint64_t()
- * @see list_meter_float()
- * @see list_meter_double()
- * @see list_meter_string()
- */
- KS_DECLARE(int) list_attributes_copy(list_t *restrict l, element_meter metric_fun, int copy_data);
-
- /**
- * set the element hash computing function for the list elements.
- *
- * [ advanced preference ]
- *
- * An hash can be requested depicting the list status at a given time. An hash
- * only depends on the elements and their order. By default, the hash of an
- * element is only computed on its reference. With this function, the user can
- * set a custom function computing the hash of an element. If such function is
- * provided, the list_hash() function automatically computes the list hash using
- * the custom function instead of simply referring to element references.
- *
- * @param l list to operate
- * @param hash_computer_fun pointer to the actual hash computing function
- * @return 0 if the attribute was successfully set; -1 otherwise
- *
- * @see element_hash_computer()
- */
- KS_DECLARE(int) list_attributes_hash_computer(list_t *restrict l, element_hash_computer hash_computer_fun);
-
- /**
- * set the element serializer function for the list elements.
- *
- * [ advanced preference ]
- *
- * Serialize functions are used for dumping the list to some persistent
- * storage. The serializer function is called for each element; it is passed
- * a reference to the element and a reference to a size_t object. It will
- * provide (and return) the buffer with the serialization of the element and
- * fill the size_t object with the length of this serialization data.
- *
- * @param l list to operate
- * @param serializer_fun pointer to the actual serializer function
- * @return 0 if the attribute was successfully set; -1 otherwise
- *
- * @see element_serializer()
- * @see list_dump_filedescriptor()
- * @see list_restore_filedescriptor()
- */
- KS_DECLARE(int) list_attributes_serializer(list_t *restrict l, element_serializer serializer_fun);
-
- /**
- * set the element unserializer function for the list elements.
- *
- * [ advanced preference ]
- *
- * Unserialize functions are used for restoring the list from some persistent
- * storage. The unserializer function is called for each element segment read
- * from the storage; it is passed the segment and a reference to an integer.
- * It shall allocate and return a buffer compiled with the resumed memory
- * representation of the element, and set the integer value to the length of
- * this buffer.
- *
- * @param l list to operate
- * @param unserializer_fun pointer to the actual unserializer function
- * @return 0 if the attribute was successfully set; -1 otherwise
- *
- * @see element_unserializer()
- * @see list_dump_filedescriptor()
- * @see list_restore_filedescriptor()
- */
- KS_DECLARE(int) list_attributes_unserializer(list_t *restrict l, element_unserializer unserializer_fun);
-
- /**
- * append data at the end of the list.
- *
- * This function is useful for adding elements with a FIFO/queue policy.
- *
- * @param l list to operate
- * @param data pointer to user data to append
- *
- * @return 1 for success. < 0 for failure
- */
- KS_DECLARE(int) list_append(list_t *restrict l, const void *data);
-
- /**
- * insert data in the head of the list.
- *
- * This function is useful for adding elements with a LIFO/Stack policy.
- *
- * @param l list to operate
- * @param data pointer to user data to append
- *
- * @return 1 for success. < 0 for failure
- */
- KS_DECLARE(int) list_prepend(list_t *restrict l, const void *restrict data);
-
- /**
- * extract the element in the top of the list.
- *
- * This function is for using a list with a FIFO/queue policy.
- *
- * @param l list to operate
- * @return reference to user datum, or NULL on errors
- */
- KS_DECLARE(void *) list_fetch(list_t *restrict l);
-
- /**
- * retrieve an element at a given position.
- *
- * @param l list to operate
- * @param pos [0,size-1] position index of the element wanted
- * @return reference to user datum, or NULL on errors
- */
- KS_DECLARE(void *) list_get_at(const list_t *restrict l, unsigned int pos);
-
- /**
- * return the maximum element of the list.
- *
- * @warning Requires a comparator function to be set for the list.
- *
- * Returns the maximum element with respect to the comparator function output.
- *
- * @see list_attributes_comparator()
- *
- * @param l list to operate
- * @return the reference to the element, or NULL
- */
- KS_DECLARE(void *) list_get_max(const list_t *restrict l);
-
- /**
- * return the minimum element of the list.
- *
- * @warning Requires a comparator function to be set for the list.
- *
- * Returns the minimum element with respect to the comparator function output.
- *
- * @see list_attributes_comparator()
- *
- * @param l list to operate
- * @return the reference to the element, or NULL
- */
- KS_DECLARE(void *) list_get_min(const list_t *restrict l);
-
- /**
- * retrieve and remove from list an element at a given position.
- *
- * @param l list to operate
- * @param pos [0,size-1] position index of the element wanted
- * @return reference to user datum, or NULL on errors
- */
- KS_DECLARE(void *) list_extract_at(list_t *restrict l, unsigned int pos);
-
- /**
- * insert an element at a given position.
- *
- * @param l list to operate
- * @param data reference to data to be inserted
- * @param pos [0,size-1] position index to insert the element at
- * @return positive value on success. Negative on failure
- */
- KS_DECLARE(int) list_insert_at(list_t *restrict l, const void *data, unsigned int pos);
-
- /**
- * expunge the first found given element from the list.
- *
- * Inspects the given list looking for the given element; if the element
- * is found, it is removed. Only the first occurence is removed.
- * If a comparator function was not set, elements are compared by reference.
- * Otherwise, the comparator is used to match the element.
- *
- * @param l list to operate
- * @param data reference of the element to search for
- * @return 0 on success. Negative value on failure
- *
- * @see list_attributes_comparator()
- * @see list_delete_at()
- */
- KS_DECLARE(int) list_delete(list_t *restrict l, const void *data);
-
- /**
- * expunge an element at a given position from the list.
- *
- * @param l list to operate
- * @param pos [0,size-1] position index of the element to be deleted
- * @return 0 on success. Negative value on failure
- */
- KS_DECLARE(int) list_delete_at(list_t *restrict l, unsigned int pos);
-
- /**
- * expunge an array of elements from the list, given their position range.
- *
- * @param l list to operate
- * @param posstart [0,size-1] position index of the first element to be deleted
- * @param posend [posstart,size-1] position of the last element to be deleted
- * @return the number of elements successfully removed on success, <0 on error
- */
- KS_DECLARE(int) list_delete_range(list_t *restrict l, unsigned int posstart, unsigned int posend);
-
- /**
- * clear all the elements off of the list.
- *
- * The element datums will not be freed.
- *
- * @see list_delete_range()
- * @see list_size()
- *
- * @param l list to operate
- * @return the number of elements removed on success, <0 on error
- */
- KS_DECLARE(int) list_clear(list_t *restrict l);
-
- /**
- * inspect the number of elements in the list.
- *
- * @param l list to operate
- * @return number of elements currently held by the list
- */
- KS_DECLARE(unsigned int) list_size(const list_t *restrict l);
-
- /**
- * inspect whether the list is empty.
- *
- * @param l list to operate
- * @return 0 iff the list is not empty
- *
- * @see list_size()
- */
- KS_DECLARE(int) list_empty(const list_t *restrict l);
-
- /**
- * find the position of an element in a list.
- *
- * @warning Requires a comparator function to be set for the list.
- *
- * Inspects the given list looking for the given element; if the element
- * is found, its position into the list is returned.
- * Elements are inspected comparing references if a comparator has not been
- * set. Otherwise, the comparator is used to find the element.
- *
- * @param l list to operate
- * @param data reference of the element to search for
- * @return position of element in the list, or <0 if not found
- *
- * @see list_attributes_comparator()
- * @see list_get_at()
- */
- KS_DECLARE(int) list_locate(const list_t *restrict l, const void *data);
-
- /**
- * returns an element given an indicator.
- *
- * @warning Requires a seeker function to be set for the list.
- *
- * Inspect the given list looking with the seeker if an element matches
- * an indicator. If such element is found, the reference to the element
- * is returned.
- *
- * @param l list to operate
- * @param indicator indicator data to pass to the seeker along with elements
- * @return reference to the element accepted by the seeker, or NULL if none found
- */
- KS_DECLARE(void *) list_seek(list_t *restrict l, const void *indicator);
-
- /**
- * inspect whether some data is member of the list.
- *
- * @warning Requires a comparator function to be set for the list.
- *
- * By default, a per-reference comparison is accomplished. That is,
- * the data is in list if any element of the list points to the same
- * location of data.
- * A "semantic" comparison is accomplished, otherwise, if a comparator
- * function has been set previously, with list_attributes_comparator();
- * in which case, the given data reference is believed to be in list iff
- * comparator_fun(elementdata, userdata) == 0 for any element in the list.
- *
- * @param l list to operate
- * @param data reference to the data to search
- * @return 0 iff the list does not contain data as an element
- *
- * @see list_attributes_comparator()
- */
- KS_DECLARE(int) list_contains(const list_t *restrict l, const void *data);
-
- /**
- * concatenate two lists
- *
- * Concatenates one list with another, and stores the result into a
- * user-provided list object, which must be different from both the
- * lists to concatenate. Attributes from the original lists are not
- * cloned.
- * The destination list referred is threated as virgin room: if it
- * is an existing list containing elements, memory leaks will happen.
- * It is OK to specify the same list twice as source, for "doubling"
- * it in the destination.
- *
- * @param l1 base list
- * @param l2 list to append to the base
- * @param dest reference to the destination list
- * @return 0 for success, -1 for errors
- */
- KS_DECLARE(int) list_concat(const list_t *l1, const list_t *l2, list_t *restrict dest);
-
- /**
- * sort list elements.
- *
- * @warning Requires a comparator function to be set for the list.
- *
- * Sorts the list in ascending or descending order as specified by the versus
- * flag. The algorithm chooses autonomously what algorithm is best suited for
- * sorting the list wrt its current status.
- *
- * @param l list to operate
- * @param versus positive: order small to big; negative: order big to small
- * @return 0 iff sorting was successful
- *
- * @see list_attributes_comparator()
- */
- KS_DECLARE(int) list_sort(list_t *restrict l, int versus);
-
- /**
- * start an iteration session.
- *
- * This function prepares the list to be iterated.
- *
- * @param l list to operate
- * @return 0 if the list cannot be currently iterated. >0 otherwise
- *
- * @see list_iterator_stop()
- */
- KS_DECLARE(int) list_iterator_start(list_t *restrict l);
-
- /**
- * return the next element in the iteration session.
- *
- * @param l list to operate
- * @return element datum, or NULL on errors
- */
- KS_DECLARE(void *) list_iterator_next(list_t *restrict l);
-
- /**
- * inspect whether more elements are available in the iteration session.
- *
- * @param l list to operate
- * @return 0 iff no more elements are available.
- */
- KS_DECLARE(int) list_iterator_hasnext(const list_t *restrict l);
-
- /**
- * end an iteration session.
- *
- * @param l list to operate
- * @return 0 iff the iteration session cannot be stopped
- */
- KS_DECLARE(int) list_iterator_stop(list_t *restrict l);
-
- /**
- * return the hash of the current status of the list.
- *
- * @param l list to operate
- * @param hash where the resulting hash is put
- *
- * @return 0 for success; <0 for failure
- */
- KS_DECLARE(int) list_hash(const list_t *restrict l, list_hash_t *restrict hash);
+ * initialize a list object for use.
+ *
+ * @param l must point to a user-provided memory location
+ * @return 0 for success. -1 for failure
+ */
+ int list_init(list_t *restrict l);
+
+ /**
+ * completely remove the list from memory.
+ *
+ * This function is the inverse of list_init(). It is meant to be called when
+ * the list is no longer going to be used. Elements and possible memory taken
+ * for internal use are freed.
+ *
+ * @param l list to destroy
+ */
+ void list_destroy(list_t *restrict l);
+
+ /**
+ * set the comparator function for list elements.
+ *
+ * Comparator functions are used for searching and sorting. If NULL is passed
+ * as reference to the function, the comparator is disabled.
+ *
+ * @param l list to operate
+ * @param comparator_fun pointer to the actual comparator function
+ * @return 0 if the attribute was successfully set; -1 otherwise
+ *
+ * @see element_comparator()
+ */
+ int list_attributes_comparator(list_t *restrict l, element_comparator comparator_fun);
+
+ /**
+ * set a seeker function for list elements.
+ *
+ * Seeker functions are used for finding elements. If NULL is passed as reference
+ * to the function, the seeker is disabled.
+ *
+ * @param l list to operate
+ * @param seeker_fun pointer to the actual seeker function
+ * @return 0 if the attribute was successfully set; -1 otherwise
+ *
+ * @see element_seeker()
+ */
+ int list_attributes_seeker(list_t *restrict l, element_seeker seeker_fun);
+
+ /**
+ * require to free element data when list entry is removed (default: don't free).
+ *
+ * [ advanced preference ]
+ *
+ * By default, when an element is removed from the list, it disappears from
+ * the list by its actual data is not free()d. With this option, every
+ * deletion causes element data to be freed.
+ *
+ * It is responsability of this function to correctly handle NULL values, if
+ * NULL elements are inserted into the list.
+ *
+ * @param l list to operate
+ * @param metric_fun pointer to the actual metric function
+ * @param copy_data 0: do not free element data (default); non-0: do free
+ * @return 0 if the attribute was successfully set; -1 otherwise
+ *
+ * @see element_meter()
+ * @see list_meter_int8_t()
+ * @see list_meter_int16_t()
+ * @see list_meter_int32_t()
+ * @see list_meter_int64_t()
+ * @see list_meter_uint8_t()
+ * @see list_meter_uint16_t()
+ * @see list_meter_uint32_t()
+ * @see list_meter_uint64_t()
+ * @see list_meter_float()
+ * @see list_meter_double()
+ * @see list_meter_string()
+ */
+ int list_attributes_copy(list_t *restrict l, element_meter metric_fun, int copy_data);
+
+ /**
+ * set the element hash computing function for the list elements.
+ *
+ * [ advanced preference ]
+ *
+ * An hash can be requested depicting the list status at a given time. An hash
+ * only depends on the elements and their order. By default, the hash of an
+ * element is only computed on its reference. With this function, the user can
+ * set a custom function computing the hash of an element. If such function is
+ * provided, the list_hash() function automatically computes the list hash using
+ * the custom function instead of simply referring to element references.
+ *
+ * @param l list to operate
+ * @param hash_computer_fun pointer to the actual hash computing function
+ * @return 0 if the attribute was successfully set; -1 otherwise
+ *
+ * @see element_hash_computer()
+ */
+ int list_attributes_hash_computer(list_t *restrict l, element_hash_computer hash_computer_fun);
+
+ /**
+ * set the element serializer function for the list elements.
+ *
+ * [ advanced preference ]
+ *
+ * Serialize functions are used for dumping the list to some persistent
+ * storage. The serializer function is called for each element; it is passed
+ * a reference to the element and a reference to a size_t object. It will
+ * provide (and return) the buffer with the serialization of the element and
+ * fill the size_t object with the length of this serialization data.
+ *
+ * @param l list to operate
+ * @param serializer_fun pointer to the actual serializer function
+ * @return 0 if the attribute was successfully set; -1 otherwise
+ *
+ * @see element_serializer()
+ * @see list_dump_filedescriptor()
+ * @see list_restore_filedescriptor()
+ */
+ int list_attributes_serializer(list_t *restrict l, element_serializer serializer_fun);
+
+ /**
+ * set the element unserializer function for the list elements.
+ *
+ * [ advanced preference ]
+ *
+ * Unserialize functions are used for restoring the list from some persistent
+ * storage. The unserializer function is called for each element segment read
+ * from the storage; it is passed the segment and a reference to an integer.
+ * It shall allocate and return a buffer compiled with the resumed memory
+ * representation of the element, and set the integer value to the length of
+ * this buffer.
+ *
+ * @param l list to operate
+ * @param unserializer_fun pointer to the actual unserializer function
+ * @return 0 if the attribute was successfully set; -1 otherwise
+ *
+ * @see element_unserializer()
+ * @see list_dump_filedescriptor()
+ * @see list_restore_filedescriptor()
+ */
+ int list_attributes_unserializer(list_t *restrict l, element_unserializer unserializer_fun);
+
+ /**
+ * append data at the end of the list.
+ *
+ * This function is useful for adding elements with a FIFO/queue policy.
+ *
+ * @param l list to operate
+ * @param data pointer to user data to append
+ *
+ * @return 1 for success. < 0 for failure
+ */
+ int list_append(list_t *restrict l, const void *data);
+
+ /**
+ * insert data in the head of the list.
+ *
+ * This function is useful for adding elements with a LIFO/Stack policy.
+ *
+ * @param l list to operate
+ * @param data pointer to user data to append
+ *
+ * @return 1 for success. < 0 for failure
+ */
+ int list_prepend(list_t *restrict l, const void *restrict data);
+
+ /**
+ * extract the element in the top of the list.
+ *
+ * This function is for using a list with a FIFO/queue policy.
+ *
+ * @param l list to operate
+ * @return reference to user datum, or NULL on errors
+ */
+ void *list_fetch(list_t *restrict l);
+
+ /**
+ * retrieve an element at a given position.
+ *
+ * @param l list to operate
+ * @param pos [0,size-1] position index of the element wanted
+ * @return reference to user datum, or NULL on errors
+ */
+ void *list_get_at(const list_t *restrict l, unsigned int pos);
+
+ /**
+ * return the maximum element of the list.
+ *
+ * @warning Requires a comparator function to be set for the list.
+ *
+ * Returns the maximum element with respect to the comparator function output.
+ *
+ * @see list_attributes_comparator()
+ *
+ * @param l list to operate
+ * @return the reference to the element, or NULL
+ */
+ void *list_get_max(const list_t *restrict l);
+
+ /**
+ * return the minimum element of the list.
+ *
+ * @warning Requires a comparator function to be set for the list.
+ *
+ * Returns the minimum element with respect to the comparator function output.
+ *
+ * @see list_attributes_comparator()
+ *
+ * @param l list to operate
+ * @return the reference to the element, or NULL
+ */
+ void *list_get_min(const list_t *restrict l);
+
+ /**
+ * retrieve and remove from list an element at a given position.
+ *
+ * @param l list to operate
+ * @param pos [0,size-1] position index of the element wanted
+ * @return reference to user datum, or NULL on errors
+ */
+ void *list_extract_at(list_t *restrict l, unsigned int pos);
+
+ /**
+ * insert an element at a given position.
+ *
+ * @param l list to operate
+ * @param data reference to data to be inserted
+ * @param pos [0,size-1] position index to insert the element at
+ * @return positive value on success. Negative on failure
+ */
+ int list_insert_at(list_t *restrict l, const void *data, unsigned int pos);
+
+ /**
+ * expunge the first found given element from the list.
+ *
+ * Inspects the given list looking for the given element; if the element
+ * is found, it is removed. Only the first occurence is removed.
+ * If a comparator function was not set, elements are compared by reference.
+ * Otherwise, the comparator is used to match the element.
+ *
+ * @param l list to operate
+ * @param data reference of the element to search for
+ * @return 0 on success. Negative value on failure
+ *
+ * @see list_attributes_comparator()
+ * @see list_delete_at()
+ */
+ int list_delete(list_t *restrict l, const void *data);
+
+ /**
+ * expunge an element at a given position from the list.
+ *
+ * @param l list to operate
+ * @param pos [0,size-1] position index of the element to be deleted
+ * @return 0 on success. Negative value on failure
+ */
+ int list_delete_at(list_t *restrict l, unsigned int pos);
+
+ /**
+ * expunge an array of elements from the list, given their position range.
+ *
+ * @param l list to operate
+ * @param posstart [0,size-1] position index of the first element to be deleted
+ * @param posend [posstart,size-1] position of the last element to be deleted
+ * @return the number of elements successfully removed on success, <0 on error
+ */
+ int list_delete_range(list_t *restrict l, unsigned int posstart, unsigned int posend);
+
+ /**
+ * clear all the elements off of the list.
+ *
+ * The element datums will not be freed.
+ *
+ * @see list_delete_range()
+ * @see list_size()
+ *
+ * @param l list to operate
+ * @return the number of elements removed on success, <0 on error
+ */
+ int list_clear(list_t *restrict l);
+
+ /**
+ * inspect the number of elements in the list.
+ *
+ * @param l list to operate
+ * @return number of elements currently held by the list
+ */
+ unsigned int list_size(const list_t *restrict l);
+
+ /**
+ * inspect whether the list is empty.
+ *
+ * @param l list to operate
+ * @return 0 iff the list is not empty
+ *
+ * @see list_size()
+ */
+ int list_empty(const list_t *restrict l);
+
+ /**
+ * find the position of an element in a list.
+ *
+ * @warning Requires a comparator function to be set for the list.
+ *
+ * Inspects the given list looking for the given element; if the element
+ * is found, its position into the list is returned.
+ * Elements are inspected comparing references if a comparator has not been
+ * set. Otherwise, the comparator is used to find the element.
+ *
+ * @param l list to operate
+ * @param data reference of the element to search for
+ * @return position of element in the list, or <0 if not found
+ *
+ * @see list_attributes_comparator()
+ * @see list_get_at()
+ */
+ int list_locate(const list_t *restrict l, const void *data);
+
+ /**
+ * returns an element given an indicator.
+ *
+ * @warning Requires a seeker function to be set for the list.
+ *
+ * Inspect the given list looking with the seeker if an element matches
+ * an indicator. If such element is found, the reference to the element
+ * is returned.
+ *
+ * @param l list to operate
+ * @param indicator indicator data to pass to the seeker along with elements
+ * @return reference to the element accepted by the seeker, or NULL if none found
+ */
+ void *list_seek(list_t *restrict l, const void *indicator);
+
+ /**
+ * inspect whether some data is member of the list.
+ *
+ * @warning Requires a comparator function to be set for the list.
+ *
+ * By default, a per-reference comparison is accomplished. That is,
+ * the data is in list if any element of the list points to the same
+ * location of data.
+ * A "semantic" comparison is accomplished, otherwise, if a comparator
+ * function has been set previously, with list_attributes_comparator();
+ * in which case, the given data reference is believed to be in list iff
+ * comparator_fun(elementdata, userdata) == 0 for any element in the list.
+ *
+ * @param l list to operate
+ * @param data reference to the data to search
+ * @return 0 iff the list does not contain data as an element
+ *
+ * @see list_attributes_comparator()
+ */
+ int list_contains(const list_t *restrict l, const void *data);
+
+ /**
+ * concatenate two lists
+ *
+ * Concatenates one list with another, and stores the result into a
+ * user-provided list object, which must be different from both the
+ * lists to concatenate. Attributes from the original lists are not
+ * cloned.
+ * The destination list referred is threated as virgin room: if it
+ * is an existing list containing elements, memory leaks will happen.
+ * It is OK to specify the same list twice as source, for "doubling"
+ * it in the destination.
+ *
+ * @param l1 base list
+ * @param l2 list to append to the base
+ * @param dest reference to the destination list
+ * @return 0 for success, -1 for errors
+ */
+ int list_concat(const list_t *l1, const list_t *l2, list_t *restrict dest);
+
+ /**
+ * sort list elements.
+ *
+ * @warning Requires a comparator function to be set for the list.
+ *
+ * Sorts the list in ascending or descending order as specified by the versus
+ * flag. The algorithm chooses autonomously what algorithm is best suited for
+ * sorting the list wrt its current status.
+ *
+ * @param l list to operate
+ * @param versus positive: order small to big; negative: order big to small
+ * @return 0 iff sorting was successful
+ *
+ * @see list_attributes_comparator()
+ */
+ int list_sort(list_t *restrict l, int versus);
+
+ /**
+ * start an iteration session.
+ *
+ * This function prepares the list to be iterated.
+ *
+ * @param l list to operate
+ * @return 0 if the list cannot be currently iterated. >0 otherwise
+ *
+ * @see list_iterator_stop()
+ */
+ int list_iterator_start(list_t *restrict l);
+
+ /**
+ * return the next element in the iteration session.
+ *
+ * @param l list to operate
+ * @return element datum, or NULL on errors
+ */
+ void *list_iterator_next(list_t *restrict l);
+
+ /**
+ * inspect whether more elements are available in the iteration session.
+ *
+ * @param l list to operate
+ * @return 0 iff no more elements are available.
+ */
+ int list_iterator_hasnext(const list_t *restrict l);
+
+ /**
+ * end an iteration session.
+ *
+ * @param l list to operate
+ * @return 0 iff the iteration session cannot be stopped
+ */
+ int list_iterator_stop(list_t *restrict l);
+
+ /**
+ * return the hash of the current status of the list.
+ *
+ * @param l list to operate
+ * @param hash where the resulting hash is put
+ *
+ * @return 0 for success; <0 for failure
+ */
+ int list_hash(const list_t *restrict l, list_hash_t *restrict hash);
#ifndef SIMCLIST_NO_DUMPRESTORE
/**
- * get meta informations on a list dump on filedescriptor.
- *
- * [ advanced function ]
- *
- * Extracts the meta information from a SimCList dump located in a file
- * descriptor. The file descriptor must be open and positioned at the
- * beginning of the SimCList dump block.
- *
- * @param fd file descriptor to get metadata from
- * @param info reference to a dump metainformation structure to fill
- * @return 0 for success; <0 for failure
- *
- * @see list_dump_filedescriptor()
- */
- KS_DECLARE(int) list_dump_getinfo_filedescriptor(int fd, list_dump_info_t *restrict info);
-
- /**
- * get meta informations on a list dump on file.
- *
- * [ advanced function ]
- *
- * Extracts the meta information from a SimCList dump located in a file.
- *
- * @param filename filename of the file to fetch from
- * @param info reference to a dump metainformation structure to fill
- * @return 0 for success; <0 for failure
- *
- * @see list_dump_filedescriptor()
- */
- KS_DECLARE(int) list_dump_getinfo_file(const char *restrict filename, list_dump_info_t *restrict info);
-
- /**
- * dump the list into an open, writable file descriptor.
- *
- * This function "dumps" the list to a persistent storage so it can be
- * preserved across process terminations.
- * When called, the file descriptor must be open for writing and positioned
- * where the serialized data must begin. It writes its serialization of the
- * list in a form which is portable across different architectures. Dump can
- * be safely performed on stream-only (non seekable) descriptors. The file
- * descriptor is not closed at the end of the operations.
- *
- * To use dump functions, either of these conditions must be satisfied:
- * -# a metric function has been specified with list_attributes_copy()
- * -# a serializer function has been specified with list_attributes_serializer()
- *
- * If a metric function has been specified, each element of the list is dumped
- * as-is from memory, copying it from its pointer for its length down to the
- * file descriptor. This might have impacts on portability of the dump to
- * different architectures.
- *
- * If a serializer function has been specified, its result for each element is
- * dumped to the file descriptor.
- *
- *
- * @param l list to operate
- * @param fd file descriptor to write to
- * @param len location to store the resulting length of the dump (bytes), or NULL
- *
- * @return 0 if successful; -1 otherwise
- *
- * @see element_serializer()
- * @see list_attributes_copy()
- * @see list_attributes_serializer()
- */
- KS_DECLARE(int) list_dump_filedescriptor(const list_t *restrict l, int fd, size_t *restrict len);
-
- /**
- * dump the list to a file name.
- *
- * This function creates a filename and dumps the current content of the list
- * to it. If the file exists it is overwritten. The number of bytes written to
- * the file can be returned in a specified argument.
- *
- * @param l list to operate
- * @param filename filename to write to
- * @param len location to store the resulting length of the dump (bytes), or NULL
- *
- * @return 0 if successful; -1 otherwise
- *
- * @see list_attributes_copy()
- * @see element_serializer()
- * @see list_attributes_serializer()
- * @see list_dump_filedescriptor()
- * @see list_restore_file()
- *
- * This function stores a representation of the list
- */
- KS_DECLARE(int) list_dump_file(const list_t *restrict l, const char *restrict filename, size_t *restrict len);
-
- /**
- * restore the list from an open, readable file descriptor to memory.
- *
- * This function is the "inverse" of list_dump_filedescriptor(). It restores
- * the list content from a (open, read-ready) file descriptor to memory. An
- * unserializer might be needed to restore elements from the persistent
- * representation back into memory-consistent format. List attributes can not
- * be restored and must be set manually.
- *
- * @see list_dump_filedescriptor()
- * @see list_attributes_serializer()
- * @see list_attributes_unserializer()
- *
- * @param l list to restore to
- * @param fd file descriptor to read from.
- * @param len location to store the length of the dump read (bytes), or NULL
- * @return 0 if successful; -1 otherwise
- */
- KS_DECLARE(int) list_restore_filedescriptor(list_t *restrict l, int fd, size_t *restrict len);
-
- /**
- * restore the list from a file name.
- *
- * This function restores the content of a list from a file into memory. It is
- * the inverse of list_dump_file().
- *
- * @see element_unserializer()
- * @see list_attributes_unserializer()
- * @see list_dump_file()
- * @see list_restore_filedescriptor()
- *
- * @param l list to restore to
- * @param filename filename to read data from
- * @param len location to store the length of the dump read (bytes), or NULL
- * @return 0 if successful; -1 otherwise
- */
- KS_DECLARE(int) list_restore_file(list_t *restrict l, const char *restrict filename, size_t *len);
+ * get meta informations on a list dump on filedescriptor.
+ *
+ * [ advanced function ]
+ *
+ * Extracts the meta information from a SimCList dump located in a file
+ * descriptor. The file descriptor must be open and positioned at the
+ * beginning of the SimCList dump block.
+ *
+ * @param fd file descriptor to get metadata from
+ * @param info reference to a dump metainformation structure to fill
+ * @return 0 for success; <0 for failure
+ *
+ * @see list_dump_filedescriptor()
+ */
+ int list_dump_getinfo_filedescriptor(int fd, list_dump_info_t *restrict info);
+
+ /**
+ * get meta informations on a list dump on file.
+ *
+ * [ advanced function ]
+ *
+ * Extracts the meta information from a SimCList dump located in a file.
+ *
+ * @param filename filename of the file to fetch from
+ * @param info reference to a dump metainformation structure to fill
+ * @return 0 for success; <0 for failure
+ *
+ * @see list_dump_filedescriptor()
+ */
+ int list_dump_getinfo_file(const char *restrict filename, list_dump_info_t *restrict info);
+
+ /**
+ * dump the list into an open, writable file descriptor.
+ *
+ * This function "dumps" the list to a persistent storage so it can be
+ * preserved across process terminations.
+ * When called, the file descriptor must be open for writing and positioned
+ * where the serialized data must begin. It writes its serialization of the
+ * list in a form which is portable across different architectures. Dump can
+ * be safely performed on stream-only (non seekable) descriptors. The file
+ * descriptor is not closed at the end of the operations.
+ *
+ * To use dump functions, either of these conditions must be satisfied:
+ * -# a metric function has been specified with list_attributes_copy()
+ * -# a serializer function has been specified with list_attributes_serializer()
+ *
+ * If a metric function has been specified, each element of the list is dumped
+ * as-is from memory, copying it from its pointer for its length down to the
+ * file descriptor. This might have impacts on portability of the dump to
+ * different architectures.
+ *
+ * If a serializer function has been specified, its result for each element is
+ * dumped to the file descriptor.
+ *
+ *
+ * @param l list to operate
+ * @param fd file descriptor to write to
+ * @param len location to store the resulting length of the dump (bytes), or NULL
+ *
+ * @return 0 if successful; -1 otherwise
+ *
+ * @see element_serializer()
+ * @see list_attributes_copy()
+ * @see list_attributes_serializer()
+ */
+ int list_dump_filedescriptor(const list_t *restrict l, int fd, size_t *restrict len);
+
+ /**
+ * dump the list to a file name.
+ *
+ * This function creates a filename and dumps the current content of the list
+ * to it. If the file exists it is overwritten. The number of bytes written to
+ * the file can be returned in a specified argument.
+ *
+ * @param l list to operate
+ * @param filename filename to write to
+ * @param len location to store the resulting length of the dump (bytes), or NULL
+ *
+ * @return 0 if successful; -1 otherwise
+ *
+ * @see list_attributes_copy()
+ * @see element_serializer()
+ * @see list_attributes_serializer()
+ * @see list_dump_filedescriptor()
+ * @see list_restore_file()
+ *
+ * This function stores a representation of the list
+ */
+ int list_dump_file(const list_t *restrict l, const char *restrict filename, size_t *restrict len);
+
+ /**
+ * restore the list from an open, readable file descriptor to memory.
+ *
+ * This function is the "inverse" of list_dump_filedescriptor(). It restores
+ * the list content from a (open, read-ready) file descriptor to memory. An
+ * unserializer might be needed to restore elements from the persistent
+ * representation back into memory-consistent format. List attributes can not
+ * be restored and must be set manually.
+ *
+ * @see list_dump_filedescriptor()
+ * @see list_attributes_serializer()
+ * @see list_attributes_unserializer()
+ *
+ * @param l list to restore to
+ * @param fd file descriptor to read from.
+ * @param len location to store the length of the dump read (bytes), or NULL
+ * @return 0 if successful; -1 otherwise
+ */
+ int list_restore_filedescriptor(list_t *restrict l, int fd, size_t *restrict len);
+
+ /**
+ * restore the list from a file name.
+ *
+ * This function restores the content of a list from a file into memory. It is
+ * the inverse of list_dump_file().
+ *
+ * @see element_unserializer()
+ * @see list_attributes_unserializer()
+ * @see list_dump_file()
+ * @see list_restore_filedescriptor()
+ *
+ * @param l list to restore to
+ * @param filename filename to read data from
+ * @param len location to store the length of the dump read (bytes), or NULL
+ * @return 0 if successful; -1 otherwise
+ */
+ int list_restore_file(list_t *restrict l, const char *restrict filename, size_t *len);
#endif
/* ready-made comparators, meters and hash computers */
/* comparator functions */
/**
- * ready-made comparator for int8_t elements.
- * @see list_attributes_comparator()
- */
- KS_DECLARE(int) list_comparator_int8_t (const void *a, const void *b);
+ * ready-made comparator for int8_t elements.
+ * @see list_attributes_comparator()
+ */
+ int list_comparator_int8_t(const void *a, const void *b);
/**
- * ready-made comparator for int16_t elements.
- * @see list_attributes_comparator()
- */
- KS_DECLARE(int) list_comparator_int16_t (const void *a, const void *b);
+ * ready-made comparator for int16_t elements.
+ * @see list_attributes_comparator()
+ */
+ int list_comparator_int16_t(const void *a, const void *b);
/**
- * ready-made comparator for int32_t elements.
- * @see list_attributes_comparator()
- */
- KS_DECLARE(int) list_comparator_int32_t (const void *a, const void *b);
+ * ready-made comparator for int32_t elements.
+ * @see list_attributes_comparator()
+ */
+ int list_comparator_int32_t(const void *a, const void *b);
/**
- * ready-made comparator for int64_t elements.
- * @see list_attributes_comparator()
- */
- KS_DECLARE(int) list_comparator_int64_t (const void *a, const void *b);
+ * ready-made comparator for int64_t elements.
+ * @see list_attributes_comparator()
+ */
+ int list_comparator_int64_t(const void *a, const void *b);
/**
- * ready-made comparator for uint8_t elements.
- * @see list_attributes_comparator()
- */
- KS_DECLARE(int) list_comparator_uint8_t (const void *a, const void *b);
+ * ready-made comparator for uint8_t elements.
+ * @see list_attributes_comparator()
+ */
+ int list_comparator_uint8_t(const void *a, const void *b);
/**
- * ready-made comparator for uint16_t elements.
- * @see list_attributes_comparator()
- */
- KS_DECLARE(int) list_comparator_uint16_t (const void *a, const void *b);
+ * ready-made comparator for uint16_t elements.
+ * @see list_attributes_comparator()
+ */
+ int list_comparator_uint16_t(const void *a, const void *b);
/**
- * ready-made comparator for uint32_t elements.
- * @see list_attributes_comparator()
- */
- KS_DECLARE(int) list_comparator_uint32_t (const void *a, const void *b);
+ * ready-made comparator for uint32_t elements.
+ * @see list_attributes_comparator()
+ */
+ int list_comparator_uint32_t(const void *a, const void *b);
/**
- * ready-made comparator for uint64_t elements.
- * @see list_attributes_comparator()
- */
- KS_DECLARE(int) list_comparator_uint64_t (const void *a, const void *b);
+ * ready-made comparator for uint64_t elements.
+ * @see list_attributes_comparator()
+ */
+ int list_comparator_uint64_t(const void *a, const void *b);
/**
- * ready-made comparator for float elements.
- * @see list_attributes_comparator()
- */
- KS_DECLARE(int) list_comparator_float(const void *a, const void *b);
+ * ready-made comparator for float elements.
+ * @see list_attributes_comparator()
+ */
+ int list_comparator_float(const void *a, const void *b);
/**
- * ready-made comparator for double elements.
- * @see list_attributes_comparator()
- */
- KS_DECLARE(int) list_comparator_double(const void *a, const void *b);
+ * ready-made comparator for double elements.
+ * @see list_attributes_comparator()
+ */
+ int list_comparator_double(const void *a, const void *b);
/**
- * ready-made comparator for string elements.
- * @see list_attributes_comparator()
- */
- KS_DECLARE(int) list_comparator_string(const void *a, const void *b);
+ * ready-made comparator for string elements.
+ * @see list_attributes_comparator()
+ */
+ int list_comparator_string(const void *a, const void *b);
/* metric functions */
/**
- * ready-made metric function for int8_t elements.
- * @see list_attributes_copy()
- */
- KS_DECLARE(size_t) list_meter_int8_t (const void *el);
+ * ready-made metric function for int8_t elements.
+ * @see list_attributes_copy()
+ */
+ size_t list_meter_int8_t(const void *el);
/**
- * ready-made metric function for int16_t elements.
- * @see list_attributes_copy()
- */
- KS_DECLARE(size_t) list_meter_int16_t (const void *el);
+ * ready-made metric function for int16_t elements.
+ * @see list_attributes_copy()
+ */
+ size_t list_meter_int16_t(const void *el);
/**
- * ready-made metric function for int32_t elements.
- * @see list_attributes_copy()
- */
- KS_DECLARE(size_t) list_meter_int32_t (const void *el);
+ * ready-made metric function for int32_t elements.
+ * @see list_attributes_copy()
+ */
+ size_t list_meter_int32_t(const void *el);
/**
- * ready-made metric function for int64_t elements.
- * @see list_attributes_copy()
- */
- KS_DECLARE(size_t) list_meter_int64_t (const void *el);
+ * ready-made metric function for int64_t elements.
+ * @see list_attributes_copy()
+ */
+ size_t list_meter_int64_t(const void *el);
/**
- * ready-made metric function for uint8_t elements.
- * @see list_attributes_copy()
- */
- KS_DECLARE(size_t) list_meter_uint8_t (const void *el);
+ * ready-made metric function for uint8_t elements.
+ * @see list_attributes_copy()
+ */
+ size_t list_meter_uint8_t(const void *el);
/**
- * ready-made metric function for uint16_t elements.
- * @see list_attributes_copy()
- */
- KS_DECLARE(size_t) list_meter_uint16_t (const void *el);
+ * ready-made metric function for uint16_t elements.
+ * @see list_attributes_copy()
+ */
+ size_t list_meter_uint16_t(const void *el);
/**
- * ready-made metric function for uint32_t elements.
- * @see list_attributes_copy()
- */
- KS_DECLARE(size_t) list_meter_uint32_t (const void *el);
+ * ready-made metric function for uint32_t elements.
+ * @see list_attributes_copy()
+ */
+ size_t list_meter_uint32_t(const void *el);
/**
- * ready-made metric function for uint64_t elements.
- * @see list_attributes_copy()
- */
- KS_DECLARE(size_t) list_meter_uint64_t (const void *el);
+ * ready-made metric function for uint64_t elements.
+ * @see list_attributes_copy()
+ */
+ size_t list_meter_uint64_t(const void *el);
/**
- * ready-made metric function for float elements.
- * @see list_attributes_copy()
- */
- KS_DECLARE(size_t) list_meter_float(const void *el);
+ * ready-made metric function for float elements.
+ * @see list_attributes_copy()
+ */
+ size_t list_meter_float(const void *el);
/**
- * ready-made metric function for double elements.
- * @see list_attributes_copy()
- */
- KS_DECLARE(size_t) list_meter_double(const void *el);
+ * ready-made metric function for double elements.
+ * @see list_attributes_copy()
+ */
+ size_t list_meter_double(const void *el);
/**
- * ready-made metric function for string elements.
- * @see list_attributes_copy()
- */
- KS_DECLARE(size_t) list_meter_string(const void *el);
+ * ready-made metric function for string elements.
+ * @see list_attributes_copy()
+ */
+ size_t list_meter_string(const void *el);
/* hash functions */
/**
- * ready-made hash function for int8_t elements.
- * @see list_attributes_hash_computer()
- */
- KS_DECLARE(list_hash_t) list_hashcomputer_int8_t(const void *el);
+ * ready-made hash function for int8_t elements.
+ * @see list_attributes_hash_computer()
+ */
+ list_hash_t list_hashcomputer_int8_t(const void *el);
/**
- * ready-made hash function for int16_t elements.
- * @see list_attributes_hash_computer()
- */
- KS_DECLARE(list_hash_t) list_hashcomputer_int16_t(const void *el);
+ * ready-made hash function for int16_t elements.
+ * @see list_attributes_hash_computer()
+ */
+ list_hash_t list_hashcomputer_int16_t(const void *el);
/**
- * ready-made hash function for int32_t elements.
- * @see list_attributes_hash_computer()
- */
- KS_DECLARE(list_hash_t) list_hashcomputer_int32_t(const void *el);
+ * ready-made hash function for int32_t elements.
+ * @see list_attributes_hash_computer()
+ */
+ list_hash_t list_hashcomputer_int32_t(const void *el);
/**
- * ready-made hash function for int64_t elements.
- * @see list_attributes_hash_computer()
- */
- KS_DECLARE(list_hash_t) list_hashcomputer_int64_t(const void *el);
+ * ready-made hash function for int64_t elements.
+ * @see list_attributes_hash_computer()
+ */
+ list_hash_t list_hashcomputer_int64_t(const void *el);
/**
- * ready-made hash function for uint8_t elements.
- * @see list_attributes_hash_computer()
- */
- KS_DECLARE(list_hash_t) list_hashcomputer_uint8_t(const void *el);
+ * ready-made hash function for uint8_t elements.
+ * @see list_attributes_hash_computer()
+ */
+ list_hash_t list_hashcomputer_uint8_t(const void *el);
/**
- * ready-made hash function for uint16_t elements.
- * @see list_attributes_hash_computer()
- */
- KS_DECLARE(list_hash_t) list_hashcomputer_uint16_t(const void *el);
+ * ready-made hash function for uint16_t elements.
+ * @see list_attributes_hash_computer()
+ */
+ list_hash_t list_hashcomputer_uint16_t(const void *el);
/**
- * ready-made hash function for uint32_t elements.
- * @see list_attributes_hash_computer()
- */
- KS_DECLARE(list_hash_t) list_hashcomputer_uint32_t(const void *el);
+ * ready-made hash function for uint32_t elements.
+ * @see list_attributes_hash_computer()
+ */
+ list_hash_t list_hashcomputer_uint32_t(const void *el);
/**
- * ready-made hash function for uint64_t elements.
- * @see list_attributes_hash_computer()
- */
- KS_DECLARE(list_hash_t) list_hashcomputer_uint64_t(const void *el);
+ * ready-made hash function for uint64_t elements.
+ * @see list_attributes_hash_computer()
+ */
+ list_hash_t list_hashcomputer_uint64_t(const void *el);
/**
- * ready-made hash function for float elements.
- * @see list_attributes_hash_computer()
- */
- KS_DECLARE(list_hash_t) list_hashcomputer_float(const void *el);
+ * ready-made hash function for float elements.
+ * @see list_attributes_hash_computer()
+ */
+ list_hash_t list_hashcomputer_float(const void *el);
/**
- * ready-made hash function for double elements.
- * @see list_attributes_hash_computer()
- */
- KS_DECLARE(list_hash_t) list_hashcomputer_double(const void *el);
+ * ready-made hash function for double elements.
+ * @see list_attributes_hash_computer()
+ */
+ list_hash_t list_hashcomputer_double(const void *el);
/**
- * ready-made hash function for string elements.
- * @see list_attributes_hash_computer()
- */
- KS_DECLARE(list_hash_t) list_hashcomputer_string(const void *el);
+ * ready-made hash function for string elements.
+ * @see list_attributes_hash_computer()
+ */
+ list_hash_t list_hashcomputer_string(const void *el);
#ifdef __cplusplus
}
#endif
+
#endif
+
/* For Emacs:
* Local Variables:
* mode:c
/*
- * Copyright (c) 2007,2008,2009,2010,2011 Mij <mij@bitchx.it>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS 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, DIRECT, 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.
- */
+* Copyright (c) 2007,2008,2009,2010,2011 Mij <mij@bitchx.it>
+*
+* Permission to use, copy, modify, and distribute this software for any
+* purpose with or without fee is hereby granted, provided that the above
+* copyright notice and this permission notice appear in all copies.
+*
+* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS 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, DIRECT, 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.
+*/
/*
- * SimCList library. See http://mij.oltrelinux.com/devel/simclist
- */
+* SimCList library. See http://mij.oltrelinux.com/devel/simclist
+*/
/* SimCList implementation, version 1.6 */
#include <ks.h>
#include <stdlib.h>
#include <string.h>
-#include <errno.h> /* for setting errno */
+#include <errno.h> /* for setting errno */
#include <sys/types.h>
#ifndef _WIN32
/* not in Windows! */
-#include <unistd.h>
-#include <stdint.h>
-#else
-//#include <Windows.h>
+# include <unistd.h>
+# include <stdint.h>
#endif
#ifndef SIMCLIST_NO_DUMPRESTORE
/* includes for dump/restore */
-#include <time.h>
-#include <sys/uio.h> /* for READ_ERRCHECK() and write() */
-#include <fcntl.h> /* for open() etc */
-#ifndef _WIN32
-#include <arpa/inet.h> /* for htons() on UNIX */
-#else
-#include <winsock2.h> /* for htons() on Windows */
-#endif
+# include <time.h>
+# include <sys/uio.h> /* for READ_ERRCHECK() and write() */
+# include <fcntl.h> /* for open() etc */
+# ifndef _WIN32
+# include <arpa/inet.h> /* for htons() on UNIX */
+# else
+# include <winsock2.h> /* for htons() on Windows */
+# endif
#endif
/* disable asserts */
#ifndef SIMCLIST_DEBUG
-#ifndef NDEBUG
#define NDEBUG
#endif
-#endif
#include <assert.h>
-#include <sys/stat.h> /* for open()'s access modes S_IRUSR etc */
+#include <sys/stat.h> /* for open()'s access modes S_IRUSR etc */
#include <limits.h>
#if defined(_MSC_VER) || defined(__MINGW32__)
#ifdef _MSC_VER
#pragma comment(lib, "Winmm.lib")
#endif
-int gettimeofday(struct timeval *tp, void *tzp)
-{
+int gettimeofday(struct timeval *tp, void *tzp) {
DWORD t;
/* XSI says: "If tzp is not a null pointer, the behavior is unspecified" */
/* work around lack of inttypes.h support in broken Microsoft Visual Studio compilers */
#if !defined(_WIN32) || !defined(_MSC_VER)
-#include <inttypes.h> /* (u)int*_t */
+# include <inttypes.h> /* (u)int*_t */
#else
-#include <basetsd.h>
-typedef UINT8 uint8_t;
-typedef UINT16 uint16_t;
+# include <basetsd.h>
+typedef UINT8 uint8_t;
+typedef UINT16 uint16_t;
typedef ULONG32 uint32_t;
-typedef UINT64 uint64_t;
-typedef INT8 int8_t;
-typedef INT16 int16_t;
-typedef LONG32 int32_t;
-typedef INT64 int64_t;
+typedef UINT64 uint64_t;
+typedef INT8 int8_t;
+typedef INT16 int16_t;
+typedef LONG32 int32_t;
+typedef INT64 int64_t;
#endif
/* define some commodity macros for Dump/Restore functionality */
#ifndef SIMCLIST_NO_DUMPRESTORE
/* write() decorated with error checking logic */
-#define WRITE_ERRCHECK(fd, msgbuf, msglen) do { \
- if (write(fd, msgbuf, msglen) < 0) return -1; \
- } while (0);
+#define WRITE_ERRCHECK(fd, msgbuf, msglen) do { \
+ if (write(fd, msgbuf, msglen) < 0) return -1; \
+ } while (0);
/* READ_ERRCHECK() decorated with error checking logic */
-#define READ_ERRCHECK(fd, msgbuf, msglen) do { \
- if (read(fd, msgbuf, msglen) != msglen) { \
- /*errno = EPROTO;*/ \
- return -1; \
- } \
- } while (0);
+#define READ_ERRCHECK(fd, msgbuf, msglen) do { \
+ if (read(fd, msgbuf, msglen) != msglen) { \
+ /*errno = EPROTO;*/ \
+ return -1; \
+ } \
+ } while (0);
/* convert 64bit integers from host to network format */
-#define hton64(x) ( \
- htons(1) == 1 ? \
- (uint64_t)x /* big endian */ \
- : /* little endian */ \
- ((uint64_t)((((uint64_t)(x) & 0xff00000000000000ULL) >> 56) | \
- (((uint64_t)(x) & 0x00ff000000000000ULL) >> 40) | \
- (((uint64_t)(x) & 0x0000ff0000000000ULL) >> 24) | \
- (((uint64_t)(x) & 0x000000ff00000000ULL) >> 8) | \
- (((uint64_t)(x) & 0x00000000ff000000ULL) << 8) | \
- (((uint64_t)(x) & 0x0000000000ff0000ULL) << 24) | \
- (((uint64_t)(x) & 0x000000000000ff00ULL) << 40) | \
- (((uint64_t)(x) & 0x00000000000000ffULL) << 56))) \
- )
+#define hton64(x) (\
+ htons(1) == 1 ? \
+ (uint64_t)x /* big endian */ \
+ : /* little endian */ \
+ ((uint64_t)((((uint64_t)(x) & 0xff00000000000000ULL) >> 56) | \
+ (((uint64_t)(x) & 0x00ff000000000000ULL) >> 40) | \
+ (((uint64_t)(x) & 0x0000ff0000000000ULL) >> 24) | \
+ (((uint64_t)(x) & 0x000000ff00000000ULL) >> 8) | \
+ (((uint64_t)(x) & 0x00000000ff000000ULL) << 8) | \
+ (((uint64_t)(x) & 0x0000000000ff0000ULL) << 24) | \
+ (((uint64_t)(x) & 0x000000000000ff00ULL) << 40) | \
+ (((uint64_t)(x) & 0x00000000000000ffULL) << 56))) \
+ )
/* convert 64bit integers from network to host format */
#define ntoh64(x) (hton64(x))
#ifdef SIMCLIST_WITH_THREADS
/* limit (approx) to the number of threads running
- * for threaded operations. Only meant when
- * SIMCLIST_WITH_THREADS is defined */
+* for threaded operations. Only meant when
+* SIMCLIST_WITH_THREADS is defined */
#define SIMCLIST_MAXTHREADS 2
#endif
/*
- * how many elems to keep as spare. During a deletion, an element
- * can be saved in a "free-list", not free()d immediately. When
- * latter insertions are performed, spare elems can be used instead
- * of malloc()ing new elems.
- *
- * about this param, some values for appending
- * 10 million elems into an empty list:
- * (#, time[sec], gain[%], gain/no[%])
- * 0 2,164 0,00 0,00 <-- feature disabled
- * 1 1,815 34,9 34,9
- * 2 1,446 71,8 35,9 <-- MAX gain/no
- * 3 1,347 81,7 27,23
- * 5 1,213 95,1 19,02
- * 8 1,064 110,0 13,75
- * 10 1,015 114,9 11,49 <-- MAX gain w/ likely sol
- * 15 1,019 114,5 7,63
- * 25 0,985 117,9 4,72
- * 50 1,088 107,6 2,15
- * 75 1,016 114,8 1,53
- * 100 0,988 117,6 1,18
- * 150 1,022 114,2 0,76
- * 200 0,939 122,5 0,61 <-- MIN time
- */
+* how many elems to keep as spare. During a deletion, an element
+* can be saved in a "free-list", not free()d immediately. When
+* latter insertions are performed, spare elems can be used instead
+* of malloc()ing new elems.
+*
+* about this param, some values for appending
+* 10 million elems into an empty list:
+* (#, time[sec], gain[%], gain/no[%])
+* 0 2,164 0,00 0,00 <-- feature disabled
+* 1 1,815 34,9 34,9
+* 2 1,446 71,8 35,9 <-- MAX gain/no
+* 3 1,347 81,7 27,23
+* 5 1,213 95,1 19,02
+* 8 1,064 110,0 13,75
+* 10 1,015 114,9 11,49 <-- MAX gain w/ likely sol
+* 15 1,019 114,5 7,63
+* 25 0,985 117,9 4,72
+* 50 1,088 107,6 2,15
+* 75 1,016 114,8 1,53
+* 100 0,988 117,6 1,18
+* 150 1,022 114,2 0,76
+* 200 0,939 122,5 0,61 <-- MIN time
+*/
#ifndef SIMCLIST_MAX_SPARE_ELEMS
#define SIMCLIST_MAX_SPARE_ELEMS 5
#endif
/* list dump declarations */
-#define SIMCLIST_DUMPFORMAT_VERSION 1 /* (short integer) version of fileformat managed by _dump* and _restore* functions */
+#define SIMCLIST_DUMPFORMAT_VERSION 1 /* (short integer) version of fileformat managed by _dump* and _restore* functions */
-#define SIMCLIST_DUMPFORMAT_HEADERLEN 30 /* length of the header */
+#define SIMCLIST_DUMPFORMAT_HEADERLEN 30 /* length of the header */
/* header for a list dump */
struct list_dump_header_s {
- uint16_t ver; /* version */
- int32_t timestamp_sec; /* dump timestamp, seconds since UNIX Epoch */
- int32_t timestamp_usec; /* dump timestamp, microseconds since timestamp_sec */
- int32_t rndterm; /* random value terminator -- terminates the data sequence */
-
- uint32_t totlistlen; /* sum of every element' size, bytes */
- uint32_t numels; /* number of elements */
- uint32_t elemlen; /* bytes length of an element, for constant-size lists, <= 0 otherwise */
- int32_t listhash; /* hash of the list at the time of dumping, or 0 if to be ignored */
+ uint16_t ver; /* version */
+ int32_t timestamp_sec; /* dump timestamp, seconds since UNIX Epoch */
+ int32_t timestamp_usec; /* dump timestamp, microseconds since timestamp_sec */
+ int32_t rndterm; /* random value terminator -- terminates the data sequence */
+
+ uint32_t totlistlen; /* sum of every element' size, bytes */
+ uint32_t numels; /* number of elements */
+ uint32_t elemlen; /* bytes length of an element, for constant-size lists, <= 0 otherwise */
+ int32_t listhash; /* hash of the list at the time of dumping, or 0 if to be ignored */
};
#endif
/* do not inline, this is recursive */
-static void list_sort_quicksort(list_t *restrict l, int versus, unsigned int first, struct list_entry_s *fel, unsigned int last, struct list_entry_s *lel);
+static void list_sort_quicksort(list_t *restrict l, int versus,
+ unsigned int first, struct list_entry_s *fel,
+ unsigned int last, struct list_entry_s *lel);
static inline void list_sort_selectionsort(list_t *restrict l, int versus,
- unsigned int first, struct list_entry_s *fel, unsigned int last, struct list_entry_s *lel);
+ unsigned int first, struct list_entry_s *fel,
+ unsigned int last, struct list_entry_s *lel);
static void *list_get_minmax(const list_t *restrict l, int versus);
static inline struct list_entry_s *list_findpos(const list_t *restrict l, int posstart);
/*
- * Random Number Generator
- *
- * The user is expected to seed the RNG (ie call srand()) if
- * SIMCLIST_SYSTEM_RNG is defined.
- *
- * Otherwise, a self-contained RNG based on LCG is used; see
- * http://en.wikipedia.org/wiki/Linear_congruential_generator .
- *
- * Facts pro local RNG:
- * 1. no need for the user to call srand() on his own
- * 2. very fast, possibly faster than OS
- * 3. avoid interference with user's RNG
- *
- * Facts pro system RNG:
- * 1. may be more accurate (irrelevant for SimCList randno purposes)
- * 2. why reinvent the wheel
- *
- * Default to local RNG for user's ease of use.
- */
+* Random Number Generator
+*
+* The user is expected to seed the RNG (ie call srand()) if
+* SIMCLIST_SYSTEM_RNG is defined.
+*
+* Otherwise, a self-contained RNG based on LCG is used; see
+* http://en.wikipedia.org/wiki/Linear_congruential_generator .
+*
+* Facts pro local RNG:
+* 1. no need for the user to call srand() on his own
+* 2. very fast, possibly faster than OS
+* 3. avoid interference with user's RNG
+*
+* Facts pro system RNG:
+* 1. may be more accurate (irrelevant for SimCList randno purposes)
+* 2. why reinvent the wheel
+*
+* Default to local RNG for user's ease of use.
+*/
#ifdef SIMCLIST_SYSTEM_RNG
/* keep track whether we initialized already (non-0) or not (0) */
static unsigned random_seed = 0;
/* use local RNG */
-static inline void seed_random(void)
-{
+static inline void seed_random(void) {
if (random_seed == 0)
- random_seed = (unsigned) getpid() ^ (unsigned) time(NULL);
+ random_seed = (unsigned)getpid() ^ (unsigned)time(NULL);
}
-static inline long get_random(void)
-{
+static inline long get_random(void) {
random_seed = (1664525 * random_seed + 1013904223);
return random_seed;
}
#else
/* use OS's random generator */
-#define seed_random()
-#define get_random() (rand())
+# define seed_random()
+# define get_random() (rand())
#endif
/* list initialization */
-KS_DECLARE(int) list_init(list_t *restrict l)
-{
- if (l == NULL)
- return -1;
+int list_init(list_t *restrict l) {
+ if (l == NULL) return -1;
seed_random();
l->numels = 0;
/* head/tail sentinels and mid pointer */
- l->head_sentinel = (struct list_entry_s *) malloc(sizeof(struct list_entry_s));
- l->tail_sentinel = (struct list_entry_s *) malloc(sizeof(struct list_entry_s));
+ l->head_sentinel = (struct list_entry_s *)malloc(sizeof(struct list_entry_s));
+ l->tail_sentinel = (struct list_entry_s *)malloc(sizeof(struct list_entry_s));
l->head_sentinel->next = l->tail_sentinel;
l->tail_sentinel->prev = l->head_sentinel;
l->head_sentinel->prev = l->tail_sentinel->next = l->mid = NULL;
l->iter_curentry = NULL;
/* free-list attributes */
- l->spareels = (struct list_entry_s **) malloc(SIMCLIST_MAX_SPARE_ELEMS * sizeof(struct list_entry_s *));
+ l->spareels = (struct list_entry_s **)malloc(SIMCLIST_MAX_SPARE_ELEMS * sizeof(struct list_entry_s *));
l->spareelsnum = 0;
#ifdef SIMCLIST_WITH_THREADS
return 0;
}
-KS_DECLARE(void) list_destroy(list_t *restrict l)
-{
+void list_destroy(list_t *restrict l) {
unsigned int i;
list_clear(l);
free(l->tail_sentinel);
}
-int list_attributes_setdefaults(list_t *restrict l)
-{
+int list_attributes_setdefaults(list_t *restrict l) {
l->attrs.comparator = NULL;
l->attrs.seeker = NULL;
}
/* setting list properties */
-KS_DECLARE(int) list_attributes_comparator(list_t *restrict l, element_comparator comparator_fun)
-{
- if (l == NULL)
- return -1;
+int list_attributes_comparator(list_t *restrict l, element_comparator comparator_fun) {
+ if (l == NULL) return -1;
l->attrs.comparator = comparator_fun;
return 0;
}
-KS_DECLARE(int) list_attributes_seeker(list_t *restrict l, element_seeker seeker_fun)
-{
- if (l == NULL)
- return -1;
+int list_attributes_seeker(list_t *restrict l, element_seeker seeker_fun) {
+ if (l == NULL) return -1;
l->attrs.seeker = seeker_fun;
assert(list_attrOk(l));
return 0;
}
-KS_DECLARE(int) list_attributes_copy(list_t *restrict l, element_meter metric_fun, int copy_data)
-{
- if (l == NULL || (metric_fun == NULL && copy_data != 0))
- return -1;
+int list_attributes_copy(list_t *restrict l, element_meter metric_fun, int copy_data) {
+ if (l == NULL || (metric_fun == NULL && copy_data != 0)) return -1;
l->attrs.meter = metric_fun;
l->attrs.copy_data = copy_data;
return 0;
}
-KS_DECLARE(int) list_attributes_hash_computer(list_t *restrict l, element_hash_computer hash_computer_fun)
-{
- if (l == NULL)
- return -1;
+int list_attributes_hash_computer(list_t *restrict l, element_hash_computer hash_computer_fun) {
+ if (l == NULL) return -1;
l->attrs.hasher = hash_computer_fun;
assert(list_attrOk(l));
return 0;
}
-KS_DECLARE(int) list_attributes_serializer(list_t *restrict l, element_serializer serializer_fun)
-{
- if (l == NULL)
- return -1;
+int list_attributes_serializer(list_t *restrict l, element_serializer serializer_fun) {
+ if (l == NULL) return -1;
l->attrs.serializer = serializer_fun;
assert(list_attrOk(l));
return 0;
}
-KS_DECLARE(int) list_attributes_unserializer(list_t *restrict l, element_unserializer unserializer_fun)
-{
- if (l == NULL)
- return -1;
+int list_attributes_unserializer(list_t *restrict l, element_unserializer unserializer_fun) {
+ if (l == NULL) return -1;
l->attrs.unserializer = unserializer_fun;
assert(list_attrOk(l));
return 0;
}
-KS_DECLARE(int) list_append(list_t *restrict l, const void *data)
-{
+int list_append(list_t *restrict l, const void *data) {
return list_insert_at(l, data, l->numels);
}
-KS_DECLARE(int) list_prepend(list_t *restrict l, const void *data)
-{
+int list_prepend(list_t *restrict l, const void *data) {
return list_insert_at(l, data, 0);
}
-KS_DECLARE(void *) list_fetch(list_t *restrict l)
-{
+void *list_fetch(list_t *restrict l) {
return list_extract_at(l, 0);
}
-KS_DECLARE(void *) list_get_at(const list_t *restrict l, unsigned int pos)
-{
+void *list_get_at(const list_t *restrict l, unsigned int pos) {
struct list_entry_s *tmp;
tmp = list_findpos(l, pos);
return (tmp != NULL ? tmp->data : NULL);
}
-KS_DECLARE(void *) list_get_max(const list_t *restrict l)
-{
+void *list_get_max(const list_t *restrict l) {
return list_get_minmax(l, +1);
}
-KS_DECLARE(void *) list_get_min(const list_t *restrict l)
-{
+void *list_get_min(const list_t *restrict l) {
return list_get_minmax(l, -1);
}
/* REQUIRES {list->numels >= 1}
- * return the min (versus < 0) or max value (v > 0) in l */
-static void *list_get_minmax(const list_t *restrict l, int versus)
-{
+* return the min (versus < 0) or max value (v > 0) in l */
+static void *list_get_minmax(const list_t *restrict l, int versus) {
void *curminmax;
struct list_entry_s *s;
}
/* set tmp to point to element at index posstart in l */
-static inline struct list_entry_s *list_findpos(const list_t *restrict l, int posstart)
-{
+static inline struct list_entry_s *list_findpos(const list_t *restrict l, int posstart) {
struct list_entry_s *ptr;
float x;
int i;
/* accept 1 slot overflow for fetching head and tail sentinels */
- if (posstart < -1 || posstart > (int) l->numels)
- return NULL;
+ if (posstart < -1 || posstart >(int)l->numels) return NULL;
- x = (float) (posstart + 1) / l->numels;
+ x = (float)(posstart + 1) / l->numels;
if (x <= 0.25) {
/* first quarter: get to posstart from head */
for (i = -1, ptr = l->head_sentinel; i < posstart; ptr = ptr->next, i++);
- } else if (x < 0.5) {
+ }
+ else if (x < 0.5) {
/* second quarter: get to posstart from mid */
for (i = (l->numels - 1) / 2, ptr = l->mid; i > posstart; ptr = ptr->prev, i--);
- } else if (x <= 0.75) {
+ }
+ else if (x <= 0.75) {
/* third quarter: get to posstart from mid */
for (i = (l->numels - 1) / 2, ptr = l->mid; i < posstart; ptr = ptr->next, i++);
- } else {
+ }
+ else {
/* fourth quarter: get to posstart from tail */
for (i = l->numels, ptr = l->tail_sentinel; i > posstart; ptr = ptr->prev, i--);
}
return ptr;
}
-KS_DECLARE(void *) list_extract_at(list_t *restrict l, unsigned int pos)
-{
+void *list_extract_at(list_t *restrict l, unsigned int pos) {
struct list_entry_s *tmp;
void *data;
- if (l->iter_active || pos >= l->numels)
- return NULL;
+ if (l->iter_active || pos >= l->numels) return NULL;
tmp = list_findpos(l, pos);
data = tmp->data;
- tmp->data = NULL; /* save data from list_drop_elem() free() */
+ tmp->data = NULL; /* save data from list_drop_elem() free() */
list_drop_elem(l, tmp, pos);
l->numels--;
return data;
}
-KS_DECLARE(int) list_insert_at(list_t *restrict l, const void *data, unsigned int pos)
-{
+int list_insert_at(list_t *restrict l, const void *data, unsigned int pos) {
struct list_entry_s *lent, *succ, *prec;
- if (l->iter_active || pos > l->numels)
- return -1;
+ if (l->iter_active || pos > l->numels) return -1;
/* this code optimizes malloc() with a free-list */
if (l->spareelsnum > 0) {
lent = l->spareels[l->spareelsnum - 1];
l->spareelsnum--;
- } else {
- lent = (struct list_entry_s *) malloc(sizeof(struct list_entry_s));
+ }
+ else {
+ lent = (struct list_entry_s *)malloc(sizeof(struct list_entry_s));
if (lent == NULL)
return -1;
}
if (l->attrs.copy_data) {
/* make room for user' data (has to be copied) */
size_t datalen = l->attrs.meter(data);
- lent->data = (struct list_entry_s *) malloc(datalen);
+ lent->data = (struct list_entry_s *)malloc(datalen);
memcpy(lent->data, data, datalen);
- } else {
- lent->data = (void *) data;
+ }
+ else {
+ lent->data = (void*)data;
}
/* actually append element */
l->numels++;
/* fix mid pointer */
- if (l->numels == 1) { /* first element, set pointer */
+ if (l->numels == 1) { /* first element, set pointer */
l->mid = lent;
- } else if (l->numels % 2) { /* now odd */
- if (pos >= (l->numels - 1) / 2)
- l->mid = l->mid->next;
- } else { /* now even */
- if (pos <= (l->numels - 1) / 2)
- l->mid = l->mid->prev;
+ }
+ else if (l->numels % 2) { /* now odd */
+ if (pos >= (l->numels - 1) / 2) l->mid = l->mid->next;
+ }
+ else { /* now even */
+ if (pos <= (l->numels - 1) / 2) l->mid = l->mid->prev;
}
assert(list_repOk(l));
return 1;
}
-KS_DECLARE(int) list_delete(list_t *restrict l, const void *data)
-{
+int list_delete(list_t *restrict l, const void *data) {
int pos, r;
pos = list_locate(l, data);
return 0;
}
-KS_DECLARE(int) list_delete_at(list_t *restrict l, unsigned int pos)
-{
+int list_delete_at(list_t *restrict l, unsigned int pos) {
struct list_entry_s *delendo;
- if (l->iter_active || pos >= l->numels)
- return -1;
+ if (l->iter_active || pos >= l->numels) return -1;
delendo = list_findpos(l, pos);
assert(list_repOk(l));
- return 0;
+ return 0;
}
-KS_DECLARE(int) list_delete_range(list_t *restrict l, unsigned int posstart, unsigned int posend)
-{
+int list_delete_range(list_t *restrict l, unsigned int posstart, unsigned int posend) {
struct list_entry_s *lastvalid, *tmp, *tmp2;
unsigned int numdel, midposafter, i;
int movedx;
- if (l->iter_active || posend < posstart || posend >= l->numels)
- return -1;
+ if (l->iter_active || posend < posstart || posend >= l->numels) return -1;
numdel = posend - posstart + 1;
- if (numdel == l->numels)
- return list_clear(l);
+ if (numdel == l->numels) return list_clear(l);
- tmp = list_findpos(l, posstart); /* first el to be deleted */
- lastvalid = tmp->prev; /* last valid element */
+ tmp = list_findpos(l, posstart); /* first el to be deleted */
+ lastvalid = tmp->prev; /* last valid element */
midposafter = (l->numels - 1 - numdel) / 2;
midposafter = midposafter < posstart ? midposafter : midposafter + numdel;
movedx = midposafter - (l->numels - 1) / 2;
- if (movedx > 0) { /* move right */
- for (i = 0; i < (unsigned int) movedx; l->mid = l->mid->next, i++);
- } else { /* move left */
+ if (movedx > 0) { /* move right */
+ for (i = 0; i < (unsigned int)movedx; l->mid = l->mid->next, i++);
+ }
+ else { /* move left */
movedx = -movedx;
- for (i = 0; i < (unsigned int) movedx; l->mid = l->mid->prev, i++);
+ for (i = 0; i < (unsigned int)movedx; l->mid = l->mid->prev, i++);
}
assert(posstart == 0 || lastvalid != l->head_sentinel);
for (; i <= posend; i++) {
tmp2 = tmp;
tmp = tmp->next;
- if (tmp2->data != NULL)
- free(tmp2->data);
+ if (tmp2->data != NULL) free(tmp2->data);
if (l->spareelsnum < SIMCLIST_MAX_SPARE_ELEMS) {
l->spareels[l->spareelsnum++] = tmp2;
- } else {
+ }
+ else {
free(tmp2);
}
}
- } else {
+ }
+ else {
/* only free containers */
for (; i <= posend; i++) {
tmp2 = tmp;
tmp = tmp->next;
if (l->spareelsnum < SIMCLIST_MAX_SPARE_ELEMS) {
l->spareels[l->spareelsnum++] = tmp2;
- } else {
+ }
+ else {
free(tmp2);
}
}
return numdel;
}
-KS_DECLARE(int) list_clear(list_t *restrict l)
-{
+int list_clear(list_t *restrict l) {
struct list_entry_s *s;
unsigned int numels;
/* will be returned */
numels = l->numels;
- if (l->iter_active)
- return -1;
+ if (l->iter_active) return -1;
- if (l->attrs.copy_data) { /* also free user data */
- /* spare a loop conditional with two loops: spareing elems and freeing elems */
+ if (l->attrs.copy_data) { /* also free user data */
+ /* spare a loop conditional with two loops: spareing elems and freeing elems */
for (s = l->head_sentinel->next; l->spareelsnum < SIMCLIST_MAX_SPARE_ELEMS && s != l->tail_sentinel; s = s->next) {
/* move elements as spares as long as there is room */
- if (s->data != NULL)
- free(s->data);
+ if (s->data != NULL) free(s->data);
l->spareels[l->spareelsnum++] = s;
}
while (s != l->tail_sentinel) {
/* free the remaining elems */
- if (s->data != NULL)
- free(s->data);
+ if (s->data != NULL) free(s->data);
s = s->next;
free(s->prev);
}
l->head_sentinel->next = l->tail_sentinel;
l->tail_sentinel->prev = l->head_sentinel;
- } else { /* only free element containers */
- /* spare a loop conditional with two loops: spareing elems and freeing elems */
+ }
+ else { /* only free element containers */
+ /* spare a loop conditional with two loops: spareing elems and freeing elems */
for (s = l->head_sentinel->next; l->spareelsnum < SIMCLIST_MAX_SPARE_ELEMS && s != l->tail_sentinel; s = s->next) {
/* move elements as spares as long as there is room */
l->spareels[l->spareelsnum++] = s;
return numels;
}
-KS_DECLARE(unsigned int) list_size(const list_t *restrict l)
-{
+unsigned int list_size(const list_t *restrict l) {
return l->numels;
}
-KS_DECLARE(int) list_empty(const list_t *restrict l)
-{
+int list_empty(const list_t *restrict l) {
return (l->numels == 0);
}
-KS_DECLARE(int) list_locate(const list_t *restrict l, const void *data)
-{
+int list_locate(const list_t *restrict l, const void *data) {
struct list_entry_s *el;
int pos = 0;
if (l->attrs.comparator != NULL) {
/* use comparator */
for (el = l->head_sentinel->next; el != l->tail_sentinel; el = el->next, pos++) {
- if (l->attrs.comparator(data, el->data) == 0)
- break;
+ if (l->attrs.comparator(data, el->data) == 0) break;
}
- } else {
+ }
+ else {
/* compare references */
for (el = l->head_sentinel->next; el != l->tail_sentinel; el = el->next, pos++) {
- if (el->data == data)
- break;
+ if (el->data == data) break;
}
}
- if (el == l->tail_sentinel)
- return -1;
+ if (el == l->tail_sentinel) return -1;
return pos;
}
-KS_DECLARE(void *) list_seek(list_t *restrict l, const void *indicator)
-{
+void *list_seek(list_t *restrict l, const void *indicator) {
const struct list_entry_s *iter;
- if (l->attrs.seeker == NULL)
- return NULL;
+ if (l->attrs.seeker == NULL) return NULL;
for (iter = l->head_sentinel->next; iter != l->tail_sentinel; iter = iter->next) {
- if (l->attrs.seeker(iter->data, indicator) != 0)
- return iter->data;
+ if (l->attrs.seeker(iter->data, indicator) != 0) return iter->data;
}
return NULL;
}
-KS_DECLARE(int) list_contains(const list_t *restrict l, const void *data)
-{
+int list_contains(const list_t *restrict l, const void *data) {
return (list_locate(l, data) >= 0);
}
-KS_DECLARE(int) list_concat(const list_t *l1, const list_t *l2, list_t *restrict dest)
-{
+int list_concat(const list_t *l1, const list_t *l2, list_t *restrict dest) {
struct list_entry_s *el, *srcel;
unsigned int cnt;
int err;
srcel = l1->head_sentinel->next;
el = dest->head_sentinel;
while (srcel != l1->tail_sentinel) {
- el->next = (struct list_entry_s *) malloc(sizeof(struct list_entry_s));
+ el->next = (struct list_entry_s *)malloc(sizeof(struct list_entry_s));
el->next->prev = el;
el = el->next;
el->data = srcel->data;
srcel = srcel->next;
}
- dest->mid = el; /* approximate position (adjust later) */
- /* copy list 2 */
+ dest->mid = el; /* approximate position (adjust later) */
+ /* copy list 2 */
srcel = l2->head_sentinel->next;
while (srcel != l2->tail_sentinel) {
- el->next = (struct list_entry_s *) malloc(sizeof(struct list_entry_s));
+ el->next = (struct list_entry_s *)malloc(sizeof(struct list_entry_s));
el->next->prev = el;
el = el->next;
el->data = srcel->data;
/* fix mid pointer */
err = l2->numels - l1->numels;
- if ((err + 1) / 2 > 0) { /* correct pos RIGHT (err-1)/2 moves */
+ if ((err + 1) / 2 > 0) { /* correct pos RIGHT (err-1)/2 moves */
err = (err + 1) / 2;
- for (cnt = 0; cnt < (unsigned int) err; cnt++)
- dest->mid = dest->mid->next;
- } else if (err / 2 < 0) { /* correct pos LEFT (err/2)-1 moves */
+ for (cnt = 0; cnt < (unsigned int)err; cnt++) dest->mid = dest->mid->next;
+ }
+ else if (err / 2 < 0) { /* correct pos LEFT (err/2)-1 moves */
err = -err / 2;
- for (cnt = 0; cnt < (unsigned int) err; cnt++)
- dest->mid = dest->mid->prev;
+ for (cnt = 0; cnt < (unsigned int)err; cnt++) dest->mid = dest->mid->prev;
}
assert(!(list_repOk(l1) && list_repOk(l2)) || list_repOk(dest));
return 0;
}
-KS_DECLARE(int) list_sort(list_t *restrict l, int versus)
-{
- if (l->iter_active || l->attrs.comparator == NULL) /* cannot modify list in the middle of an iteration */
+int list_sort(list_t *restrict l, int versus) {
+ if (l->iter_active || l->attrs.comparator == NULL) /* cannot modify list in the middle of an iteration */
return -1;
if (l->numels <= 1)
struct list_entry_s *fel, *lel;
};
-static void *list_sort_quicksort_threadwrapper(void *wrapped_params)
-{
- struct list_sort_wrappedparams *wp = (struct list_sort_wrappedparams *) wrapped_params;
+static void *list_sort_quicksort_threadwrapper(void *wrapped_params) {
+ struct list_sort_wrappedparams *wp = (struct list_sort_wrappedparams *)wrapped_params;
list_sort_quicksort(wp->l, wp->versus, wp->first, wp->fel, wp->last, wp->lel);
free(wp);
pthread_exit(NULL);
#endif
static inline void list_sort_selectionsort(list_t *restrict l, int versus,
- unsigned int first, struct list_entry_s *fel, unsigned int last, struct list_entry_s *lel)
-{
+ unsigned int first, struct list_entry_s *fel,
+ unsigned int last, struct list_entry_s *lel) {
struct list_entry_s *cursor, *toswap, *firstunsorted;
void *tmpdata;
- if (last <= first) /* <= 1-element lists are always sorted */
+ if (last <= first) /* <= 1-element lists are always sorted */
return;
for (firstunsorted = fel; firstunsorted != lel; firstunsorted = firstunsorted->next) {
/* find min or max in the remainder of the list */
for (toswap = firstunsorted, cursor = firstunsorted->next; cursor != lel->next; cursor = cursor->next)
- if (l->attrs.comparator(toswap->data, cursor->data) * -versus > 0)
- toswap = cursor;
- if (toswap != firstunsorted) { /* swap firstunsorted with toswap */
+ if (l->attrs.comparator(toswap->data, cursor->data) * -versus > 0) toswap = cursor;
+ if (toswap != firstunsorted) { /* swap firstunsorted with toswap */
tmpdata = firstunsorted->data;
firstunsorted->data = toswap->data;
toswap->data = tmpdata;
}
}
-static void list_sort_quicksort(list_t *restrict l, int versus, unsigned int first, struct list_entry_s *fel, unsigned int last, struct list_entry_s *lel)
-{
+static void list_sort_quicksort(list_t *restrict l, int versus,
+ unsigned int first, struct list_entry_s *fel,
+ unsigned int last, struct list_entry_s *lel) {
unsigned int pivotid;
unsigned int i;
register struct list_entry_s *pivot;
#endif
- if (last <= first) /* <= 1-element lists are always sorted */
+ if (last <= first) /* <= 1-element lists are always sorted */
return;
if (last - first + 1 <= SIMCLIST_MINQUICKSORTELS) {
}
/* base of iteration: one element list */
- if (!(last > first))
- return;
+ if (!(last > first)) return;
pivotid = (get_random() % (last - first + 1));
/* pivotid = (last - first + 1) / 2; */
/* find pivot */
if (pivotid < (last - first + 1) / 2) {
for (i = 0, pivot = fel; i < pivotid; pivot = pivot->next, i++);
- } else {
+ }
+ else {
for (i = last - first, pivot = lel; i > pivotid; pivot = pivot->prev, i--);
}
}
/* now either left points to pivot (end run), or right */
- if (right == pivot) { /* left part longer */
+ if (right == pivot) { /* left part longer */
while (left != pivot) {
if (l->attrs.comparator(left->data, pivot->data) * -versus > 0) {
tmpdata = left->data;
pivot->data = tmpdata;
pivot = pivot->prev;
pivotid--;
- if (pivot == left)
- break;
- } else {
+ if (pivot == left) break;
+ }
+ else {
left = left->next;
}
}
- } else { /* right part longer */
+ }
+ else { /* right part longer */
while (right != pivot) {
if (l->attrs.comparator(right->data, pivot->data) * -versus < 0) {
/* move current right before pivot */
pivot->data = tmpdata;
pivot = pivot->next;
pivotid++;
- if (pivot == right)
- break;
- } else {
+ if (pivot == right) break;
+ }
+ else {
right = right->prev;
}
}
if (pivotid > 0) {
/* prepare wrapped args, then start thread */
if (l->threadcount < SIMCLIST_MAXTHREADS - 1) {
- struct list_sort_wrappedparams *wp = (struct list_sort_wrappedparams *) malloc(sizeof(struct list_sort_wrappedparams));
+ struct list_sort_wrappedparams *wp = (struct list_sort_wrappedparams *)malloc(sizeof(struct list_sort_wrappedparams));
l->threadcount++;
traised = 1;
wp->l = l;
traised = 0;
list_sort_quicksort(l, versus, first, fel, first + pivotid - 1, pivot->prev);
}
- } else {
+ }
+ else {
list_sort_quicksort(l, versus, first, fel, first + pivotid - 1, pivot->prev);
}
}
- if (first + pivotid < last)
- list_sort_quicksort(l, versus, first + pivotid + 1, pivot->next, last, lel);
+ if (first + pivotid < last) list_sort_quicksort(l, versus, first + pivotid + 1, pivot->next, last, lel);
if (traised) {
- pthread_join(tid, (void **) NULL);
+ pthread_join(tid, (void **)NULL);
l->threadcount--;
}
#else
- if (pivotid > 0)
- list_sort_quicksort(l, versus, first, fel, first + pivotid - 1, pivot->prev);
- if (first + pivotid < last)
- list_sort_quicksort(l, versus, first + pivotid + 1, pivot->next, last, lel);
+ if (pivotid > 0) list_sort_quicksort(l, versus, first, fel, first + pivotid - 1, pivot->prev);
+ if (first + pivotid < last) list_sort_quicksort(l, versus, first + pivotid + 1, pivot->next, last, lel);
#endif
}
-KS_DECLARE(int) list_iterator_start(list_t *restrict l)
-{
- if (l->iter_active)
- return 0;
+int list_iterator_start(list_t *restrict l) {
+ if (l->iter_active) return 0;
l->iter_pos = 0;
l->iter_active = 1;
l->iter_curentry = l->head_sentinel->next;
return 1;
}
-KS_DECLARE(void *) list_iterator_next(list_t *restrict l)
-{
+void *list_iterator_next(list_t *restrict l) {
void *toret;
- if (!l->iter_active)
- return NULL;
+ if (!l->iter_active) return NULL;
toret = l->iter_curentry->data;
l->iter_curentry = l->iter_curentry->next;
return toret;
}
-KS_DECLARE(int) list_iterator_hasnext(const list_t *restrict l)
-{
- if (!l->iter_active)
- return 0;
+int list_iterator_hasnext(const list_t *restrict l) {
+ if (!l->iter_active) return 0;
return (l->iter_pos < l->numels);
}
-KS_DECLARE(int) list_iterator_stop(list_t *restrict l)
-{
- if (!l->iter_active)
- return 0;
+int list_iterator_stop(list_t *restrict l) {
+ if (!l->iter_active) return 0;
l->iter_pos = 0;
l->iter_active = 0;
return 1;
}
-KS_DECLARE(int) list_hash(const list_t *restrict l, list_hash_t *restrict hash)
-{
+int list_hash(const list_t *restrict l, list_hash_t *restrict hash) {
struct list_entry_s *x;
list_hash_t tmphash;
if (l->attrs.hasher == NULL) {
#ifdef SIMCLIST_ALLOW_LOCATIONBASED_HASHES
/* ENABLE WITH CARE !! */
-#warning "Memlocation-based hash is consistent only for testing modification in the same program run."
- int i;
+ #warning "Memlocation-based hash is consistent only for testing modification in the same program run."
+ int i;
/* only use element references */
for (x = l->head_sentinel->next; x != l->tail_sentinel; x = x->next) {
for (i = 0; i < sizeof(x->data); i++) {
- tmphash += (tmphash ^ (uintptr_t) x->data);
+ tmphash += (tmphash ^ (uintptr_t)x->data);
}
tmphash += tmphash % l->numels;
}
#else
return -1;
#endif
- } else {
+ }
+ else {
/* hash each element with the user-given function */
for (x = l->head_sentinel->next; x != l->tail_sentinel; x = x->next) {
tmphash += tmphash ^ l->attrs.hasher(x->data);
}
#ifndef SIMCLIST_NO_DUMPRESTORE
-KS_DECLARE(int) list_dump_getinfo_filedescriptor(int fd, list_dump_info_t *restrict info)
-{
+int list_dump_getinfo_filedescriptor(int fd, list_dump_info_t *restrict info) {
int32_t terminator_head, terminator_tail;
uint32_t elemlen;
off_t hop;
if (elemlen > 0) {
/* constant length, hop by size only */
hop = info->list_size;
- } else {
+ }
+ else {
/* non-constant length, hop by size + all element length blocks */
- hop = info->list_size + elemlen * info->list_numels;
+ hop = info->list_size + elemlen*info->list_numels;
}
if (lseek(fd, hop, SEEK_CUR) == -1) {
return -1;
return 0;
}
-KS_DECLARE(int) list_dump_getinfo_file(const char *restrict filename, list_dump_info_t *restrict info)
-{
+int list_dump_getinfo_file(const char *restrict filename, list_dump_info_t *restrict info) {
int fd, ret;
fd = open(filename, O_RDONLY, 0);
- if (fd < 0)
- return -1;
+ if (fd < 0) return -1;
ret = list_dump_getinfo_filedescriptor(fd, info);
close(fd);
return ret;
}
-KS_DECLARE(int) list_dump_filedescriptor(const list_t *restrict l, int fd, size_t *restrict len)
-{
+int list_dump_filedescriptor(const list_t *restrict l, int fd, size_t *restrict len) {
struct list_entry_s *x;
void *ser_buf;
uint32_t bufsize;
/**** DUMP FORMAT ****
- [ ver timestamp | totlen numels elemlen hash | DATA ]
+ [ ver timestamp | totlen numels elemlen hash | DATA ]
- where DATA can be:
- @ for constant-size list (element size is constant; elemlen > 0)
- [ elem elem ... elem ]
- @ for other lists (element size dictated by element_meter each time; elemlen <= 0)
- [ size elem size elem ... size elem ]
+ where DATA can be:
+ @ for constant-size list (element size is constant; elemlen > 0)
+ [ elem elem ... elem ]
+ @ for other lists (element size dictated by element_meter each time; elemlen <= 0)
+ [ size elem size elem ... size elem ]
- all integers are encoded in NETWORK BYTE FORMAT
- *****/
+ all integers are encoded in NETWORK BYTE FORMAT
+ *****/
/* prepare HEADER */
header.timestamp_sec = htonl(timeofday.tv_sec);
header.timestamp_usec = htonl(timeofday.tv_usec);
- header.rndterm = htonl((int32_t) get_random());
+ header.rndterm = htonl((int32_t)get_random());
/* total list size is postprocessed afterwards */
/* could not compute list hash! */
return -1;
}
- } else {
+ }
+ else {
header.listhash = htonl(0);
}
if (l->numels > 0) {
/* SPECULATE that the list has constant element size */
- if (l->attrs.serializer != NULL) { /* user user-specified serializer */
- /* get preliminary length of serialized element in header.elemlen */
+ if (l->attrs.serializer != NULL) { /* user user-specified serializer */
+ /* get preliminary length of serialized element in header.elemlen */
ser_buf = l->attrs.serializer(l->head_sentinel->next->data, &header.elemlen);
free(ser_buf);
/* request custom serialization of each element */
for (x = l->head_sentinel->next; x != l->tail_sentinel; x = x->next) {
ser_buf = l->attrs.serializer(x->data, &bufsize);
header.totlistlen += bufsize;
- if (header.elemlen != 0) { /* continue on speculation */
+ if (header.elemlen != 0) { /* continue on speculation */
if (header.elemlen != bufsize) {
free(ser_buf);
/* constant element length speculation broken! */
}
/* speculation confirmed */
WRITE_ERRCHECK(fd, ser_buf, bufsize);
- } else { /* speculation found broken */
+ }
+ else { /* speculation found broken */
WRITE_ERRCHECK(fd, &bufsize, sizeof(size_t));
WRITE_ERRCHECK(fd, ser_buf, bufsize);
}
free(ser_buf);
}
- } else if (l->attrs.meter != NULL) {
- header.elemlen = (uint32_t) l->attrs.meter(l->head_sentinel->next->data);
+ }
+ else if (l->attrs.meter != NULL) {
+ header.elemlen = (uint32_t)l->attrs.meter(l->head_sentinel->next->data);
/* serialize the element straight from its data */
for (x = l->head_sentinel->next; x != l->tail_sentinel; x = x->next) {
continue;
}
WRITE_ERRCHECK(fd, x->data, bufsize);
- } else {
+ }
+ else {
WRITE_ERRCHECK(fd, &bufsize, sizeof(size_t));
WRITE_ERRCHECK(fd, x->data, bufsize);
}
}
/* write random terminator */
- WRITE_ERRCHECK(fd, &header.rndterm, sizeof(header.rndterm)); /* list terminator */
+ WRITE_ERRCHECK(fd, &header.rndterm, sizeof(header.rndterm)); /* list terminator */
- /* write header */
+ /* write header */
lseek(fd, 0, SEEK_SET);
- WRITE_ERRCHECK(fd, &header.ver, sizeof(header.ver)); /* version */
- WRITE_ERRCHECK(fd, &header.timestamp_sec, sizeof(header.timestamp_sec)); /* timestamp seconds */
- WRITE_ERRCHECK(fd, &header.timestamp_usec, sizeof(header.timestamp_usec)); /* timestamp microseconds */
- WRITE_ERRCHECK(fd, &header.rndterm, sizeof(header.rndterm)); /* random terminator */
+ WRITE_ERRCHECK(fd, &header.ver, sizeof(header.ver)); /* version */
+ WRITE_ERRCHECK(fd, &header.timestamp_sec, sizeof(header.timestamp_sec)); /* timestamp seconds */
+ WRITE_ERRCHECK(fd, &header.timestamp_usec, sizeof(header.timestamp_usec)); /* timestamp microseconds */
+ WRITE_ERRCHECK(fd, &header.rndterm, sizeof(header.rndterm)); /* random terminator */
- WRITE_ERRCHECK(fd, &header.totlistlen, sizeof(header.totlistlen)); /* total length of elements */
- WRITE_ERRCHECK(fd, &header.numels, sizeof(header.numels)); /* number of elements */
- WRITE_ERRCHECK(fd, &header.elemlen, sizeof(header.elemlen)); /* size of each element, or 0 for independent */
- WRITE_ERRCHECK(fd, &header.listhash, sizeof(header.listhash)); /* list hash, or 0 for "ignore" */
+ WRITE_ERRCHECK(fd, &header.totlistlen, sizeof(header.totlistlen)); /* total length of elements */
+ WRITE_ERRCHECK(fd, &header.numels, sizeof(header.numels)); /* number of elements */
+ WRITE_ERRCHECK(fd, &header.elemlen, sizeof(header.elemlen)); /* size of each element, or 0 for independent */
+ WRITE_ERRCHECK(fd, &header.listhash, sizeof(header.listhash)); /* list hash, or 0 for "ignore" */
- /* possibly store total written length in "len" */
+ /* possibly store total written length in "len" */
if (len != NULL) {
*len = sizeof(header) + ntohl(header.totlistlen);
}
return 0;
}
-KS_DECLARE(int) list_restore_filedescriptor(list_t *restrict l, int fd, size_t *restrict len)
-{
+int list_restore_filedescriptor(list_t *restrict l, int fd, size_t *restrict len) {
struct list_dump_header_s header;
unsigned long cnt;
void *buf;
list_append(l, l->attrs.unserializer(buf, &elsize));
totmemorylen += elsize;
}
- } else {
+ }
+ else {
/* copy verbatim into memory */
for (cnt = 0; cnt < header.numels; cnt++) {
buf = malloc(header.elemlen);
totmemorylen = header.numels * header.elemlen;
}
totreadlen = header.numels * header.elemlen;
- } else {
+ }
+ else {
/* elements have variable size. Each element is preceded by its size */
if (l->attrs.unserializer != NULL) {
/* use unserializer */
for (cnt = 0; cnt < header.numels; cnt++) {
READ_ERRCHECK(fd, &elsize, sizeof(elsize));
- buf = malloc((size_t) elsize);
+ buf = malloc((size_t)elsize);
READ_ERRCHECK(fd, buf, elsize);
totreadlen += elsize;
list_append(l, l->attrs.unserializer(buf, &elsize));
totmemorylen += elsize;
}
- } else {
+ }
+ else {
/* copy verbatim into memory */
for (cnt = 0; cnt < header.numels; cnt++) {
READ_ERRCHECK(fd, &elsize, sizeof(elsize));
}
}
- READ_ERRCHECK(fd, &elsize, sizeof(elsize)); /* read list terminator */
+ READ_ERRCHECK(fd, &elsize, sizeof(elsize)); /* read list terminator */
elsize = ntohl(elsize);
/* possibly verify the list consistency */
/* wrt hash */
/* don't do that
- if (header.listhash != 0 && header.listhash != list_hash(l)) {
- errno = ECANCELED;
- return -1;
- }
- */
+ if (header.listhash != 0 && header.listhash != list_hash(l)) {
+ errno = ECANCELED;
+ return -1;
+ }
+ */
/* wrt header */
- if (totreadlen != header.totlistlen && (int32_t) elsize == header.rndterm) {
+ if (totreadlen != header.totlistlen && (int32_t)elsize == header.rndterm) {
errno = EPROTO;
return -1;
}
return 0;
}
-KS_DECLARE(int) list_dump_file(const list_t *restrict l, const char *restrict filename, size_t *restrict len)
-{
+int list_dump_file(const list_t *restrict l, const char *restrict filename, size_t *restrict len) {
int fd, oflag, mode;
#ifndef _WIN32
mode = _S_IRUSR | _S_IWUSR | _S_IRGRP | _S_IROTH;
#endif
fd = open(filename, oflag, mode);
- if (fd < 0)
- return -1;
+ if (fd < 0) return -1;
list_dump_filedescriptor(l, fd, len);
close(fd);
return 0;
}
-KS_DECLARE(int) list_restore_file(list_t *restrict l, const char *restrict filename, size_t *restrict len)
-{
+int list_restore_file(list_t *restrict l, const char *restrict filename, size_t *restrict len) {
int fd;
fd = open(filename, O_RDONLY, 0);
- if (fd < 0)
- return -1;
+ if (fd < 0) return -1;
list_restore_filedescriptor(l, fd, len);
close(fd);
#endif /* ifndef SIMCLIST_NO_DUMPRESTORE */
-static int list_drop_elem(list_t *restrict l, struct list_entry_s *tmp, unsigned int pos)
-{
- if (tmp == NULL)
- return -1;
+static int list_drop_elem(list_t *restrict l, struct list_entry_s *tmp, unsigned int pos) {
+ if (tmp == NULL) return -1;
/* fix mid pointer. This is wrt the PRE situation */
- if (l->numels % 2) { /* now odd */
- /* sort out the base case by hand */
- if (l->numels == 1)
- l->mid = NULL;
- else if (pos >= l->numels / 2)
- l->mid = l->mid->prev;
- } else { /* now even */
- if (pos < l->numels / 2)
- l->mid = l->mid->next;
+ if (l->numels % 2) { /* now odd */
+ /* sort out the base case by hand */
+ if (l->numels == 1) l->mid = NULL;
+ else if (pos >= l->numels / 2) l->mid = l->mid->prev;
+ }
+ else { /* now even */
+ if (pos < l->numels / 2) l->mid = l->mid->next;
}
tmp->prev->next = tmp->next;
if (l->spareelsnum < SIMCLIST_MAX_SPARE_ELEMS) {
l->spareels[l->spareelsnum++] = tmp;
- } else {
+ }
+ else {
free(tmp);
}
}
/* ready-made comparators and meters */
-#define SIMCLIST_NUMBER_COMPARATOR(type) KS_DECLARE(int) list_comparator_##type(const void *a, const void *b) { return( *(type *)a < *(type *)b) - (*(type *)a > *(type *)b); }
+#define SIMCLIST_NUMBER_COMPARATOR(type) int list_comparator_##type(const void *a, const void *b) { return( *(type *)a < *(type *)b) - (*(type *)a > *(type *)b); }
SIMCLIST_NUMBER_COMPARATOR(int8_t)
-SIMCLIST_NUMBER_COMPARATOR(int16_t) SIMCLIST_NUMBER_COMPARATOR(int32_t) SIMCLIST_NUMBER_COMPARATOR(int64_t)
- SIMCLIST_NUMBER_COMPARATOR(uint8_t) SIMCLIST_NUMBER_COMPARATOR(uint16_t) SIMCLIST_NUMBER_COMPARATOR(uint32_t) SIMCLIST_NUMBER_COMPARATOR(uint64_t)
- SIMCLIST_NUMBER_COMPARATOR(float) SIMCLIST_NUMBER_COMPARATOR(double)
+SIMCLIST_NUMBER_COMPARATOR(int16_t)
+SIMCLIST_NUMBER_COMPARATOR(int32_t)
+SIMCLIST_NUMBER_COMPARATOR(int64_t)
-KS_DECLARE(int) list_comparator_string(const void *a, const void *b)
-{
- return strcmp((const char *) b, (const char *) a);
-}
+SIMCLIST_NUMBER_COMPARATOR(uint8_t)
+SIMCLIST_NUMBER_COMPARATOR(uint16_t)
+SIMCLIST_NUMBER_COMPARATOR(uint32_t)
+SIMCLIST_NUMBER_COMPARATOR(uint64_t)
+
+SIMCLIST_NUMBER_COMPARATOR(float)
+SIMCLIST_NUMBER_COMPARATOR(double)
+
+int list_comparator_string(const void *a, const void *b) { return strcmp((const char *)b, (const char *)a); }
/* ready-made metric functions */
-#define SIMCLIST_METER(type) KS_DECLARE(size_t) list_meter_##type(const void *el) { if (el) { /* kill compiler whinge */ } return sizeof(type); }
+#define SIMCLIST_METER(type) size_t list_meter_##type(const void *el) { if (el) { /* kill compiler whinge */ } return sizeof(type); }
-SIMCLIST_METER(int8_t) SIMCLIST_METER(int16_t) SIMCLIST_METER(int32_t) SIMCLIST_METER(int64_t)
- SIMCLIST_METER(uint8_t) SIMCLIST_METER(uint16_t) SIMCLIST_METER(uint32_t) SIMCLIST_METER(uint64_t)
- SIMCLIST_METER(float) SIMCLIST_METER(double)
+SIMCLIST_METER(int8_t)
+SIMCLIST_METER(int16_t)
+SIMCLIST_METER(int32_t)
+SIMCLIST_METER(int64_t)
-KS_DECLARE(size_t) list_meter_string(const void *el)
-{
- return strlen((const char *) el) + 1;
-}
+SIMCLIST_METER(uint8_t)
+SIMCLIST_METER(uint16_t)
+SIMCLIST_METER(uint32_t)
+SIMCLIST_METER(uint64_t)
+
+SIMCLIST_METER(float)
+SIMCLIST_METER(double)
+
+size_t list_meter_string(const void *el) { return strlen((const char *)el) + 1; }
/* ready-made hashing functions */
-#define SIMCLIST_HASHCOMPUTER(type) KS_DECLARE(list_hash_t) list_hashcomputer_##type(const void *el) { return (list_hash_t)(*(type *)el); }
+#define SIMCLIST_HASHCOMPUTER(type) list_hash_t list_hashcomputer_##type(const void *el) { return (list_hash_t)(*(type *)el); }
+
+SIMCLIST_HASHCOMPUTER(int8_t)
+SIMCLIST_HASHCOMPUTER(int16_t)
+SIMCLIST_HASHCOMPUTER(int32_t)
+SIMCLIST_HASHCOMPUTER(int64_t)
-SIMCLIST_HASHCOMPUTER(int8_t) SIMCLIST_HASHCOMPUTER(int16_t) SIMCLIST_HASHCOMPUTER(int32_t) SIMCLIST_HASHCOMPUTER(int64_t)
- SIMCLIST_HASHCOMPUTER(uint8_t) SIMCLIST_HASHCOMPUTER(uint16_t) SIMCLIST_HASHCOMPUTER(uint32_t) SIMCLIST_HASHCOMPUTER(uint64_t)
- SIMCLIST_HASHCOMPUTER(float) SIMCLIST_HASHCOMPUTER(double)
+SIMCLIST_HASHCOMPUTER(uint8_t)
+SIMCLIST_HASHCOMPUTER(uint16_t)
+SIMCLIST_HASHCOMPUTER(uint32_t)
+SIMCLIST_HASHCOMPUTER(uint64_t)
-KS_DECLARE(list_hash_t) list_hashcomputer_string(const void *el)
-{
+SIMCLIST_HASHCOMPUTER(float)
+SIMCLIST_HASHCOMPUTER(double)
+
+list_hash_t list_hashcomputer_string(const void *el) {
size_t l;
list_hash_t hash = 123;
- const char *str = (const char *) el;
+ const char *str = (const char *)el;
char plus;
for (l = 0; str[l] != '\0'; l++) {
- if (l)
- plus = (char)(hash ^ str[l]);
- else
- plus = (char)(hash ^ (str[l] - str[0]));
+ if (l) plus = (char)(hash ^ str[l]);
+ else plus = (char)(hash ^ (str[l] - str[0]));
hash += (plus << (CHAR_BIT * (l % sizeof(list_hash_t))));
}
#ifndef NDEBUG
-static int list_repOk(const list_t *restrict l)
-{
+static int list_repOk(const list_t *restrict l) {
int ok, i;
struct list_entry_s *s;
ok = (l != NULL) && (
- /* head/tail checks */
- (l->head_sentinel != NULL && l->tail_sentinel != NULL) &&
- (l->head_sentinel != l->tail_sentinel) && (l->head_sentinel->prev == NULL && l->tail_sentinel->next == NULL) &&
- /* empty list */
- (l->numels > 0 || (l->mid == NULL && l->head_sentinel->next == l->tail_sentinel && l->tail_sentinel->prev == l->head_sentinel))
- &&
- /* spare elements checks */
- l->spareelsnum <= SIMCLIST_MAX_SPARE_ELEMS);
-
- if (!ok)
- return 0;
+ /* head/tail checks */
+ (l->head_sentinel != NULL && l->tail_sentinel != NULL) &&
+ (l->head_sentinel != l->tail_sentinel) && (l->head_sentinel->prev == NULL && l->tail_sentinel->next == NULL) &&
+ /* empty list */
+ (l->numels > 0 || (l->mid == NULL && l->head_sentinel->next == l->tail_sentinel && l->tail_sentinel->prev == l->head_sentinel)) &&
+ /* spare elements checks */
+ l->spareelsnum <= SIMCLIST_MAX_SPARE_ELEMS
+ );
+
+ if (!ok) return 0;
if (l->numels >= 1) {
/* correct referencing */
- for (i = -1, s = l->head_sentinel; i < (int) (l->numels - 1) / 2 && s->next != NULL; i++, s = s->next) {
- if (s->next->prev != s)
- break;
+ for (i = -1, s = l->head_sentinel; i < (int)(l->numels - 1) / 2 && s->next != NULL; i++, s = s->next) {
+ if (s->next->prev != s) break;
}
- ok = (i == (int) (l->numels - 1) / 2 && l->mid == s);
- if (!ok)
- return 0;
+ ok = (i == (int)(l->numels - 1) / 2 && l->mid == s);
+ if (!ok) return 0;
for (; s->next != NULL; i++, s = s->next) {
- if (s->next->prev != s)
- break;
+ if (s->next->prev != s) break;
}
- ok = (i == (int) l->numels && s == l->tail_sentinel);
+ ok = (i == (int)l->numels && s == l->tail_sentinel);
}
return ok;
}
-static int list_attrOk(const list_t *restrict l)
-{
+static int list_attrOk(const list_t *restrict l) {
int ok;
ok = (l->attrs.copy_data == 0 || l->attrs.meter != NULL);
#endif
+
/* For Emacs:
* Local Variables:
* mode:c