* mpool_resize only.
*/
typedef void (*mpool_log_func_t)(const void *mp_p,
- const int func_id,
- const unsigned long byte_size,
- const unsigned long ele_n,
- const void *old_addr, const void *new_addr,
- const unsigned long old_byte_size);
+ const int func_id,
+ const unsigned long byte_size,
+ const unsigned long ele_n,
+ const void *old_addr, const void *new_addr,
+ const unsigned long old_byte_size);
#ifdef MPOOL_MAIN
*/
extern
mpool_t *mpool_open(const unsigned int flags, const unsigned int page_size,
- void *start_addr, int *error_p);
+ void *start_addr, int *error_p);
/*
* int mpool_close
*/
extern
void *mpool_alloc(mpool_t *mp_p, const unsigned long byte_size,
- int *error_p);
+ int *error_p);
/*
* void *mpool_calloc
*/
extern
void *mpool_calloc(mpool_t *mp_p, const unsigned long ele_n,
- const unsigned long ele_size, int *error_p);
+ const unsigned long ele_size, int *error_p);
/*
* int mpool_free
*/
extern
void *mpool_resize(mpool_t *mp_p, void *old_addr,
- const unsigned long old_byte_size,
- const unsigned long new_byte_size,
- int *error_p);
+ const unsigned long old_byte_size,
+ const unsigned long new_byte_size,
+ int *error_p);
/*
* int mpool_stats
*/
extern
int mpool_stats(const mpool_t *mp_p, unsigned int *page_size_p,
- unsigned long *num_alloced_p,
- unsigned long *user_alloced_p,
- unsigned long *max_alloced_p,
- unsigned long *tot_alloced_p);
+ unsigned long *num_alloced_p,
+ unsigned long *user_alloced_p,
+ unsigned long *max_alloced_p,
+ unsigned long *tot_alloced_p);
/*
* int mpool_set_log_func
/*<<<<<<<<<< This is end of the auto-generated output from fillproto. */
#endif /* ! __MPOOL_H__ */
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
+ */
#endif
-/* Be friend of both C90 and C99 compilers */
+ /* Be friend of both C90 and C99 compilers */
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
/* "inline" and "restrict" are keywords */
#else
#endif
-/**
- * Type representing list hashes.
- *
- * This is a signed integer value.
- */
-typedef int32_t list_hash_t;
+ /**
+ * 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 */
- uint32_t list_size;
- uint32_t list_numels;
- 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 */
-} list_dump_info_t;
+ typedef struct {
+ 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 */
+ uint32_t dumpsize;
+ 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);
-
-/* [private-use] list entry -- olds actual user datum */
-struct list_entry_s {
- void *data;
-
- /* doubly-linked list service references */
- struct list_entry_s *next;
- struct list_entry_s *prev;
-};
-
-/* [private-use] list attributes */
-struct list_attributes_s {
- /* user-set routine for comparing list elements */
- element_comparator comparator;
- /* user-set routing for seeking elements */
- element_seeker seeker;
- /* user-set routine for determining the length of an element */
- element_meter meter;
- int copy_data;
- /* user-set routine for computing the hash of an element */
- element_hash_computer hasher;
- /* user-set routine for serializing an element */
- element_serializer serializer;
- /* user-set routine for unserializing an element */
- element_unserializer unserializer;
-};
-
-/** list object */
-typedef struct {
- struct list_entry_s *head_sentinel;
- struct list_entry_s *tail_sentinel;
- struct list_entry_s *mid;
-
- unsigned int numels;
-
- /* array of spare elements */
- struct list_entry_s **spareels;
- unsigned int spareelsnum;
+ /**
+ * 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 {
+ void *data;
+
+ /* doubly-linked list service references */
+ struct list_entry_s *next;
+ struct list_entry_s *prev;
+ };
+
+ /* [private-use] list attributes */
+ struct list_attributes_s {
+ /* user-set routine for comparing list elements */
+ element_comparator comparator;
+ /* user-set routing for seeking elements */
+ element_seeker seeker;
+ /* user-set routine for determining the length of an element */
+ element_meter meter;
+ int copy_data;
+ /* user-set routine for computing the hash of an element */
+ element_hash_computer hasher;
+ /* user-set routine for serializing an element */
+ element_serializer serializer;
+ /* user-set routine for unserializing an element */
+ element_unserializer unserializer;
+ };
+
+ /** list object */
+ typedef struct {
+ struct list_entry_s *head_sentinel;
+ struct list_entry_s *tail_sentinel;
+ struct list_entry_s *mid;
+
+ unsigned int numels;
+
+ /* array of spare elements */
+ struct list_entry_s **spareels;
+ unsigned int spareelsnum;
#ifdef SIMCLIST_WITH_THREADS
- /* how many threads are currently running */
- unsigned int threadcount;
+ /* how many threads are currently running */
+ unsigned int threadcount;
#endif
- /* service variables for list iteration */
- int iter_active;
- unsigned int iter_pos;
- struct list_entry_s *iter_curentry;
-
- /* list attributes */
- struct list_attributes_s attrs;
-} 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
- */
-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);
+ /* service variables for list iteration */
+ int iter_active;
+ unsigned int iter_pos;
+ struct list_entry_s *iter_curentry;
+
+ /* list attributes */
+ struct list_attributes_s attrs;
+ } 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
+ */
+ 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()
- */
-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);
+ /**
+ * 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()
- */
-int list_comparator_int8_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()
- */
-int list_comparator_int32_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()
- */
-int list_comparator_uint8_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()
- */
-int list_comparator_uint32_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()
- */
-int list_comparator_float(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()
- */
-int list_comparator_string(const void *a, const void *b);
-
- /* metric functions */
-/**
- * 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()
- */
-size_t list_meter_int16_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()
- */
-size_t list_meter_int64_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()
- */
-size_t list_meter_uint16_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()
- */
-size_t list_meter_uint64_t(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()
- */
-size_t list_meter_double(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()
- */
-list_hash_t list_hashcomputer_int8_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()
- */
-list_hash_t list_hashcomputer_int32_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()
- */
-list_hash_t list_hashcomputer_uint8_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()
- */
-list_hash_t list_hashcomputer_uint32_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()
- */
-list_hash_t list_hashcomputer_float(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()
- */
-list_hash_t list_hashcomputer_string(const void *el);
+ /* ready-made comparators, meters and hash computers */
+ /* comparator functions */
+ /**
+ * 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()
+ */
+ int list_comparator_int16_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()
+ */
+ int list_comparator_int64_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()
+ */
+ int list_comparator_uint16_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()
+ */
+ int list_comparator_uint64_t(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()
+ */
+ int list_comparator_double(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()
+ */
+ size_t list_meter_int8_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()
+ */
+ size_t list_meter_int32_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()
+ */
+ size_t list_meter_uint8_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()
+ */
+ size_t list_meter_uint32_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()
+ */
+ size_t list_meter_float(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()
+ */
+ size_t list_meter_string(const void *el);
+
+ /* hash functions */
+ /**
+ * 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()
+ */
+ list_hash_t list_hashcomputer_int16_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()
+ */
+ list_hash_t list_hashcomputer_int64_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()
+ */
+ list_hash_t list_hashcomputer_uint16_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()
+ */
+ list_hash_t list_hashcomputer_uint64_t(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()
+ */
+ list_hash_t list_hashcomputer_double(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
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
+ */
extern "C" {
#endif /* __cplusplus */
-/*
- * To build a "key" in any of the below routines, pass in a pointer to
- * the key and its size [i.e. sizeof(int), etc]. With any of the
- * "key" or "data" arguments, if their size is < 0, it will do an
- * internal strlen of the item and add 1 for the \0.
- *
- * If you are using firstkey() and nextkey() functions, be careful if,
- * after starting your firstkey loop, you use delete or insert, it
- * will not crash but may produce interesting results. If you are
- * deleting from firstkey to NULL it will work fine.
- */
+ /*
+ * To build a "key" in any of the below routines, pass in a pointer to
+ * the key and its size [i.e. sizeof(int), etc]. With any of the
+ * "key" or "data" arguments, if their size is < 0, it will do an
+ * internal strlen of the item and add 1 for the \0.
+ *
+ * If you are using firstkey() and nextkey() functions, be careful if,
+ * after starting your firstkey loop, you use delete or insert, it
+ * will not crash but may produce interesting results. If you are
+ * deleting from firstkey to NULL it will work fine.
+ */
-/* return types for table functions */
+ /* return types for table functions */
#define TABLE_ERROR_NONE 1 /* no error from function */
#define TABLE_ERROR_PNT 2 /* bad table pointer */
#define TABLE_ERROR_ARG_NULL 3 /* buffer args were null */
#define TABLE_ERROR_COMPARE 19 /* problems with internal comparison */
#define TABLE_ERROR_FREE 20 /* memory free error */
-/*
- * Table flags set with table_attr.
- */
+ /*
+ * Table flags set with table_attr.
+ */
-/*
- * Automatically adjust the number of table buckets on the fly.
- * Whenever the number of entries gets above some threshold, the
- * number of buckets is realloced to a new size and each entry is
- * re-hashed. Although this may take some time when it re-hashes, the
- * table will perform better over time.
- */
+ /*
+ * Automatically adjust the number of table buckets on the fly.
+ * Whenever the number of entries gets above some threshold, the
+ * number of buckets is realloced to a new size and each entry is
+ * re-hashed. Although this may take some time when it re-hashes, the
+ * table will perform better over time.
+ */
#define TABLE_FLAG_AUTO_ADJUST (1<<0)
-/*
- * If the above auto-adjust flag is set, also adjust the number of
- * table buckets down as we delete entries.
- */
+ /*
+ * If the above auto-adjust flag is set, also adjust the number of
+ * table buckets down as we delete entries.
+ */
#define TABLE_FLAG_ADJUST_DOWN (1<<1)
-/* structure to walk through the fields in a linear order */
-typedef struct {
- unsigned int tl_magic; /* magic structure to ensure correct init */
- unsigned int tl_bucket_c; /* where in the table buck array we are */
- unsigned int tl_entry_c; /* in the bucket, which entry we are on */
-} table_linear_t;
+ /* structure to walk through the fields in a linear order */
+ typedef struct {
+ unsigned int tl_magic; /* magic structure to ensure correct init */
+ unsigned int tl_bucket_c; /* where in the table buck array we are */
+ unsigned int tl_entry_c; /* in the bucket, which entry we are on */
+ } table_linear_t;
-/*
- * int (*table_compare_t)
- *
- * DESCRIPTION
- *
- * Comparison function which compares two key/data pairs for table
- * order.
- *
- * RETURNS:
- *
- * -1, 0, or 1 if key1 is <, ==, or > than key2.
- *
- * ARGUMENTS:
- *
- * key1 - Pointer to the first key entry.
- *
- * key1_size - Pointer to the size of the first key entry.
- *
- * data1 - Pointer to the first data entry.
- *
- * data1_size - Pointer to the size of the first data entry.
- *
- * key2 - Pointer to the second key entry.
- *
- * key2_size - Pointer to the size of the second key entry.
- *
- * data2 - Pointer to the second data entry.
- *
- * data2_size - Pointer to the size of the second data entry.
- */
-typedef int (*table_compare_t)(const void *key1, const int key1_size,
- const void *data1, const int data1_size,
- const void *key2, const int key2_size,
- const void *data2, const int data2_size);
+ /*
+ * int (*table_compare_t)
+ *
+ * DESCRIPTION
+ *
+ * Comparison function which compares two key/data pairs for table
+ * order.
+ *
+ * RETURNS:
+ *
+ * -1, 0, or 1 if key1 is <, ==, or > than key2.
+ *
+ * ARGUMENTS:
+ *
+ * key1 - Pointer to the first key entry.
+ *
+ * key1_size - Pointer to the size of the first key entry.
+ *
+ * data1 - Pointer to the first data entry.
+ *
+ * data1_size - Pointer to the size of the first data entry.
+ *
+ * key2 - Pointer to the second key entry.
+ *
+ * key2_size - Pointer to the size of the second key entry.
+ *
+ * data2 - Pointer to the second data entry.
+ *
+ * data2_size - Pointer to the size of the second data entry.
+ */
+ typedef int (*table_compare_t)(const void *key1, const int key1_size,
+ const void *data1, const int data1_size,
+ const void *key2, const int key2_size,
+ const void *data2, const int data2_size);
-/*
- * int (*table_mem_alloc_t)
- *
- * DESCRIPTION
- *
- * Function to override the table's allocation function.
- *
- * RETURNS:
- *
- * Success - Newly allocated pointer.
- *
- * Failure - NULL
- *
- * ARGUMENTS:
- *
- * pool_p <-> Pointer to our memory pool. If no pool is set then this
- * will be NULL.
- *
- * size -> Number of bytes that needs to be allocated.
- */
-typedef void *(*table_mem_alloc_t)(void *pool_p, const unsigned long size);
+ /*
+ * int (*table_mem_alloc_t)
+ *
+ * DESCRIPTION
+ *
+ * Function to override the table's allocation function.
+ *
+ * RETURNS:
+ *
+ * Success - Newly allocated pointer.
+ *
+ * Failure - NULL
+ *
+ * ARGUMENTS:
+ *
+ * pool_p <-> Pointer to our memory pool. If no pool is set then this
+ * will be NULL.
+ *
+ * size -> Number of bytes that needs to be allocated.
+ */
+ typedef void *(*table_mem_alloc_t)(void *pool_p, const unsigned long size);
-/*
- * int (*table_mem_resize_t)
- *
- * DESCRIPTION
- *
- * Function to override the table's memory resize function. The
- * difference between this and realloc is that this provides the
- * previous allocation size. You can specify NULL for this function
- * in which cause the library will allocate, copy, and free itself.
- *
- * RETURNS:
- *
- * Success - Newly allocated pointer.
- *
- * Failure - NULL
- *
- * ARGUMENTS:
- *
- * pool_p <-> Pointer to our memory pool. If no pool is set then this
- * will be NULL.
- *
- * old_addr -> Previously allocated address.
- *
- * old_size -> Size of the old address. Since the system is
- * lightweight, it does not store size information on the pointer.
- *
- * new_size -> New size of the allocation.
- */
-typedef void *(*table_mem_resize_t)(void *pool_p, void *old_addr,
- const unsigned long old_size,
- const unsigned long new_size);
+ /*
+ * int (*table_mem_resize_t)
+ *
+ * DESCRIPTION
+ *
+ * Function to override the table's memory resize function. The
+ * difference between this and realloc is that this provides the
+ * previous allocation size. You can specify NULL for this function
+ * in which cause the library will allocate, copy, and free itself.
+ *
+ * RETURNS:
+ *
+ * Success - Newly allocated pointer.
+ *
+ * Failure - NULL
+ *
+ * ARGUMENTS:
+ *
+ * pool_p <-> Pointer to our memory pool. If no pool is set then this
+ * will be NULL.
+ *
+ * old_addr -> Previously allocated address.
+ *
+ * old_size -> Size of the old address. Since the system is
+ * lightweight, it does not store size information on the pointer.
+ *
+ * new_size -> New size of the allocation.
+ */
+ typedef void *(*table_mem_resize_t)(void *pool_p, void *old_addr,
+ const unsigned long old_size,
+ const unsigned long new_size);
-/*
- * int (*table_mem_free_t)
- *
- * DESCRIPTION
- *
- * Function to override the table's free function.
- *
- * RETURNS:
- *
- * Success - 1
- *
- * Failure - 0
- *
- * ARGUMENTS:
- *
- * pool_p <-> Pointer to our memory pool. If no pool is set then this
- * will be NULL.
- *
- * addr -> Address that we are freeing.
- *
- * min_size -> Minimum size of the address being freed or 0 if not
- * known. This can also be the exact size if known.
- */
-typedef int (*table_mem_free_t)(void *pool_p, void *addr,
- const unsigned long min_size);
+ /*
+ * int (*table_mem_free_t)
+ *
+ * DESCRIPTION
+ *
+ * Function to override the table's free function.
+ *
+ * RETURNS:
+ *
+ * Success - 1
+ *
+ * Failure - 0
+ *
+ * ARGUMENTS:
+ *
+ * pool_p <-> Pointer to our memory pool. If no pool is set then this
+ * will be NULL.
+ *
+ * addr -> Address that we are freeing.
+ *
+ * min_size -> Minimum size of the address being freed or 0 if not
+ * known. This can also be the exact size if known.
+ */
+ typedef int (*table_mem_free_t)(void *pool_p, void *addr,
+ const unsigned long min_size);
#ifdef TABLE_MAIN
#else
-/* generic table type */
-typedef void table_t;
+ /* generic table type */
+ typedef void table_t;
-/* generic table entry type */
-typedef void table_entry_t;
+ /* generic table entry type */
+ typedef void table_entry_t;
#endif
-/*<<<<<<<<<< The below prototypes are auto-generated by fillproto */
+ /*<<<<<<<<<< The below prototypes are auto-generated by fillproto */
-/*
- * table_t *table_alloc
- *
- * DESCRIPTION:
- *
- * Allocate a new table structure.
- *
- * RETURNS:
- *
- * A pointer to the new table structure which must be passed to
- * table_free to be deallocated. On error a NULL is returned.
- *
- * ARGUMENTS:
- *
- * bucket_n - Number of buckets for the hash table. Our current hash
- * value works best with base two numbers. Set to 0 to take the
- * library default of 1024.
- *
- * error_p - Pointer to an integer which, if not NULL, will contain a
- * table error code.
- */
-extern
-table_t *table_alloc(const unsigned int bucket_n, int *error_p);
+ /*
+ * table_t *table_alloc
+ *
+ * DESCRIPTION:
+ *
+ * Allocate a new table structure.
+ *
+ * RETURNS:
+ *
+ * A pointer to the new table structure which must be passed to
+ * table_free to be deallocated. On error a NULL is returned.
+ *
+ * ARGUMENTS:
+ *
+ * bucket_n - Number of buckets for the hash table. Our current hash
+ * value works best with base two numbers. Set to 0 to take the
+ * library default of 1024.
+ *
+ * error_p - Pointer to an integer which, if not NULL, will contain a
+ * table error code.
+ */
+ extern
+ table_t *table_alloc(const unsigned int bucket_n, int *error_p);
-/*
- * table_t *table_alloc_in_pool
- *
- * DESCRIPTION:
- *
- * Allocate a new table structure in a memory pool or using
- * alternative allocation and free functions.
- *
- * RETURNS:
- *
- * A pointer to the new table structure which must be passed to
- * table_free to be deallocated. On error a NULL is returned.
- *
- * ARGUMENTS:
- *
- * bucket_n - Number of buckets for the hash table. Our current hash
- * value works best with base two numbers. Set to 0 to take the
- * library default of 1024.
- *
- * mem_pool <-> Memory pool to associate with the table. Can be NULL.
- *
- * alloc_func -> Allocate function we are overriding malloc() with.
- *
- * resize_func -> Resize function we are overriding the standard
- * memory resize/realloc with. This can be NULL in which cause the
- * library will allocate, copy, and free itself.
- *
- * free_func -> Free function we are overriding free() with.
- *
- * error_p - Pointer to an integer which, if not NULL, will contain a
- * table error code.
- */
-extern
-table_t *table_alloc_in_pool(const unsigned int bucket_n,
- void *mem_pool,
- table_mem_alloc_t alloc_func,
- table_mem_resize_t resize_func,
- table_mem_free_t free_func, int *error_p);
+ /*
+ * table_t *table_alloc_in_pool
+ *
+ * DESCRIPTION:
+ *
+ * Allocate a new table structure in a memory pool or using
+ * alternative allocation and free functions.
+ *
+ * RETURNS:
+ *
+ * A pointer to the new table structure which must be passed to
+ * table_free to be deallocated. On error a NULL is returned.
+ *
+ * ARGUMENTS:
+ *
+ * bucket_n - Number of buckets for the hash table. Our current hash
+ * value works best with base two numbers. Set to 0 to take the
+ * library default of 1024.
+ *
+ * mem_pool <-> Memory pool to associate with the table. Can be NULL.
+ *
+ * alloc_func -> Allocate function we are overriding malloc() with.
+ *
+ * resize_func -> Resize function we are overriding the standard
+ * memory resize/realloc with. This can be NULL in which cause the
+ * library will allocate, copy, and free itself.
+ *
+ * free_func -> Free function we are overriding free() with.
+ *
+ * error_p - Pointer to an integer which, if not NULL, will contain a
+ * table error code.
+ */
+ extern
+ table_t *table_alloc_in_pool(const unsigned int bucket_n,
+ void *mem_pool,
+ table_mem_alloc_t alloc_func,
+ table_mem_resize_t resize_func,
+ table_mem_free_t free_func, int *error_p);
-/*
- * int table_attr
- *
- * DESCRIPTION:
- *
- * Set the attributes for the table. The available attributes are
- * specified at the top of table.h.
- *
- * RETURNS:
- *
- * Success - TABLE_ERROR_NONE
- *
- * Failure - Table error code.
- *
- * ARGUMENTS:
- *
- * table_p - Pointer to a table structure which we will be altering.
- *
- * attr - Attribute(s) that we will be applying to the table.
- */
-extern
-int table_attr(table_t *table_p, const int attr);
+ /*
+ * int table_attr
+ *
+ * DESCRIPTION:
+ *
+ * Set the attributes for the table. The available attributes are
+ * specified at the top of table.h.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Pointer to a table structure which we will be altering.
+ *
+ * attr - Attribute(s) that we will be applying to the table.
+ */
+ extern
+ int table_attr(table_t *table_p, const int attr);
-/*
- * int table_set_data_alignment
- *
- * DESCRIPTION:
- *
- * Set the alignment for the data in the table. This is used when you
- * want to store binary data types and refer to them directly out of
- * the table storage. For instance if you are storing integers as
- * data in the table and want to be able to retrieve the location of
- * the interger and then increment it as (*loc_p)++. Otherwise you
- * would have to memcpy it out to an integer, increment it, and memcpy
- * it back. If you are storing character data, no alignment is
- * necessary.
- *
- * For most data elements, sizeof(long) is recommended unless you use
- * smaller data types exclusively.
- *
- * WARNING: If necessary, you must set the data alignment before any
- * data gets put into the table. Otherwise a TABLE_ERROR_NOT_EMPTY
- * error will be returned.
- *
- * NOTE: there is no way to set the key data alignment although it
- * should automatically be long aligned.
- *
- * RETURNS:
- *
- * Success - TABLE_ERROR_NONE
- *
- * Failure - Table error code.
- *
- * ARGUMENTS:
- *
- * table_p - Pointer to a table structure which we will be altering.
- *
- * alignment - Alignment requested for the data. Must be a power of
- * 2. Set to 0 for none.
- */
-extern
-int table_set_data_alignment(table_t *table_p, const int alignment);
+ /*
+ * int table_set_data_alignment
+ *
+ * DESCRIPTION:
+ *
+ * Set the alignment for the data in the table. This is used when you
+ * want to store binary data types and refer to them directly out of
+ * the table storage. For instance if you are storing integers as
+ * data in the table and want to be able to retrieve the location of
+ * the interger and then increment it as (*loc_p)++. Otherwise you
+ * would have to memcpy it out to an integer, increment it, and memcpy
+ * it back. If you are storing character data, no alignment is
+ * necessary.
+ *
+ * For most data elements, sizeof(long) is recommended unless you use
+ * smaller data types exclusively.
+ *
+ * WARNING: If necessary, you must set the data alignment before any
+ * data gets put into the table. Otherwise a TABLE_ERROR_NOT_EMPTY
+ * error will be returned.
+ *
+ * NOTE: there is no way to set the key data alignment although it
+ * should automatically be long aligned.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Pointer to a table structure which we will be altering.
+ *
+ * alignment - Alignment requested for the data. Must be a power of
+ * 2. Set to 0 for none.
+ */
+ extern
+ int table_set_data_alignment(table_t *table_p, const int alignment);
-/*
- * int table_clear
- *
- * DESCRIPTION:
- *
- * Clear out and free all elements in a table structure.
- *
- * RETURNS:
- *
- * Success - TABLE_ERROR_NONE
- *
- * Failure - Table error code.
- *
- * ARGUMENTS:
- *
- * table_p - Table structure pointer that we will be clearing.
- */
-extern
-int table_clear(table_t *table_p);
+ /*
+ * int table_clear
+ *
+ * DESCRIPTION:
+ *
+ * Clear out and free all elements in a table structure.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer that we will be clearing.
+ */
+ extern
+ int table_clear(table_t *table_p);
-/*
- * int table_free
- *
- * DESCRIPTION:
- *
- * Deallocates a table structure.
- *
- * RETURNS:
- *
- * Success - TABLE_ERROR_NONE
- *
- * Failure - Table error code.
- *
- * ARGUMENTS:
- *
- * table_p - Table structure pointer that we will be freeing.
- */
-extern
-int table_free(table_t *table_p);
+ /*
+ * int table_free
+ *
+ * DESCRIPTION:
+ *
+ * Deallocates a table structure.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer that we will be freeing.
+ */
+ extern
+ int table_free(table_t *table_p);
-/*
- * int table_insert_kd
- *
- * DESCRIPTION:
- *
- * Like table_insert except it passes back a pointer to the key and
- * the data buffers after they have been inserted into the table
- * structure.
- *
- * This routine adds a key/data pair both of which are made up of a
- * buffer of bytes and an associated size. Both the key and the data
- * will be copied into buffers allocated inside the table. If the key
- * exists already, the associated data will be replaced if the
- * overwrite flag is set, otherwise an error is returned.
- *
- * NOTE: be very careful changing the values since the table library
- * provides the pointers to its memory. The key can _never_ be
- * changed otherwise you will not find it again. The data can be
- * changed but its length can never be altered unless you delete and
- * re-insert it into the table.
- *
- * WARNING: The pointers to the key and data are not in any specific
- * alignment. Accessing the key and/or data as an short, integer, or
- * long pointer directly can cause problems.
- *
- * WARNING: Replacing a data cell (not inserting) will cause the table
- * linked list to be temporarily invalid. Care must be taken with
- * multiple threaded programs which are relying on the first/next
- * linked list to be always valid.
- *
- * RETURNS:
- *
- * Success - TABLE_ERROR_NONE
- *
- * Failure - Table error code.
- *
- * ARGUMENTS:
- *
- * table_p - Table structure pointer into which we will be inserting a
- * new key/data pair.
- *
- * key_buf - Buffer of bytes of the key that we are inserting. If you
- * are storing an (int) as the key (for example) then key_buf should
- * be a (int *).
- *
- * key_size - Size of the key_buf buffer. If set to < 0 then the
- * library will do a strlen of key_buf and add 1 for the '\0'. If you
- * are storing an (int) as the key (for example) then key_size should
- * be sizeof(int).
- *
- * data_buf - Buffer of bytes of the data that we are inserting. If
- * it is NULL then the library will allocate space for the data in the
- * table without copying in any information. If data_buf is NULL and
- * data_size is 0 then the library will associate a NULL data pointer
- * with the key. If you are storing a (long) as the data (for
- * example) then data_buf should be a (long *).
- *
- * data_size - Size of the data_buf buffer. If set to < 0 then the
- * library will do a strlen of data_buf and add 1 for the '\0'. If
- * you are storing an (long) as the key (for example) then key_size
- * should be sizeof(long).
- *
- * key_buf_p - Pointer which, if not NULL, will be set to the address
- * of the key storage that was allocated in the table. If you are
- * storing an (int) as the key (for example) then key_buf_p should be
- * (int **) i.e. the address of a (int *).
- *
- * data_buf_p - Pointer which, if not NULL, will be set to the address
- * of the data storage that was allocated in the table. If you are
- * storing an (long) as the data (for example) then data_buf_p should
- * be (long **) i.e. the address of a (long *).
- *
- * overwrite - Flag which, if set to 1, will allow the overwriting of
- * the data in the table with the new data if the key already exists
- * in the table.
- */
-extern
-int table_insert_kd(table_t *table_p,
- const void *key_buf, const int key_size,
- const void *data_buf, const int data_size,
- void **key_buf_p, void **data_buf_p,
- const char overwrite_b);
+ /*
+ * int table_insert_kd
+ *
+ * DESCRIPTION:
+ *
+ * Like table_insert except it passes back a pointer to the key and
+ * the data buffers after they have been inserted into the table
+ * structure.
+ *
+ * This routine adds a key/data pair both of which are made up of a
+ * buffer of bytes and an associated size. Both the key and the data
+ * will be copied into buffers allocated inside the table. If the key
+ * exists already, the associated data will be replaced if the
+ * overwrite flag is set, otherwise an error is returned.
+ *
+ * NOTE: be very careful changing the values since the table library
+ * provides the pointers to its memory. The key can _never_ be
+ * changed otherwise you will not find it again. The data can be
+ * changed but its length can never be altered unless you delete and
+ * re-insert it into the table.
+ *
+ * WARNING: The pointers to the key and data are not in any specific
+ * alignment. Accessing the key and/or data as an short, integer, or
+ * long pointer directly can cause problems.
+ *
+ * WARNING: Replacing a data cell (not inserting) will cause the table
+ * linked list to be temporarily invalid. Care must be taken with
+ * multiple threaded programs which are relying on the first/next
+ * linked list to be always valid.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer into which we will be inserting a
+ * new key/data pair.
+ *
+ * key_buf - Buffer of bytes of the key that we are inserting. If you
+ * are storing an (int) as the key (for example) then key_buf should
+ * be a (int *).
+ *
+ * key_size - Size of the key_buf buffer. If set to < 0 then the
+ * library will do a strlen of key_buf and add 1 for the '\0'. If you
+ * are storing an (int) as the key (for example) then key_size should
+ * be sizeof(int).
+ *
+ * data_buf - Buffer of bytes of the data that we are inserting. If
+ * it is NULL then the library will allocate space for the data in the
+ * table without copying in any information. If data_buf is NULL and
+ * data_size is 0 then the library will associate a NULL data pointer
+ * with the key. If you are storing a (long) as the data (for
+ * example) then data_buf should be a (long *).
+ *
+ * data_size - Size of the data_buf buffer. If set to < 0 then the
+ * library will do a strlen of data_buf and add 1 for the '\0'. If
+ * you are storing an (long) as the key (for example) then key_size
+ * should be sizeof(long).
+ *
+ * key_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the key storage that was allocated in the table. If you are
+ * storing an (int) as the key (for example) then key_buf_p should be
+ * (int **) i.e. the address of a (int *).
+ *
+ * data_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the data storage that was allocated in the table. If you are
+ * storing an (long) as the data (for example) then data_buf_p should
+ * be (long **) i.e. the address of a (long *).
+ *
+ * overwrite - Flag which, if set to 1, will allow the overwriting of
+ * the data in the table with the new data if the key already exists
+ * in the table.
+ */
+ extern
+ int table_insert_kd(table_t *table_p,
+ const void *key_buf, const int key_size,
+ const void *data_buf, const int data_size,
+ void **key_buf_p, void **data_buf_p,
+ const char overwrite_b);
-/*
- * int table_insert
- *
- * DESCRIPTION:
- *
- * Exactly the same as table_insert_kd except it does not pass back a
- * pointer to the key after they have been inserted into the table
- * structure. This is still here for backwards compatibility.
- *
- * See table_insert_kd for more information.
- *
- * RETURNS:
- *
- * Success - TABLE_ERROR_NONE
- *
- * Failure - Table error code.
- *
- * ARGUMENTS:
- *
- * table_p - Table structure pointer into which we will be inserting a
- * new key/data pair.
- *
- * key_buf - Buffer of bytes of the key that we are inserting. If you
- * are storing an (int) as the key (for example) then key_buf should
- * be a (int *).
- *
- * key_size - Size of the key_buf buffer. If set to < 0 then the
- * library will do a strlen of key_buf and add 1 for the '\0'. If you
- * are storing an (int) as the key (for example) then key_size should
- * be sizeof(int).
- *
- * data_buf - Buffer of bytes of the data that we are inserting. If
- * it is NULL then the library will allocate space for the data in the
- * table without copying in any information. If data_buf is NULL and
- * data_size is 0 then the library will associate a NULL data pointer
- * with the key. If you are storing a (long) as the data (for
- * example) then data_buf should be a (long *).
- *
- * data_size - Size of the data_buf buffer. If set to < 0 then the
- * library will do a strlen of data_buf and add 1 for the '\0'. If
- * you are storing an (long) as the key (for example) then key_size
- * should be sizeof(long).
- *
- * data_buf_p - Pointer which, if not NULL, will be set to the address
- * of the data storage that was allocated in the table. If you are
- * storing an (long) as the data (for example) then data_buf_p should
- * be (long **) i.e. the address of a (long *).
- *
- * overwrite - Flag which, if set to 1, will allow the overwriting of
- * the data in the table with the new data if the key already exists
- * in the table.
- */
-extern
-int table_insert(table_t *table_p,
- const void *key_buf, const int key_size,
- const void *data_buf, const int data_size,
- void **data_buf_p, const char overwrite_b);
+ /*
+ * int table_insert
+ *
+ * DESCRIPTION:
+ *
+ * Exactly the same as table_insert_kd except it does not pass back a
+ * pointer to the key after they have been inserted into the table
+ * structure. This is still here for backwards compatibility.
+ *
+ * See table_insert_kd for more information.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer into which we will be inserting a
+ * new key/data pair.
+ *
+ * key_buf - Buffer of bytes of the key that we are inserting. If you
+ * are storing an (int) as the key (for example) then key_buf should
+ * be a (int *).
+ *
+ * key_size - Size of the key_buf buffer. If set to < 0 then the
+ * library will do a strlen of key_buf and add 1 for the '\0'. If you
+ * are storing an (int) as the key (for example) then key_size should
+ * be sizeof(int).
+ *
+ * data_buf - Buffer of bytes of the data that we are inserting. If
+ * it is NULL then the library will allocate space for the data in the
+ * table without copying in any information. If data_buf is NULL and
+ * data_size is 0 then the library will associate a NULL data pointer
+ * with the key. If you are storing a (long) as the data (for
+ * example) then data_buf should be a (long *).
+ *
+ * data_size - Size of the data_buf buffer. If set to < 0 then the
+ * library will do a strlen of data_buf and add 1 for the '\0'. If
+ * you are storing an (long) as the key (for example) then key_size
+ * should be sizeof(long).
+ *
+ * data_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the data storage that was allocated in the table. If you are
+ * storing an (long) as the data (for example) then data_buf_p should
+ * be (long **) i.e. the address of a (long *).
+ *
+ * overwrite - Flag which, if set to 1, will allow the overwriting of
+ * the data in the table with the new data if the key already exists
+ * in the table.
+ */
+ extern
+ int table_insert(table_t *table_p,
+ const void *key_buf, const int key_size,
+ const void *data_buf, const int data_size,
+ void **data_buf_p, const char overwrite_b);
-/*
- * int table_retrieve
- *
- * DESCRIPTION:
- *
- * This routine looks up a key made up of a buffer of bytes and an
- * associated size in the table. If found then it returns the
- * associated data information.
- *
- * RETURNS:
- *
- * Success - TABLE_ERROR_NONE
- *
- * Failure - Table error code.
- *
- * ARGUMENTS:
- *
- * table_p - Table structure pointer into which we will be searching
- * for the key.
- *
- * key_buf - Buffer of bytes of the key that we are searching for. If
- * you are looking for an (int) as the key (for example) then key_buf
- * should be a (int *).
- *
- * key_size - Size of the key_buf buffer. If set to < 0 then the
- * library will do a strlen of key_buf and add 1 for the '\0'. If you
- * are looking for an (int) as the key (for example) then key_size
- * should be sizeof(int).
- *
- * data_buf_p - Pointer which, if not NULL, will be set to the address
- * of the data storage that was allocated in the table and that is
- * associated with the key. If a (long) was stored as the data (for
- * example) then data_buf_p should be (long **) i.e. the address of a
- * (long *).
- *
- * data_size_p - Pointer to an integer which, if not NULL, will be set
- * to the size of the data stored in the table that is associated with
- * the key.
- */
-extern
-int table_retrieve(table_t *table_p,
- const void *key_buf, const int key_size,
- void **data_buf_p, int *data_size_p);
+ /*
+ * int table_retrieve
+ *
+ * DESCRIPTION:
+ *
+ * This routine looks up a key made up of a buffer of bytes and an
+ * associated size in the table. If found then it returns the
+ * associated data information.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer into which we will be searching
+ * for the key.
+ *
+ * key_buf - Buffer of bytes of the key that we are searching for. If
+ * you are looking for an (int) as the key (for example) then key_buf
+ * should be a (int *).
+ *
+ * key_size - Size of the key_buf buffer. If set to < 0 then the
+ * library will do a strlen of key_buf and add 1 for the '\0'. If you
+ * are looking for an (int) as the key (for example) then key_size
+ * should be sizeof(int).
+ *
+ * data_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the data storage that was allocated in the table and that is
+ * associated with the key. If a (long) was stored as the data (for
+ * example) then data_buf_p should be (long **) i.e. the address of a
+ * (long *).
+ *
+ * data_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the data stored in the table that is associated with
+ * the key.
+ */
+ extern
+ int table_retrieve(table_t *table_p,
+ const void *key_buf, const int key_size,
+ void **data_buf_p, int *data_size_p);
-/*
- * int table_delete
- *
- * DESCRIPTION:
- *
- * This routine looks up a key made up of a buffer of bytes and an
- * associated size in the table. If found then it will be removed
- * from the table. The associated data can be passed back to the user
- * if requested.
- *
- * RETURNS:
- *
- * Success - TABLE_ERROR_NONE
- *
- * Failure - Table error code.
- *
- * NOTE: this could be an allocation error if the library is to return
- * the data to the user.
- *
- * ARGUMENTS:
- *
- * table_p - Table structure pointer from which we will be deleteing
- * the key.
- *
- * key_buf - Buffer of bytes of the key that we are searching for to
- * delete. If you are deleting an (int) key (for example) then
- * key_buf should be a (int *).
- *
- * key_size - Size of the key_buf buffer. If set to < 0 then the
- * library will do a strlen of key_buf and add 1 for the '\0'. If you
- * are deleting an (int) key (for example) then key_size should be
- * sizeof(int).
- *
- * data_buf_p - Pointer which, if not NULL, will be set to the address
- * of the data storage that was allocated in the table and that was
- * associated with the key. If a (long) was stored as the data (for
- * example) then data_buf_p should be (long **) i.e. the address of a
- * (long *). If a pointer is passed in, the caller is responsible for
- * freeing it after use. If data_buf_p is NULL then the library will
- * free up the data allocation itself.
- *
- * data_size_p - Pointer to an integer which, if not NULL, will be set
- * to the size of the data that was stored in the table and that was
- * associated with the key.
- */
-extern
-int table_delete(table_t *table_p,
- const void *key_buf, const int key_size,
- void **data_buf_p, int *data_size_p);
+ /*
+ * int table_delete
+ *
+ * DESCRIPTION:
+ *
+ * This routine looks up a key made up of a buffer of bytes and an
+ * associated size in the table. If found then it will be removed
+ * from the table. The associated data can be passed back to the user
+ * if requested.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * NOTE: this could be an allocation error if the library is to return
+ * the data to the user.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer from which we will be deleteing
+ * the key.
+ *
+ * key_buf - Buffer of bytes of the key that we are searching for to
+ * delete. If you are deleting an (int) key (for example) then
+ * key_buf should be a (int *).
+ *
+ * key_size - Size of the key_buf buffer. If set to < 0 then the
+ * library will do a strlen of key_buf and add 1 for the '\0'. If you
+ * are deleting an (int) key (for example) then key_size should be
+ * sizeof(int).
+ *
+ * data_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the data storage that was allocated in the table and that was
+ * associated with the key. If a (long) was stored as the data (for
+ * example) then data_buf_p should be (long **) i.e. the address of a
+ * (long *). If a pointer is passed in, the caller is responsible for
+ * freeing it after use. If data_buf_p is NULL then the library will
+ * free up the data allocation itself.
+ *
+ * data_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the data that was stored in the table and that was
+ * associated with the key.
+ */
+ extern
+ int table_delete(table_t *table_p,
+ const void *key_buf, const int key_size,
+ void **data_buf_p, int *data_size_p);
-/*
- * int table_delete_first
- *
- * DESCRIPTION:
- *
- * This is like the table_delete routines except it deletes the first
- * key/data pair in the table instead of an entry corresponding to a
- * particular key. The associated key and data information can be
- * passed back to the user if requested. This routines is handy to
- * clear out a table.
- *
- * RETURNS:
- *
- * Success - TABLE_ERROR_NONE
- *
- * Failure - Table error code.
- *
- * NOTE: this could be an allocation error if the library is to return
- * the data to the user.
- *
- * ARGUMENTS:
- *
- * table_p - Table structure pointer from which we will be deleteing
- * the first key.
- *
- * key_buf_p - Pointer which, if not NULL, will be set to the address
- * of the storage of the first key that was allocated in the table.
- * If an (int) was stored as the first key (for example) then
- * key_buf_p should be (int **) i.e. the address of a (int *). If a
- * pointer is passed in, the caller is responsible for freeing it
- * after use. If key_buf_p is NULL then the library will free up the
- * key allocation itself.
- *
- * key_size_p - Pointer to an integer which, if not NULL, will be set
- * to the size of the key that was stored in the table and that was
- * associated with the key.
- *
- * data_buf_p - Pointer which, if not NULL, will be set to the address
- * of the data storage that was allocated in the table and that was
- * associated with the key. If a (long) was stored as the data (for
- * example) then data_buf_p should be (long **) i.e. the address of a
- * (long *). If a pointer is passed in, the caller is responsible for
- * freeing it after use. If data_buf_p is NULL then the library will
- * free up the data allocation itself.
- *
- * data_size_p - Pointer to an integer which, if not NULL, will be set
- * to the size of the data that was stored in the table and that was
- * associated with the key.
- */
-extern
-int table_delete_first(table_t *table_p,
- void **key_buf_p, int *key_size_p,
- void **data_buf_p, int *data_size_p);
+ /*
+ * int table_delete_first
+ *
+ * DESCRIPTION:
+ *
+ * This is like the table_delete routines except it deletes the first
+ * key/data pair in the table instead of an entry corresponding to a
+ * particular key. The associated key and data information can be
+ * passed back to the user if requested. This routines is handy to
+ * clear out a table.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * NOTE: this could be an allocation error if the library is to return
+ * the data to the user.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer from which we will be deleteing
+ * the first key.
+ *
+ * key_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the storage of the first key that was allocated in the table.
+ * If an (int) was stored as the first key (for example) then
+ * key_buf_p should be (int **) i.e. the address of a (int *). If a
+ * pointer is passed in, the caller is responsible for freeing it
+ * after use. If key_buf_p is NULL then the library will free up the
+ * key allocation itself.
+ *
+ * key_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the key that was stored in the table and that was
+ * associated with the key.
+ *
+ * data_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the data storage that was allocated in the table and that was
+ * associated with the key. If a (long) was stored as the data (for
+ * example) then data_buf_p should be (long **) i.e. the address of a
+ * (long *). If a pointer is passed in, the caller is responsible for
+ * freeing it after use. If data_buf_p is NULL then the library will
+ * free up the data allocation itself.
+ *
+ * data_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the data that was stored in the table and that was
+ * associated with the key.
+ */
+ extern
+ int table_delete_first(table_t *table_p,
+ void **key_buf_p, int *key_size_p,
+ void **data_buf_p, int *data_size_p);
-/*
- * int table_info
- *
- * DESCRIPTION:
- *
- * Get some information about a table_p structure.
- *
- * RETURNS:
- *
- * Success - TABLE_ERROR_NONE
- *
- * Failure - Table error code.
- *
- * ARGUMENTS:
- *
- * table_p - Table structure pointer from which we are getting
- * information.
- *
- * num_buckets_p - Pointer to an integer which, if not NULL, will
- * contain the number of buckets in the table.
- *
- * num_entries_p - Pointer to an integer which, if not NULL, will
- * contain the number of entries stored in the table.
- */
-extern
-int table_info(table_t *table_p, int *num_buckets_p, int *num_entries_p);
+ /*
+ * int table_info
+ *
+ * DESCRIPTION:
+ *
+ * Get some information about a table_p structure.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer from which we are getting
+ * information.
+ *
+ * num_buckets_p - Pointer to an integer which, if not NULL, will
+ * contain the number of buckets in the table.
+ *
+ * num_entries_p - Pointer to an integer which, if not NULL, will
+ * contain the number of entries stored in the table.
+ */
+ extern
+ int table_info(table_t *table_p, int *num_buckets_p, int *num_entries_p);
-/*
- * int table_adjust
- *
- * DESCRIPTION:
- *
- * Set the number of buckets in a table to a certain value.
- *
- * RETURNS:
- *
- * Success - TABLE_ERROR_NONE
- *
- * Failure - Table error code.
- *
- * ARGUMENTS:
- *
- * table_p - Table structure pointer of which we are adjusting.
- *
- * bucket_n - Number buckets to adjust the table to. Set to 0 to
- * adjust the table to its number of entries.
- */
-extern
-int table_adjust(table_t *table_p, const int bucket_n);
+ /*
+ * int table_adjust
+ *
+ * DESCRIPTION:
+ *
+ * Set the number of buckets in a table to a certain value.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer of which we are adjusting.
+ *
+ * bucket_n - Number buckets to adjust the table to. Set to 0 to
+ * adjust the table to its number of entries.
+ */
+ extern
+ int table_adjust(table_t *table_p, const int bucket_n);
-/*
- * int table_type_size
- *
- * DESCRIPTION:
- *
- * Return the size of the internal table type.
- *
- * RETURNS:
- *
- * The size of the table_t type.
- *
- * ARGUMENTS:
- *
- * None.
- */
-extern
-int table_type_size(void);
+ /*
+ * int table_type_size
+ *
+ * DESCRIPTION:
+ *
+ * Return the size of the internal table type.
+ *
+ * RETURNS:
+ *
+ * The size of the table_t type.
+ *
+ * ARGUMENTS:
+ *
+ * None.
+ */
+ extern
+ int table_type_size(void);
-/*
- * int table_first
- *
- * DESCRIPTION:
- *
- * Find first element in a table and pass back information about the
- * key/data pair. If any of the key/data pointers are NULL then they
- * are ignored.
- *
- * NOTE: This function is not reentrant. More than one thread cannot
- * be doing a first and next on the same table at the same time. Use
- * the table_first_r version below for this.
- *
- * RETURNS:
- *
- * Success - TABLE_ERROR_NONE
- *
- * Failure - Table error code.
- *
- * ARGUMENTS:
- *
- * table_p - Table structure pointer from which we are getting the
- * first element.
- *
- * key_buf_p - Pointer which, if not NULL, will be set to the address
- * of the storage of the first key that is allocated in the table. If
- * an (int) is stored as the first key (for example) then key_buf_p
- * should be (int **) i.e. the address of a (int *).
- *
- * key_size_p - Pointer to an integer which, if not NULL, will be set
- * to the size of the key that is stored in the table and that is
- * associated with the first key.
- *
- * data_buf_p - Pointer which, if not NULL, will be set to the address
- * of the data storage that is allocated in the table and that is
- * associated with the first key. If a (long) is stored as the data
- * (for example) then data_buf_p should be (long **) i.e. the address
- * of a (long *).
- *
- * data_size_p - Pointer to an integer which, if not NULL, will be set
- * to the size of the data that is stored in the table and that is
- * associated with the first key.
- */
-extern
-int table_first(table_t *table_p,
- void **key_buf_p, int *key_size_p,
- void **data_buf_p, int *data_size_p);
+ /*
+ * int table_first
+ *
+ * DESCRIPTION:
+ *
+ * Find first element in a table and pass back information about the
+ * key/data pair. If any of the key/data pointers are NULL then they
+ * are ignored.
+ *
+ * NOTE: This function is not reentrant. More than one thread cannot
+ * be doing a first and next on the same table at the same time. Use
+ * the table_first_r version below for this.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer from which we are getting the
+ * first element.
+ *
+ * key_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the storage of the first key that is allocated in the table. If
+ * an (int) is stored as the first key (for example) then key_buf_p
+ * should be (int **) i.e. the address of a (int *).
+ *
+ * key_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the key that is stored in the table and that is
+ * associated with the first key.
+ *
+ * data_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the data storage that is allocated in the table and that is
+ * associated with the first key. If a (long) is stored as the data
+ * (for example) then data_buf_p should be (long **) i.e. the address
+ * of a (long *).
+ *
+ * data_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the data that is stored in the table and that is
+ * associated with the first key.
+ */
+ extern
+ int table_first(table_t *table_p,
+ void **key_buf_p, int *key_size_p,
+ void **data_buf_p, int *data_size_p);
-/*
- * int table_next
- *
- * DESCRIPTION:
- *
- * Find the next element in a table and pass back information about
- * the key/data pair. If any of the key/data pointers are NULL then
- * they are ignored.
- *
- * NOTE: This function is not reentrant. More than one thread cannot
- * be doing a first and next on the same table at the same time. Use
- * the table_next_r version below for this.
- *
- * RETURNS:
- *
- * Success - TABLE_ERROR_NONE
- *
- * Failure - Table error code.
- *
- * ARGUMENTS:
- *
- * table_p - Table structure pointer from which we are getting the
- * next element.
- *
- * key_buf_p - Pointer which, if not NULL, will be set to the address
- * of the storage of the next key that is allocated in the table. If
- * an (int) is stored as the next key (for example) then key_buf_p
- * should be (int **) i.e. the address of a (int *).
- *
- * key_size_p - Pointer to an integer which, if not NULL, will be set
- * to the size of the key that is stored in the table and that is
- * associated with the next key.
- *
- * data_buf_p - Pointer which, if not NULL, will be set to the address
- * of the data storage that is allocated in the table and that is
- * associated with the next key. If a (long) is stored as the data
- * (for example) then data_buf_p should be (long **) i.e. the address
- * of a (long *).
- *
- * data_size_p - Pointer to an integer which, if not NULL, will be set
- * to the size of the data that is stored in the table and that is
- * associated with the next key.
- */
-extern
-int table_next(table_t *table_p,
- void **key_buf_p, int *key_size_p,
- void **data_buf_p, int *data_size_p);
+ /*
+ * int table_next
+ *
+ * DESCRIPTION:
+ *
+ * Find the next element in a table and pass back information about
+ * the key/data pair. If any of the key/data pointers are NULL then
+ * they are ignored.
+ *
+ * NOTE: This function is not reentrant. More than one thread cannot
+ * be doing a first and next on the same table at the same time. Use
+ * the table_next_r version below for this.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer from which we are getting the
+ * next element.
+ *
+ * key_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the storage of the next key that is allocated in the table. If
+ * an (int) is stored as the next key (for example) then key_buf_p
+ * should be (int **) i.e. the address of a (int *).
+ *
+ * key_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the key that is stored in the table and that is
+ * associated with the next key.
+ *
+ * data_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the data storage that is allocated in the table and that is
+ * associated with the next key. If a (long) is stored as the data
+ * (for example) then data_buf_p should be (long **) i.e. the address
+ * of a (long *).
+ *
+ * data_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the data that is stored in the table and that is
+ * associated with the next key.
+ */
+ extern
+ int table_next(table_t *table_p,
+ void **key_buf_p, int *key_size_p,
+ void **data_buf_p, int *data_size_p);
-/*
- * int table_this
- *
- * DESCRIPTION:
- *
- * Find the current element in a table and pass back information about
- * the key/data pair. If any of the key/data pointers are NULL then
- * they are ignored.
- *
- * NOTE: This function is not reentrant. Use the table_current_r
- * version below.
- *
- * RETURNS:
- *
- * Success - TABLE_ERROR_NONE
- *
- * Failure - Table error code.
- *
- * ARGUMENTS:
- *
- * table_p - Table structure pointer from which we are getting the
- * current element.
- *
- * key_buf_p - Pointer which, if not NULL, will be set to the address
- * of the storage of the current key that is allocated in the table.
- * If an (int) is stored as the current key (for example) then
- * key_buf_p should be (int **) i.e. the address of a (int *).
- *
- * key_size_p - Pointer to an integer which, if not NULL, will be set
- * to the size of the key that is stored in the table and that is
- * associated with the current key.
- *
- * data_buf_p - Pointer which, if not NULL, will be set to the address
- * of the data storage that is allocated in the table and that is
- * associated with the current key. If a (long) is stored as the data
- * (for example) then data_buf_p should be (long **) i.e. the address
- * of a (long *).
- *
- * data_size_p - Pointer to an integer which, if not NULL, will be set
- * to the size of the data that is stored in the table and that is
- * associated with the current key.
- */
-extern
-int table_this(table_t *table_p,
- void **key_buf_p, int *key_size_p,
- void **data_buf_p, int *data_size_p);
+ /*
+ * int table_this
+ *
+ * DESCRIPTION:
+ *
+ * Find the current element in a table and pass back information about
+ * the key/data pair. If any of the key/data pointers are NULL then
+ * they are ignored.
+ *
+ * NOTE: This function is not reentrant. Use the table_current_r
+ * version below.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer from which we are getting the
+ * current element.
+ *
+ * key_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the storage of the current key that is allocated in the table.
+ * If an (int) is stored as the current key (for example) then
+ * key_buf_p should be (int **) i.e. the address of a (int *).
+ *
+ * key_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the key that is stored in the table and that is
+ * associated with the current key.
+ *
+ * data_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the data storage that is allocated in the table and that is
+ * associated with the current key. If a (long) is stored as the data
+ * (for example) then data_buf_p should be (long **) i.e. the address
+ * of a (long *).
+ *
+ * data_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the data that is stored in the table and that is
+ * associated with the current key.
+ */
+ extern
+ int table_this(table_t *table_p,
+ void **key_buf_p, int *key_size_p,
+ void **data_buf_p, int *data_size_p);
-/*
- * int table_first_r
- *
- * DESCRIPTION:
- *
- * Reetrant version of the table_first routine above. Find first
- * element in a table and pass back information about the key/data
- * pair. If any of the key/data pointers are NULL then they are
- * ignored.
- *
- * RETURNS:
- *
- * Success - TABLE_ERROR_NONE
- *
- * Failure - Table error code.
- *
- * ARGUMENTS:
- *
- * table_p - Table structure pointer from which we are getting the
- * first element.
- *
- * linear_p - Pointer to a table linear structure which is initialized
- * here. The same pointer should then be passed to table_next_r
- * below.
- *
- * key_buf_p - Pointer which, if not NULL, will be set to the address
- * of the storage of the first key that is allocated in the table. If
- * an (int) is stored as the first key (for example) then key_buf_p
- * should be (int **) i.e. the address of a (int *).
- *
- * key_size_p - Pointer to an integer which, if not NULL, will be set
- * to the size of the key that is stored in the table and that is
- * associated with the first key.
- *
- * data_buf_p - Pointer which, if not NULL, will be set to the address
- * of the data storage that is allocated in the table and that is
- * associated with the first key. If a (long) is stored as the data
- * (for example) then data_buf_p should be (long **) i.e. the address
- * of a (long *).
- *
- * data_size_p - Pointer to an integer which, if not NULL, will be set
- * to the size of the data that is stored in the table and that is
- * associated with the first key.
- */
-extern
-int table_first_r(table_t *table_p, table_linear_t *linear_p,
- void **key_buf_p, int *key_size_p,
- void **data_buf_p, int *data_size_p);
+ /*
+ * int table_first_r
+ *
+ * DESCRIPTION:
+ *
+ * Reetrant version of the table_first routine above. Find first
+ * element in a table and pass back information about the key/data
+ * pair. If any of the key/data pointers are NULL then they are
+ * ignored.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer from which we are getting the
+ * first element.
+ *
+ * linear_p - Pointer to a table linear structure which is initialized
+ * here. The same pointer should then be passed to table_next_r
+ * below.
+ *
+ * key_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the storage of the first key that is allocated in the table. If
+ * an (int) is stored as the first key (for example) then key_buf_p
+ * should be (int **) i.e. the address of a (int *).
+ *
+ * key_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the key that is stored in the table and that is
+ * associated with the first key.
+ *
+ * data_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the data storage that is allocated in the table and that is
+ * associated with the first key. If a (long) is stored as the data
+ * (for example) then data_buf_p should be (long **) i.e. the address
+ * of a (long *).
+ *
+ * data_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the data that is stored in the table and that is
+ * associated with the first key.
+ */
+ extern
+ int table_first_r(table_t *table_p, table_linear_t *linear_p,
+ void **key_buf_p, int *key_size_p,
+ void **data_buf_p, int *data_size_p);
-/*
- * int table_next_r
- *
- * DESCRIPTION:
- *
- * Reetrant version of the table_next routine above. Find next
- * element in a table and pass back information about the key/data
- * pair. If any of the key/data pointers are NULL then they are
- * ignored.
- *
- * RETURNS:
- *
- * Success - TABLE_ERROR_NONE
- *
- * Failure - Table error code.
- *
- * ARGUMENTS:
- *
- * table_p - Table structure pointer from which we are getting the
- * next element.
- *
- * linear_p - Pointer to a table linear structure which is incremented
- * here. The same pointer must have been passed to table_first_r
- * first so that it can be initialized.
- *
- * key_buf_p - Pointer which, if not NULL, will be set to the address
- * of the storage of the next key that is allocated in the table. If
- * an (int) is stored as the next key (for example) then key_buf_p
- * should be (int **) i.e. the address of a (int *).
- *
- * key_size_p - Pointer to an integer which, if not NULL will be set
- * to the size of the key that is stored in the table and that is
- * associated with the next key.
- *
- * data_buf_p - Pointer which, if not NULL, will be set to the address
- * of the data storage that is allocated in the table and that is
- * associated with the next key. If a (long) is stored as the data
- * (for example) then data_buf_p should be (long **) i.e. the address
- * of a (long *).
- *
- * data_size_p - Pointer to an integer which, if not NULL, will be set
- * to the size of the data that is stored in the table and that is
- * associated with the next key.
- */
-extern
-int table_next_r(table_t *table_p, table_linear_t *linear_p,
- void **key_buf_p, int *key_size_p,
- void **data_buf_p, int *data_size_p);
+ /*
+ * int table_next_r
+ *
+ * DESCRIPTION:
+ *
+ * Reetrant version of the table_next routine above. Find next
+ * element in a table and pass back information about the key/data
+ * pair. If any of the key/data pointers are NULL then they are
+ * ignored.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer from which we are getting the
+ * next element.
+ *
+ * linear_p - Pointer to a table linear structure which is incremented
+ * here. The same pointer must have been passed to table_first_r
+ * first so that it can be initialized.
+ *
+ * key_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the storage of the next key that is allocated in the table. If
+ * an (int) is stored as the next key (for example) then key_buf_p
+ * should be (int **) i.e. the address of a (int *).
+ *
+ * key_size_p - Pointer to an integer which, if not NULL will be set
+ * to the size of the key that is stored in the table and that is
+ * associated with the next key.
+ *
+ * data_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the data storage that is allocated in the table and that is
+ * associated with the next key. If a (long) is stored as the data
+ * (for example) then data_buf_p should be (long **) i.e. the address
+ * of a (long *).
+ *
+ * data_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the data that is stored in the table and that is
+ * associated with the next key.
+ */
+ extern
+ int table_next_r(table_t *table_p, table_linear_t *linear_p,
+ void **key_buf_p, int *key_size_p,
+ void **data_buf_p, int *data_size_p);
-/*
- * int table_this_r
- *
- * DESCRIPTION:
- *
- * Reetrant version of the table_this routine above. Find current
- * element in a table and pass back information about the key/data
- * pair. If any of the key/data pointers are NULL then they are
- * ignored.
- *
- * RETURNS:
- *
- * Success - TABLE_ERROR_NONE
- *
- * Failure - Table error code.
- *
- * ARGUMENTS:
- *
- * table_p - Table structure pointer from which we are getting the
- * current element.
- *
- * linear_p - Pointer to a table linear structure which is accessed
- * here. The same pointer must have been passed to table_first_r
- * first so that it can be initialized.
- *
- * key_buf_p - Pointer which, if not NULL, will be set to the address
- * of the storage of the current key that is allocated in the table.
- * If an (int) is stored as the current key (for example) then
- * key_buf_p should be (int **) i.e. the address of a (int *).
- *
- * key_size_p - Pointer to an integer which, if not NULL, will be set
- * to the size of the key that is stored in the table and that is
- * associated with the current key.
- *
- * data_buf_p - Pointer which, if not NULL, will be set to the address
- * of the data storage that is allocated in the table and that is
- * associated with the current key. If a (long) is stored as the data
- * (for example) then data_buf_p should be (long **) i.e. the address
- * of a (long *).
- *
- * data_size_p - Pointer to an integer which, if not NULL, will be set
- * to the size of the data that is stored in the table and that is
- * associated with the current key.
- */
-extern
-int table_this_r(table_t *table_p, table_linear_t *linear_p,
- void **key_buf_p, int *key_size_p,
- void **data_buf_p, int *data_size_p);
+ /*
+ * int table_this_r
+ *
+ * DESCRIPTION:
+ *
+ * Reetrant version of the table_this routine above. Find current
+ * element in a table and pass back information about the key/data
+ * pair. If any of the key/data pointers are NULL then they are
+ * ignored.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer from which we are getting the
+ * current element.
+ *
+ * linear_p - Pointer to a table linear structure which is accessed
+ * here. The same pointer must have been passed to table_first_r
+ * first so that it can be initialized.
+ *
+ * key_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the storage of the current key that is allocated in the table.
+ * If an (int) is stored as the current key (for example) then
+ * key_buf_p should be (int **) i.e. the address of a (int *).
+ *
+ * key_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the key that is stored in the table and that is
+ * associated with the current key.
+ *
+ * data_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the data storage that is allocated in the table and that is
+ * associated with the current key. If a (long) is stored as the data
+ * (for example) then data_buf_p should be (long **) i.e. the address
+ * of a (long *).
+ *
+ * data_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the data that is stored in the table and that is
+ * associated with the current key.
+ */
+ extern
+ int table_this_r(table_t *table_p, table_linear_t *linear_p,
+ void **key_buf_p, int *key_size_p,
+ void **data_buf_p, int *data_size_p);
-/*
- * table_t *table_mmap
- *
- * DESCRIPTION:
- *
- * Mmap a table from a file that had been written to disk earlier via
- * table_write.
- *
- * RETURNS:
- *
- * A pointer to the new table structure which must be passed to
- * table_munmap to be deallocated. On error a NULL is returned.
- *
- * ARGUMENTS:
- *
- * path - Table file to mmap in.
- *
- * error_p - Pointer to an integer which, if not NULL, will contain a
- * table error code.
- */
-extern
-table_t *table_mmap(const char *path, int *error_p);
+ /*
+ * table_t *table_mmap
+ *
+ * DESCRIPTION:
+ *
+ * Mmap a table from a file that had been written to disk earlier via
+ * table_write.
+ *
+ * RETURNS:
+ *
+ * A pointer to the new table structure which must be passed to
+ * table_munmap to be deallocated. On error a NULL is returned.
+ *
+ * ARGUMENTS:
+ *
+ * path - Table file to mmap in.
+ *
+ * error_p - Pointer to an integer which, if not NULL, will contain a
+ * table error code.
+ */
+ extern
+ table_t *table_mmap(const char *path, int *error_p);
-/*
- * int table_munmap
- *
- * DESCRIPTION:
- *
- * Unmmap a table that was previously mmapped using table_mmap.
- *
- * RETURNS:
- *
- * Returns table error codes.
- *
- * ARGUMENTS:
- *
- * table_p - Mmaped table pointer to unmap.
- */
-extern
-int table_munmap(table_t *table_p);
+ /*
+ * int table_munmap
+ *
+ * DESCRIPTION:
+ *
+ * Unmmap a table that was previously mmapped using table_mmap.
+ *
+ * RETURNS:
+ *
+ * Returns table error codes.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Mmaped table pointer to unmap.
+ */
+ extern
+ int table_munmap(table_t *table_p);
-/*
- * int table_read
- *
- * DESCRIPTION:
- *
- * Read in a table from a file that had been written to disk earlier
- * via table_write.
- *
- * RETURNS:
- *
- * Success - Pointer to the new table structure which must be passed
- * to table_free to be deallocated.
- *
- * Failure - NULL
- *
- * ARGUMENTS:
- *
- * path - Table file to read in.
- *
- * error_p - Pointer to an integer which, if not NULL, will contain a
- * table error code.
- */
-extern
-table_t *table_read(const char *path, int *error_p);
+ /*
+ * int table_read
+ *
+ * DESCRIPTION:
+ *
+ * Read in a table from a file that had been written to disk earlier
+ * via table_write.
+ *
+ * RETURNS:
+ *
+ * Success - Pointer to the new table structure which must be passed
+ * to table_free to be deallocated.
+ *
+ * Failure - NULL
+ *
+ * ARGUMENTS:
+ *
+ * path - Table file to read in.
+ *
+ * error_p - Pointer to an integer which, if not NULL, will contain a
+ * table error code.
+ */
+ extern
+ table_t *table_read(const char *path, int *error_p);
-/*
- * int table_write
- *
- * DESCRIPTION:
- *
- * Write a table from memory to file.
- *
- * RETURNS:
- *
- * Success - TABLE_ERROR_NONE
- *
- * Failure - Table error code.
- *
- * ARGUMENTS:
- *
- * table_p - Pointer to the table that we are writing to the file.
- *
- * path - Table file to write out to.
- *
- * mode - Mode of the file. This argument is passed on to open when
- * the file is created.
- */
-extern
-int table_write(const table_t *table_p, const char *path, const int mode);
+ /*
+ * int table_write
+ *
+ * DESCRIPTION:
+ *
+ * Write a table from memory to file.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Pointer to the table that we are writing to the file.
+ *
+ * path - Table file to write out to.
+ *
+ * mode - Mode of the file. This argument is passed on to open when
+ * the file is created.
+ */
+ extern
+ int table_write(const table_t *table_p, const char *path, const int mode);
-/*
- * table_entry_t *table_order
- *
- * DESCRIPTION:
- *
- * Order a table by building an array of table entry pointers and then
- * sorting this array using the qsort function. To retrieve the
- * sorted entries, you can then use the table_entry routine to access
- * each entry in order.
- *
- * NOTE: This routine is thread safe and makes use of an internal
- * status qsort function.
- *
- * RETURNS:
- *
- * Success - An allocated list of table-linear structures which must
- * be freed by table_order_free later.
- *
- * Failure - NULL
- *
- * ARGUMENTS:
- *
- * table_p - Pointer to the table that we are ordering.
- *
- * compare - Comparison function defined by the user. Its definition
- * is at the top of the table.h file. If this is NULL then it will
- * order the table my memcmp-ing the keys.
- *
- * num_entries_p - Pointer to an integer which, if not NULL, will
- * contain the number of entries in the returned entry pointer array.
- *
- * error_p - Pointer to an integer which, if not NULL, will contain a
- * table error code.
- */
-extern
-table_entry_t **table_order(table_t *table_p, table_compare_t compare,
- int *num_entries_p, int *error_p);
+ /*
+ * table_entry_t *table_order
+ *
+ * DESCRIPTION:
+ *
+ * Order a table by building an array of table entry pointers and then
+ * sorting this array using the qsort function. To retrieve the
+ * sorted entries, you can then use the table_entry routine to access
+ * each entry in order.
+ *
+ * NOTE: This routine is thread safe and makes use of an internal
+ * status qsort function.
+ *
+ * RETURNS:
+ *
+ * Success - An allocated list of table-linear structures which must
+ * be freed by table_order_free later.
+ *
+ * Failure - NULL
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Pointer to the table that we are ordering.
+ *
+ * compare - Comparison function defined by the user. Its definition
+ * is at the top of the table.h file. If this is NULL then it will
+ * order the table my memcmp-ing the keys.
+ *
+ * num_entries_p - Pointer to an integer which, if not NULL, will
+ * contain the number of entries in the returned entry pointer array.
+ *
+ * error_p - Pointer to an integer which, if not NULL, will contain a
+ * table error code.
+ */
+ extern
+ table_entry_t **table_order(table_t *table_p, table_compare_t compare,
+ int *num_entries_p, int *error_p);
-/*
- * int table_order_free
- *
- * DESCRIPTION:
- *
- * Free the pointer returned by the table_order or table_order_pos
- * routines.
- *
- * RETURNS:
- *
- * Success - TABLE_ERROR_NONE
- *
- * Failure - Table error code.
- *
- * ARGUMENTS:
- *
- * table_p - Pointer to the table.
- *
- * table_entries - Allocated list of entry pointers returned by
- * table_order.
- *
- * entry_n - Number of entries in the array as passed back by
- * table_order or table_order_pos in num_entries_p.
- */
-extern
-int table_order_free(table_t *table_p, table_entry_t **table_entries,
- const int entry_n);
+ /*
+ * int table_order_free
+ *
+ * DESCRIPTION:
+ *
+ * Free the pointer returned by the table_order or table_order_pos
+ * routines.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Pointer to the table.
+ *
+ * table_entries - Allocated list of entry pointers returned by
+ * table_order.
+ *
+ * entry_n - Number of entries in the array as passed back by
+ * table_order or table_order_pos in num_entries_p.
+ */
+ extern
+ int table_order_free(table_t *table_p, table_entry_t **table_entries,
+ const int entry_n);
-/*
- * int table_entry
- *
- * DESCRIPTION:
- *
- * Get information about an element. The element is one from the
- * array returned by the table_order function. If any of the key/data
- * pointers are NULL then they are ignored.
- *
- * RETURNS:
- *
- * Success - TABLE_ERROR_NONE
- *
- * Failure - Table error code.
- *
- * ARGUMENTS:
- *
- * table_p - Table structure pointer from which we are getting the
- * element.
- *
- * entry_p - Pointer to a table entry from the array returned by the
- * table_order function.
- *
- * key_buf_p - Pointer which, if not NULL, will be set to the address
- * of the storage of this entry that is allocated in the table. If an
- * (int) is stored as this entry (for example) then key_buf_p should
- * be (int **) i.e. the address of a (int *).
- *
- * key_size_p - Pointer to an integer which, if not NULL, will be set
- * to the size of the key that is stored in the table.
- *
- * data_buf_p - Pointer which, if not NULL, will be set to the address
- * of the data storage of this entry that is allocated in the table.
- * If a (long) is stored as this entry data (for example) then
- * data_buf_p should be (long **) i.e. the address of a (long *).
- *
- * data_size_p - Pointer to an integer which, if not NULL, will be set
- * to the size of the data that is stored in the table.
- */
-extern
-int table_entry(table_t *table_p, table_entry_t *entry_p,
- void **key_buf_p, int *key_size_p,
- void **data_buf_p, int *data_size_p);
+ /*
+ * int table_entry
+ *
+ * DESCRIPTION:
+ *
+ * Get information about an element. The element is one from the
+ * array returned by the table_order function. If any of the key/data
+ * pointers are NULL then they are ignored.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer from which we are getting the
+ * element.
+ *
+ * entry_p - Pointer to a table entry from the array returned by the
+ * table_order function.
+ *
+ * key_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the storage of this entry that is allocated in the table. If an
+ * (int) is stored as this entry (for example) then key_buf_p should
+ * be (int **) i.e. the address of a (int *).
+ *
+ * key_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the key that is stored in the table.
+ *
+ * data_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the data storage of this entry that is allocated in the table.
+ * If a (long) is stored as this entry data (for example) then
+ * data_buf_p should be (long **) i.e. the address of a (long *).
+ *
+ * data_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the data that is stored in the table.
+ */
+ extern
+ int table_entry(table_t *table_p, table_entry_t *entry_p,
+ void **key_buf_p, int *key_size_p,
+ void **data_buf_p, int *data_size_p);
-/*
- * table_linear_t *table_order_pos
- *
- * DESCRIPTION:
- *
- * Order a table by building an array of table linear structures and
- * then sorting this array using the qsort function. To retrieve the
- * sorted entries, you can then use the table_entry_pos routine to
- * access each entry in order.
- *
- * NOTE: This routine is thread safe and makes use of an internal
- * status qsort function.
- *
- * RETURNS:
- *
- * Success - An allocated list of table-linear structures which must
- * be freed by table_order_pos_free later.
- *
- * Failure - NULL
- *
- * ARGUMENTS:
- *
- * table_p - Pointer to the table that we are ordering.
- *
- * compare - Comparison function defined by the user. Its definition
- * is at the top of the table.h file. If this is NULL then it will
- * order the table my memcmp-ing the keys.
- *
- * num_entries_p - Pointer to an integer which, if not NULL, will
- * contain the number of entries in the returned entry pointer array.
- *
- * error_p - Pointer to an integer which, if not NULL, will contain a
- * table error code.
- */
-extern
-table_linear_t *table_order_pos(table_t *table_p, table_compare_t compare,
- int *num_entries_p, int *error_p);
+ /*
+ * table_linear_t *table_order_pos
+ *
+ * DESCRIPTION:
+ *
+ * Order a table by building an array of table linear structures and
+ * then sorting this array using the qsort function. To retrieve the
+ * sorted entries, you can then use the table_entry_pos routine to
+ * access each entry in order.
+ *
+ * NOTE: This routine is thread safe and makes use of an internal
+ * status qsort function.
+ *
+ * RETURNS:
+ *
+ * Success - An allocated list of table-linear structures which must
+ * be freed by table_order_pos_free later.
+ *
+ * Failure - NULL
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Pointer to the table that we are ordering.
+ *
+ * compare - Comparison function defined by the user. Its definition
+ * is at the top of the table.h file. If this is NULL then it will
+ * order the table my memcmp-ing the keys.
+ *
+ * num_entries_p - Pointer to an integer which, if not NULL, will
+ * contain the number of entries in the returned entry pointer array.
+ *
+ * error_p - Pointer to an integer which, if not NULL, will contain a
+ * table error code.
+ */
+ extern
+ table_linear_t *table_order_pos(table_t *table_p, table_compare_t compare,
+ int *num_entries_p, int *error_p);
-/*
- * int table_order_pos_free
- *
- * DESCRIPTION:
- *
- * Free the pointer returned by the table_order or table_order_pos
- * routines.
- *
- * RETURNS:
- *
- * Success - TABLE_ERROR_NONE
- *
- * Failure - Table error code.
- *
- * ARGUMENTS:
- *
- * table_p - Pointer to the table.
- *
- * table_entries - Allocated list of entry pointers returned by
- * table_order_pos.
- *
- * entry_n - Number of entries in the array as passed back by
- * table_order or table_order_pos in num_entries_p.
- */
-extern
-int table_order_pos_free(table_t *table_p, table_linear_t *table_entries,
- const int entry_n);
+ /*
+ * int table_order_pos_free
+ *
+ * DESCRIPTION:
+ *
+ * Free the pointer returned by the table_order or table_order_pos
+ * routines.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Pointer to the table.
+ *
+ * table_entries - Allocated list of entry pointers returned by
+ * table_order_pos.
+ *
+ * entry_n - Number of entries in the array as passed back by
+ * table_order or table_order_pos in num_entries_p.
+ */
+ extern
+ int table_order_pos_free(table_t *table_p, table_linear_t *table_entries,
+ const int entry_n);
-/*
- * int table_entry_pos
- *
- * DESCRIPTION:
- *
- * Get information about an element. The element is one from the
- * array returned by the table_order function. If any of the key/data
- * pointers are NULL then they are ignored.
- *
- * RETURNS:
- *
- * Success - TABLE_ERROR_NONE
- *
- * Failure - Table error code.
- *
- * ARGUMENTS:
- *
- * table_p - Table structure pointer from which we are getting the
- * element.
- *
- * linear_p - Pointer to a table linear structure from the array
- * returned by the table_order function.
- *
- * key_buf_p - Pointer which, if not NULL, will be set to the address
- * of the storage of this entry that is allocated in the table. If an
- * (int) is stored as this entry (for example) then key_buf_p should
- * be (int **) i.e. the address of a (int *).
- *
- * key_size_p - Pointer to an integer which, if not NULL, will be set
- * to the size of the key that is stored in the table.
- *
- * data_buf_p - Pointer which, if not NULL, will be set to the address
- * of the data storage of this entry that is allocated in the table.
- * If a (long) is stored as this entry data (for example) then
- * data_buf_p should be (long **) i.e. the address of a (long *).
- *
- * data_size_p - Pointer to an integer which, if not NULL, will be set
- * to the size of the data that is stored in the table.
- */
-extern
-int table_entry_pos(table_t *table_p, table_linear_t *linear_p,
- void **key_buf_p, int *key_size_p,
- void **data_buf_p, int *data_size_p);
+ /*
+ * int table_entry_pos
+ *
+ * DESCRIPTION:
+ *
+ * Get information about an element. The element is one from the
+ * array returned by the table_order function. If any of the key/data
+ * pointers are NULL then they are ignored.
+ *
+ * RETURNS:
+ *
+ * Success - TABLE_ERROR_NONE
+ *
+ * Failure - Table error code.
+ *
+ * ARGUMENTS:
+ *
+ * table_p - Table structure pointer from which we are getting the
+ * element.
+ *
+ * linear_p - Pointer to a table linear structure from the array
+ * returned by the table_order function.
+ *
+ * key_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the storage of this entry that is allocated in the table. If an
+ * (int) is stored as this entry (for example) then key_buf_p should
+ * be (int **) i.e. the address of a (int *).
+ *
+ * key_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the key that is stored in the table.
+ *
+ * data_buf_p - Pointer which, if not NULL, will be set to the address
+ * of the data storage of this entry that is allocated in the table.
+ * If a (long) is stored as this entry data (for example) then
+ * data_buf_p should be (long **) i.e. the address of a (long *).
+ *
+ * data_size_p - Pointer to an integer which, if not NULL, will be set
+ * to the size of the data that is stored in the table.
+ */
+ extern
+ int table_entry_pos(table_t *table_p, table_linear_t *linear_p,
+ void **key_buf_p, int *key_size_p,
+ void **data_buf_p, int *data_size_p);
-/*
- * const char *table_strerror
- *
- * DESCRIPTION:
- *
- * Return the corresponding string for the error number.
- *
- * RETURNS:
- *
- * Success - String equivalient of the error.
- *
- * Failure - String "invalid error code"
- *
- * ARGUMENTS:
- *
- * error - Error number that we are converting.
- */
-extern
-const char *table_strerror(const int error);
+ /*
+ * const char *table_strerror
+ *
+ * DESCRIPTION:
+ *
+ * Return the corresponding string for the error number.
+ *
+ * RETURNS:
+ *
+ * Success - String equivalient of the error.
+ *
+ * Failure - String "invalid error code"
+ *
+ * ARGUMENTS:
+ *
+ * error - Error number that we are converting.
+ */
+ extern
+ const char *table_strerror(const int error);
-/*<<<<<<<<<< This is end of the auto-generated output from fillproto. */
+ /*<<<<<<<<<< This is end of the auto-generated output from fillproto. */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* ! __TABLE_H__ */
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
+ */
* were about 2^68 hashes to choose from. I only tested about a
* billion of those.
*/
-#define HASH_MIX(a, b, c) \
- do { \
- a -= b; a -= c; a ^= (c >> 13); \
- b -= c; b -= a; b ^= (a << 8); \
- c -= a; c -= b; c ^= (b >> 13); \
- a -= b; a -= c; a ^= (c >> 12); \
- b -= c; b -= a; b ^= (a << 16); \
- c -= a; c -= b; c ^= (b >> 5); \
- a -= b; a -= c; a ^= (c >> 3); \
- b -= c; b -= a; b ^= (a << 10); \
- c -= a; c -= b; c ^= (b >> 15); \
- } while(0)
-
-#define SET_POINTER(pnt, val) \
- do { \
- if ((pnt) != NULL) { \
- (*(pnt)) = (val); \
- } \
- } while(0)
+#define HASH_MIX(a, b, c) \
+ do { \
+ a -= b; a -= c; a ^= (c >> 13); \
+ b -= c; b -= a; b ^= (a << 8); \
+ c -= a; c -= b; c ^= (b >> 13); \
+ a -= b; a -= c; a ^= (c >> 12); \
+ b -= c; b -= a; b ^= (a << 16); \
+ c -= a; c -= b; c ^= (b >> 5); \
+ a -= b; a -= c; a ^= (c >> 3); \
+ b -= c; b -= a; b ^= (a << 10); \
+ c -= a; c -= b; c ^= (b >> 15); \
+ } while(0)
+
+#define SET_POINTER(pnt, val) \
+ do { \
+ if ((pnt) != NULL) { \
+ (*(pnt)) = (val); \
+ } \
+ } while(0)
/*
* The following macros take care of the mmap case. When we are
#else
-#define TABLE_POINTER(tab_p, type, pnt) \
- ((tab_p)->ta_mmap == NULL || (pnt) == NULL ? (pnt) : \
- (type)((char *)((tab_p)->ta_mmap) + (long)(pnt)))
+#define TABLE_POINTER(tab_p, type, pnt) \
+ ((tab_p)->ta_mmap == NULL || (pnt) == NULL ? (pnt) : \
+ (type)((char *)((tab_p)->ta_mmap) + (long)(pnt)))
#endif
* Macros to get at the key and the data pointers
*/
#define ENTRY_KEY_BUF(entry_p) ((entry_p)->te_key_buf)
-#define ENTRY_DATA_BUF(tab_p, entry_p) \
- (ENTRY_KEY_BUF(entry_p) + (entry_p)->te_key_size)
+#define ENTRY_DATA_BUF(tab_p, entry_p) \
+ (ENTRY_KEY_BUF(entry_p) + (entry_p)->te_key_size)
/*
* Table structures...
* faster.
*/
typedef struct table_shell_st {
- unsigned int te_key_size; /* size of data */
- unsigned int te_data_size; /* size of data */
- struct table_shell_st *te_next_p; /* pointer to next in the list */
- /* NOTE: this does not have the te_key_buf field here */
+ unsigned int te_key_size; /* size of data */
+ unsigned int te_data_size; /* size of data */
+ struct table_shell_st *te_next_p; /* pointer to next in the list */
+ /* NOTE: this does not have the te_key_buf field here */
} table_shell_t;
/*
* changed to match.
*/
typedef struct table_entry_st {
- unsigned int te_key_size; /* size of data */
- unsigned int te_data_size; /* size of data */
- struct table_entry_st *te_next_p; /* pointer to next in the list */
- unsigned char te_key_buf[1]; /* 1st byte of key buf */
+ unsigned int te_key_size; /* size of data */
+ unsigned int te_data_size; /* size of data */
+ struct table_entry_st *te_next_p; /* pointer to next in the list */
+ unsigned char te_key_buf[1]; /* 1st byte of key buf */
} table_entry_t;
/* external structure for debuggers be able to see void */
/* main table structure */
typedef struct table_st {
- unsigned int ta_magic; /* magic number */
- unsigned int ta_flags; /* table's flags defined in table.h */
- unsigned int ta_bucket_n; /* num of buckets, should be 2^X */
- unsigned int ta_entry_n; /* num of entries in all buckets */
- unsigned int ta_data_align; /* data alignment value */
- table_entry_t **ta_buckets; /* array of linked lists */
- table_linear_t ta_linear; /* linear tracking */
- struct table_st *ta_mmap; /* mmaped table */
- unsigned long ta_file_size; /* size of on-disk space */
+ unsigned int ta_magic; /* magic number */
+ unsigned int ta_flags; /* table's flags defined in table.h */
+ unsigned int ta_bucket_n; /* num of buckets, should be 2^X */
+ unsigned int ta_entry_n; /* num of entries in all buckets */
+ unsigned int ta_data_align; /* data alignment value */
+ table_entry_t **ta_buckets; /* array of linked lists */
+ table_linear_t ta_linear; /* linear tracking */
+ struct table_st *ta_mmap; /* mmaped table */
+ unsigned long ta_file_size; /* size of on-disk space */
- void *ta_mem_pool; /* pointer to some memory pool */
- table_mem_alloc_t ta_alloc_func; /* memory allocation function */
- table_mem_resize_t ta_resize_func; /* memory resize function */
- table_mem_free_t ta_free_func; /* memory free function */
+ void *ta_mem_pool; /* pointer to some memory pool */
+ table_mem_alloc_t ta_alloc_func; /* memory allocation function */
+ table_mem_resize_t ta_resize_func; /* memory resize function */
+ table_mem_free_t ta_free_func; /* memory free function */
} table_t;
/* external table structure for debuggers */
/* local comparison functions */
typedef int (*compare_t)(const void *element1_p, const void *element2_p,
- table_compare_t user_compare,
- const table_t *table_p, int *err_bp);
+ table_compare_t user_compare,
+ const table_t *table_p, int *err_bp);
/*
* to map error to string
*/
typedef struct {
- int es_error; /* error number */
- char *es_string; /* assocaited string */
+ int es_error; /* error number */
+ char *es_string; /* assocaited string */
} error_str_t;
static error_str_t errors[] = {
- { TABLE_ERROR_NONE, "no error" },
- { TABLE_ERROR_PNT, "invalid table pointer" },
- { TABLE_ERROR_ARG_NULL, "buffer argument is null" },
- { TABLE_ERROR_SIZE, "incorrect size argument" },
- { TABLE_ERROR_OVERWRITE, "key exists and no overwrite" },
- { TABLE_ERROR_NOT_FOUND, "key does not exist" },
- { TABLE_ERROR_ALLOC, "error allocating memory" },
- { TABLE_ERROR_LINEAR, "linear access not in progress" },
- { TABLE_ERROR_OPEN, "could not open file" },
- { TABLE_ERROR_SEEK, "could not seek to position in file" },
- { TABLE_ERROR_READ, "could not read from file" },
- { TABLE_ERROR_WRITE, "could not write to file" },
- { TABLE_ERROR_MMAP_NONE, "no mmap support compiled in library" },
- { TABLE_ERROR_MMAP, "could not mmap the file" },
- { TABLE_ERROR_MMAP_OP, "operation not valid on mmap files" },
- { TABLE_ERROR_EMPTY, "table is empty" },
- { TABLE_ERROR_NOT_EMPTY, "table contains data" },
- { TABLE_ERROR_ALIGNMENT, "invalid alignment value" },
- { TABLE_ERROR_COMPARE, "problems with internal comparison" },
- { TABLE_ERROR_FREE, "memory free error" },
- { 0 }
+ { TABLE_ERROR_NONE, "no error" },
+ { TABLE_ERROR_PNT, "invalid table pointer" },
+ { TABLE_ERROR_ARG_NULL, "buffer argument is null" },
+ { TABLE_ERROR_SIZE, "incorrect size argument" },
+ { TABLE_ERROR_OVERWRITE, "key exists and no overwrite" },
+ { TABLE_ERROR_NOT_FOUND, "key does not exist" },
+ { TABLE_ERROR_ALLOC, "error allocating memory" },
+ { TABLE_ERROR_LINEAR, "linear access not in progress" },
+ { TABLE_ERROR_OPEN, "could not open file" },
+ { TABLE_ERROR_SEEK, "could not seek to position in file" },
+ { TABLE_ERROR_READ, "could not read from file" },
+ { TABLE_ERROR_WRITE, "could not write to file" },
+ { TABLE_ERROR_MMAP_NONE, "no mmap support compiled in library" },
+ { TABLE_ERROR_MMAP, "could not mmap the file" },
+ { TABLE_ERROR_MMAP_OP, "operation not valid on mmap files" },
+ { TABLE_ERROR_EMPTY, "table is empty" },
+ { TABLE_ERROR_NOT_EMPTY, "table contains data" },
+ { TABLE_ERROR_ALIGNMENT, "invalid alignment value" },
+ { TABLE_ERROR_COMPARE, "problems with internal comparison" },
+ { TABLE_ERROR_FREE, "memory free error" },
+ { 0 }
};
#define INVALID_ERROR "invalid error code"
#endif /* ! __TABLE_LOC_H__ */
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
+ */
+
*/
static void startup(void)
{
- int bit_c;
- unsigned long size = 1;
+ int bit_c;
+ unsigned long size = 1;
- if (enabled_b) {
- return;
- }
+ if (enabled_b) {
+ return;
+ }
- /* allocate our free bit array list */
- for (bit_c = 0; bit_c <= MAX_BITS; bit_c++) {
- bit_array[bit_c] = size;
+ /* allocate our free bit array list */
+ for (bit_c = 0; bit_c <= MAX_BITS; bit_c++) {
+ bit_array[bit_c] = size;
- /*
- * Note our minimum number of bits that can store a pointer. This
- * is smallest address that we can have a linked list for.
- */
- if (min_bit_free_next == 0 && size >= sizeof(void *)) {
- min_bit_free_next = bit_c;
- }
- /*
- * Note our minimum number of bits that can store a pointer and
- * the size of the block.
- */
- if (min_bit_free_size == 0 && size >= sizeof(mpool_free_t)) {
- min_bit_free_size = bit_c;
- }
+ /*
+ * Note our minimum number of bits that can store a pointer. This
+ * is smallest address that we can have a linked list for.
+ */
+ if (min_bit_free_next == 0 && size >= sizeof(void *)) {
+ min_bit_free_next = bit_c;
+ }
+ /*
+ * Note our minimum number of bits that can store a pointer and
+ * the size of the block.
+ */
+ if (min_bit_free_size == 0 && size >= sizeof(mpool_free_t)) {
+ min_bit_free_size = bit_c;
+ }
- size *= 2;
- }
+ size *= 2;
+ }
- enabled_b = 1;
+ enabled_b = 1;
}
/*
*/
static int size_to_bits(const unsigned long size)
{
- int bit_c = 0;
+ int bit_c = 0;
- for (bit_c = 0; bit_c <= MAX_BITS; bit_c++) {
- if (size <= bit_array[bit_c]) {
- break;
- }
- }
+ for (bit_c = 0; bit_c <= MAX_BITS; bit_c++) {
+ if (size <= bit_array[bit_c]) {
+ break;
+ }
+ }
- return bit_c;
+ return bit_c;
}
/*
*/
static int size_to_free_bits(const unsigned long size)
{
- int bit_c = 0;
+ int bit_c = 0;
- if (size == 0) {
- return 0;
- }
+ if (size == 0) {
+ return 0;
+ }
- for (bit_c = 0; bit_c <= MAX_BITS; bit_c++) {
- if (size < bit_array[bit_c]) {
- break;
- }
- }
+ for (bit_c = 0; bit_c <= MAX_BITS; bit_c++) {
+ if (size < bit_array[bit_c]) {
+ break;
+ }
+ }
- return bit_c - 1;
+ return bit_c - 1;
}
/*
*/
static unsigned long bits_to_size(const int bit_n)
{
- if (bit_n > MAX_BITS) {
- return bit_array[MAX_BITS];
- }
- else {
- return bit_array[bit_n];
- }
+ if (bit_n > MAX_BITS) {
+ return bit_array[MAX_BITS];
+ }
+ else {
+ return bit_array[bit_n];
+ }
}
/*
* a mpool error code.
*/
static void *alloc_pages(mpool_t *mp_p, const unsigned int page_n,
- int *error_p)
+ int *error_p)
{
- void *mem, *fill_mem;
- unsigned long size, fill;
- int state;
-
- /* are we over our max-pages? */
- if (mp_p->mp_max_pages > 0 && mp_p->mp_page_c >= mp_p->mp_max_pages) {
- SET_POINTER(error_p, MPOOL_ERROR_NO_PAGES);
- return NULL;
- }
+ void *mem, *fill_mem;
+ unsigned long size, fill;
+ int state;
+
+ /* are we over our max-pages? */
+ if (mp_p->mp_max_pages > 0 && mp_p->mp_page_c >= mp_p->mp_max_pages) {
+ SET_POINTER(error_p, MPOOL_ERROR_NO_PAGES);
+ return NULL;
+ }
- size = SIZE_OF_PAGES(mp_p, page_n);
+ size = SIZE_OF_PAGES(mp_p, page_n);
#ifdef DEBUG
- (void)printf("allocating %u pages or %lu bytes\n", page_n, size);
+ (void)printf("allocating %u pages or %lu bytes\n", page_n, size);
#endif
- if (BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_USE_SBRK)) {
- mem = sbrk(size);
- if (mem == (void *)-1) {
- SET_POINTER(error_p, MPOOL_ERROR_NO_MEM);
- return NULL;
- }
- fill = (unsigned long)mem % mp_p->mp_page_size;
+ if (BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_USE_SBRK)) {
+ mem = sbrk(size);
+ if (mem == (void *)-1) {
+ SET_POINTER(error_p, MPOOL_ERROR_NO_MEM);
+ return NULL;
+ }
+ fill = (unsigned long)mem % mp_p->mp_page_size;
- if (fill > 0) {
- fill = mp_p->mp_page_size - fill;
- fill_mem = sbrk(fill);
- if (fill_mem == (void *)-1) {
- SET_POINTER(error_p, MPOOL_ERROR_NO_MEM);
- return NULL;
- }
- if ((char *)fill_mem != (char *)mem + size) {
- SET_POINTER(error_p, MPOOL_ERROR_SBRK_CONTIG);
- return NULL;
- }
- mem = (char *)mem + fill;
- }
- }
- else {
- state = MAP_PRIVATE;
+ if (fill > 0) {
+ fill = mp_p->mp_page_size - fill;
+ fill_mem = sbrk(fill);
+ if (fill_mem == (void *)-1) {
+ SET_POINTER(error_p, MPOOL_ERROR_NO_MEM);
+ return NULL;
+ }
+ if ((char *)fill_mem != (char *)mem + size) {
+ SET_POINTER(error_p, MPOOL_ERROR_SBRK_CONTIG);
+ return NULL;
+ }
+ mem = (char *)mem + fill;
+ }
+ }
+ else {
+ state = MAP_PRIVATE;
#ifdef MAP_FILE
- state |= MAP_FILE;
+ state |= MAP_FILE;
#endif
#ifdef MAP_VARIABLE
- state |= MAP_VARIABLE;
+ state |= MAP_VARIABLE;
#endif
- /* mmap from /dev/zero */
- mem = mmap((caddr_t)mp_p->mp_addr, size, PROT_READ | PROT_WRITE, state,
- mp_p->mp_fd, mp_p->mp_top);
- if (mem == (void *)MAP_FAILED) {
- if (errno == ENOMEM) {
- SET_POINTER(error_p, MPOOL_ERROR_NO_MEM);
- }
- else {
- SET_POINTER(error_p, MPOOL_ERROR_MMAP);
- }
- return NULL;
- }
- mp_p->mp_top += size;
- if (mp_p->mp_addr != NULL) {
- mp_p->mp_addr = (char *)mp_p->mp_addr + size;
- }
- }
-
- mp_p->mp_page_c += page_n;
-
- SET_POINTER(error_p, MPOOL_ERROR_NONE);
- return mem;
+ /* mmap from /dev/zero */
+ mem = mmap((caddr_t)mp_p->mp_addr, size, PROT_READ | PROT_WRITE, state,
+ mp_p->mp_fd, mp_p->mp_top);
+ if (mem == (void *)MAP_FAILED) {
+ if (errno == ENOMEM) {
+ SET_POINTER(error_p, MPOOL_ERROR_NO_MEM);
+ }
+ else {
+ SET_POINTER(error_p, MPOOL_ERROR_MMAP);
+ }
+ return NULL;
+ }
+ mp_p->mp_top += size;
+ if (mp_p->mp_addr != NULL) {
+ mp_p->mp_addr = (char *)mp_p->mp_addr + size;
+ }
+ }
+
+ mp_p->mp_page_c += page_n;
+
+ SET_POINTER(error_p, MPOOL_ERROR_NONE);
+ return mem;
}
/*
* sbrk_b -> Set to one if the pages were allocated with sbrk else mmap.
*/
static int free_pages(void *pages, const unsigned long size,
- const int sbrk_b)
+ const int sbrk_b)
{
- if (! sbrk_b) {
- (void)munmap((caddr_t)pages, size);
- }
+ if (! sbrk_b) {
+ (void)munmap((caddr_t)pages, size);
+ }
- return MPOOL_ERROR_NONE;
+ return MPOOL_ERROR_NONE;
}
/*
*/
static int check_magic(const void *addr, const unsigned long size)
{
- const unsigned char *mem_p;
+ const unsigned char *mem_p;
- /* set our starting point */
- mem_p = (unsigned char *)addr + size;
+ /* set our starting point */
+ mem_p = (unsigned char *)addr + size;
- if (*mem_p == FENCE_MAGIC0 && *(mem_p + 1) == FENCE_MAGIC1) {
- return MPOOL_ERROR_NONE;
- }
- else {
- return MPOOL_ERROR_PNT_OVER;
- }
+ if (*mem_p == FENCE_MAGIC0 && *(mem_p + 1) == FENCE_MAGIC1) {
+ return MPOOL_ERROR_NONE;
+ }
+ else {
+ return MPOOL_ERROR_PNT_OVER;
+ }
}
/*
*/
static void write_magic(const void *addr)
{
- *(unsigned char *)addr = FENCE_MAGIC0;
- *((unsigned char *)addr + 1) = FENCE_MAGIC1;
+ *(unsigned char *)addr = FENCE_MAGIC0;
+ *((unsigned char *)addr + 1) = FENCE_MAGIC1;
}
/*
* size -> Size of the address space.
*/
static int free_pointer(mpool_t *mp_p, void *addr,
- const unsigned long size)
+ const unsigned long size)
{
- unsigned int bit_n;
- unsigned long real_size;
- mpool_free_t free_pnt;
+ unsigned int bit_n;
+ unsigned long real_size;
+ mpool_free_t free_pnt;
#ifdef DEBUG
- (void)printf("freeing a block at %lx of %lu bytes\n", (long)addr, size);
+ (void)printf("freeing a block at %lx of %lu bytes\n", (long)addr, size);
#endif
- if (size == 0) {
- return MPOOL_ERROR_NONE;
- }
-
- /*
- * if the user size is larger then can fit in an entire block then
- * we change the size
- */
- if (size > MAX_BLOCK_USER_MEMORY(mp_p)) {
- real_size = SIZE_OF_PAGES(mp_p, PAGES_IN_SIZE(mp_p, size)) -
- sizeof(mpool_block_t);
- }
- else {
- real_size = size;
- }
-
- /*
- * We use a specific free bits calculation here because if we are
- * freeing 10 bytes then we will be putting it into the 8-byte free
- * list and not the 16 byte list. size_to_bits(10) will return 4
- * instead of 3.
- */
- bit_n = size_to_free_bits(real_size);
-
- /*
- * Minimal error checking. We could go all the way through the
- * list however this might be prohibitive.
- */
- if (mp_p->mp_free[bit_n] == addr) {
- return MPOOL_ERROR_IS_FREE;
- }
-
- /* add the freed pointer to the free list */
- if (bit_n < min_bit_free_next) {
- /*
- * Yes we know this will lose 99% of the allocations but what else
- * can we do? No space for a next pointer.
- */
- if (mp_p->mp_free[bit_n] == NULL) {
- mp_p->mp_free[bit_n] = addr;
- }
- }
- else if (bit_n < min_bit_free_size) {
- /* we copy, not assign, to maintain the free list */
- memcpy(addr, mp_p->mp_free + bit_n, sizeof(void *));
- mp_p->mp_free[bit_n] = addr;
- }
- else {
+ if (size == 0) {
+ return MPOOL_ERROR_NONE;
+ }
+
+ /*
+ * if the user size is larger then can fit in an entire block then
+ * we change the size
+ */
+ if (size > MAX_BLOCK_USER_MEMORY(mp_p)) {
+ real_size = SIZE_OF_PAGES(mp_p, PAGES_IN_SIZE(mp_p, size)) -
+ sizeof(mpool_block_t);
+ }
+ else {
+ real_size = size;
+ }
+
+ /*
+ * We use a specific free bits calculation here because if we are
+ * freeing 10 bytes then we will be putting it into the 8-byte free
+ * list and not the 16 byte list. size_to_bits(10) will return 4
+ * instead of 3.
+ */
+ bit_n = size_to_free_bits(real_size);
+
+ /*
+ * Minimal error checking. We could go all the way through the
+ * list however this might be prohibitive.
+ */
+ if (mp_p->mp_free[bit_n] == addr) {
+ return MPOOL_ERROR_IS_FREE;
+ }
+
+ /* add the freed pointer to the free list */
+ if (bit_n < min_bit_free_next) {
+ /*
+ * Yes we know this will lose 99% of the allocations but what else
+ * can we do? No space for a next pointer.
+ */
+ if (mp_p->mp_free[bit_n] == NULL) {
+ mp_p->mp_free[bit_n] = addr;
+ }
+ }
+ else if (bit_n < min_bit_free_size) {
+ /* we copy, not assign, to maintain the free list */
+ memcpy(addr, mp_p->mp_free + bit_n, sizeof(void *));
+ mp_p->mp_free[bit_n] = addr;
+ }
+ else {
- /* setup our free list structure */
- free_pnt.mf_next_p = mp_p->mp_free[bit_n];
- free_pnt.mf_size = real_size;
+ /* setup our free list structure */
+ free_pnt.mf_next_p = mp_p->mp_free[bit_n];
+ free_pnt.mf_size = real_size;
- /* we copy the structure in since we don't know about alignment */
- memcpy(addr, &free_pnt, sizeof(free_pnt));
- mp_p->mp_free[bit_n] = addr;
- }
+ /* we copy the structure in since we don't know about alignment */
+ memcpy(addr, &free_pnt, sizeof(free_pnt));
+ mp_p->mp_free[bit_n] = addr;
+ }
- return MPOOL_ERROR_NONE;
+ return MPOOL_ERROR_NONE;
}
/*
* size -> Size of the space that we are taking from address.
*/
static int split_block(mpool_t *mp_p, void *free_addr,
- const unsigned long size)
+ const unsigned long size)
{
- mpool_block_t *block_p, *new_block_p;
- int ret, page_n;
- void *end_p;
-
- /*
- * 1st we find the block pointer from our free addr. At this point
- * the pointer must be the 1st one in the block if it is spans
- * multiple blocks.
- */
- block_p = (mpool_block_t *)((char *)free_addr - sizeof(mpool_block_t));
- if (block_p->mb_magic != BLOCK_MAGIC
- || block_p->mb_magic2 != BLOCK_MAGIC) {
- return MPOOL_ERROR_POOL_OVER;
- }
-
- page_n = PAGES_IN_SIZE(mp_p, size);
-
- /* we are creating a new block structure for the 2nd ... */
- new_block_p = (mpool_block_t *)((char *)block_p +
- SIZE_OF_PAGES(mp_p, page_n));
- new_block_p->mb_magic = BLOCK_MAGIC;
- /* New bounds is 1st block bounds. The 1st block's is reset below. */
- new_block_p->mb_bounds_p = block_p->mb_bounds_p;
- /* Continue the linked list. The 1st block will point to us below. */
- new_block_p->mb_next_p = block_p->mb_next_p;
- new_block_p->mb_magic2 = BLOCK_MAGIC;
-
- /* bounds for the 1st block are reset to the 1st page only */
- block_p->mb_bounds_p = (char *)new_block_p;
- /* the next block pointer for the 1st block is now the new one */
- block_p->mb_next_p = new_block_p;
-
- /* only free the space in the 1st block if it is only 1 block in size */
- if (page_n == 1) {
- /* now free the rest of the 1st block block */
- end_p = (char *)free_addr + size;
- ret = free_pointer(mp_p, end_p,
- (char *)block_p->mb_bounds_p - (char *)end_p);
- if (ret != MPOOL_ERROR_NONE) {
- return ret;
- }
- }
-
- /* now free the rest of the block */
- ret = free_pointer(mp_p, FIRST_ADDR_IN_BLOCK(new_block_p),
- MEMORY_IN_BLOCK(new_block_p));
- if (ret != MPOOL_ERROR_NONE) {
- return ret;
- }
-
- return MPOOL_ERROR_NONE;
+ mpool_block_t *block_p, *new_block_p;
+ int ret, page_n;
+ void *end_p;
+
+ /*
+ * 1st we find the block pointer from our free addr. At this point
+ * the pointer must be the 1st one in the block if it is spans
+ * multiple blocks.
+ */
+ block_p = (mpool_block_t *)((char *)free_addr - sizeof(mpool_block_t));
+ if (block_p->mb_magic != BLOCK_MAGIC
+ || block_p->mb_magic2 != BLOCK_MAGIC) {
+ return MPOOL_ERROR_POOL_OVER;
+ }
+
+ page_n = PAGES_IN_SIZE(mp_p, size);
+
+ /* we are creating a new block structure for the 2nd ... */
+ new_block_p = (mpool_block_t *)((char *)block_p +
+ SIZE_OF_PAGES(mp_p, page_n));
+ new_block_p->mb_magic = BLOCK_MAGIC;
+ /* New bounds is 1st block bounds. The 1st block's is reset below. */
+ new_block_p->mb_bounds_p = block_p->mb_bounds_p;
+ /* Continue the linked list. The 1st block will point to us below. */
+ new_block_p->mb_next_p = block_p->mb_next_p;
+ new_block_p->mb_magic2 = BLOCK_MAGIC;
+
+ /* bounds for the 1st block are reset to the 1st page only */
+ block_p->mb_bounds_p = (char *)new_block_p;
+ /* the next block pointer for the 1st block is now the new one */
+ block_p->mb_next_p = new_block_p;
+
+ /* only free the space in the 1st block if it is only 1 block in size */
+ if (page_n == 1) {
+ /* now free the rest of the 1st block block */
+ end_p = (char *)free_addr + size;
+ ret = free_pointer(mp_p, end_p,
+ (char *)block_p->mb_bounds_p - (char *)end_p);
+ if (ret != MPOOL_ERROR_NONE) {
+ return ret;
+ }
+ }
+
+ /* now free the rest of the block */
+ ret = free_pointer(mp_p, FIRST_ADDR_IN_BLOCK(new_block_p),
+ MEMORY_IN_BLOCK(new_block_p));
+ if (ret != MPOOL_ERROR_NONE) {
+ return ret;
+ }
+
+ return MPOOL_ERROR_NONE;
}
/*
* a mpool error code.
*/
static void *get_space(mpool_t *mp_p, const unsigned long byte_size,
- int *error_p)
+ int *error_p)
{
- mpool_block_t *block_p;
- mpool_free_t free_pnt;
- int ret;
- unsigned long size;
- unsigned int bit_c, page_n, left;
- void *free_addr = NULL, *free_end;
-
- size = byte_size;
- while ((size & (sizeof(void *) - 1)) > 0) {
- size++;
- }
-
- /*
- * First we check the free lists looking for something with enough
- * pages. Maybe we should only look X bits higher in the list.
- *
- * XXX: this is where we'd do the best fit. We'd look for the
- * closest match. We then could put the rest of the allocation that
- * we did not use in a lower free list. Have a define which states
- * how deep in the free list to go to find the closest match.
- */
- for (bit_c = size_to_bits(size); bit_c <= MAX_BITS; bit_c++) {
- if (mp_p->mp_free[bit_c] != NULL) {
- free_addr = mp_p->mp_free[bit_c];
- break;
- }
- }
-
- /*
- * If we haven't allocated any blocks or if the last block doesn't
- * have enough memory then we need a new block.
- */
- if (bit_c > MAX_BITS) {
+ mpool_block_t *block_p;
+ mpool_free_t free_pnt;
+ int ret;
+ unsigned long size;
+ unsigned int bit_c, page_n, left;
+ void *free_addr = NULL, *free_end;
+
+ size = byte_size;
+ while ((size & (sizeof(void *) - 1)) > 0) {
+ size++;
+ }
+
+ /*
+ * First we check the free lists looking for something with enough
+ * pages. Maybe we should only look X bits higher in the list.
+ *
+ * XXX: this is where we'd do the best fit. We'd look for the
+ * closest match. We then could put the rest of the allocation that
+ * we did not use in a lower free list. Have a define which states
+ * how deep in the free list to go to find the closest match.
+ */
+ for (bit_c = size_to_bits(size); bit_c <= MAX_BITS; bit_c++) {
+ if (mp_p->mp_free[bit_c] != NULL) {
+ free_addr = mp_p->mp_free[bit_c];
+ break;
+ }
+ }
+
+ /*
+ * If we haven't allocated any blocks or if the last block doesn't
+ * have enough memory then we need a new block.
+ */
+ if (bit_c > MAX_BITS) {
- /* we need to allocate more space */
+ /* we need to allocate more space */
- page_n = PAGES_IN_SIZE(mp_p, size);
+ page_n = PAGES_IN_SIZE(mp_p, size);
- /* now we try and get the pages we need/want */
- block_p = alloc_pages(mp_p, page_n, error_p);
- if (block_p == NULL) {
- /* error_p set in alloc_pages */
- return NULL;
- }
+ /* now we try and get the pages we need/want */
+ block_p = alloc_pages(mp_p, page_n, error_p);
+ if (block_p == NULL) {
+ /* error_p set in alloc_pages */
+ return NULL;
+ }
- /* init the block header */
- block_p->mb_magic = BLOCK_MAGIC;
- block_p->mb_bounds_p = (char *)block_p + SIZE_OF_PAGES(mp_p, page_n);
- block_p->mb_next_p = mp_p->mp_first_p;
- block_p->mb_magic2 = BLOCK_MAGIC;
+ /* init the block header */
+ block_p->mb_magic = BLOCK_MAGIC;
+ block_p->mb_bounds_p = (char *)block_p + SIZE_OF_PAGES(mp_p, page_n);
+ block_p->mb_next_p = mp_p->mp_first_p;
+ block_p->mb_magic2 = BLOCK_MAGIC;
- /*
- * We insert it into the front of the queue. We could add it to
- * the end but there is not much use.
- */
- mp_p->mp_first_p = block_p;
- if (mp_p->mp_last_p == NULL) {
- mp_p->mp_last_p = block_p;
- }
+ /*
+ * We insert it into the front of the queue. We could add it to
+ * the end but there is not much use.
+ */
+ mp_p->mp_first_p = block_p;
+ if (mp_p->mp_last_p == NULL) {
+ mp_p->mp_last_p = block_p;
+ }
- free_addr = FIRST_ADDR_IN_BLOCK(block_p);
+ free_addr = FIRST_ADDR_IN_BLOCK(block_p);
#ifdef DEBUG
- (void)printf("had to allocate space for %lx of %lu bytes\n",
- (long)free_addr, size);
+ (void)printf("had to allocate space for %lx of %lu bytes\n",
+ (long)free_addr, size);
#endif
- free_end = (char *)free_addr + size;
- left = (char *)block_p->mb_bounds_p - (char *)free_end;
- }
- else {
+ free_end = (char *)free_addr + size;
+ left = (char *)block_p->mb_bounds_p - (char *)free_end;
+ }
+ else {
- if (bit_c < min_bit_free_next) {
- mp_p->mp_free[bit_c] = NULL;
- /* calculate the number of left over bytes */
- left = bits_to_size(bit_c) - size;
- }
- else if (bit_c < min_bit_free_next) {
- /* grab the next pointer from the freed address into our list */
- memcpy(mp_p->mp_free + bit_c, free_addr, sizeof(void *));
- /* calculate the number of left over bytes */
- left = bits_to_size(bit_c) - size;
- }
- else {
- /* grab the free structure from the address */
- memcpy(&free_pnt, free_addr, sizeof(free_pnt));
- mp_p->mp_free[bit_c] = free_pnt.mf_next_p;
+ if (bit_c < min_bit_free_next) {
+ mp_p->mp_free[bit_c] = NULL;
+ /* calculate the number of left over bytes */
+ left = bits_to_size(bit_c) - size;
+ }
+ else if (bit_c < min_bit_free_next) {
+ /* grab the next pointer from the freed address into our list */
+ memcpy(mp_p->mp_free + bit_c, free_addr, sizeof(void *));
+ /* calculate the number of left over bytes */
+ left = bits_to_size(bit_c) - size;
+ }
+ else {
+ /* grab the free structure from the address */
+ memcpy(&free_pnt, free_addr, sizeof(free_pnt));
+ mp_p->mp_free[bit_c] = free_pnt.mf_next_p;
- /* are we are splitting up a multiblock chunk into fewer blocks? */
- if (PAGES_IN_SIZE(mp_p, free_pnt.mf_size) > PAGES_IN_SIZE(mp_p, size)) {
- ret = split_block(mp_p, free_addr, size);
- if (ret != MPOOL_ERROR_NONE) {
- SET_POINTER(error_p, ret);
- return NULL;
- }
- /* left over memory was taken care of in split_block */
- left = 0;
- }
- else {
- /* calculate the number of left over bytes */
- left = free_pnt.mf_size - size;
- }
- }
+ /* are we are splitting up a multiblock chunk into fewer blocks? */
+ if (PAGES_IN_SIZE(mp_p, free_pnt.mf_size) > PAGES_IN_SIZE(mp_p, size)) {
+ ret = split_block(mp_p, free_addr, size);
+ if (ret != MPOOL_ERROR_NONE) {
+ SET_POINTER(error_p, ret);
+ return NULL;
+ }
+ /* left over memory was taken care of in split_block */
+ left = 0;
+ }
+ else {
+ /* calculate the number of left over bytes */
+ left = free_pnt.mf_size - size;
+ }
+ }
#ifdef DEBUG
- (void)printf("found a free block at %lx of %lu bytes\n",
- (long)free_addr, left + size);
+ (void)printf("found a free block at %lx of %lu bytes\n",
+ (long)free_addr, left + size);
#endif
- free_end = (char *)free_addr + size;
- }
-
- /*
- * If we have memory left over then we free it so someone else can
- * use it. We do not free the space if we just allocated a
- * multi-block chunk because we need to have every allocation easily
- * find the start of the block. Every user address % page-size
- * should take us to the start of the block.
- */
- if (left > 0 && size <= MAX_BLOCK_USER_MEMORY(mp_p)) {
- /* free the rest of the block */
- ret = free_pointer(mp_p, free_end, left);
- if (ret != MPOOL_ERROR_NONE) {
- SET_POINTER(error_p, ret);
- return NULL;
- }
- }
-
- /* update our bounds */
- if (free_addr > mp_p->mp_bounds_p) {
- mp_p->mp_bounds_p = free_addr;
- }
- else if (free_addr < mp_p->mp_min_p) {
- mp_p->mp_min_p = free_addr;
- }
-
- return free_addr;
+ free_end = (char *)free_addr + size;
+ }
+
+ /*
+ * If we have memory left over then we free it so someone else can
+ * use it. We do not free the space if we just allocated a
+ * multi-block chunk because we need to have every allocation easily
+ * find the start of the block. Every user address % page-size
+ * should take us to the start of the block.
+ */
+ if (left > 0 && size <= MAX_BLOCK_USER_MEMORY(mp_p)) {
+ /* free the rest of the block */
+ ret = free_pointer(mp_p, free_end, left);
+ if (ret != MPOOL_ERROR_NONE) {
+ SET_POINTER(error_p, ret);
+ return NULL;
+ }
+ }
+
+ /* update our bounds */
+ if (free_addr > mp_p->mp_bounds_p) {
+ mp_p->mp_bounds_p = free_addr;
+ }
+ else if (free_addr < mp_p->mp_min_p) {
+ mp_p->mp_min_p = free_addr;
+ }
+
+ return free_addr;
}
/*
* a mpool error code.
*/
static void *alloc_mem(mpool_t *mp_p, const unsigned long byte_size,
- int *error_p)
+ int *error_p)
{
- unsigned long size, fence;
- void *addr;
-
- /* make sure we have enough bytes */
- if (byte_size < MIN_ALLOCATION) {
- size = MIN_ALLOCATION;
- }
- else {
- size = byte_size;
- }
-
- if (BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_NO_FREE)) {
- fence = 0;
- }
- else {
- fence = FENCE_SIZE;
- }
-
- /* get our free space + the space for the fence post */
- addr = get_space(mp_p, size + fence, error_p);
- if (addr == NULL) {
- /* error_p set in get_space */
- return NULL;
- }
-
- if (! BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_NO_FREE)) {
- write_magic((char *)addr + size);
- }
-
- /* maintain our stats */
- mp_p->mp_alloc_c++;
- mp_p->mp_user_alloc += size;
- if (mp_p->mp_user_alloc > mp_p->mp_max_alloc) {
- mp_p->mp_max_alloc = mp_p->mp_user_alloc;
- }
-
- SET_POINTER(error_p, MPOOL_ERROR_NONE);
- return addr;
+ unsigned long size, fence;
+ void *addr;
+
+ /* make sure we have enough bytes */
+ if (byte_size < MIN_ALLOCATION) {
+ size = MIN_ALLOCATION;
+ }
+ else {
+ size = byte_size;
+ }
+
+ if (BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_NO_FREE)) {
+ fence = 0;
+ }
+ else {
+ fence = FENCE_SIZE;
+ }
+
+ /* get our free space + the space for the fence post */
+ addr = get_space(mp_p, size + fence, error_p);
+ if (addr == NULL) {
+ /* error_p set in get_space */
+ return NULL;
+ }
+
+ if (! BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_NO_FREE)) {
+ write_magic((char *)addr + size);
+ }
+
+ /* maintain our stats */
+ mp_p->mp_alloc_c++;
+ mp_p->mp_user_alloc += size;
+ if (mp_p->mp_user_alloc > mp_p->mp_max_alloc) {
+ mp_p->mp_max_alloc = mp_p->mp_user_alloc;
+ }
+
+ SET_POINTER(error_p, MPOOL_ERROR_NONE);
+ return addr;
}
/*
*/
static int free_mem(mpool_t *mp_p, void *addr, const unsigned long size)
{
- unsigned long old_size, fence;
- int ret;
- mpool_block_t *block_p;
-
- /*
- * If the size is larger than a block then the allocation must be at
- * the front of the block.
- */
- if (size > MAX_BLOCK_USER_MEMORY(mp_p)) {
- block_p = (mpool_block_t *)((char *)addr - sizeof(mpool_block_t));
- if (block_p->mb_magic != BLOCK_MAGIC
- || block_p->mb_magic2 != BLOCK_MAGIC) {
- return MPOOL_ERROR_POOL_OVER;
- }
- }
-
- /* make sure we have enough bytes */
- if (size < MIN_ALLOCATION) {
- old_size = MIN_ALLOCATION;
- }
- else {
- old_size = size;
- }
-
- /* if we are packing the pool smaller */
- if (BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_NO_FREE)) {
- fence = 0;
- }
- else {
- /* find the user's magic numbers if they were written */
- ret = check_magic(addr, old_size);
- if (ret != MPOOL_ERROR_NONE) {
- return ret;
- }
- fence = FENCE_SIZE;
- }
-
- /* now we free the pointer */
- ret = free_pointer(mp_p, addr, old_size + fence);
- if (ret != MPOOL_ERROR_NONE) {
- return ret;
- }
- mp_p->mp_user_alloc -= old_size;
-
- /* adjust our stats */
- mp_p->mp_alloc_c--;
-
- return MPOOL_ERROR_NONE;
+ unsigned long old_size, fence;
+ int ret;
+ mpool_block_t *block_p;
+
+ /*
+ * If the size is larger than a block then the allocation must be at
+ * the front of the block.
+ */
+ if (size > MAX_BLOCK_USER_MEMORY(mp_p)) {
+ block_p = (mpool_block_t *)((char *)addr - sizeof(mpool_block_t));
+ if (block_p->mb_magic != BLOCK_MAGIC
+ || block_p->mb_magic2 != BLOCK_MAGIC) {
+ return MPOOL_ERROR_POOL_OVER;
+ }
+ }
+
+ /* make sure we have enough bytes */
+ if (size < MIN_ALLOCATION) {
+ old_size = MIN_ALLOCATION;
+ }
+ else {
+ old_size = size;
+ }
+
+ /* if we are packing the pool smaller */
+ if (BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_NO_FREE)) {
+ fence = 0;
+ }
+ else {
+ /* find the user's magic numbers if they were written */
+ ret = check_magic(addr, old_size);
+ if (ret != MPOOL_ERROR_NONE) {
+ return ret;
+ }
+ fence = FENCE_SIZE;
+ }
+
+ /* now we free the pointer */
+ ret = free_pointer(mp_p, addr, old_size + fence);
+ if (ret != MPOOL_ERROR_NONE) {
+ return ret;
+ }
+ mp_p->mp_user_alloc -= old_size;
+
+ /* adjust our stats */
+ mp_p->mp_alloc_c--;
+
+ return MPOOL_ERROR_NONE;
}
/***************************** exported routines *****************************/
* a mpool error code.
*/
mpool_t *mpool_open(const unsigned int flags, const unsigned int page_size,
- void *start_addr, int *error_p)
+ void *start_addr, int *error_p)
{
- mpool_block_t *block_p;
- int page_n, ret;
- mpool_t mp, *mp_p;
- void *free_addr;
-
- if (! enabled_b) {
- startup();
- }
-
- /* zero our temp struct */
- memset(&mp, 0, sizeof(mp));
-
- mp.mp_magic = MPOOL_MAGIC;
- mp.mp_flags = flags;
- mp.mp_alloc_c = 0;
- mp.mp_user_alloc = 0;
- mp.mp_max_alloc = 0;
- mp.mp_page_c = 0;
- /* mp.mp_page_size set below */
- /* mp.mp_blocks_bit_n set below */
- /* mp.mp_fd set below */
- /* mp.mp_top set below */
- /* mp.mp_addr set below */
- mp.mp_log_func = NULL;
- mp.mp_min_p = NULL;
- mp.mp_bounds_p = NULL;
- mp.mp_first_p = NULL;
- mp.mp_last_p = NULL;
- mp.mp_magic2 = MPOOL_MAGIC;
-
- /* get and sanity check our page size */
- if (page_size > 0) {
- mp.mp_page_size = page_size;
- if (mp.mp_page_size % getpagesize() != 0) {
- SET_POINTER(error_p, MPOOL_ERROR_ARG_INVALID);
- return NULL;
- }
- }
- else {
- mp.mp_page_size = getpagesize() * DEFAULT_PAGE_MULT;
- if (mp.mp_page_size % 1024 != 0) {
- SET_POINTER(error_p, MPOOL_ERROR_PAGE_SIZE);
- return NULL;
- }
- }
-
- if (BIT_IS_SET(flags, MPOOL_FLAG_USE_SBRK)) {
- mp.mp_fd = -1;
- mp.mp_addr = NULL;
- mp.mp_top = 0;
- }
- else {
- /* open dev-zero for our mmaping */
- mp.mp_fd = open("/dev/zero", O_RDWR, 0);
- if (mp.mp_fd < 0) {
- SET_POINTER(error_p, MPOOL_ERROR_OPEN_ZERO);
- return NULL;
- }
- mp.mp_addr = start_addr;
- /* we start at the front of the file */
- mp.mp_top = 0;
- }
-
- /*
- * Find out how many pages we need for our mpool structure.
- *
- * NOTE: this adds possibly unneeded space for mpool_block_t which
- * may not be in this block.
- */
- page_n = PAGES_IN_SIZE(&mp, sizeof(mpool_t));
-
- /* now allocate us space for the actual struct */
- mp_p = alloc_pages(&mp, page_n, error_p);
- if (mp_p == NULL) {
- if (mp.mp_fd >= 0) {
- (void)close(mp.mp_fd);
- mp.mp_fd = -1;
- }
- return NULL;
- }
-
- /*
- * NOTE: we do not normally free the rest of the block here because
- * we want to lesson the chance of an allocation overwriting the
- * main structure.
- */
- if (BIT_IS_SET(flags, MPOOL_FLAG_HEAVY_PACKING)) {
+ mpool_block_t *block_p;
+ int page_n, ret;
+ mpool_t mp, *mp_p;
+ void *free_addr;
+
+ if (! enabled_b) {
+ startup();
+ }
+
+ /* zero our temp struct */
+ memset(&mp, 0, sizeof(mp));
+
+ mp.mp_magic = MPOOL_MAGIC;
+ mp.mp_flags = flags;
+ mp.mp_alloc_c = 0;
+ mp.mp_user_alloc = 0;
+ mp.mp_max_alloc = 0;
+ mp.mp_page_c = 0;
+ /* mp.mp_page_size set below */
+ /* mp.mp_blocks_bit_n set below */
+ /* mp.mp_fd set below */
+ /* mp.mp_top set below */
+ /* mp.mp_addr set below */
+ mp.mp_log_func = NULL;
+ mp.mp_min_p = NULL;
+ mp.mp_bounds_p = NULL;
+ mp.mp_first_p = NULL;
+ mp.mp_last_p = NULL;
+ mp.mp_magic2 = MPOOL_MAGIC;
+
+ /* get and sanity check our page size */
+ if (page_size > 0) {
+ mp.mp_page_size = page_size;
+ if (mp.mp_page_size % getpagesize() != 0) {
+ SET_POINTER(error_p, MPOOL_ERROR_ARG_INVALID);
+ return NULL;
+ }
+ }
+ else {
+ mp.mp_page_size = getpagesize() * DEFAULT_PAGE_MULT;
+ if (mp.mp_page_size % 1024 != 0) {
+ SET_POINTER(error_p, MPOOL_ERROR_PAGE_SIZE);
+ return NULL;
+ }
+ }
+
+ if (BIT_IS_SET(flags, MPOOL_FLAG_USE_SBRK)) {
+ mp.mp_fd = -1;
+ mp.mp_addr = NULL;
+ mp.mp_top = 0;
+ }
+ else {
+ /* open dev-zero for our mmaping */
+ mp.mp_fd = open("/dev/zero", O_RDWR, 0);
+ if (mp.mp_fd < 0) {
+ SET_POINTER(error_p, MPOOL_ERROR_OPEN_ZERO);
+ return NULL;
+ }
+ mp.mp_addr = start_addr;
+ /* we start at the front of the file */
+ mp.mp_top = 0;
+ }
+
+ /*
+ * Find out how many pages we need for our mpool structure.
+ *
+ * NOTE: this adds possibly unneeded space for mpool_block_t which
+ * may not be in this block.
+ */
+ page_n = PAGES_IN_SIZE(&mp, sizeof(mpool_t));
+
+ /* now allocate us space for the actual struct */
+ mp_p = alloc_pages(&mp, page_n, error_p);
+ if (mp_p == NULL) {
+ if (mp.mp_fd >= 0) {
+ (void)close(mp.mp_fd);
+ mp.mp_fd = -1;
+ }
+ return NULL;
+ }
+
+ /*
+ * NOTE: we do not normally free the rest of the block here because
+ * we want to lesson the chance of an allocation overwriting the
+ * main structure.
+ */
+ if (BIT_IS_SET(flags, MPOOL_FLAG_HEAVY_PACKING)) {
- /* we add a block header to the front of the block */
- block_p = (mpool_block_t *)mp_p;
+ /* we add a block header to the front of the block */
+ block_p = (mpool_block_t *)mp_p;
- /* init the block header */
- block_p->mb_magic = BLOCK_MAGIC;
- block_p->mb_bounds_p = (char *)block_p + SIZE_OF_PAGES(&mp, page_n);
- block_p->mb_next_p = NULL;
- block_p->mb_magic2 = BLOCK_MAGIC;
+ /* init the block header */
+ block_p->mb_magic = BLOCK_MAGIC;
+ block_p->mb_bounds_p = (char *)block_p + SIZE_OF_PAGES(&mp, page_n);
+ block_p->mb_next_p = NULL;
+ block_p->mb_magic2 = BLOCK_MAGIC;
- /* the mpool pointer is then the 2nd thing in the block */
- mp_p = FIRST_ADDR_IN_BLOCK(block_p);
- free_addr = (char *)mp_p + sizeof(mpool_t);
+ /* the mpool pointer is then the 2nd thing in the block */
+ mp_p = FIRST_ADDR_IN_BLOCK(block_p);
+ free_addr = (char *)mp_p + sizeof(mpool_t);
- /* free the rest of the block */
- ret = free_pointer(&mp, free_addr,
- (char *)block_p->mb_bounds_p - (char *)free_addr);
- if (ret != MPOOL_ERROR_NONE) {
- if (mp.mp_fd >= 0) {
- (void)close(mp.mp_fd);
- mp.mp_fd = -1;
- }
- /* NOTE: after this line mp_p will be invalid */
- (void)free_pages(block_p, SIZE_OF_PAGES(&mp, page_n),
- BIT_IS_SET(flags, MPOOL_FLAG_USE_SBRK));
- SET_POINTER(error_p, ret);
- return NULL;
- }
+ /* free the rest of the block */
+ ret = free_pointer(&mp, free_addr,
+ (char *)block_p->mb_bounds_p - (char *)free_addr);
+ if (ret != MPOOL_ERROR_NONE) {
+ if (mp.mp_fd >= 0) {
+ (void)close(mp.mp_fd);
+ mp.mp_fd = -1;
+ }
+ /* NOTE: after this line mp_p will be invalid */
+ (void)free_pages(block_p, SIZE_OF_PAGES(&mp, page_n),
+ BIT_IS_SET(flags, MPOOL_FLAG_USE_SBRK));
+ SET_POINTER(error_p, ret);
+ return NULL;
+ }
- /*
- * NOTE: if we are HEAVY_PACKING then the 1st block with the mpool
- * header is not on the block linked list.
- */
+ /*
+ * NOTE: if we are HEAVY_PACKING then the 1st block with the mpool
+ * header is not on the block linked list.
+ */
- /* now copy our tmp structure into our new memory area */
- memcpy(mp_p, &mp, sizeof(mpool_t));
+ /* now copy our tmp structure into our new memory area */
+ memcpy(mp_p, &mp, sizeof(mpool_t));
- /* we setup min/max to our current address which is as good as any */
- mp_p->mp_min_p = block_p;
- mp_p->mp_bounds_p = block_p->mb_bounds_p;
- }
- else {
- /* now copy our tmp structure into our new memory area */
- memcpy(mp_p, &mp, sizeof(mpool_t));
+ /* we setup min/max to our current address which is as good as any */
+ mp_p->mp_min_p = block_p;
+ mp_p->mp_bounds_p = block_p->mb_bounds_p;
+ }
+ else {
+ /* now copy our tmp structure into our new memory area */
+ memcpy(mp_p, &mp, sizeof(mpool_t));
- /* we setup min/max to our current address which is as good as any */
- mp_p->mp_min_p = mp_p;
- mp_p->mp_bounds_p = (char *)mp_p + SIZE_OF_PAGES(mp_p, page_n);
- }
+ /* we setup min/max to our current address which is as good as any */
+ mp_p->mp_min_p = mp_p;
+ mp_p->mp_bounds_p = (char *)mp_p + SIZE_OF_PAGES(mp_p, page_n);
+ }
- SET_POINTER(error_p, MPOOL_ERROR_NONE);
- return mp_p;
+ SET_POINTER(error_p, MPOOL_ERROR_NONE);
+ return mp_p;
}
/*
*/
int mpool_close(mpool_t *mp_p)
{
- mpool_block_t *block_p, *next_p;
- void *addr;
- unsigned long size;
- int ret, final = MPOOL_ERROR_NONE;
-
- /* special case, just return no-error */
- if (mp_p == NULL) {
- return MPOOL_ERROR_ARG_NULL;
- }
- if (mp_p->mp_magic != MPOOL_MAGIC) {
- return MPOOL_ERROR_PNT;
- }
- if (mp_p->mp_magic2 != MPOOL_MAGIC) {
- return MPOOL_ERROR_POOL_OVER;
- }
-
- if (mp_p->mp_log_func != NULL) {
- mp_p->mp_log_func(mp_p, MPOOL_FUNC_CLOSE, 0, 0, NULL, NULL, 0);
- }
-
- /*
- * NOTE: if we are HEAVY_PACKING then the 1st block with the mpool
- * header is not on the linked list.
- */
-
- /* free/invalidate the blocks */
- for (block_p = mp_p->mp_first_p; block_p != NULL; block_p = next_p) {
- if (block_p->mb_magic != BLOCK_MAGIC
- || block_p->mb_magic2 != BLOCK_MAGIC) {
- final = MPOOL_ERROR_POOL_OVER;
- break;
- }
- block_p->mb_magic = 0;
- block_p->mb_magic2 = 0;
- /* record the next pointer because it might be invalidated below */
- next_p = block_p->mb_next_p;
- ret = free_pages(block_p, (char *)block_p->mb_bounds_p - (char *)block_p,
- BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_USE_SBRK));
- if (ret != MPOOL_ERROR_NONE) {
- final = ret;
- }
- }
-
- /* close /dev/zero if necessary */
- if (mp_p->mp_fd >= 0) {
- (void)close(mp_p->mp_fd);
- mp_p->mp_fd = -1;
- }
-
- /* invalidate the mpool before we ditch it */
- mp_p->mp_magic = 0;
- mp_p->mp_magic2 = 0;
-
- /* last we munmap the mpool pointer itself */
- if (! BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_USE_SBRK)) {
+ mpool_block_t *block_p, *next_p;
+ void *addr;
+ unsigned long size;
+ int ret, final = MPOOL_ERROR_NONE;
+
+ /* special case, just return no-error */
+ if (mp_p == NULL) {
+ return MPOOL_ERROR_ARG_NULL;
+ }
+ if (mp_p->mp_magic != MPOOL_MAGIC) {
+ return MPOOL_ERROR_PNT;
+ }
+ if (mp_p->mp_magic2 != MPOOL_MAGIC) {
+ return MPOOL_ERROR_POOL_OVER;
+ }
+
+ if (mp_p->mp_log_func != NULL) {
+ mp_p->mp_log_func(mp_p, MPOOL_FUNC_CLOSE, 0, 0, NULL, NULL, 0);
+ }
+
+ /*
+ * NOTE: if we are HEAVY_PACKING then the 1st block with the mpool
+ * header is not on the linked list.
+ */
+
+ /* free/invalidate the blocks */
+ for (block_p = mp_p->mp_first_p; block_p != NULL; block_p = next_p) {
+ if (block_p->mb_magic != BLOCK_MAGIC
+ || block_p->mb_magic2 != BLOCK_MAGIC) {
+ final = MPOOL_ERROR_POOL_OVER;
+ break;
+ }
+ block_p->mb_magic = 0;
+ block_p->mb_magic2 = 0;
+ /* record the next pointer because it might be invalidated below */
+ next_p = block_p->mb_next_p;
+ ret = free_pages(block_p, (char *)block_p->mb_bounds_p - (char *)block_p,
+ BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_USE_SBRK));
+ if (ret != MPOOL_ERROR_NONE) {
+ final = ret;
+ }
+ }
+
+ /* close /dev/zero if necessary */
+ if (mp_p->mp_fd >= 0) {
+ (void)close(mp_p->mp_fd);
+ mp_p->mp_fd = -1;
+ }
+
+ /* invalidate the mpool before we ditch it */
+ mp_p->mp_magic = 0;
+ mp_p->mp_magic2 = 0;
+
+ /* last we munmap the mpool pointer itself */
+ if (! BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_USE_SBRK)) {
- /* if we are heavy packing then we need to free the 1st block later */
- if (BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_HEAVY_PACKING)) {
- addr = (char *)mp_p - sizeof(mpool_block_t);
- }
- else {
- addr = mp_p;
- }
- size = SIZE_OF_PAGES(mp_p, PAGES_IN_SIZE(mp_p, sizeof(mpool_t)));
+ /* if we are heavy packing then we need to free the 1st block later */
+ if (BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_HEAVY_PACKING)) {
+ addr = (char *)mp_p - sizeof(mpool_block_t);
+ }
+ else {
+ addr = mp_p;
+ }
+ size = SIZE_OF_PAGES(mp_p, PAGES_IN_SIZE(mp_p, sizeof(mpool_t)));
- (void)munmap((caddr_t)addr, size);
- }
+ (void)munmap((caddr_t)addr, size);
+ }
- return final;
+ return final;
}
/*
*/
int mpool_clear(mpool_t *mp_p)
{
- mpool_block_t *block_p;
- int final = MPOOL_ERROR_NONE, bit_n, ret;
- void *first_p;
-
- /* special case, just return no-error */
- if (mp_p == NULL) {
- return MPOOL_ERROR_ARG_NULL;
- }
- if (mp_p->mp_magic != MPOOL_MAGIC) {
- return MPOOL_ERROR_PNT;
- }
- if (mp_p->mp_magic2 != MPOOL_MAGIC) {
- return MPOOL_ERROR_POOL_OVER;
- }
-
- if (mp_p->mp_log_func != NULL) {
- mp_p->mp_log_func(mp_p, MPOOL_FUNC_CLEAR, 0, 0, NULL, NULL, 0);
- }
-
- /* reset all of our free lists */
- for (bit_n = 0; bit_n <= MAX_BITS; bit_n++) {
- mp_p->mp_free[bit_n] = NULL;
- }
-
- /* free the blocks */
- for (block_p = mp_p->mp_first_p;
- block_p != NULL;
- block_p = block_p->mb_next_p) {
- if (block_p->mb_magic != BLOCK_MAGIC
- || block_p->mb_magic2 != BLOCK_MAGIC) {
- final = MPOOL_ERROR_POOL_OVER;
- break;
- }
+ mpool_block_t *block_p;
+ int final = MPOOL_ERROR_NONE, bit_n, ret;
+ void *first_p;
+
+ /* special case, just return no-error */
+ if (mp_p == NULL) {
+ return MPOOL_ERROR_ARG_NULL;
+ }
+ if (mp_p->mp_magic != MPOOL_MAGIC) {
+ return MPOOL_ERROR_PNT;
+ }
+ if (mp_p->mp_magic2 != MPOOL_MAGIC) {
+ return MPOOL_ERROR_POOL_OVER;
+ }
+
+ if (mp_p->mp_log_func != NULL) {
+ mp_p->mp_log_func(mp_p, MPOOL_FUNC_CLEAR, 0, 0, NULL, NULL, 0);
+ }
+
+ /* reset all of our free lists */
+ for (bit_n = 0; bit_n <= MAX_BITS; bit_n++) {
+ mp_p->mp_free[bit_n] = NULL;
+ }
+
+ /* free the blocks */
+ for (block_p = mp_p->mp_first_p;
+ block_p != NULL;
+ block_p = block_p->mb_next_p) {
+ if (block_p->mb_magic != BLOCK_MAGIC
+ || block_p->mb_magic2 != BLOCK_MAGIC) {
+ final = MPOOL_ERROR_POOL_OVER;
+ break;
+ }
- first_p = FIRST_ADDR_IN_BLOCK(block_p);
+ first_p = FIRST_ADDR_IN_BLOCK(block_p);
- /* free the memory */
- ret = free_pointer(mp_p, first_p, MEMORY_IN_BLOCK(block_p));
- if (ret != MPOOL_ERROR_NONE) {
- final = ret;
- }
- }
-
- return final;
+ /* free the memory */
+ ret = free_pointer(mp_p, first_p, MEMORY_IN_BLOCK(block_p));
+ if (ret != MPOOL_ERROR_NONE) {
+ final = ret;
+ }
+ }
+
+ return final;
}
/*
* a mpool error code.
*/
void *mpool_alloc(mpool_t *mp_p, const unsigned long byte_size,
- int *error_p)
+ int *error_p)
{
- void *addr;
-
- if (mp_p == NULL) {
- /* special case -- do a normal malloc */
- addr = (void *)malloc(byte_size);
- if (addr == NULL) {
- SET_POINTER(error_p, MPOOL_ERROR_ALLOC);
- return NULL;
- }
- else {
- SET_POINTER(error_p, MPOOL_ERROR_NONE);
- return addr;
- }
- }
-
- if (mp_p->mp_magic != MPOOL_MAGIC) {
- SET_POINTER(error_p, MPOOL_ERROR_PNT);
- return NULL;
- }
- if (mp_p->mp_magic2 != MPOOL_MAGIC) {
- SET_POINTER(error_p, MPOOL_ERROR_POOL_OVER);
- return NULL;
- }
-
- if (byte_size == 0) {
- SET_POINTER(error_p, MPOOL_ERROR_ARG_INVALID);
- return NULL;
- }
-
- addr = alloc_mem(mp_p, byte_size, error_p);
-
- if (mp_p->mp_log_func != NULL) {
- mp_p->mp_log_func(mp_p, MPOOL_FUNC_ALLOC, byte_size, 0, addr, NULL, 0);
- }
-
- return addr;
+ void *addr;
+
+ if (mp_p == NULL) {
+ /* special case -- do a normal malloc */
+ addr = (void *)malloc(byte_size);
+ if (addr == NULL) {
+ SET_POINTER(error_p, MPOOL_ERROR_ALLOC);
+ return NULL;
+ }
+ else {
+ SET_POINTER(error_p, MPOOL_ERROR_NONE);
+ return addr;
+ }
+ }
+
+ if (mp_p->mp_magic != MPOOL_MAGIC) {
+ SET_POINTER(error_p, MPOOL_ERROR_PNT);
+ return NULL;
+ }
+ if (mp_p->mp_magic2 != MPOOL_MAGIC) {
+ SET_POINTER(error_p, MPOOL_ERROR_POOL_OVER);
+ return NULL;
+ }
+
+ if (byte_size == 0) {
+ SET_POINTER(error_p, MPOOL_ERROR_ARG_INVALID);
+ return NULL;
+ }
+
+ addr = alloc_mem(mp_p, byte_size, error_p);
+
+ if (mp_p->mp_log_func != NULL) {
+ mp_p->mp_log_func(mp_p, MPOOL_FUNC_ALLOC, byte_size, 0, addr, NULL, 0);
+ }
+
+ return addr;
}
/*
* a mpool error code.
*/
void *mpool_calloc(mpool_t *mp_p, const unsigned long ele_n,
- const unsigned long ele_size, int *error_p)
+ const unsigned long ele_size, int *error_p)
{
- void *addr;
- unsigned long byte_size;
-
- if (mp_p == NULL) {
- /* special case -- do a normal calloc */
- addr = (void *)calloc(ele_n, ele_size);
- if (addr == NULL) {
- SET_POINTER(error_p, MPOOL_ERROR_ALLOC);
- return NULL;
- }
- else {
- SET_POINTER(error_p, MPOOL_ERROR_NONE);
- return addr;
- }
+ void *addr;
+ unsigned long byte_size;
+
+ if (mp_p == NULL) {
+ /* special case -- do a normal calloc */
+ addr = (void *)calloc(ele_n, ele_size);
+ if (addr == NULL) {
+ SET_POINTER(error_p, MPOOL_ERROR_ALLOC);
+ return NULL;
+ }
+ else {
+ SET_POINTER(error_p, MPOOL_ERROR_NONE);
+ return addr;
+ }
- }
- if (mp_p->mp_magic != MPOOL_MAGIC) {
- SET_POINTER(error_p, MPOOL_ERROR_PNT);
- return NULL;
- }
- if (mp_p->mp_magic2 != MPOOL_MAGIC) {
- SET_POINTER(error_p, MPOOL_ERROR_POOL_OVER);
- return NULL;
- }
-
- if (ele_n == 0 || ele_size == 0) {
- SET_POINTER(error_p, MPOOL_ERROR_ARG_INVALID);
- return NULL;
- }
-
- byte_size = ele_n * ele_size;
- addr = alloc_mem(mp_p, byte_size, error_p);
- if (addr != NULL) {
- memset(addr, 0, byte_size);
- }
-
- if (mp_p->mp_log_func != NULL) {
- mp_p->mp_log_func(mp_p, MPOOL_FUNC_CALLOC, ele_size, ele_n, addr, NULL, 0);
- }
-
- /* NOTE: error_p set above */
- return addr;
+ }
+ if (mp_p->mp_magic != MPOOL_MAGIC) {
+ SET_POINTER(error_p, MPOOL_ERROR_PNT);
+ return NULL;
+ }
+ if (mp_p->mp_magic2 != MPOOL_MAGIC) {
+ SET_POINTER(error_p, MPOOL_ERROR_POOL_OVER);
+ return NULL;
+ }
+
+ if (ele_n == 0 || ele_size == 0) {
+ SET_POINTER(error_p, MPOOL_ERROR_ARG_INVALID);
+ return NULL;
+ }
+
+ byte_size = ele_n * ele_size;
+ addr = alloc_mem(mp_p, byte_size, error_p);
+ if (addr != NULL) {
+ memset(addr, 0, byte_size);
+ }
+
+ if (mp_p->mp_log_func != NULL) {
+ mp_p->mp_log_func(mp_p, MPOOL_FUNC_CALLOC, ele_size, ele_n, addr, NULL, 0);
+ }
+
+ /* NOTE: error_p set above */
+ return addr;
}
/*
*/
int mpool_free(mpool_t *mp_p, void *addr, const unsigned long size)
{
- if (mp_p == NULL) {
- /* special case -- do a normal free */
- free(addr);
- return MPOOL_ERROR_NONE;
- }
- if (mp_p->mp_magic != MPOOL_MAGIC) {
- return MPOOL_ERROR_PNT;
- }
- if (mp_p->mp_magic2 != MPOOL_MAGIC) {
- return MPOOL_ERROR_POOL_OVER;
- }
-
- if (mp_p->mp_log_func != NULL) {
- mp_p->mp_log_func(mp_p, MPOOL_FUNC_FREE, size, 0, NULL, addr, 0);
- }
-
- if (addr == NULL) {
- return MPOOL_ERROR_ARG_NULL;
- }
- if (size == 0) {
- return MPOOL_ERROR_ARG_INVALID;
- }
-
- return free_mem(mp_p, addr, size);
+ if (mp_p == NULL) {
+ /* special case -- do a normal free */
+ free(addr);
+ return MPOOL_ERROR_NONE;
+ }
+ if (mp_p->mp_magic != MPOOL_MAGIC) {
+ return MPOOL_ERROR_PNT;
+ }
+ if (mp_p->mp_magic2 != MPOOL_MAGIC) {
+ return MPOOL_ERROR_POOL_OVER;
+ }
+
+ if (mp_p->mp_log_func != NULL) {
+ mp_p->mp_log_func(mp_p, MPOOL_FUNC_FREE, size, 0, NULL, addr, 0);
+ }
+
+ if (addr == NULL) {
+ return MPOOL_ERROR_ARG_NULL;
+ }
+ if (size == 0) {
+ return MPOOL_ERROR_ARG_INVALID;
+ }
+
+ return free_mem(mp_p, addr, size);
}
/*
* a mpool error code.
*/
void *mpool_resize(mpool_t *mp_p, void *old_addr,
- const unsigned long old_byte_size,
- const unsigned long new_byte_size,
- int *error_p)
+ const unsigned long old_byte_size,
+ const unsigned long new_byte_size,
+ int *error_p)
{
- unsigned long copy_size, new_size, old_size, fence;
- void *new_addr;
- mpool_block_t *block_p;
- int ret;
-
- if (mp_p == NULL) {
- /* special case -- do a normal realloc */
- new_addr = (void *)realloc(old_addr, new_byte_size);
- if (new_addr == NULL) {
- SET_POINTER(error_p, MPOOL_ERROR_ALLOC);
- return NULL;
- }
- else {
- SET_POINTER(error_p, MPOOL_ERROR_NONE);
- return new_addr;
- }
- }
-
- if (mp_p->mp_magic != MPOOL_MAGIC) {
- SET_POINTER(error_p, MPOOL_ERROR_PNT);
- return NULL;
- }
- if (mp_p->mp_magic2 != MPOOL_MAGIC) {
- SET_POINTER(error_p, MPOOL_ERROR_POOL_OVER);
- return NULL;
- }
-
- if (old_addr == NULL) {
- SET_POINTER(error_p, MPOOL_ERROR_ARG_NULL);
- return NULL;
- }
- if (old_byte_size == 0) {
- SET_POINTER(error_p, MPOOL_ERROR_ARG_INVALID);
- return NULL;
- }
-
- /*
- * If the size is larger than a block then the allocation must be at
- * the front of the block.
- */
- if (old_byte_size > MAX_BLOCK_USER_MEMORY(mp_p)) {
- block_p = (mpool_block_t *)((char *)old_addr - sizeof(mpool_block_t));
- if (block_p->mb_magic != BLOCK_MAGIC
- || block_p->mb_magic2 != BLOCK_MAGIC) {
- SET_POINTER(error_p, MPOOL_ERROR_POOL_OVER);
- return NULL;
- }
- }
-
- /* make sure we have enough bytes */
- if (old_byte_size < MIN_ALLOCATION) {
- old_size = MIN_ALLOCATION;
- }
- else {
- old_size = old_byte_size;
- }
-
- /* verify that the size matches exactly if we can */
- if (BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_NO_FREE)) {
- fence = 0;
- }
- else if (old_size > 0) {
- ret = check_magic(old_addr, old_size);
- if (ret != MPOOL_ERROR_NONE) {
- SET_POINTER(error_p, ret);
- return NULL;
- }
- fence = FENCE_SIZE;
- }
-
- /* make sure we have enough bytes */
- if (new_byte_size < MIN_ALLOCATION) {
- new_size = MIN_ALLOCATION;
- }
- else {
- new_size = new_byte_size;
- }
-
- /*
- * NOTE: we could here see if the size is the same or less and then
- * use the current memory and free the space above. This is harder
- * than it sounds if we are changing the block size of the
- * allocation.
- */
-
- /* we need to get another address */
- new_addr = alloc_mem(mp_p, new_byte_size, error_p);
- if (new_addr == NULL) {
- /* error_p set in mpool_alloc */
- return NULL;
- }
-
- if (new_byte_size > old_byte_size) {
- copy_size = old_byte_size;
- }
- else {
- copy_size = new_byte_size;
- }
- memcpy(new_addr, old_addr, copy_size);
-
- /* free the old address */
- ret = free_mem(mp_p, old_addr, old_byte_size);
- if (ret != MPOOL_ERROR_NONE) {
- /* if the old free failed, try and free the new address */
- (void)free_mem(mp_p, new_addr, new_byte_size);
- SET_POINTER(error_p, ret);
- return NULL;
- }
-
- if (mp_p->mp_log_func != NULL) {
- mp_p->mp_log_func(mp_p, MPOOL_FUNC_RESIZE, new_byte_size,
- 0, new_addr, old_addr, old_byte_size);
- }
-
- SET_POINTER(error_p, MPOOL_ERROR_NONE);
- return new_addr;
+ unsigned long copy_size, new_size, old_size, fence;
+ void *new_addr;
+ mpool_block_t *block_p;
+ int ret;
+
+ if (mp_p == NULL) {
+ /* special case -- do a normal realloc */
+ new_addr = (void *)realloc(old_addr, new_byte_size);
+ if (new_addr == NULL) {
+ SET_POINTER(error_p, MPOOL_ERROR_ALLOC);
+ return NULL;
+ }
+ else {
+ SET_POINTER(error_p, MPOOL_ERROR_NONE);
+ return new_addr;
+ }
+ }
+
+ if (mp_p->mp_magic != MPOOL_MAGIC) {
+ SET_POINTER(error_p, MPOOL_ERROR_PNT);
+ return NULL;
+ }
+ if (mp_p->mp_magic2 != MPOOL_MAGIC) {
+ SET_POINTER(error_p, MPOOL_ERROR_POOL_OVER);
+ return NULL;
+ }
+
+ if (old_addr == NULL) {
+ SET_POINTER(error_p, MPOOL_ERROR_ARG_NULL);
+ return NULL;
+ }
+ if (old_byte_size == 0) {
+ SET_POINTER(error_p, MPOOL_ERROR_ARG_INVALID);
+ return NULL;
+ }
+
+ /*
+ * If the size is larger than a block then the allocation must be at
+ * the front of the block.
+ */
+ if (old_byte_size > MAX_BLOCK_USER_MEMORY(mp_p)) {
+ block_p = (mpool_block_t *)((char *)old_addr - sizeof(mpool_block_t));
+ if (block_p->mb_magic != BLOCK_MAGIC
+ || block_p->mb_magic2 != BLOCK_MAGIC) {
+ SET_POINTER(error_p, MPOOL_ERROR_POOL_OVER);
+ return NULL;
+ }
+ }
+
+ /* make sure we have enough bytes */
+ if (old_byte_size < MIN_ALLOCATION) {
+ old_size = MIN_ALLOCATION;
+ }
+ else {
+ old_size = old_byte_size;
+ }
+
+ /* verify that the size matches exactly if we can */
+ if (BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_NO_FREE)) {
+ fence = 0;
+ }
+ else if (old_size > 0) {
+ ret = check_magic(old_addr, old_size);
+ if (ret != MPOOL_ERROR_NONE) {
+ SET_POINTER(error_p, ret);
+ return NULL;
+ }
+ fence = FENCE_SIZE;
+ }
+
+ /* make sure we have enough bytes */
+ if (new_byte_size < MIN_ALLOCATION) {
+ new_size = MIN_ALLOCATION;
+ }
+ else {
+ new_size = new_byte_size;
+ }
+
+ /*
+ * NOTE: we could here see if the size is the same or less and then
+ * use the current memory and free the space above. This is harder
+ * than it sounds if we are changing the block size of the
+ * allocation.
+ */
+
+ /* we need to get another address */
+ new_addr = alloc_mem(mp_p, new_byte_size, error_p);
+ if (new_addr == NULL) {
+ /* error_p set in mpool_alloc */
+ return NULL;
+ }
+
+ if (new_byte_size > old_byte_size) {
+ copy_size = old_byte_size;
+ }
+ else {
+ copy_size = new_byte_size;
+ }
+ memcpy(new_addr, old_addr, copy_size);
+
+ /* free the old address */
+ ret = free_mem(mp_p, old_addr, old_byte_size);
+ if (ret != MPOOL_ERROR_NONE) {
+ /* if the old free failed, try and free the new address */
+ (void)free_mem(mp_p, new_addr, new_byte_size);
+ SET_POINTER(error_p, ret);
+ return NULL;
+ }
+
+ if (mp_p->mp_log_func != NULL) {
+ mp_p->mp_log_func(mp_p, MPOOL_FUNC_RESIZE, new_byte_size,
+ 0, new_addr, old_addr, old_byte_size);
+ }
+
+ SET_POINTER(error_p, MPOOL_ERROR_NONE);
+ return new_addr;
}
/*
* overhead) used by the pool.
*/
int mpool_stats(const mpool_t *mp_p, unsigned int *page_size_p,
- unsigned long *num_alloced_p,
- unsigned long *user_alloced_p,
- unsigned long *max_alloced_p,
- unsigned long *tot_alloced_p)
+ unsigned long *num_alloced_p,
+ unsigned long *user_alloced_p,
+ unsigned long *max_alloced_p,
+ unsigned long *tot_alloced_p)
{
- if (mp_p == NULL) {
- return MPOOL_ERROR_ARG_NULL;
- }
- if (mp_p->mp_magic != MPOOL_MAGIC) {
- return MPOOL_ERROR_PNT;
- }
- if (mp_p->mp_magic2 != MPOOL_MAGIC) {
- return MPOOL_ERROR_POOL_OVER;
- }
-
- SET_POINTER(page_size_p, mp_p->mp_page_size);
- SET_POINTER(num_alloced_p, mp_p->mp_alloc_c);
- SET_POINTER(user_alloced_p, mp_p->mp_user_alloc);
- SET_POINTER(max_alloced_p, mp_p->mp_max_alloc);
- SET_POINTER(tot_alloced_p, SIZE_OF_PAGES(mp_p, mp_p->mp_page_c));
-
- return MPOOL_ERROR_NONE;
+ if (mp_p == NULL) {
+ return MPOOL_ERROR_ARG_NULL;
+ }
+ if (mp_p->mp_magic != MPOOL_MAGIC) {
+ return MPOOL_ERROR_PNT;
+ }
+ if (mp_p->mp_magic2 != MPOOL_MAGIC) {
+ return MPOOL_ERROR_POOL_OVER;
+ }
+
+ SET_POINTER(page_size_p, mp_p->mp_page_size);
+ SET_POINTER(num_alloced_p, mp_p->mp_alloc_c);
+ SET_POINTER(user_alloced_p, mp_p->mp_user_alloc);
+ SET_POINTER(max_alloced_p, mp_p->mp_max_alloc);
+ SET_POINTER(tot_alloced_p, SIZE_OF_PAGES(mp_p, mp_p->mp_page_c));
+
+ return MPOOL_ERROR_NONE;
}
/*
*/
int mpool_set_log_func(mpool_t *mp_p, mpool_log_func_t log_func)
{
- if (mp_p == NULL) {
- return MPOOL_ERROR_ARG_NULL;
- }
- if (mp_p->mp_magic != MPOOL_MAGIC) {
- return MPOOL_ERROR_PNT;
- }
- if (mp_p->mp_magic2 != MPOOL_MAGIC) {
- return MPOOL_ERROR_POOL_OVER;
- }
-
- mp_p->mp_log_func = log_func;
-
- return MPOOL_ERROR_NONE;
+ if (mp_p == NULL) {
+ return MPOOL_ERROR_ARG_NULL;
+ }
+ if (mp_p->mp_magic != MPOOL_MAGIC) {
+ return MPOOL_ERROR_PNT;
+ }
+ if (mp_p->mp_magic2 != MPOOL_MAGIC) {
+ return MPOOL_ERROR_POOL_OVER;
+ }
+
+ mp_p->mp_log_func = log_func;
+
+ return MPOOL_ERROR_NONE;
}
/*
*/
int mpool_set_max_pages(mpool_t *mp_p, const unsigned int max_pages)
{
- if (mp_p == NULL) {
- return MPOOL_ERROR_ARG_NULL;
- }
- if (mp_p->mp_magic != MPOOL_MAGIC) {
- return MPOOL_ERROR_PNT;
- }
- if (mp_p->mp_magic2 != MPOOL_MAGIC) {
- return MPOOL_ERROR_POOL_OVER;
- }
-
- if (BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_HEAVY_PACKING)) {
- mp_p->mp_max_pages = max_pages;
- }
- else {
- /*
- * If we are not heavy-packing the pool then we don't count the
- * 1st page allocated which holds the mpool header structure.
- */
- mp_p->mp_max_pages = max_pages + 1;
- }
-
- return MPOOL_ERROR_NONE;
+ if (mp_p == NULL) {
+ return MPOOL_ERROR_ARG_NULL;
+ }
+ if (mp_p->mp_magic != MPOOL_MAGIC) {
+ return MPOOL_ERROR_PNT;
+ }
+ if (mp_p->mp_magic2 != MPOOL_MAGIC) {
+ return MPOOL_ERROR_POOL_OVER;
+ }
+
+ if (BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_HEAVY_PACKING)) {
+ mp_p->mp_max_pages = max_pages;
+ }
+ else {
+ /*
+ * If we are not heavy-packing the pool then we don't count the
+ * 1st page allocated which holds the mpool header structure.
+ */
+ mp_p->mp_max_pages = max_pages + 1;
+ }
+
+ return MPOOL_ERROR_NONE;
}
/*
*/
const char *mpool_strerror(const int error)
{
- switch (error) {
- case MPOOL_ERROR_NONE:
- return "no error";
- break;
- case MPOOL_ERROR_ARG_NULL:
- return "function argument is null";
- break;
- case MPOOL_ERROR_ARG_INVALID:
- return "function argument is invalid";
- break;
- case MPOOL_ERROR_PNT:
- return "invalid mpool pointer";
- break;
- case MPOOL_ERROR_POOL_OVER:
- return "mpool structure was overwritten";
- break;
- case MPOOL_ERROR_PAGE_SIZE:
- return "could not get system page-size";
- break;
- case MPOOL_ERROR_OPEN_ZERO:
- return "could not open /dev/zero";
- break;
- case MPOOL_ERROR_NO_MEM:
- return "no memory available";
- break;
- case MPOOL_ERROR_MMAP:
- return "problems with mmap";
- break;
- case MPOOL_ERROR_SIZE:
- return "error processing requested size";
- break;
- case MPOOL_ERROR_TOO_BIG:
- return "allocation exceeds pool max size";
- break;
- case MPOOL_ERROR_MEM:
- return "invalid memory address";
- break;
- case MPOOL_ERROR_MEM_OVER:
- return "memory lower bounds overwritten";
- break;
- case MPOOL_ERROR_NOT_FOUND:
- return "memory block not found in pool";
- break;
- case MPOOL_ERROR_IS_FREE:
- return "memory address has already been freed";
- break;
- case MPOOL_ERROR_BLOCK_STAT:
- return "invalid internal block status";
- break;
- case MPOOL_ERROR_FREE_ADDR:
- return "invalid internal free address";
- break;
- case MPOOL_ERROR_SBRK_CONTIG:
- return "sbrk did not return contiguous memory";
- break;
- case MPOOL_ERROR_NO_PAGES:
- return "no available pages left in pool";
- break;
- case MPOOL_ERROR_ALLOC:
- return "system alloc function failed";
- break;
- case MPOOL_ERROR_PNT_OVER:
- return "user pointer admin space overwritten";
- break;
- default:
- break;
- }
-
- return "invalid error code";
+ switch (error) {
+ case MPOOL_ERROR_NONE:
+ return "no error";
+ break;
+ case MPOOL_ERROR_ARG_NULL:
+ return "function argument is null";
+ break;
+ case MPOOL_ERROR_ARG_INVALID:
+ return "function argument is invalid";
+ break;
+ case MPOOL_ERROR_PNT:
+ return "invalid mpool pointer";
+ break;
+ case MPOOL_ERROR_POOL_OVER:
+ return "mpool structure was overwritten";
+ break;
+ case MPOOL_ERROR_PAGE_SIZE:
+ return "could not get system page-size";
+ break;
+ case MPOOL_ERROR_OPEN_ZERO:
+ return "could not open /dev/zero";
+ break;
+ case MPOOL_ERROR_NO_MEM:
+ return "no memory available";
+ break;
+ case MPOOL_ERROR_MMAP:
+ return "problems with mmap";
+ break;
+ case MPOOL_ERROR_SIZE:
+ return "error processing requested size";
+ break;
+ case MPOOL_ERROR_TOO_BIG:
+ return "allocation exceeds pool max size";
+ break;
+ case MPOOL_ERROR_MEM:
+ return "invalid memory address";
+ break;
+ case MPOOL_ERROR_MEM_OVER:
+ return "memory lower bounds overwritten";
+ break;
+ case MPOOL_ERROR_NOT_FOUND:
+ return "memory block not found in pool";
+ break;
+ case MPOOL_ERROR_IS_FREE:
+ return "memory address has already been freed";
+ break;
+ case MPOOL_ERROR_BLOCK_STAT:
+ return "invalid internal block status";
+ break;
+ case MPOOL_ERROR_FREE_ADDR:
+ return "invalid internal free address";
+ break;
+ case MPOOL_ERROR_SBRK_CONTIG:
+ return "sbrk did not return contiguous memory";
+ break;
+ case MPOOL_ERROR_NO_PAGES:
+ return "no available pages left in pool";
+ break;
+ case MPOOL_ERROR_ALLOC:
+ return "system alloc function failed";
+ break;
+ case MPOOL_ERROR_PNT_OVER:
+ return "user pointer admin space overwritten";
+ break;
+ default:
+ break;
+ }
+
+ return "invalid error code";
}
+
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
+ */
#include <errno.h> /* for setting errno */
#include <sys/types.h>
#ifndef _WIN32
- /* not in Windows! */
+/* not in Windows! */
# include <unistd.h>
# include <stdint.h>
#endif
#ifndef SIMCLIST_NO_DUMPRESTORE
- /* includes for dump/restore */
+/* includes for dump/restore */
# include <time.h>
# include <sys/uio.h> /* for READ_ERRCHECK() and write() */
# include <fcntl.h> /* for open() etc */
/* 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))
/* 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);
+ 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);
#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;
}
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 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;
/**** 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
*****/
/* 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 */
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
- );
+ /* 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;
#endif
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
+ */
#endif
static char *rcs_id =
- "$Id: table.c,v 1.19 2000/03/09 03:30:41 gray Exp $";
+ "$Id: table.c,v 1.19 2000/03/09 03:30:41 gray Exp $";
/*
* Version id for the library. You also need to add an entry to the
* and then find the corresponding entry.
*/
static table_entry_t *first_entry(const table_t *table_p,
- table_linear_t *linear_p)
+ table_linear_t *linear_p)
{
- table_entry_t *entry_p;
- unsigned int bucket_c = 0;
-
- /* look for the first non-empty bucket */
- for (bucket_c = 0; bucket_c < table_p->ta_bucket_n; bucket_c++) {
- entry_p = table_p->ta_buckets[bucket_c];
- if (entry_p != NULL) {
- if (linear_p != NULL) {
- linear_p->tl_bucket_c = bucket_c;
- linear_p->tl_entry_c = 0;
- }
- return TABLE_POINTER(table_p, table_entry_t *, entry_p);
- }
- }
+ table_entry_t *entry_p;
+ unsigned int bucket_c = 0;
+
+ /* look for the first non-empty bucket */
+ for (bucket_c = 0; bucket_c < table_p->ta_bucket_n; bucket_c++) {
+ entry_p = table_p->ta_buckets[bucket_c];
+ if (entry_p != NULL) {
+ if (linear_p != NULL) {
+ linear_p->tl_bucket_c = bucket_c;
+ linear_p->tl_entry_c = 0;
+ }
+ return TABLE_POINTER(table_p, table_entry_t *, entry_p);
+ }
+ }
- return NULL;
+ return NULL;
}
/*
* will contain a table error code.
*/
static table_entry_t *next_entry(const table_t *table_p,
- table_linear_t *linear_p, int *error_p)
+ table_linear_t *linear_p, int *error_p)
{
- table_entry_t *entry_p;
- int entry_c;
-
- /* can't next if we haven't first-ed */
- if (linear_p == NULL) {
- SET_POINTER(error_p, TABLE_ERROR_LINEAR);
- return NULL;
- }
-
- if (linear_p->tl_bucket_c >= table_p->ta_bucket_n) {
- /*
- * NOTE: this might happen if we delete an item which shortens the
- * table bucket numbers.
- */
- SET_POINTER(error_p, TABLE_ERROR_NOT_FOUND);
- return NULL;
- }
-
- linear_p->tl_entry_c++;
-
- /* find the entry which is the nth in the list */
- entry_p = table_p->ta_buckets[linear_p->tl_bucket_c];
- /* NOTE: we swap the order here to be more efficient */
- for (entry_c = linear_p->tl_entry_c; entry_c > 0; entry_c--) {
- /* did we reach the end of the list? */
- if (entry_p == NULL) {
- break;
- }
- entry_p = TABLE_POINTER(table_p, table_entry_t *, entry_p)->te_next_p;
- }
-
- /* did we find an entry in the current bucket? */
- if (entry_p != NULL) {
- SET_POINTER(error_p, TABLE_ERROR_NONE);
- return TABLE_POINTER(table_p, table_entry_t *, entry_p);
- }
-
- /* find the first entry in the next non-empty bucket */
-
- linear_p->tl_entry_c = 0;
- for (linear_p->tl_bucket_c++; linear_p->tl_bucket_c < table_p->ta_bucket_n;
- linear_p->tl_bucket_c++) {
- entry_p = table_p->ta_buckets[linear_p->tl_bucket_c];
- if (entry_p != NULL) {
- SET_POINTER(error_p, TABLE_ERROR_NONE);
- return TABLE_POINTER(table_p, table_entry_t *, entry_p);
- }
- }
-
- SET_POINTER(error_p, TABLE_ERROR_NOT_FOUND);
- return NULL;
+ table_entry_t *entry_p;
+ int entry_c;
+
+ /* can't next if we haven't first-ed */
+ if (linear_p == NULL) {
+ SET_POINTER(error_p, TABLE_ERROR_LINEAR);
+ return NULL;
+ }
+
+ if (linear_p->tl_bucket_c >= table_p->ta_bucket_n) {
+ /*
+ * NOTE: this might happen if we delete an item which shortens the
+ * table bucket numbers.
+ */
+ SET_POINTER(error_p, TABLE_ERROR_NOT_FOUND);
+ return NULL;
+ }
+
+ linear_p->tl_entry_c++;
+
+ /* find the entry which is the nth in the list */
+ entry_p = table_p->ta_buckets[linear_p->tl_bucket_c];
+ /* NOTE: we swap the order here to be more efficient */
+ for (entry_c = linear_p->tl_entry_c; entry_c > 0; entry_c--) {
+ /* did we reach the end of the list? */
+ if (entry_p == NULL) {
+ break;
+ }
+ entry_p = TABLE_POINTER(table_p, table_entry_t *, entry_p)->te_next_p;
+ }
+
+ /* did we find an entry in the current bucket? */
+ if (entry_p != NULL) {
+ SET_POINTER(error_p, TABLE_ERROR_NONE);
+ return TABLE_POINTER(table_p, table_entry_t *, entry_p);
+ }
+
+ /* find the first entry in the next non-empty bucket */
+
+ linear_p->tl_entry_c = 0;
+ for (linear_p->tl_bucket_c++; linear_p->tl_bucket_c < table_p->ta_bucket_n;
+ linear_p->tl_bucket_c++) {
+ entry_p = table_p->ta_buckets[linear_p->tl_bucket_c];
+ if (entry_p != NULL) {
+ SET_POINTER(error_p, TABLE_ERROR_NONE);
+ return TABLE_POINTER(table_p, table_entry_t *, entry_p);
+ }
+ }
+
+ SET_POINTER(error_p, TABLE_ERROR_NOT_FOUND);
+ return NULL;
}
/*
* will contain a table error code.
*/
static table_entry_t *this_entry(const table_t *table_p,
- const table_linear_t *linear_p,
- int *error_p)
+ const table_linear_t *linear_p,
+ int *error_p)
{
- table_entry_t *entry_p;
- int entry_c;
-
- /* can't next if we haven't first-ed */
- if (linear_p == NULL) {
- SET_POINTER(error_p, TABLE_ERROR_LINEAR);
- return NULL;
- }
-
- if (linear_p->tl_bucket_c >= table_p->ta_bucket_n) {
- /*
- * NOTE: this might happen if we delete an item which shortens the
- * table bucket numbers.
- */
- SET_POINTER(error_p, TABLE_ERROR_NOT_FOUND);
- return NULL;
- }
-
- /* find the entry which is the nth in the list */
- entry_p = table_p->ta_buckets[linear_p->tl_bucket_c];
-
- /* NOTE: we swap the order here to be more efficient */
- for (entry_c = linear_p->tl_entry_c; entry_c > 0; entry_c--) {
- /* did we reach the end of the list? */
- if (entry_p == NULL) {
- break;
- }
- entry_p = TABLE_POINTER(table_p, table_entry_t *, entry_p)->te_next_p;
- }
-
- /* did we find an entry in the current bucket? */
- if (entry_p == NULL) {
- SET_POINTER(error_p, TABLE_ERROR_NOT_FOUND);
- return NULL;
- }
- else {
- SET_POINTER(error_p, TABLE_ERROR_NONE);
- return TABLE_POINTER(table_p, table_entry_t *, entry_p);
- }
+ table_entry_t *entry_p;
+ int entry_c;
+
+ /* can't next if we haven't first-ed */
+ if (linear_p == NULL) {
+ SET_POINTER(error_p, TABLE_ERROR_LINEAR);
+ return NULL;
+ }
+
+ if (linear_p->tl_bucket_c >= table_p->ta_bucket_n) {
+ /*
+ * NOTE: this might happen if we delete an item which shortens the
+ * table bucket numbers.
+ */
+ SET_POINTER(error_p, TABLE_ERROR_NOT_FOUND);
+ return NULL;
+ }
+
+ /* find the entry which is the nth in the list */
+ entry_p = table_p->ta_buckets[linear_p->tl_bucket_c];
+
+ /* NOTE: we swap the order here to be more efficient */
+ for (entry_c = linear_p->tl_entry_c; entry_c > 0; entry_c--) {
+ /* did we reach the end of the list? */
+ if (entry_p == NULL) {
+ break;
+ }
+ entry_p = TABLE_POINTER(table_p, table_entry_t *, entry_p)->te_next_p;
+ }
+
+ /* did we find an entry in the current bucket? */
+ if (entry_p == NULL) {
+ SET_POINTER(error_p, TABLE_ERROR_NOT_FOUND);
+ return NULL;
+ }
+ else {
+ SET_POINTER(error_p, TABLE_ERROR_NONE);
+ return TABLE_POINTER(table_p, table_entry_t *, entry_p);
+ }
}
/*
* for (i=0, h=0; i<N; ++i) h = hash( keys[i], len[i], h);
*/
static unsigned int hash(const unsigned char *key,
- const unsigned int length,
- const unsigned int init_val)
+ const unsigned int length,
+ const unsigned int init_val)
{
- const unsigned char *key_p = key;
- unsigned int a, b, c, len;
-
- /* set up the internal state */
- a = 0x9e3779b9; /* the golden ratio; an arbitrary value */
- b = 0x9e3779b9;
- c = init_val; /* the previous hash value */
-
- /* handle most of the key */
- for (len = length; len >= 12; len -= 12) {
- a += (key_p[0]
- + ((unsigned int)key_p[1] << 8)
- + ((unsigned int)key_p[2] << 16)
- + ((unsigned int)key_p[3] << 24));
- b += (key_p[4]
- + ((unsigned int)key_p[5] << 8)
- + ((unsigned int)key_p[6] << 16)
- + ((unsigned int)key_p[7] << 24));
- c += (key_p[8]
- + ((unsigned int)key_p[9] << 8)
- + ((unsigned int)key_p[10] << 16)
- + ((unsigned int)key_p[11] << 24));
- HASH_MIX(a,b,c);
- key_p += 12;
- }
-
- c += length;
-
- /* all the case statements fall through to the next */
- switch(len) {
- case 11:
- c += ((unsigned int)key_p[10] << 24);
- case 10:
- c += ((unsigned int)key_p[9] << 16);
- case 9:
- c += ((unsigned int)key_p[8] << 8);
- /* the first byte of c is reserved for the length */
- case 8:
- b += ((unsigned int)key_p[7] << 24);
- case 7:
- b += ((unsigned int)key_p[6] << 16);
- case 6:
- b += ((unsigned int)key_p[5] << 8);
- case 5:
- b += key_p[4];
- case 4:
- a += ((unsigned int)key_p[3] << 24);
- case 3:
- a += ((unsigned int)key_p[2] << 16);
- case 2:
- a += ((unsigned int)key_p[1] << 8);
- case 1:
- a += key_p[0];
- /* case 0: nothing left to add */
- }
- HASH_MIX(a, b, c);
-
- return c;
+ const unsigned char *key_p = key;
+ unsigned int a, b, c, len;
+
+ /* set up the internal state */
+ a = 0x9e3779b9; /* the golden ratio; an arbitrary value */
+ b = 0x9e3779b9;
+ c = init_val; /* the previous hash value */
+
+ /* handle most of the key */
+ for (len = length; len >= 12; len -= 12) {
+ a += (key_p[0]
+ + ((unsigned int)key_p[1] << 8)
+ + ((unsigned int)key_p[2] << 16)
+ + ((unsigned int)key_p[3] << 24));
+ b += (key_p[4]
+ + ((unsigned int)key_p[5] << 8)
+ + ((unsigned int)key_p[6] << 16)
+ + ((unsigned int)key_p[7] << 24));
+ c += (key_p[8]
+ + ((unsigned int)key_p[9] << 8)
+ + ((unsigned int)key_p[10] << 16)
+ + ((unsigned int)key_p[11] << 24));
+ HASH_MIX(a,b,c);
+ key_p += 12;
+ }
+
+ c += length;
+
+ /* all the case statements fall through to the next */
+ switch(len) {
+ case 11:
+ c += ((unsigned int)key_p[10] << 24);
+ case 10:
+ c += ((unsigned int)key_p[9] << 16);
+ case 9:
+ c += ((unsigned int)key_p[8] << 8);
+ /* the first byte of c is reserved for the length */
+ case 8:
+ b += ((unsigned int)key_p[7] << 24);
+ case 7:
+ b += ((unsigned int)key_p[6] << 16);
+ case 6:
+ b += ((unsigned int)key_p[5] << 8);
+ case 5:
+ b += key_p[4];
+ case 4:
+ a += ((unsigned int)key_p[3] << 24);
+ case 3:
+ a += ((unsigned int)key_p[2] << 16);
+ case 2:
+ a += ((unsigned int)key_p[1] << 8);
+ case 1:
+ a += key_p[0];
+ /* case 0: nothing left to add */
+ }
+ HASH_MIX(a, b, c);
+
+ return c;
}
/*
* data - Size of the entry data.
*/
static int entry_size(const table_t *table_p, const unsigned int key_size,
- const unsigned int data_size)
+ const unsigned int data_size)
{
- int size, left;
+ int size, left;
- /* initial size -- key is already aligned if right after struct */
- size = sizeof(struct table_shell_st) + key_size;
+ /* initial size -- key is already aligned if right after struct */
+ size = sizeof(struct table_shell_st) + key_size;
- /* if there is no alignment then it is easy */
- if (table_p->ta_data_align == 0) {
- return size + data_size;
- }
+ /* if there is no alignment then it is easy */
+ if (table_p->ta_data_align == 0) {
+ return size + data_size;
+ }
- /* add in our alignement */
- left = size & (table_p->ta_data_align - 1);
- if (left > 0) {
- size += table_p->ta_data_align - left;
- }
+ /* add in our alignement */
+ left = size & (table_p->ta_data_align - 1);
+ if (left > 0) {
+ size += table_p->ta_data_align - left;
+ }
- /* we add the data size here after the alignment */
- size += data_size;
+ /* we add the data size here after the alignment */
+ size += data_size;
- return size;
+ return size;
}
/*
* entry_p - Entry whose data pointer we are determining.
*/
static unsigned char *entry_data_buf(const table_t *table_p,
- const table_entry_t *entry_p)
+ const table_entry_t *entry_p)
{
- const unsigned char *buf_p;
- unsigned int size, pad;
+ const unsigned char *buf_p;
+ unsigned int size, pad;
- buf_p = entry_p->te_key_buf + entry_p->te_key_size;
+ buf_p = entry_p->te_key_buf + entry_p->te_key_size;
- /* we need the size of the space before the data */
- size = sizeof(struct table_shell_st) + entry_p->te_key_size;
+ /* we need the size of the space before the data */
+ size = sizeof(struct table_shell_st) + entry_p->te_key_size;
- /* add in our alignment */
- pad = size & (table_p->ta_data_align - 1);
- if (pad > 0) {
- pad = table_p->ta_data_align - pad;
- }
+ /* add in our alignment */
+ pad = size & (table_p->ta_data_align - 1);
+ if (pad > 0) {
+ pad = table_p->ta_data_align - pad;
+ }
- return (unsigned char *)buf_p + pad;
+ return (unsigned char *)buf_p + pad;
}
/******************************* sort routines *******************************/
* has occurred. It cannot be NULL.
*/
static int local_compare(const void *p1, const void *p2,
- table_compare_t compare, const table_t *table_p,
- int *err_bp)
+ table_compare_t compare, const table_t *table_p,
+ int *err_bp)
{
- const table_entry_t * const *ent1_p = p1, * const *ent2_p = p2;
- int cmp;
- unsigned int size;
-
- /* compare as many bytes as we can */
- size = (*ent1_p)->te_key_size;
- if ((*ent2_p)->te_key_size < size) {
- size = (*ent2_p)->te_key_size;
- }
- cmp = memcmp(ENTRY_KEY_BUF(*ent1_p), ENTRY_KEY_BUF(*ent2_p), size);
- /* if common-size equal, then if next more bytes, it is larger */
- if (cmp == 0) {
- cmp = (*ent1_p)->te_key_size - (*ent2_p)->te_key_size;
- }
-
- *err_bp = 0;
- return cmp;
+ const table_entry_t * const *ent1_p = p1, * const *ent2_p = p2;
+ int cmp;
+ unsigned int size;
+
+ /* compare as many bytes as we can */
+ size = (*ent1_p)->te_key_size;
+ if ((*ent2_p)->te_key_size < size) {
+ size = (*ent2_p)->te_key_size;
+ }
+ cmp = memcmp(ENTRY_KEY_BUF(*ent1_p), ENTRY_KEY_BUF(*ent2_p), size);
+ /* if common-size equal, then if next more bytes, it is larger */
+ if (cmp == 0) {
+ cmp = (*ent1_p)->te_key_size - (*ent2_p)->te_key_size;
+ }
+
+ *err_bp = 0;
+ return cmp;
}
/*
* has occurred. It cannot be NULL.
*/
static int local_compare_pos(const void *p1, const void *p2,
- table_compare_t compare,
- const table_t *table_p, int *err_bp)
+ table_compare_t compare,
+ const table_t *table_p, int *err_bp)
{
- const table_linear_t *lin1_p = p1, *lin2_p = p2;
- const table_entry_t *ent1_p, *ent2_p;
- int cmp, ret;
- unsigned int size;
-
- /* get entry pointers */
- ent1_p = this_entry(table_p, lin1_p, &ret);
- ent2_p = this_entry(table_p, lin2_p, &ret);
- if (ent1_p == NULL || ent2_p == NULL) {
- *err_bp = 1;
- return 0;
- }
-
- /* compare as many bytes as we can */
- size = ent1_p->te_key_size;
- if (ent2_p->te_key_size < size) {
- size = ent2_p->te_key_size;
- }
- cmp = memcmp(ENTRY_KEY_BUF(ent1_p), ENTRY_KEY_BUF(ent2_p), size);
- /* if common-size equal, then if next more bytes, it is larger */
- if (cmp == 0) {
- cmp = ent1_p->te_key_size - ent2_p->te_key_size;
- }
-
- *err_bp = 0;
- return cmp;
+ const table_linear_t *lin1_p = p1, *lin2_p = p2;
+ const table_entry_t *ent1_p, *ent2_p;
+ int cmp, ret;
+ unsigned int size;
+
+ /* get entry pointers */
+ ent1_p = this_entry(table_p, lin1_p, &ret);
+ ent2_p = this_entry(table_p, lin2_p, &ret);
+ if (ent1_p == NULL || ent2_p == NULL) {
+ *err_bp = 1;
+ return 0;
+ }
+
+ /* compare as many bytes as we can */
+ size = ent1_p->te_key_size;
+ if (ent2_p->te_key_size < size) {
+ size = ent2_p->te_key_size;
+ }
+ cmp = memcmp(ENTRY_KEY_BUF(ent1_p), ENTRY_KEY_BUF(ent2_p), size);
+ /* if common-size equal, then if next more bytes, it is larger */
+ if (cmp == 0) {
+ cmp = ent1_p->te_key_size - ent2_p->te_key_size;
+ }
+
+ *err_bp = 0;
+ return cmp;
}
/*
* has occurred. It cannot be NULL.
*/
static int external_compare(const void *p1, const void *p2,
- table_compare_t user_compare,
- const table_t *table_p, int *err_bp)
+ table_compare_t user_compare,
+ const table_t *table_p, int *err_bp)
{
- const table_entry_t * const *ent1_p = p1, * const *ent2_p = p2;
- /* since we know we are not aligned we can use the EXTRY_DATA_BUF macro */
- *err_bp = 0;
- return user_compare(ENTRY_KEY_BUF(*ent1_p), (*ent1_p)->te_key_size,
- ENTRY_DATA_BUF(table_p, *ent1_p),
- (*ent1_p)->te_data_size,
- ENTRY_KEY_BUF(*ent2_p), (*ent2_p)->te_key_size,
- ENTRY_DATA_BUF(table_p, *ent2_p),
- (*ent2_p)->te_data_size);
+ const table_entry_t * const *ent1_p = p1, * const *ent2_p = p2;
+ /* since we know we are not aligned we can use the EXTRY_DATA_BUF macro */
+ *err_bp = 0;
+ return user_compare(ENTRY_KEY_BUF(*ent1_p), (*ent1_p)->te_key_size,
+ ENTRY_DATA_BUF(table_p, *ent1_p),
+ (*ent1_p)->te_data_size,
+ ENTRY_KEY_BUF(*ent2_p), (*ent2_p)->te_key_size,
+ ENTRY_DATA_BUF(table_p, *ent2_p),
+ (*ent2_p)->te_data_size);
}
/*
*
* err_bp - Pointer to an integer which will be set with 1 if an error
* has occurred. It cannot be NULL.
-*/
+ */
static int external_compare_pos(const void *p1, const void *p2,
- table_compare_t user_compare,
- const table_t *table_p, int *err_bp)
+ table_compare_t user_compare,
+ const table_t *table_p, int *err_bp)
{
- const table_linear_t *lin1_p = p1, *lin2_p = p2;
- const table_entry_t *ent1_p, *ent2_p;
- int ret;
-
- /* get entry pointers */
- ent1_p = this_entry(table_p, lin1_p, &ret);
- ent2_p = this_entry(table_p, lin2_p, &ret);
- if (ent1_p == NULL || ent2_p == NULL) {
- *err_bp = 1;
- return 0;
- }
-
- /* since we know we are not aligned we can use the EXTRY_DATA_BUF macro */
- *err_bp = 0;
- return user_compare(ENTRY_KEY_BUF(ent1_p), (ent1_p)->te_key_size,
- ENTRY_DATA_BUF(table_p, ent1_p), ent1_p->te_data_size,
- ENTRY_KEY_BUF(ent2_p), ent2_p->te_key_size,
- ENTRY_DATA_BUF(table_p, ent2_p), ent2_p->te_data_size);
+ const table_linear_t *lin1_p = p1, *lin2_p = p2;
+ const table_entry_t *ent1_p, *ent2_p;
+ int ret;
+
+ /* get entry pointers */
+ ent1_p = this_entry(table_p, lin1_p, &ret);
+ ent2_p = this_entry(table_p, lin2_p, &ret);
+ if (ent1_p == NULL || ent2_p == NULL) {
+ *err_bp = 1;
+ return 0;
+ }
+
+ /* since we know we are not aligned we can use the EXTRY_DATA_BUF macro */
+ *err_bp = 0;
+ return user_compare(ENTRY_KEY_BUF(ent1_p), (ent1_p)->te_key_size,
+ ENTRY_DATA_BUF(table_p, ent1_p), ent1_p->te_data_size,
+ ENTRY_KEY_BUF(ent2_p), ent2_p->te_key_size,
+ ENTRY_DATA_BUF(table_p, ent2_p), ent2_p->te_data_size);
}
/*
* has occurred. It cannot be NULL.
*/
static int external_compare_align(const void *p1, const void *p2,
- table_compare_t user_compare,
- const table_t *table_p, int *err_bp)
+ table_compare_t user_compare,
+ const table_t *table_p, int *err_bp)
{
- const table_entry_t * const *ent1_p = p1, * const *ent2_p = p2;
- /* since we are aligned we have to use the entry_data_buf function */
- *err_bp = 0;
- return user_compare(ENTRY_KEY_BUF(*ent1_p), (*ent1_p)->te_key_size,
- entry_data_buf(table_p, *ent1_p),
- (*ent1_p)->te_data_size,
- ENTRY_KEY_BUF(*ent2_p), (*ent2_p)->te_key_size,
- entry_data_buf(table_p, *ent2_p),
- (*ent2_p)->te_data_size);
+ const table_entry_t * const *ent1_p = p1, * const *ent2_p = p2;
+ /* since we are aligned we have to use the entry_data_buf function */
+ *err_bp = 0;
+ return user_compare(ENTRY_KEY_BUF(*ent1_p), (*ent1_p)->te_key_size,
+ entry_data_buf(table_p, *ent1_p),
+ (*ent1_p)->te_data_size,
+ ENTRY_KEY_BUF(*ent2_p), (*ent2_p)->te_key_size,
+ entry_data_buf(table_p, *ent2_p),
+ (*ent2_p)->te_data_size);
}
/*
* has occurred. It cannot be NULL.
*/
static int external_compare_align_pos(const void *p1, const void *p2,
- table_compare_t user_compare,
- const table_t *table_p, int *err_bp)
+ table_compare_t user_compare,
+ const table_t *table_p, int *err_bp)
{
- const table_linear_t *lin1_p = p1, *lin2_p = p2;
- const table_entry_t *ent1_p, *ent2_p;
- int ret;
-
- /* get entry pointers */
- ent1_p = this_entry(table_p, lin1_p, &ret);
- ent2_p = this_entry(table_p, lin2_p, &ret);
- if (ent1_p == NULL || ent2_p == NULL) {
- *err_bp = 1;
- return 0;
- }
-
- /* since we are aligned we have to use the entry_data_buf function */
- *err_bp = 0;
- return user_compare(ENTRY_KEY_BUF(ent1_p), ent1_p->te_key_size,
- entry_data_buf(table_p, ent1_p), ent1_p->te_data_size,
- ENTRY_KEY_BUF(ent2_p), ent2_p->te_key_size,
- entry_data_buf(table_p, ent2_p), ent2_p->te_data_size);
+ const table_linear_t *lin1_p = p1, *lin2_p = p2;
+ const table_entry_t *ent1_p, *ent2_p;
+ int ret;
+
+ /* get entry pointers */
+ ent1_p = this_entry(table_p, lin1_p, &ret);
+ ent2_p = this_entry(table_p, lin2_p, &ret);
+ if (ent1_p == NULL || ent2_p == NULL) {
+ *err_bp = 1;
+ return 0;
+ }
+
+ /* since we are aligned we have to use the entry_data_buf function */
+ *err_bp = 0;
+ return user_compare(ENTRY_KEY_BUF(ent1_p), ent1_p->te_key_size,
+ entry_data_buf(table_p, ent1_p), ent1_p->te_data_size,
+ ENTRY_KEY_BUF(ent2_p), ent2_p->te_key_size,
+ entry_data_buf(table_p, ent2_p), ent2_p->te_data_size);
}
/*
* ele_size -> Size of the two items.
*/
static void swap_bytes(unsigned char *item1_p, unsigned char *item2_p,
- int ele_size)
+ int ele_size)
{
- unsigned char char_temp;
-
- for (; ele_size > 0; ele_size--) {
- char_temp = *item1_p;
- *item1_p = *item2_p;
- *item2_p = char_temp;
- item1_p++;
- item2_p++;
- }
+ unsigned char char_temp;
+
+ for (; ele_size > 0; ele_size--) {
+ char_temp = *item1_p;
+ *item1_p = *item2_p;
+ *item2_p = char_temp;
+ item1_p++;
+ item2_p++;
+ }
}
/*
* table_p -> Associated table being sorted.
*/
static int insert_sort(unsigned char *first_p, unsigned char *last_p,
- unsigned char *holder_p,
- const unsigned int ele_size, compare_t compare,
- table_compare_t user_compare, table_t *table_p)
+ unsigned char *holder_p,
+ const unsigned int ele_size, compare_t compare,
+ table_compare_t user_compare, table_t *table_p)
{
- unsigned char *inner_p, *outer_p;
- int ret, err_b;
+ unsigned char *inner_p, *outer_p;
+ int ret, err_b;
- for (outer_p = first_p + ele_size; outer_p <= last_p; ) {
+ for (outer_p = first_p + ele_size; outer_p <= last_p; ) {
- /* look for the place to insert the entry */
- for (inner_p = outer_p - ele_size;
- inner_p >= first_p;
- inner_p -= ele_size) {
- ret = compare(outer_p, inner_p, user_compare, table_p, &err_b);
- if (err_b) {
- return TABLE_ERROR_COMPARE;
- }
- if (ret >= 0) {
- break;
- }
- }
- inner_p += ele_size;
+ /* look for the place to insert the entry */
+ for (inner_p = outer_p - ele_size;
+ inner_p >= first_p;
+ inner_p -= ele_size) {
+ ret = compare(outer_p, inner_p, user_compare, table_p, &err_b);
+ if (err_b) {
+ return TABLE_ERROR_COMPARE;
+ }
+ if (ret >= 0) {
+ break;
+ }
+ }
+ inner_p += ele_size;
- /* do we need to insert the entry in? */
- if (outer_p != inner_p) {
- /*
- * Now we shift the entry down into its place in the already
- * sorted list.
- */
- memcpy(holder_p, outer_p, ele_size);
- memmove(inner_p + ele_size, inner_p, outer_p - inner_p);
- memcpy(inner_p, holder_p, ele_size);
- }
+ /* do we need to insert the entry in? */
+ if (outer_p != inner_p) {
+ /*
+ * Now we shift the entry down into its place in the already
+ * sorted list.
+ */
+ memcpy(holder_p, outer_p, ele_size);
+ memmove(inner_p + ele_size, inner_p, outer_p - inner_p);
+ memcpy(inner_p, holder_p, ele_size);
+ }
- outer_p += ele_size;
- }
+ outer_p += ele_size;
+ }
- return TABLE_ERROR_NONE;
+ return TABLE_ERROR_NONE;
}
/*
* table_p -> Associated table being sorted.
*/
static int split(unsigned char *first_p, unsigned char *last_p,
- const unsigned int ele_size, compare_t compare,
- table_compare_t user_compare, table_t *table_p)
+ const unsigned int ele_size, compare_t compare,
+ table_compare_t user_compare, table_t *table_p)
{
- unsigned char *left_p, *right_p, *pivot_p, *left_last_p, *right_first_p;
- unsigned char *firsts[MAX_QSORT_SPLITS], *lasts[MAX_QSORT_SPLITS], *pivot;
- unsigned int width, split_c = 0;
- int size1, size2, min_qsort_size;
- int ret, err_b;
-
- /*
- * Allocate some space for our pivot value. We also use this as
- * holder space for our insert sort.
- */
- pivot = alloca(ele_size);
- if (pivot == NULL) {
- /* what else can we do? */
- abort();
- }
-
- min_qsort_size = MAX_QSORT_MANY * ele_size;
-
- while (1) {
+ unsigned char *left_p, *right_p, *pivot_p, *left_last_p, *right_first_p;
+ unsigned char *firsts[MAX_QSORT_SPLITS], *lasts[MAX_QSORT_SPLITS], *pivot;
+ unsigned int width, split_c = 0;
+ int size1, size2, min_qsort_size;
+ int ret, err_b;
+
+ /*
+ * Allocate some space for our pivot value. We also use this as
+ * holder space for our insert sort.
+ */
+ pivot = alloca(ele_size);
+ if (pivot == NULL) {
+ /* what else can we do? */
+ abort();
+ }
+
+ min_qsort_size = MAX_QSORT_MANY * ele_size;
+
+ while (1) {
- /* find the left, right, and mid point */
- left_p = first_p;
- right_p = last_p;
- /* is there a faster way to find this? */
- width = (last_p - first_p) / ele_size;
- pivot_p = first_p + ele_size * (width >> 1);
+ /* find the left, right, and mid point */
+ left_p = first_p;
+ right_p = last_p;
+ /* is there a faster way to find this? */
+ width = (last_p - first_p) / ele_size;
+ pivot_p = first_p + ele_size * (width >> 1);
- /*
- * Find which of the left, middle, and right elements is the
- * median (Knuth vol3 p123).
- */
- ret = compare(first_p, pivot_p, user_compare, table_p, &err_b);
- if (err_b) {
- return TABLE_ERROR_COMPARE;
- }
- if (ret > 0) {
- swap_bytes(first_p, pivot_p, ele_size);
- }
- ret = compare(pivot_p, last_p, user_compare, table_p, &err_b);
- if (err_b) {
- return TABLE_ERROR_COMPARE;
- }
- if (ret > 0) {
- swap_bytes(pivot_p, last_p, ele_size);
- ret = compare(first_p, pivot_p, user_compare, table_p, &err_b);
- if (err_b) {
- return TABLE_ERROR_COMPARE;
- }
- if (ret > 0) {
- swap_bytes(first_p, pivot_p, ele_size);
- }
- }
+ /*
+ * Find which of the left, middle, and right elements is the
+ * median (Knuth vol3 p123).
+ */
+ ret = compare(first_p, pivot_p, user_compare, table_p, &err_b);
+ if (err_b) {
+ return TABLE_ERROR_COMPARE;
+ }
+ if (ret > 0) {
+ swap_bytes(first_p, pivot_p, ele_size);
+ }
+ ret = compare(pivot_p, last_p, user_compare, table_p, &err_b);
+ if (err_b) {
+ return TABLE_ERROR_COMPARE;
+ }
+ if (ret > 0) {
+ swap_bytes(pivot_p, last_p, ele_size);
+ ret = compare(first_p, pivot_p, user_compare, table_p, &err_b);
+ if (err_b) {
+ return TABLE_ERROR_COMPARE;
+ }
+ if (ret > 0) {
+ swap_bytes(first_p, pivot_p, ele_size);
+ }
+ }
- /*
- * save our pivot so we don't have to worry about hitting and
- * swapping it elsewhere while we iterate across the list below.
- */
- memcpy(pivot, pivot_p, ele_size);
+ /*
+ * save our pivot so we don't have to worry about hitting and
+ * swapping it elsewhere while we iterate across the list below.
+ */
+ memcpy(pivot, pivot_p, ele_size);
- do {
+ do {
- /* shift the left side up until we reach the pivot value */
- while (1) {
- ret = compare(left_p, pivot, user_compare, table_p, &err_b);
- if (err_b) {
- return TABLE_ERROR_COMPARE;
- }
- if (ret >= 0) {
- break;
- }
- left_p += ele_size;
- }
- /* shift the right side down until we reach the pivot value */
- while (1) {
- ret = compare(pivot, right_p, user_compare, table_p, &err_b);
- if (err_b) {
- return TABLE_ERROR_COMPARE;
- }
- if (ret >= 0) {
- break;
- }
- right_p -= ele_size;
- }
+ /* shift the left side up until we reach the pivot value */
+ while (1) {
+ ret = compare(left_p, pivot, user_compare, table_p, &err_b);
+ if (err_b) {
+ return TABLE_ERROR_COMPARE;
+ }
+ if (ret >= 0) {
+ break;
+ }
+ left_p += ele_size;
+ }
+ /* shift the right side down until we reach the pivot value */
+ while (1) {
+ ret = compare(pivot, right_p, user_compare, table_p, &err_b);
+ if (err_b) {
+ return TABLE_ERROR_COMPARE;
+ }
+ if (ret >= 0) {
+ break;
+ }
+ right_p -= ele_size;
+ }
- /* if we met in the middle then we are done */
- if (left_p == right_p) {
- left_p += ele_size;
- right_p -= ele_size;
- break;
- }
- else if (left_p < right_p) {
- /*
- * swap the left and right since they both were on the wrong
- * size of the pivot and continue
- */
- swap_bytes(left_p, right_p, ele_size);
- left_p += ele_size;
- right_p -= ele_size;
- }
- } while (left_p <= right_p);
+ /* if we met in the middle then we are done */
+ if (left_p == right_p) {
+ left_p += ele_size;
+ right_p -= ele_size;
+ break;
+ }
+ else if (left_p < right_p) {
+ /*
+ * swap the left and right since they both were on the wrong
+ * size of the pivot and continue
+ */
+ swap_bytes(left_p, right_p, ele_size);
+ left_p += ele_size;
+ right_p -= ele_size;
+ }
+ } while (left_p <= right_p);
- /* Rename variables to make more sense. This will get optimized out. */
- right_first_p = left_p;
- left_last_p = right_p;
+ /* Rename variables to make more sense. This will get optimized out. */
+ right_first_p = left_p;
+ left_last_p = right_p;
- /* determine the size of the left and right hand parts */
- size1 = left_last_p - first_p;
- size2 = last_p - right_first_p;
+ /* determine the size of the left and right hand parts */
+ size1 = left_last_p - first_p;
+ size2 = last_p - right_first_p;
- /* is the 1st half small enough to just insert-sort? */
- if (size1 < min_qsort_size) {
+ /* is the 1st half small enough to just insert-sort? */
+ if (size1 < min_qsort_size) {
- /* use the pivot as our temporary space */
- ret = insert_sort(first_p, left_last_p, pivot, ele_size, compare,
- user_compare, table_p);
- if (ret != TABLE_ERROR_NONE) {
- return ret;
- }
+ /* use the pivot as our temporary space */
+ ret = insert_sort(first_p, left_last_p, pivot, ele_size, compare,
+ user_compare, table_p);
+ if (ret != TABLE_ERROR_NONE) {
+ return ret;
+ }
- /* is the 2nd part small as well? */
- if (size2 < min_qsort_size) {
+ /* is the 2nd part small as well? */
+ if (size2 < min_qsort_size) {
- /* use the pivot as our temporary space */
- ret = insert_sort(right_first_p, last_p, pivot, ele_size, compare,
- user_compare, table_p);
- if (ret != TABLE_ERROR_NONE) {
- return ret;
- }
+ /* use the pivot as our temporary space */
+ ret = insert_sort(right_first_p, last_p, pivot, ele_size, compare,
+ user_compare, table_p);
+ if (ret != TABLE_ERROR_NONE) {
+ return ret;
+ }
- /* pop a partition off our stack */
- if (split_c == 0) {
- /* we are done */
- return TABLE_ERROR_NONE;
- }
- split_c--;
- first_p = firsts[split_c];
- last_p = lasts[split_c];
- }
- else {
- /* we can just handle the right side immediately */
- first_p = right_first_p;
- /* last_p = last_p */
- }
- }
- else if (size2 < min_qsort_size) {
+ /* pop a partition off our stack */
+ if (split_c == 0) {
+ /* we are done */
+ return TABLE_ERROR_NONE;
+ }
+ split_c--;
+ first_p = firsts[split_c];
+ last_p = lasts[split_c];
+ }
+ else {
+ /* we can just handle the right side immediately */
+ first_p = right_first_p;
+ /* last_p = last_p */
+ }
+ }
+ else if (size2 < min_qsort_size) {
- /* use the pivot as our temporary space */
- ret = insert_sort(right_first_p, last_p, pivot, ele_size, compare,
- user_compare, table_p);
- if (ret != TABLE_ERROR_NONE) {
- return ret;
- }
+ /* use the pivot as our temporary space */
+ ret = insert_sort(right_first_p, last_p, pivot, ele_size, compare,
+ user_compare, table_p);
+ if (ret != TABLE_ERROR_NONE) {
+ return ret;
+ }
- /* we can just handle the left side immediately */
- /* first_p = first_p */
- last_p = left_last_p;
- }
- else {
- /*
- * neither partition is small, we'll have to push the larger one
- * of them on the stack
- */
- if (split_c >= MAX_QSORT_SPLITS) {
- /* sanity check here -- we should never get here */
- abort();
- }
- if (size1 > size2) {
- /* push the left partition on the stack */
- firsts[split_c] = first_p;
- lasts[split_c] = left_last_p;
- split_c++;
- /* continue handling the right side */
- first_p = right_first_p;
- /* last_p = last_p */
- }
- else {
- /* push the right partition on the stack */
- firsts[split_c] = right_first_p;
- lasts[split_c] = last_p;
- split_c++;
- /* continue handling the left side */
- /* first_p = first_p */
- last_p = left_last_p;
- }
- }
- }
-
- return TABLE_ERROR_NONE;
+ /* we can just handle the left side immediately */
+ /* first_p = first_p */
+ last_p = left_last_p;
+ }
+ else {
+ /*
+ * neither partition is small, we'll have to push the larger one
+ * of them on the stack
+ */
+ if (split_c >= MAX_QSORT_SPLITS) {
+ /* sanity check here -- we should never get here */
+ abort();
+ }
+ if (size1 > size2) {
+ /* push the left partition on the stack */
+ firsts[split_c] = first_p;
+ lasts[split_c] = left_last_p;
+ split_c++;
+ /* continue handling the right side */
+ first_p = right_first_p;
+ /* last_p = last_p */
+ }
+ else {
+ /* push the right partition on the stack */
+ firsts[split_c] = right_first_p;
+ lasts[split_c] = last_p;
+ split_c++;
+ /* continue handling the left side */
+ /* first_p = first_p */
+ last_p = left_last_p;
+ }
+ }
+ }
+
+ return TABLE_ERROR_NONE;
}
/*************************** exported routines *******************************/
*/
table_t *table_alloc(const unsigned int bucket_n, int *error_p)
{
- table_t *table_p = NULL;
- unsigned int buck_n;
-
- /* allocate a table structure */
- table_p = malloc(sizeof(table_t));
- if (table_p == NULL) {
- SET_POINTER(error_p, TABLE_ERROR_ALLOC);
- return NULL;
- }
-
- if (bucket_n > 0) {
- buck_n = bucket_n;
- }
- else {
- buck_n = DEFAULT_SIZE;
- }
-
- /* allocate the buckets which are NULLed */
- table_p->ta_buckets = (table_entry_t **)calloc(buck_n,
- sizeof(table_entry_t *));
- if (table_p->ta_buckets == NULL) {
- SET_POINTER(error_p, TABLE_ERROR_ALLOC);
- free(table_p);
- return NULL;
- }
-
- /* initialize structure */
- table_p->ta_magic = TABLE_MAGIC;
- table_p->ta_flags = 0;
- table_p->ta_bucket_n = buck_n;
- table_p->ta_entry_n = 0;
- table_p->ta_data_align = 0;
- table_p->ta_linear.tl_magic = 0;
- table_p->ta_linear.tl_bucket_c = 0;
- table_p->ta_linear.tl_entry_c = 0;
- table_p->ta_mmap = NULL;
- table_p->ta_file_size = 0;
- table_p->ta_mem_pool = NULL;
- table_p->ta_alloc_func = NULL;
- table_p->ta_resize_func = NULL;
- table_p->ta_free_func = NULL;
-
- SET_POINTER(error_p, TABLE_ERROR_NONE);
- return table_p;
+ table_t *table_p = NULL;
+ unsigned int buck_n;
+
+ /* allocate a table structure */
+ table_p = malloc(sizeof(table_t));
+ if (table_p == NULL) {
+ SET_POINTER(error_p, TABLE_ERROR_ALLOC);
+ return NULL;
+ }
+
+ if (bucket_n > 0) {
+ buck_n = bucket_n;
+ }
+ else {
+ buck_n = DEFAULT_SIZE;
+ }
+
+ /* allocate the buckets which are NULLed */
+ table_p->ta_buckets = (table_entry_t **)calloc(buck_n,
+ sizeof(table_entry_t *));
+ if (table_p->ta_buckets == NULL) {
+ SET_POINTER(error_p, TABLE_ERROR_ALLOC);
+ free(table_p);
+ return NULL;
+ }
+
+ /* initialize structure */
+ table_p->ta_magic = TABLE_MAGIC;
+ table_p->ta_flags = 0;
+ table_p->ta_bucket_n = buck_n;
+ table_p->ta_entry_n = 0;
+ table_p->ta_data_align = 0;
+ table_p->ta_linear.tl_magic = 0;
+ table_p->ta_linear.tl_bucket_c = 0;
+ table_p->ta_linear.tl_entry_c = 0;
+ table_p->ta_mmap = NULL;
+ table_p->ta_file_size = 0;
+ table_p->ta_mem_pool = NULL;
+ table_p->ta_alloc_func = NULL;
+ table_p->ta_resize_func = NULL;
+ table_p->ta_free_func = NULL;
+
+ SET_POINTER(error_p, TABLE_ERROR_NONE);
+ return table_p;
}
/*
* table error code.
*/
table_t *table_alloc_in_pool(const unsigned int bucket_n,
- void *mem_pool,
- table_mem_alloc_t alloc_func,
- table_mem_resize_t resize_func,
- table_mem_free_t free_func, int *error_p)
+ void *mem_pool,
+ table_mem_alloc_t alloc_func,
+ table_mem_resize_t resize_func,
+ table_mem_free_t free_func, int *error_p)
{
- table_t *table_p = NULL;
- unsigned int buck_n, size;
-
- /* make sure we have real functions, mem_pool and resize_func can be NULL */
- if (alloc_func == NULL || free_func == NULL) {
- SET_POINTER(error_p, TABLE_ERROR_ARG_NULL);
- return NULL;
- }
-
- /* allocate a table structure */
- table_p = alloc_func(mem_pool, sizeof(table_t));
- if (table_p == NULL) {
- SET_POINTER(error_p, TABLE_ERROR_ALLOC);
- return NULL;
- }
-
- if (bucket_n > 0) {
- buck_n = bucket_n;
- }
- else {
- buck_n = DEFAULT_SIZE;
- }
-
- /* allocate the buckets which are NULLed */
- size = buck_n * sizeof(table_entry_t *);
- table_p->ta_buckets = (table_entry_t **)alloc_func(mem_pool, size);
- if (table_p->ta_buckets == NULL) {
- SET_POINTER(error_p, TABLE_ERROR_ALLOC);
- (void)free_func(mem_pool, table_p, sizeof(table_t));
- return NULL;
- }
- /*
- * We zero it ourselves to save the necessity of having a
- * table_mem_calloc_t memory override function.
- */
- memset(table_p->ta_buckets, 0, size);
-
- /* initialize structure */
- table_p->ta_magic = TABLE_MAGIC;
- table_p->ta_flags = 0;
- table_p->ta_bucket_n = buck_n;
- table_p->ta_entry_n = 0;
- table_p->ta_data_align = 0;
- table_p->ta_linear.tl_magic = 0;
- table_p->ta_linear.tl_bucket_c = 0;
- table_p->ta_linear.tl_entry_c = 0;
- table_p->ta_mmap = NULL;
- table_p->ta_file_size = 0;
- table_p->ta_mem_pool = mem_pool;
- table_p->ta_alloc_func = alloc_func;
- table_p->ta_resize_func = resize_func;
- table_p->ta_free_func = free_func;
-
- SET_POINTER(error_p, TABLE_ERROR_NONE);
- return table_p;
+ table_t *table_p = NULL;
+ unsigned int buck_n, size;
+
+ /* make sure we have real functions, mem_pool and resize_func can be NULL */
+ if (alloc_func == NULL || free_func == NULL) {
+ SET_POINTER(error_p, TABLE_ERROR_ARG_NULL);
+ return NULL;
+ }
+
+ /* allocate a table structure */
+ table_p = alloc_func(mem_pool, sizeof(table_t));
+ if (table_p == NULL) {
+ SET_POINTER(error_p, TABLE_ERROR_ALLOC);
+ return NULL;
+ }
+
+ if (bucket_n > 0) {
+ buck_n = bucket_n;
+ }
+ else {
+ buck_n = DEFAULT_SIZE;
+ }
+
+ /* allocate the buckets which are NULLed */
+ size = buck_n * sizeof(table_entry_t *);
+ table_p->ta_buckets = (table_entry_t **)alloc_func(mem_pool, size);
+ if (table_p->ta_buckets == NULL) {
+ SET_POINTER(error_p, TABLE_ERROR_ALLOC);
+ (void)free_func(mem_pool, table_p, sizeof(table_t));
+ return NULL;
+ }
+ /*
+ * We zero it ourselves to save the necessity of having a
+ * table_mem_calloc_t memory override function.
+ */
+ memset(table_p->ta_buckets, 0, size);
+
+ /* initialize structure */
+ table_p->ta_magic = TABLE_MAGIC;
+ table_p->ta_flags = 0;
+ table_p->ta_bucket_n = buck_n;
+ table_p->ta_entry_n = 0;
+ table_p->ta_data_align = 0;
+ table_p->ta_linear.tl_magic = 0;
+ table_p->ta_linear.tl_bucket_c = 0;
+ table_p->ta_linear.tl_entry_c = 0;
+ table_p->ta_mmap = NULL;
+ table_p->ta_file_size = 0;
+ table_p->ta_mem_pool = mem_pool;
+ table_p->ta_alloc_func = alloc_func;
+ table_p->ta_resize_func = resize_func;
+ table_p->ta_free_func = free_func;
+
+ SET_POINTER(error_p, TABLE_ERROR_NONE);
+ return table_p;
}
/*
*/
int table_attr(table_t *table_p, const int attr)
{
- if (table_p == NULL) {
- return TABLE_ERROR_ARG_NULL;
- }
- if (table_p->ta_magic != TABLE_MAGIC) {
- return TABLE_ERROR_PNT;
- }
+ if (table_p == NULL) {
+ return TABLE_ERROR_ARG_NULL;
+ }
+ if (table_p->ta_magic != TABLE_MAGIC) {
+ return TABLE_ERROR_PNT;
+ }
- table_p->ta_flags = attr;
+ table_p->ta_flags = attr;
- return TABLE_ERROR_NONE;
+ return TABLE_ERROR_NONE;
}
/*
*/
int table_set_data_alignment(table_t *table_p, const int alignment)
{
- int val;
-
- if (table_p == NULL) {
- return TABLE_ERROR_ARG_NULL;
- }
- if (table_p->ta_magic != TABLE_MAGIC) {
- return TABLE_ERROR_PNT;
- }
- if (table_p->ta_entry_n > 0) {
- return TABLE_ERROR_NOT_EMPTY;
- }
-
- /* defaults */
- if (alignment < 2) {
- table_p->ta_data_align = 0;
- }
- else {
- /* verify we have a base 2 number */
- for (val = 2; val < MAX_ALIGNMENT; val *= 2) {
- if (val == alignment) {
- break;
- }
- }
- if (val >= MAX_ALIGNMENT) {
- return TABLE_ERROR_ALIGNMENT;
- }
- table_p->ta_data_align = alignment;
- }
-
- return TABLE_ERROR_NONE;
+ int val;
+
+ if (table_p == NULL) {
+ return TABLE_ERROR_ARG_NULL;
+ }
+ if (table_p->ta_magic != TABLE_MAGIC) {
+ return TABLE_ERROR_PNT;
+ }
+ if (table_p->ta_entry_n > 0) {
+ return TABLE_ERROR_NOT_EMPTY;
+ }
+
+ /* defaults */
+ if (alignment < 2) {
+ table_p->ta_data_align = 0;
+ }
+ else {
+ /* verify we have a base 2 number */
+ for (val = 2; val < MAX_ALIGNMENT; val *= 2) {
+ if (val == alignment) {
+ break;
+ }
+ }
+ if (val >= MAX_ALIGNMENT) {
+ return TABLE_ERROR_ALIGNMENT;
+ }
+ table_p->ta_data_align = alignment;
+ }
+
+ return TABLE_ERROR_NONE;
}
/*
*/
int table_clear(table_t *table_p)
{
- int final = TABLE_ERROR_NONE;
- table_entry_t *entry_p, *next_p;
- table_entry_t **bucket_p, **bounds_p;
+ int final = TABLE_ERROR_NONE;
+ table_entry_t *entry_p, *next_p;
+ table_entry_t **bucket_p, **bounds_p;
- if (table_p == NULL) {
- return TABLE_ERROR_ARG_NULL;
- }
- if (table_p->ta_magic != TABLE_MAGIC) {
- return TABLE_ERROR_PNT;
- }
+ if (table_p == NULL) {
+ return TABLE_ERROR_ARG_NULL;
+ }
+ if (table_p->ta_magic != TABLE_MAGIC) {
+ return TABLE_ERROR_PNT;
+ }
#ifndef NO_MMAP
- /* no mmap support so immediate error */
- if (table_p->ta_mmap != NULL) {
- return TABLE_ERROR_MMAP_OP;
- }
+ /* no mmap support so immediate error */
+ if (table_p->ta_mmap != NULL) {
+ return TABLE_ERROR_MMAP_OP;
+ }
#endif
- /* free the table allocation and table structure */
- bounds_p = table_p->ta_buckets + table_p->ta_bucket_n;
- for (bucket_p = table_p->ta_buckets; bucket_p < bounds_p; bucket_p++) {
- for (entry_p = *bucket_p; entry_p != NULL; entry_p = next_p) {
- /* record the next pointer before we free */
- next_p = entry_p->te_next_p;
- if (table_p->ta_free_func == NULL) {
- free(entry_p);
- }
- else if (! table_p->ta_free_func(table_p->ta_mem_pool, entry_p,
- entry_size(table_p,
- entry_p->te_key_size,
- entry_p->te_data_size))) {
- final = TABLE_ERROR_FREE;
- }
- }
+ /* free the table allocation and table structure */
+ bounds_p = table_p->ta_buckets + table_p->ta_bucket_n;
+ for (bucket_p = table_p->ta_buckets; bucket_p < bounds_p; bucket_p++) {
+ for (entry_p = *bucket_p; entry_p != NULL; entry_p = next_p) {
+ /* record the next pointer before we free */
+ next_p = entry_p->te_next_p;
+ if (table_p->ta_free_func == NULL) {
+ free(entry_p);
+ }
+ else if (! table_p->ta_free_func(table_p->ta_mem_pool, entry_p,
+ entry_size(table_p,
+ entry_p->te_key_size,
+ entry_p->te_data_size))) {
+ final = TABLE_ERROR_FREE;
+ }
+ }
- /* clear the bucket entry after we free its entries */
- *bucket_p = NULL;
- }
+ /* clear the bucket entry after we free its entries */
+ *bucket_p = NULL;
+ }
- /* reset table state info */
- table_p->ta_entry_n = 0;
- table_p->ta_linear.tl_magic = 0;
- table_p->ta_linear.tl_bucket_c = 0;
- table_p->ta_linear.tl_entry_c = 0;
+ /* reset table state info */
+ table_p->ta_entry_n = 0;
+ table_p->ta_linear.tl_magic = 0;
+ table_p->ta_linear.tl_bucket_c = 0;
+ table_p->ta_linear.tl_entry_c = 0;
- return final;
+ return final;
}
/*
*/
int table_free(table_t *table_p)
{
- int ret;
+ int ret;
- if (table_p == NULL) {
- return TABLE_ERROR_ARG_NULL;
- }
- if (table_p->ta_magic != TABLE_MAGIC) {
- return TABLE_ERROR_PNT;
- }
+ if (table_p == NULL) {
+ return TABLE_ERROR_ARG_NULL;
+ }
+ if (table_p->ta_magic != TABLE_MAGIC) {
+ return TABLE_ERROR_PNT;
+ }
#ifndef NO_MMAP
- /* no mmap support so immediate error */
- if (table_p->ta_mmap != NULL) {
- return TABLE_ERROR_MMAP_OP;
- }
+ /* no mmap support so immediate error */
+ if (table_p->ta_mmap != NULL) {
+ return TABLE_ERROR_MMAP_OP;
+ }
#endif
- ret = table_clear(table_p);
-
- if (table_p->ta_buckets != NULL) {
- if (table_p->ta_free_func == NULL) {
- free(table_p->ta_buckets);
- }
- else if (! table_p->ta_free_func(table_p->ta_mem_pool,
- table_p->ta_buckets,
- table_p->ta_bucket_n *
- sizeof(table_entry_t *))) {
- return TABLE_ERROR_FREE;
- }
- }
- table_p->ta_magic = 0;
- if (table_p->ta_free_func == NULL) {
- free(table_p);
- }
- else if (! table_p->ta_free_func(table_p->ta_mem_pool, table_p,
- sizeof(table_t))) {
- if (ret == TABLE_ERROR_NONE) {
- ret = TABLE_ERROR_FREE;
- }
- }
-
- return ret;
+ ret = table_clear(table_p);
+
+ if (table_p->ta_buckets != NULL) {
+ if (table_p->ta_free_func == NULL) {
+ free(table_p->ta_buckets);
+ }
+ else if (! table_p->ta_free_func(table_p->ta_mem_pool,
+ table_p->ta_buckets,
+ table_p->ta_bucket_n *
+ sizeof(table_entry_t *))) {
+ return TABLE_ERROR_FREE;
+ }
+ }
+ table_p->ta_magic = 0;
+ if (table_p->ta_free_func == NULL) {
+ free(table_p);
+ }
+ else if (! table_p->ta_free_func(table_p->ta_mem_pool, table_p,
+ sizeof(table_t))) {
+ if (ret == TABLE_ERROR_NONE) {
+ ret = TABLE_ERROR_FREE;
+ }
+ }
+
+ return ret;
}
/*
* in the table.
*/
int table_insert_kd(table_t *table_p,
- const void *key_buf, const int key_size,
- const void *data_buf, const int data_size,
- void **key_buf_p, void **data_buf_p,
- const char overwrite_b)
+ const void *key_buf, const int key_size,
+ const void *data_buf, const int data_size,
+ void **key_buf_p, void **data_buf_p,
+ const char overwrite_b)
{
- int bucket;
- unsigned int ksize, dsize, new_size, old_size, copy_size;
- table_entry_t *entry_p, *last_p, *new_entry_p;
- void *key_copy_p, *data_copy_p;
-
- /* check the arguments */
- if (table_p == NULL) {
- return TABLE_ERROR_ARG_NULL;
- }
- if (table_p->ta_magic != TABLE_MAGIC) {
- return TABLE_ERROR_PNT;
- }
- if (key_buf == NULL) {
- return TABLE_ERROR_ARG_NULL;
- }
- /* data_buf can be null but size must be >= 0, if it isn't null size != 0 */
- if ((data_buf == NULL && data_size < 0)
- || (data_buf != NULL && data_size == 0)) {
- return TABLE_ERROR_SIZE;
- }
+ int bucket;
+ unsigned int ksize, dsize, new_size, old_size, copy_size;
+ table_entry_t *entry_p, *last_p, *new_entry_p;
+ void *key_copy_p, *data_copy_p;
+
+ /* check the arguments */
+ if (table_p == NULL) {
+ return TABLE_ERROR_ARG_NULL;
+ }
+ if (table_p->ta_magic != TABLE_MAGIC) {
+ return TABLE_ERROR_PNT;
+ }
+ if (key_buf == NULL) {
+ return TABLE_ERROR_ARG_NULL;
+ }
+ /* data_buf can be null but size must be >= 0, if it isn't null size != 0 */
+ if ((data_buf == NULL && data_size < 0)
+ || (data_buf != NULL && data_size == 0)) {
+ return TABLE_ERROR_SIZE;
+ }
#ifndef NO_MMAP
- /* no mmap support so immediate error */
- if (table_p->ta_mmap != NULL) {
- return TABLE_ERROR_MMAP_OP;
- }
+ /* no mmap support so immediate error */
+ if (table_p->ta_mmap != NULL) {
+ return TABLE_ERROR_MMAP_OP;
+ }
#endif
- /* determine sizes of key and data */
- if (key_size < 0) {
- ksize = strlen((char *)key_buf) + sizeof(char);
- }
- else {
- ksize = key_size;
- }
- if (data_size < 0) {
- dsize = strlen((char *)data_buf) + sizeof(char);
- }
- else {
- dsize = data_size;
- }
-
- /* get the bucket number via a hash function */
- bucket = hash(key_buf, ksize, 0) % table_p->ta_bucket_n;
-
- /* look for the entry in this bucket, only check keys of the same size */
- last_p = NULL;
- for (entry_p = table_p->ta_buckets[bucket];
- entry_p != NULL;
- last_p = entry_p, entry_p = entry_p->te_next_p) {
- if (entry_p->te_key_size == ksize
- && memcmp(ENTRY_KEY_BUF(entry_p), key_buf, ksize) == 0) {
- break;
- }
- }
-
- /* did we find it? then we are in replace mode. */
- if (entry_p != NULL) {
-
- /* can we not overwrite existing data? */
- if (! overwrite_b) {
- SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p));
- if (data_buf_p != NULL) {
- if (entry_p->te_data_size == 0) {
- *data_buf_p = NULL;
+ /* determine sizes of key and data */
+ if (key_size < 0) {
+ ksize = strlen((char *)key_buf) + sizeof(char);
}
else {
- if (table_p->ta_data_align == 0) {
- *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
- }
- else {
- *data_buf_p = entry_data_buf(table_p, entry_p);
- }
- }
- }
- return TABLE_ERROR_OVERWRITE;
- }
+ ksize = key_size;
+ }
+ if (data_size < 0) {
+ dsize = strlen((char *)data_buf) + sizeof(char);
+ }
+ else {
+ dsize = data_size;
+ }
+
+ /* get the bucket number via a hash function */
+ bucket = hash(key_buf, ksize, 0) % table_p->ta_bucket_n;
+
+ /* look for the entry in this bucket, only check keys of the same size */
+ last_p = NULL;
+ for (entry_p = table_p->ta_buckets[bucket];
+ entry_p != NULL;
+ last_p = entry_p, entry_p = entry_p->te_next_p) {
+ if (entry_p->te_key_size == ksize
+ && memcmp(ENTRY_KEY_BUF(entry_p), key_buf, ksize) == 0) {
+ break;
+ }
+ }
+
+ /* did we find it? then we are in replace mode. */
+ if (entry_p != NULL) {
- /* re-alloc entry's data if the new size != the old */
- if (dsize != entry_p->te_data_size) {
+ /* can we not overwrite existing data? */
+ if (! overwrite_b) {
+ SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p));
+ if (data_buf_p != NULL) {
+ if (entry_p->te_data_size == 0) {
+ *data_buf_p = NULL;
+ }
+ else {
+ if (table_p->ta_data_align == 0) {
+ *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
+ }
+ else {
+ *data_buf_p = entry_data_buf(table_p, entry_p);
+ }
+ }
+ }
+ return TABLE_ERROR_OVERWRITE;
+ }
+
+ /* re-alloc entry's data if the new size != the old */
+ if (dsize != entry_p->te_data_size) {
+
+ /*
+ * First we delete it from the list to keep the list whole.
+ * This properly preserves the linked list in case we have a
+ * thread marching through the linked list while we are
+ * inserting. Maybe this is an unnecessary protection but it
+ * should not harm that much.
+ */
+ if (last_p == NULL) {
+ table_p->ta_buckets[bucket] = entry_p->te_next_p;
+ }
+ else {
+ last_p->te_next_p = entry_p->te_next_p;
+ }
- /*
- * First we delete it from the list to keep the list whole.
- * This properly preserves the linked list in case we have a
- * thread marching through the linked list while we are
- * inserting. Maybe this is an unnecessary protection but it
- * should not harm that much.
- */
- if (last_p == NULL) {
- table_p->ta_buckets[bucket] = entry_p->te_next_p;
- }
- else {
- last_p->te_next_p = entry_p->te_next_p;
- }
+ /*
+ * Realloc the structure which may change its pointer. NOTE:
+ * this may change any previous data_key_p and data_copy_p
+ * pointers.
+ */
+ new_size = entry_size(table_p, entry_p->te_key_size, dsize);
+ if (table_p->ta_resize_func == NULL) {
+ /* if the alloc function has not been overriden do realloc */
+ if (table_p->ta_alloc_func == NULL) {
+ entry_p = (table_entry_t *)realloc(entry_p, new_size);
+ if (entry_p == NULL) {
+ return TABLE_ERROR_ALLOC;
+ }
+ }
+ else {
+ old_size = new_size - dsize + entry_p->te_data_size;
+ /*
+ * if the user did override alloc but not resize, assume
+ * that the user's allocation functions can't grok realloc
+ * and do it ourselves the hard way.
+ */
+ new_entry_p =
+ (table_entry_t *)table_p->ta_alloc_func(table_p->ta_mem_pool,
+ new_size);
+ if (new_entry_p == NULL) {
+ return TABLE_ERROR_ALLOC;
+ }
+ if (new_size > old_size) {
+ copy_size = old_size;
+ }
+ else {
+ copy_size = new_size;
+ }
+ memcpy(new_entry_p, entry_p, copy_size);
+ if (! table_p->ta_free_func(table_p->ta_mem_pool, entry_p,
+ old_size)) {
+ return TABLE_ERROR_FREE;
+ }
+ entry_p = new_entry_p;
+ }
+ }
+ else {
+ old_size = new_size - dsize + entry_p->te_data_size;
+ entry_p = (table_entry_t *)
+ table_p->ta_resize_func(table_p->ta_mem_pool, entry_p,
+ old_size, new_size);
+ if (entry_p == NULL) {
+ return TABLE_ERROR_ALLOC;
+ }
+ }
- /*
- * Realloc the structure which may change its pointer. NOTE:
- * this may change any previous data_key_p and data_copy_p
- * pointers.
- */
- new_size = entry_size(table_p, entry_p->te_key_size, dsize);
- if (table_p->ta_resize_func == NULL) {
- /* if the alloc function has not been overriden do realloc */
+ /* add it back to the front of the list */
+ entry_p->te_data_size = dsize;
+ entry_p->te_next_p = table_p->ta_buckets[bucket];
+ table_p->ta_buckets[bucket] = entry_p;
+ }
+
+ /* copy or replace data in storage */
+ if (dsize > 0) {
+ if (table_p->ta_data_align == 0) {
+ data_copy_p = ENTRY_DATA_BUF(table_p, entry_p);
+ }
+ else {
+ data_copy_p = entry_data_buf(table_p, entry_p);
+ }
+ if (data_buf != NULL) {
+ memcpy(data_copy_p, data_buf, dsize);
+ }
+ }
+ else {
+ data_copy_p = NULL;
+ }
+
+ SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p));
+ SET_POINTER(data_buf_p, data_copy_p);
+
+ /* returning from the section where we were overwriting table data */
+ return TABLE_ERROR_NONE;
+ }
+
+ /*
+ * It is a new entry.
+ */
+
+ /* allocate a new entry */
+ new_size = entry_size(table_p, ksize, dsize);
if (table_p->ta_alloc_func == NULL) {
- entry_p = (table_entry_t *)realloc(entry_p, new_size);
- if (entry_p == NULL) {
- return TABLE_ERROR_ALLOC;
- }
+ entry_p = (table_entry_t *)malloc(new_size);
}
else {
- old_size = new_size - dsize + entry_p->te_data_size;
- /*
- * if the user did override alloc but not resize, assume
- * that the user's allocation functions can't grok realloc
- * and do it ourselves the hard way.
- */
- new_entry_p =
- (table_entry_t *)table_p->ta_alloc_func(table_p->ta_mem_pool,
- new_size);
- if (new_entry_p == NULL) {
- return TABLE_ERROR_ALLOC;
- }
- if (new_size > old_size) {
- copy_size = old_size;
- }
- else {
- copy_size = new_size;
- }
- memcpy(new_entry_p, entry_p, copy_size);
- if (! table_p->ta_free_func(table_p->ta_mem_pool, entry_p,
- old_size)) {
- return TABLE_ERROR_FREE;
- }
- entry_p = new_entry_p;
- }
- }
- else {
- old_size = new_size - dsize + entry_p->te_data_size;
- entry_p = (table_entry_t *)
- table_p->ta_resize_func(table_p->ta_mem_pool, entry_p,
- old_size, new_size);
+ entry_p =
+ (table_entry_t *)table_p->ta_alloc_func(table_p->ta_mem_pool, new_size);
+ }
if (entry_p == NULL) {
- return TABLE_ERROR_ALLOC;
+ return TABLE_ERROR_ALLOC;
}
- }
-
- /* add it back to the front of the list */
- entry_p->te_data_size = dsize;
- entry_p->te_next_p = table_p->ta_buckets[bucket];
- table_p->ta_buckets[bucket] = entry_p;
- }
-
- /* copy or replace data in storage */
- if (dsize > 0) {
- if (table_p->ta_data_align == 0) {
- data_copy_p = ENTRY_DATA_BUF(table_p, entry_p);
- }
- else {
- data_copy_p = entry_data_buf(table_p, entry_p);
- }
- if (data_buf != NULL) {
- memcpy(data_copy_p, data_buf, dsize);
- }
- }
- else {
- data_copy_p = NULL;
- }
-
- SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p));
- SET_POINTER(data_buf_p, data_copy_p);
-
- /* returning from the section where we were overwriting table data */
- return TABLE_ERROR_NONE;
- }
-
- /*
- * It is a new entry.
- */
-
- /* allocate a new entry */
- new_size = entry_size(table_p, ksize, dsize);
- if (table_p->ta_alloc_func == NULL) {
- entry_p = (table_entry_t *)malloc(new_size);
- }
- else {
- entry_p =
- (table_entry_t *)table_p->ta_alloc_func(table_p->ta_mem_pool, new_size);
- }
- if (entry_p == NULL) {
- return TABLE_ERROR_ALLOC;
- }
-
- /* copy key into storage */
- entry_p->te_key_size = ksize;
- key_copy_p = ENTRY_KEY_BUF(entry_p);
- memcpy(key_copy_p, key_buf, ksize);
-
- /* copy data in */
- entry_p->te_data_size = dsize;
- if (dsize > 0) {
- if (table_p->ta_data_align == 0) {
- data_copy_p = ENTRY_DATA_BUF(table_p, entry_p);
- }
- else {
- data_copy_p = entry_data_buf(table_p, entry_p);
- }
- if (data_buf != NULL) {
- memcpy(data_copy_p, data_buf, dsize);
- }
- }
- else {
- data_copy_p = NULL;
- }
-
- SET_POINTER(key_buf_p, key_copy_p);
- SET_POINTER(data_buf_p, data_copy_p);
-
- /* insert into list, no need to append */
- entry_p->te_next_p = table_p->ta_buckets[bucket];
- table_p->ta_buckets[bucket] = entry_p;
-
- table_p->ta_entry_n++;
-
- /* do we need auto-adjust? */
- if ((table_p->ta_flags & TABLE_FLAG_AUTO_ADJUST)
- && SHOULD_TABLE_GROW(table_p)) {
- return table_adjust(table_p, table_p->ta_entry_n);
- }
-
- return TABLE_ERROR_NONE;
+
+ /* copy key into storage */
+ entry_p->te_key_size = ksize;
+ key_copy_p = ENTRY_KEY_BUF(entry_p);
+ memcpy(key_copy_p, key_buf, ksize);
+
+ /* copy data in */
+ entry_p->te_data_size = dsize;
+ if (dsize > 0) {
+ if (table_p->ta_data_align == 0) {
+ data_copy_p = ENTRY_DATA_BUF(table_p, entry_p);
+ }
+ else {
+ data_copy_p = entry_data_buf(table_p, entry_p);
+ }
+ if (data_buf != NULL) {
+ memcpy(data_copy_p, data_buf, dsize);
+ }
+ }
+ else {
+ data_copy_p = NULL;
+ }
+
+ SET_POINTER(key_buf_p, key_copy_p);
+ SET_POINTER(data_buf_p, data_copy_p);
+
+ /* insert into list, no need to append */
+ entry_p->te_next_p = table_p->ta_buckets[bucket];
+ table_p->ta_buckets[bucket] = entry_p;
+
+ table_p->ta_entry_n++;
+
+ /* do we need auto-adjust? */
+ if ((table_p->ta_flags & TABLE_FLAG_AUTO_ADJUST)
+ && SHOULD_TABLE_GROW(table_p)) {
+ return table_adjust(table_p, table_p->ta_entry_n);
+ }
+
+ return TABLE_ERROR_NONE;
}
/*
* in the table.
*/
int table_insert(table_t *table_p,
- const void *key_buf, const int key_size,
- const void *data_buf, const int data_size,
- void **data_buf_p, const char overwrite_b)
+ const void *key_buf, const int key_size,
+ const void *data_buf, const int data_size,
+ void **data_buf_p, const char overwrite_b)
{
- return table_insert_kd(table_p, key_buf, key_size, data_buf, data_size,
- NULL, data_buf_p, overwrite_b);
+ return table_insert_kd(table_p, key_buf, key_size, data_buf, data_size,
+ NULL, data_buf_p, overwrite_b);
}
/*
* the key.
*/
int table_retrieve(table_t *table_p,
- const void *key_buf, const int key_size,
- void **data_buf_p, int *data_size_p)
+ const void *key_buf, const int key_size,
+ void **data_buf_p, int *data_size_p)
{
- int bucket;
- unsigned int ksize;
- table_entry_t *entry_p, **buckets;
-
- if (table_p == NULL) {
- return TABLE_ERROR_ARG_NULL;
- }
- if (table_p->ta_magic != TABLE_MAGIC) {
- return TABLE_ERROR_PNT;
- }
- if (key_buf == NULL) {
- return TABLE_ERROR_ARG_NULL;
- }
-
- /* find key size */
- if (key_size < 0) {
- ksize = strlen((char *)key_buf) + sizeof(char);
- }
- else {
- ksize = key_size;
- }
-
- /* get the bucket number via a has function */
- bucket = hash(key_buf, ksize, 0) % table_p->ta_bucket_n;
-
- /* look for the entry in this bucket, only check keys of the same size */
- buckets = table_p->ta_buckets;
- for (entry_p = buckets[bucket];
- entry_p != NULL;
- entry_p = entry_p->te_next_p) {
- entry_p = TABLE_POINTER(table_p, table_entry_t *, entry_p);
- if (entry_p->te_key_size == ksize
- && memcmp(ENTRY_KEY_BUF(entry_p), key_buf, ksize) == 0) {
- break;
- }
- }
-
- /* not found? */
- if (entry_p == NULL) {
- return TABLE_ERROR_NOT_FOUND;
- }
-
- if (data_buf_p != NULL) {
- if (entry_p->te_data_size == 0) {
- *data_buf_p = NULL;
- }
- else {
- if (table_p->ta_data_align == 0) {
- *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
- }
- else {
- *data_buf_p = entry_data_buf(table_p, entry_p);
- }
- }
- }
- SET_POINTER(data_size_p, entry_p->te_data_size);
-
- return TABLE_ERROR_NONE;
+ int bucket;
+ unsigned int ksize;
+ table_entry_t *entry_p, **buckets;
+
+ if (table_p == NULL) {
+ return TABLE_ERROR_ARG_NULL;
+ }
+ if (table_p->ta_magic != TABLE_MAGIC) {
+ return TABLE_ERROR_PNT;
+ }
+ if (key_buf == NULL) {
+ return TABLE_ERROR_ARG_NULL;
+ }
+
+ /* find key size */
+ if (key_size < 0) {
+ ksize = strlen((char *)key_buf) + sizeof(char);
+ }
+ else {
+ ksize = key_size;
+ }
+
+ /* get the bucket number via a has function */
+ bucket = hash(key_buf, ksize, 0) % table_p->ta_bucket_n;
+
+ /* look for the entry in this bucket, only check keys of the same size */
+ buckets = table_p->ta_buckets;
+ for (entry_p = buckets[bucket];
+ entry_p != NULL;
+ entry_p = entry_p->te_next_p) {
+ entry_p = TABLE_POINTER(table_p, table_entry_t *, entry_p);
+ if (entry_p->te_key_size == ksize
+ && memcmp(ENTRY_KEY_BUF(entry_p), key_buf, ksize) == 0) {
+ break;
+ }
+ }
+
+ /* not found? */
+ if (entry_p == NULL) {
+ return TABLE_ERROR_NOT_FOUND;
+ }
+
+ if (data_buf_p != NULL) {
+ if (entry_p->te_data_size == 0) {
+ *data_buf_p = NULL;
+ }
+ else {
+ if (table_p->ta_data_align == 0) {
+ *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
+ }
+ else {
+ *data_buf_p = entry_data_buf(table_p, entry_p);
+ }
+ }
+ }
+ SET_POINTER(data_size_p, entry_p->te_data_size);
+
+ return TABLE_ERROR_NONE;
}
/*
* associated with the key.
*/
int table_delete(table_t *table_p,
- const void *key_buf, const int key_size,
- void **data_buf_p, int *data_size_p)
+ const void *key_buf, const int key_size,
+ void **data_buf_p, int *data_size_p)
{
- int bucket;
- unsigned int ksize;
- unsigned char *data_copy_p;
- table_entry_t *entry_p, *last_p;
-
- if (table_p == NULL) {
- return TABLE_ERROR_ARG_NULL;
- }
- if (table_p->ta_magic != TABLE_MAGIC) {
- return TABLE_ERROR_PNT;
- }
- if (key_buf == NULL) {
- return TABLE_ERROR_ARG_NULL;
- }
+ int bucket;
+ unsigned int ksize;
+ unsigned char *data_copy_p;
+ table_entry_t *entry_p, *last_p;
+
+ if (table_p == NULL) {
+ return TABLE_ERROR_ARG_NULL;
+ }
+ if (table_p->ta_magic != TABLE_MAGIC) {
+ return TABLE_ERROR_PNT;
+ }
+ if (key_buf == NULL) {
+ return TABLE_ERROR_ARG_NULL;
+ }
#ifndef NO_MMAP
- /* no mmap support so immediate error */
- if (table_p->ta_mmap != NULL) {
- return TABLE_ERROR_MMAP_OP;
- }
+ /* no mmap support so immediate error */
+ if (table_p->ta_mmap != NULL) {
+ return TABLE_ERROR_MMAP_OP;
+ }
#endif
- /* get the key size */
- if (key_size < 0) {
- ksize = strlen((char *)key_buf) + sizeof(char);
- }
- else {
- ksize = key_size;
- }
-
- /* find our bucket */
- bucket = hash(key_buf, ksize, 0) % table_p->ta_bucket_n;
-
- /* look for the entry in this bucket, only check keys of the same size */
- for (last_p = NULL, entry_p = table_p->ta_buckets[bucket];
- entry_p != NULL;
- last_p = entry_p, entry_p = entry_p->te_next_p) {
- if (entry_p->te_key_size == ksize
- && memcmp(ENTRY_KEY_BUF(entry_p), key_buf, ksize) == 0) {
- break;
- }
- }
-
- /* did we find it? */
- if (entry_p == NULL) {
- return TABLE_ERROR_NOT_FOUND;
- }
-
- /*
- * NOTE: we may want to adjust the linear counters here if the entry
- * we are deleting is the one we are pointing on or is ahead of the
- * one in the bucket list
- */
-
- /* remove entry from the linked list */
- if (last_p == NULL) {
- table_p->ta_buckets[bucket] = entry_p->te_next_p;
- }
- else {
- last_p->te_next_p = entry_p->te_next_p;
- }
-
- /* free entry */
- if (data_buf_p != NULL) {
- if (entry_p->te_data_size == 0) {
- *data_buf_p = NULL;
- }
- else {
- /*
- * if we were storing it compacted, we now need to malloc some
- * space if the user wants the value after the delete.
- */
- if (table_p->ta_alloc_func == NULL) {
- *data_buf_p = malloc(entry_p->te_data_size);
- }
- else {
- *data_buf_p = table_p->ta_alloc_func(table_p->ta_mem_pool,
- entry_p->te_data_size);
- }
- if (*data_buf_p == NULL) {
- return TABLE_ERROR_ALLOC;
- }
- if (table_p->ta_data_align == 0) {
- data_copy_p = ENTRY_DATA_BUF(table_p, entry_p);
- }
- else {
- data_copy_p = entry_data_buf(table_p, entry_p);
- }
- memcpy(*data_buf_p, data_copy_p, entry_p->te_data_size);
- }
- }
- SET_POINTER(data_size_p, entry_p->te_data_size);
- if (table_p->ta_free_func == NULL) {
- free(entry_p);
- }
- else if (! table_p->ta_free_func(table_p->ta_mem_pool, entry_p,
- entry_size(table_p,
- entry_p->te_key_size,
- entry_p->te_data_size))) {
- return TABLE_ERROR_FREE;
- }
-
- table_p->ta_entry_n--;
-
- /* do we need auto-adjust down? */
- if ((table_p->ta_flags & TABLE_FLAG_AUTO_ADJUST)
- && (table_p->ta_flags & TABLE_FLAG_ADJUST_DOWN)
- && SHOULD_TABLE_SHRINK(table_p)) {
- return table_adjust(table_p, table_p->ta_entry_n);
- }
-
- return TABLE_ERROR_NONE;
+ /* get the key size */
+ if (key_size < 0) {
+ ksize = strlen((char *)key_buf) + sizeof(char);
+ }
+ else {
+ ksize = key_size;
+ }
+
+ /* find our bucket */
+ bucket = hash(key_buf, ksize, 0) % table_p->ta_bucket_n;
+
+ /* look for the entry in this bucket, only check keys of the same size */
+ for (last_p = NULL, entry_p = table_p->ta_buckets[bucket];
+ entry_p != NULL;
+ last_p = entry_p, entry_p = entry_p->te_next_p) {
+ if (entry_p->te_key_size == ksize
+ && memcmp(ENTRY_KEY_BUF(entry_p), key_buf, ksize) == 0) {
+ break;
+ }
+ }
+
+ /* did we find it? */
+ if (entry_p == NULL) {
+ return TABLE_ERROR_NOT_FOUND;
+ }
+
+ /*
+ * NOTE: we may want to adjust the linear counters here if the entry
+ * we are deleting is the one we are pointing on or is ahead of the
+ * one in the bucket list
+ */
+
+ /* remove entry from the linked list */
+ if (last_p == NULL) {
+ table_p->ta_buckets[bucket] = entry_p->te_next_p;
+ }
+ else {
+ last_p->te_next_p = entry_p->te_next_p;
+ }
+
+ /* free entry */
+ if (data_buf_p != NULL) {
+ if (entry_p->te_data_size == 0) {
+ *data_buf_p = NULL;
+ }
+ else {
+ /*
+ * if we were storing it compacted, we now need to malloc some
+ * space if the user wants the value after the delete.
+ */
+ if (table_p->ta_alloc_func == NULL) {
+ *data_buf_p = malloc(entry_p->te_data_size);
+ }
+ else {
+ *data_buf_p = table_p->ta_alloc_func(table_p->ta_mem_pool,
+ entry_p->te_data_size);
+ }
+ if (*data_buf_p == NULL) {
+ return TABLE_ERROR_ALLOC;
+ }
+ if (table_p->ta_data_align == 0) {
+ data_copy_p = ENTRY_DATA_BUF(table_p, entry_p);
+ }
+ else {
+ data_copy_p = entry_data_buf(table_p, entry_p);
+ }
+ memcpy(*data_buf_p, data_copy_p, entry_p->te_data_size);
+ }
+ }
+ SET_POINTER(data_size_p, entry_p->te_data_size);
+ if (table_p->ta_free_func == NULL) {
+ free(entry_p);
+ }
+ else if (! table_p->ta_free_func(table_p->ta_mem_pool, entry_p,
+ entry_size(table_p,
+ entry_p->te_key_size,
+ entry_p->te_data_size))) {
+ return TABLE_ERROR_FREE;
+ }
+
+ table_p->ta_entry_n--;
+
+ /* do we need auto-adjust down? */
+ if ((table_p->ta_flags & TABLE_FLAG_AUTO_ADJUST)
+ && (table_p->ta_flags & TABLE_FLAG_ADJUST_DOWN)
+ && SHOULD_TABLE_SHRINK(table_p)) {
+ return table_adjust(table_p, table_p->ta_entry_n);
+ }
+
+ return TABLE_ERROR_NONE;
}
/*
* associated with the key.
*/
int table_delete_first(table_t *table_p,
- void **key_buf_p, int *key_size_p,
- void **data_buf_p, int *data_size_p)
+ void **key_buf_p, int *key_size_p,
+ void **data_buf_p, int *data_size_p)
{
- unsigned char *data_copy_p;
- table_entry_t *entry_p;
- table_linear_t linear;
+ unsigned char *data_copy_p;
+ table_entry_t *entry_p;
+ table_linear_t linear;
- if (table_p == NULL) {
- return TABLE_ERROR_ARG_NULL;
- }
- if (table_p->ta_magic != TABLE_MAGIC) {
- return TABLE_ERROR_PNT;
- }
+ if (table_p == NULL) {
+ return TABLE_ERROR_ARG_NULL;
+ }
+ if (table_p->ta_magic != TABLE_MAGIC) {
+ return TABLE_ERROR_PNT;
+ }
#ifndef NO_MMAP
- /* no mmap support so immediate error */
- if (table_p->ta_mmap != NULL) {
- return TABLE_ERROR_MMAP_OP;
- }
+ /* no mmap support so immediate error */
+ if (table_p->ta_mmap != NULL) {
+ return TABLE_ERROR_MMAP_OP;
+ }
#endif
- /* take the first entry */
- entry_p = first_entry(table_p, &linear);
- if (entry_p == NULL) {
- return TABLE_ERROR_NOT_FOUND;
- }
-
- /*
- * NOTE: we may want to adjust the linear counters here if the entry
- * we are deleting is the one we are pointing on or is ahead of the
- * one in the bucket list
- */
-
- /* remove entry from the linked list */
- table_p->ta_buckets[linear.tl_bucket_c] = entry_p->te_next_p;
-
- /* free entry */
- if (key_buf_p != NULL) {
- if (entry_p->te_key_size == 0) {
- *key_buf_p = NULL;
- }
- else {
- /*
- * if we were storing it compacted, we now need to malloc some
- * space if the user wants the value after the delete.
- */
- if (table_p->ta_alloc_func == NULL) {
- *key_buf_p = malloc(entry_p->te_key_size);
- }
- else {
- *key_buf_p = table_p->ta_alloc_func(table_p->ta_mem_pool,
- entry_p->te_key_size);
- }
- if (*key_buf_p == NULL) {
- return TABLE_ERROR_ALLOC;
- }
- memcpy(*key_buf_p, ENTRY_KEY_BUF(entry_p), entry_p->te_key_size);
- }
- }
- SET_POINTER(key_size_p, entry_p->te_key_size);
-
- if (data_buf_p != NULL) {
- if (entry_p->te_data_size == 0) {
- *data_buf_p = NULL;
- }
- else {
- /*
- * if we were storing it compacted, we now need to malloc some
- * space if the user wants the value after the delete.
- */
- if (table_p->ta_alloc_func == NULL) {
- *data_buf_p = malloc(entry_p->te_data_size);
- }
- else {
- *data_buf_p = table_p->ta_alloc_func(table_p->ta_mem_pool,
- entry_p->te_data_size);
- }
- if (*data_buf_p == NULL) {
- return TABLE_ERROR_ALLOC;
- }
- if (table_p->ta_data_align == 0) {
- data_copy_p = ENTRY_DATA_BUF(table_p, entry_p);
- }
- else {
- data_copy_p = entry_data_buf(table_p, entry_p);
- }
- memcpy(*data_buf_p, data_copy_p, entry_p->te_data_size);
- }
- }
- SET_POINTER(data_size_p, entry_p->te_data_size);
- if (table_p->ta_free_func == NULL) {
- free(entry_p);
- }
- else if (! table_p->ta_free_func(table_p->ta_mem_pool, entry_p,
- entry_size(table_p,
- entry_p->te_key_size,
- entry_p->te_data_size))) {
- return TABLE_ERROR_FREE;
- }
-
- table_p->ta_entry_n--;
-
- /* do we need auto-adjust down? */
- if ((table_p->ta_flags & TABLE_FLAG_AUTO_ADJUST)
- && (table_p->ta_flags & TABLE_FLAG_ADJUST_DOWN)
- && SHOULD_TABLE_SHRINK(table_p)) {
- return table_adjust(table_p, table_p->ta_entry_n);
- }
-
- return TABLE_ERROR_NONE;
+ /* take the first entry */
+ entry_p = first_entry(table_p, &linear);
+ if (entry_p == NULL) {
+ return TABLE_ERROR_NOT_FOUND;
+ }
+
+ /*
+ * NOTE: we may want to adjust the linear counters here if the entry
+ * we are deleting is the one we are pointing on or is ahead of the
+ * one in the bucket list
+ */
+
+ /* remove entry from the linked list */
+ table_p->ta_buckets[linear.tl_bucket_c] = entry_p->te_next_p;
+
+ /* free entry */
+ if (key_buf_p != NULL) {
+ if (entry_p->te_key_size == 0) {
+ *key_buf_p = NULL;
+ }
+ else {
+ /*
+ * if we were storing it compacted, we now need to malloc some
+ * space if the user wants the value after the delete.
+ */
+ if (table_p->ta_alloc_func == NULL) {
+ *key_buf_p = malloc(entry_p->te_key_size);
+ }
+ else {
+ *key_buf_p = table_p->ta_alloc_func(table_p->ta_mem_pool,
+ entry_p->te_key_size);
+ }
+ if (*key_buf_p == NULL) {
+ return TABLE_ERROR_ALLOC;
+ }
+ memcpy(*key_buf_p, ENTRY_KEY_BUF(entry_p), entry_p->te_key_size);
+ }
+ }
+ SET_POINTER(key_size_p, entry_p->te_key_size);
+
+ if (data_buf_p != NULL) {
+ if (entry_p->te_data_size == 0) {
+ *data_buf_p = NULL;
+ }
+ else {
+ /*
+ * if we were storing it compacted, we now need to malloc some
+ * space if the user wants the value after the delete.
+ */
+ if (table_p->ta_alloc_func == NULL) {
+ *data_buf_p = malloc(entry_p->te_data_size);
+ }
+ else {
+ *data_buf_p = table_p->ta_alloc_func(table_p->ta_mem_pool,
+ entry_p->te_data_size);
+ }
+ if (*data_buf_p == NULL) {
+ return TABLE_ERROR_ALLOC;
+ }
+ if (table_p->ta_data_align == 0) {
+ data_copy_p = ENTRY_DATA_BUF(table_p, entry_p);
+ }
+ else {
+ data_copy_p = entry_data_buf(table_p, entry_p);
+ }
+ memcpy(*data_buf_p, data_copy_p, entry_p->te_data_size);
+ }
+ }
+ SET_POINTER(data_size_p, entry_p->te_data_size);
+ if (table_p->ta_free_func == NULL) {
+ free(entry_p);
+ }
+ else if (! table_p->ta_free_func(table_p->ta_mem_pool, entry_p,
+ entry_size(table_p,
+ entry_p->te_key_size,
+ entry_p->te_data_size))) {
+ return TABLE_ERROR_FREE;
+ }
+
+ table_p->ta_entry_n--;
+
+ /* do we need auto-adjust down? */
+ if ((table_p->ta_flags & TABLE_FLAG_AUTO_ADJUST)
+ && (table_p->ta_flags & TABLE_FLAG_ADJUST_DOWN)
+ && SHOULD_TABLE_SHRINK(table_p)) {
+ return table_adjust(table_p, table_p->ta_entry_n);
+ }
+
+ return TABLE_ERROR_NONE;
}
/*
*/
int table_info(table_t *table_p, int *num_buckets_p, int *num_entries_p)
{
- if (table_p == NULL) {
- return TABLE_ERROR_ARG_NULL;
- }
- if (table_p->ta_magic != TABLE_MAGIC) {
- return TABLE_ERROR_PNT;
- }
+ if (table_p == NULL) {
+ return TABLE_ERROR_ARG_NULL;
+ }
+ if (table_p->ta_magic != TABLE_MAGIC) {
+ return TABLE_ERROR_PNT;
+ }
- SET_POINTER(num_buckets_p, table_p->ta_bucket_n);
- SET_POINTER(num_entries_p, table_p->ta_entry_n);
+ SET_POINTER(num_buckets_p, table_p->ta_bucket_n);
+ SET_POINTER(num_entries_p, table_p->ta_entry_n);
- return TABLE_ERROR_NONE;
+ return TABLE_ERROR_NONE;
}
/*
*/
int table_adjust(table_t *table_p, const int bucket_n)
{
- table_entry_t *entry_p, *next_p;
- table_entry_t **buckets, **bucket_p, **bounds_p;
- int bucket;
- unsigned int buck_n, bucket_size;
-
- if (table_p == NULL) {
- return TABLE_ERROR_ARG_NULL;
- }
- if (table_p->ta_magic != TABLE_MAGIC) {
- return TABLE_ERROR_PNT;
- }
+ table_entry_t *entry_p, *next_p;
+ table_entry_t **buckets, **bucket_p, **bounds_p;
+ int bucket;
+ unsigned int buck_n, bucket_size;
+
+ if (table_p == NULL) {
+ return TABLE_ERROR_ARG_NULL;
+ }
+ if (table_p->ta_magic != TABLE_MAGIC) {
+ return TABLE_ERROR_PNT;
+ }
#ifndef NO_MMAP
- /* no mmap support so immediate error */
- if (table_p->ta_mmap != NULL) {
- return TABLE_ERROR_MMAP_OP;
- }
+ /* no mmap support so immediate error */
+ if (table_p->ta_mmap != NULL) {
+ return TABLE_ERROR_MMAP_OP;
+ }
#endif
- /*
- * NOTE: we walk through the entries and rehash them. If we stored
- * the hash value as a full int in the table-entry, all we would
- * have to do is remod it.
- */
-
- /* normalize to the number of entries */
- if (bucket_n == 0) {
- buck_n = table_p->ta_entry_n;
- }
- else {
- buck_n = bucket_n;
- }
-
- /* we must have at least 1 bucket */
- if (buck_n == 0) {
- buck_n = 1;
- }
-
- (void)printf("growing table to %d\n", buck_n);
-
- /* make sure we have something to do */
- if (buck_n == table_p->ta_bucket_n) {
- return TABLE_ERROR_NONE;
- }
-
- /* allocate a new bucket list */
- bucket_size = buck_n * sizeof(table_entry_t *);
- if (table_p->ta_alloc_func == NULL) {
- buckets = (table_entry_t **)malloc(bucket_size);
- }
- else {
- buckets =
- (table_entry_t **)table_p->ta_alloc_func(table_p->ta_mem_pool,
- bucket_size);
- }
- if (buckets == NULL) {
- return TABLE_ERROR_ALLOC;
- }
- /*
- * We zero it ourselves to save the necessity of having a
- * table_mem_calloc_t memory override function.
- */
- memset(buckets, 0, bucket_size);
-
- /*
- * run through each of the items in the current table and rehash
- * them into the newest bucket sizes
- */
- bounds_p = table_p->ta_buckets + table_p->ta_bucket_n;
- for (bucket_p = table_p->ta_buckets; bucket_p < bounds_p; bucket_p++) {
- for (entry_p = *bucket_p; entry_p != NULL; entry_p = next_p) {
+ /*
+ * NOTE: we walk through the entries and rehash them. If we stored
+ * the hash value as a full int in the table-entry, all we would
+ * have to do is remod it.
+ */
+
+ /* normalize to the number of entries */
+ if (bucket_n == 0) {
+ buck_n = table_p->ta_entry_n;
+ }
+ else {
+ buck_n = bucket_n;
+ }
+
+ /* we must have at least 1 bucket */
+ if (buck_n == 0) {
+ buck_n = 1;
+ }
+
+ (void)printf("growing table to %d\n", buck_n);
+
+ /* make sure we have something to do */
+ if (buck_n == table_p->ta_bucket_n) {
+ return TABLE_ERROR_NONE;
+ }
+
+ /* allocate a new bucket list */
+ bucket_size = buck_n * sizeof(table_entry_t *);
+ if (table_p->ta_alloc_func == NULL) {
+ buckets = (table_entry_t **)malloc(bucket_size);
+ }
+ else {
+ buckets =
+ (table_entry_t **)table_p->ta_alloc_func(table_p->ta_mem_pool,
+ bucket_size);
+ }
+ if (buckets == NULL) {
+ return TABLE_ERROR_ALLOC;
+ }
+ /*
+ * We zero it ourselves to save the necessity of having a
+ * table_mem_calloc_t memory override function.
+ */
+ memset(buckets, 0, bucket_size);
+
+ /*
+ * run through each of the items in the current table and rehash
+ * them into the newest bucket sizes
+ */
+ bounds_p = table_p->ta_buckets + table_p->ta_bucket_n;
+ for (bucket_p = table_p->ta_buckets; bucket_p < bounds_p; bucket_p++) {
+ for (entry_p = *bucket_p; entry_p != NULL; entry_p = next_p) {
- /* hash the old data into the new table size */
- bucket = hash(ENTRY_KEY_BUF(entry_p), entry_p->te_key_size, 0) % buck_n;
+ /* hash the old data into the new table size */
+ bucket = hash(ENTRY_KEY_BUF(entry_p), entry_p->te_key_size, 0) % buck_n;
- /* record the next one now since we overwrite next below */
- next_p = entry_p->te_next_p;
+ /* record the next one now since we overwrite next below */
+ next_p = entry_p->te_next_p;
- /* insert into new list, no need to append */
- entry_p->te_next_p = buckets[bucket];
- buckets[bucket] = entry_p;
+ /* insert into new list, no need to append */
+ entry_p->te_next_p = buckets[bucket];
+ buckets[bucket] = entry_p;
- /*
- * NOTE: we may want to adjust the bucket_c linear entry here to
- * keep it current
- */
- }
- /* remove the old table pointers as we go by */
- *bucket_p = NULL;
- }
-
- /* replace the table buckets with the new ones */
- if (table_p->ta_free_func == NULL) {
- free(table_p->ta_buckets);
- }
- else if (! table_p->ta_free_func(table_p->ta_mem_pool,
- table_p->ta_buckets,
- table_p->ta_bucket_n *
- sizeof(table_entry_t *))) {
- return TABLE_ERROR_FREE;
- }
- table_p->ta_buckets = buckets;
- table_p->ta_bucket_n = buck_n;
-
- return TABLE_ERROR_NONE;
+ /*
+ * NOTE: we may want to adjust the bucket_c linear entry here to
+ * keep it current
+ */
+ }
+ /* remove the old table pointers as we go by */
+ *bucket_p = NULL;
+ }
+
+ /* replace the table buckets with the new ones */
+ if (table_p->ta_free_func == NULL) {
+ free(table_p->ta_buckets);
+ }
+ else if (! table_p->ta_free_func(table_p->ta_mem_pool,
+ table_p->ta_buckets,
+ table_p->ta_bucket_n *
+ sizeof(table_entry_t *))) {
+ return TABLE_ERROR_FREE;
+ }
+ table_p->ta_buckets = buckets;
+ table_p->ta_bucket_n = buck_n;
+
+ return TABLE_ERROR_NONE;
}
/*
*/
int table_type_size(void)
{
- return sizeof(table_t);
+ return sizeof(table_t);
}
/************************* linear access routines ****************************/
* associated with the first key.
*/
int table_first(table_t *table_p,
- void **key_buf_p, int *key_size_p,
- void **data_buf_p, int *data_size_p)
+ void **key_buf_p, int *key_size_p,
+ void **data_buf_p, int *data_size_p)
{
- table_entry_t *entry_p;
-
- if (table_p == NULL) {
- return TABLE_ERROR_ARG_NULL;
- }
- if (table_p->ta_magic != TABLE_MAGIC) {
- return TABLE_ERROR_PNT;
- }
-
- /* initialize our linear magic number */
- table_p->ta_linear.tl_magic = LINEAR_MAGIC;
-
- entry_p = first_entry(table_p, &table_p->ta_linear);
- if (entry_p == NULL) {
- return TABLE_ERROR_NOT_FOUND;
- }
-
- SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p));
- SET_POINTER(key_size_p, entry_p->te_key_size);
- if (data_buf_p != NULL) {
- if (entry_p->te_data_size == 0) {
- *data_buf_p = NULL;
- }
- else {
- if (table_p->ta_data_align == 0) {
- *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
- }
- else {
- *data_buf_p = entry_data_buf(table_p, entry_p);
- }
- }
- }
- SET_POINTER(data_size_p, entry_p->te_data_size);
-
- return TABLE_ERROR_NONE;
+ table_entry_t *entry_p;
+
+ if (table_p == NULL) {
+ return TABLE_ERROR_ARG_NULL;
+ }
+ if (table_p->ta_magic != TABLE_MAGIC) {
+ return TABLE_ERROR_PNT;
+ }
+
+ /* initialize our linear magic number */
+ table_p->ta_linear.tl_magic = LINEAR_MAGIC;
+
+ entry_p = first_entry(table_p, &table_p->ta_linear);
+ if (entry_p == NULL) {
+ return TABLE_ERROR_NOT_FOUND;
+ }
+
+ SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p));
+ SET_POINTER(key_size_p, entry_p->te_key_size);
+ if (data_buf_p != NULL) {
+ if (entry_p->te_data_size == 0) {
+ *data_buf_p = NULL;
+ }
+ else {
+ if (table_p->ta_data_align == 0) {
+ *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
+ }
+ else {
+ *data_buf_p = entry_data_buf(table_p, entry_p);
+ }
+ }
+ }
+ SET_POINTER(data_size_p, entry_p->te_data_size);
+
+ return TABLE_ERROR_NONE;
}
/*
* associated with the next key.
*/
int table_next(table_t *table_p,
- void **key_buf_p, int *key_size_p,
- void **data_buf_p, int *data_size_p)
+ void **key_buf_p, int *key_size_p,
+ void **data_buf_p, int *data_size_p)
{
- table_entry_t *entry_p;
- int error;
-
- if (table_p == NULL) {
- return TABLE_ERROR_ARG_NULL;
- }
- if (table_p->ta_magic != TABLE_MAGIC) {
- return TABLE_ERROR_PNT;
- }
- if (table_p->ta_linear.tl_magic != LINEAR_MAGIC) {
- return TABLE_ERROR_LINEAR;
- }
-
- /* move to the next entry */
- entry_p = next_entry(table_p, &table_p->ta_linear, &error);
- if (entry_p == NULL) {
- return error;
- }
-
- SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p));
- SET_POINTER(key_size_p, entry_p->te_key_size);
- if (data_buf_p != NULL) {
- if (entry_p->te_data_size == 0) {
- *data_buf_p = NULL;
- }
- else {
- if (table_p->ta_data_align == 0) {
- *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
- }
- else {
- *data_buf_p = entry_data_buf(table_p, entry_p);
- }
- }
- }
- SET_POINTER(data_size_p, entry_p->te_data_size);
-
- return TABLE_ERROR_NONE;
+ table_entry_t *entry_p;
+ int error;
+
+ if (table_p == NULL) {
+ return TABLE_ERROR_ARG_NULL;
+ }
+ if (table_p->ta_magic != TABLE_MAGIC) {
+ return TABLE_ERROR_PNT;
+ }
+ if (table_p->ta_linear.tl_magic != LINEAR_MAGIC) {
+ return TABLE_ERROR_LINEAR;
+ }
+
+ /* move to the next entry */
+ entry_p = next_entry(table_p, &table_p->ta_linear, &error);
+ if (entry_p == NULL) {
+ return error;
+ }
+
+ SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p));
+ SET_POINTER(key_size_p, entry_p->te_key_size);
+ if (data_buf_p != NULL) {
+ if (entry_p->te_data_size == 0) {
+ *data_buf_p = NULL;
+ }
+ else {
+ if (table_p->ta_data_align == 0) {
+ *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
+ }
+ else {
+ *data_buf_p = entry_data_buf(table_p, entry_p);
+ }
+ }
+ }
+ SET_POINTER(data_size_p, entry_p->te_data_size);
+
+ return TABLE_ERROR_NONE;
}
/*
* associated with the current key.
*/
int table_this(table_t *table_p,
- void **key_buf_p, int *key_size_p,
- void **data_buf_p, int *data_size_p)
+ void **key_buf_p, int *key_size_p,
+ void **data_buf_p, int *data_size_p)
{
- table_entry_t *entry_p = NULL;
- int entry_c;
-
- if (table_p == NULL) {
- return TABLE_ERROR_ARG_NULL;
- }
- if (table_p->ta_magic != TABLE_MAGIC) {
- return TABLE_ERROR_PNT;
- }
- if (table_p->ta_linear.tl_magic != LINEAR_MAGIC) {
- return TABLE_ERROR_LINEAR;
- }
-
- /* if we removed an item that shorted the bucket list, we may get this */
- if (table_p->ta_linear.tl_bucket_c >= table_p->ta_bucket_n) {
- /*
- * NOTE: this might happen if we delete an item which shortens the
- * table bucket numbers.
- */
- return TABLE_ERROR_NOT_FOUND;
- }
-
- /* find the entry which is the nth in the list */
- entry_p = table_p->ta_buckets[table_p->ta_linear.tl_bucket_c];
- /* NOTE: we swap the order here to be more efficient */
- for (entry_c = table_p->ta_linear.tl_entry_c; entry_c > 0; entry_c--) {
- /* did we reach the end of the list? */
- if (entry_p == NULL) {
- break;
- }
- entry_p = TABLE_POINTER(table_p, table_entry_t *, entry_p)->te_next_p;
- }
-
- /* is this a NOT_FOUND or a LINEAR error */
- if (entry_p == NULL) {
- return TABLE_ERROR_NOT_FOUND;
- }
-
- SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p));
- SET_POINTER(key_size_p, entry_p->te_key_size);
- if (data_buf_p != NULL) {
- if (entry_p->te_data_size == 0) {
- *data_buf_p = NULL;
- }
- else {
- if (table_p->ta_data_align == 0) {
- *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
- }
- else {
- *data_buf_p = entry_data_buf(table_p, entry_p);
- }
- }
- }
- SET_POINTER(data_size_p, entry_p->te_data_size);
-
- return TABLE_ERROR_NONE;
+ table_entry_t *entry_p = NULL;
+ int entry_c;
+
+ if (table_p == NULL) {
+ return TABLE_ERROR_ARG_NULL;
+ }
+ if (table_p->ta_magic != TABLE_MAGIC) {
+ return TABLE_ERROR_PNT;
+ }
+ if (table_p->ta_linear.tl_magic != LINEAR_MAGIC) {
+ return TABLE_ERROR_LINEAR;
+ }
+
+ /* if we removed an item that shorted the bucket list, we may get this */
+ if (table_p->ta_linear.tl_bucket_c >= table_p->ta_bucket_n) {
+ /*
+ * NOTE: this might happen if we delete an item which shortens the
+ * table bucket numbers.
+ */
+ return TABLE_ERROR_NOT_FOUND;
+ }
+
+ /* find the entry which is the nth in the list */
+ entry_p = table_p->ta_buckets[table_p->ta_linear.tl_bucket_c];
+ /* NOTE: we swap the order here to be more efficient */
+ for (entry_c = table_p->ta_linear.tl_entry_c; entry_c > 0; entry_c--) {
+ /* did we reach the end of the list? */
+ if (entry_p == NULL) {
+ break;
+ }
+ entry_p = TABLE_POINTER(table_p, table_entry_t *, entry_p)->te_next_p;
+ }
+
+ /* is this a NOT_FOUND or a LINEAR error */
+ if (entry_p == NULL) {
+ return TABLE_ERROR_NOT_FOUND;
+ }
+
+ SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p));
+ SET_POINTER(key_size_p, entry_p->te_key_size);
+ if (data_buf_p != NULL) {
+ if (entry_p->te_data_size == 0) {
+ *data_buf_p = NULL;
+ }
+ else {
+ if (table_p->ta_data_align == 0) {
+ *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
+ }
+ else {
+ *data_buf_p = entry_data_buf(table_p, entry_p);
+ }
+ }
+ }
+ SET_POINTER(data_size_p, entry_p->te_data_size);
+
+ return TABLE_ERROR_NONE;
}
/*
* associated with the first key.
*/
int table_first_r(table_t *table_p, table_linear_t *linear_p,
- void **key_buf_p, int *key_size_p,
- void **data_buf_p, int *data_size_p)
+ void **key_buf_p, int *key_size_p,
+ void **data_buf_p, int *data_size_p)
{
- table_entry_t *entry_p;
-
- if (table_p == NULL) {
- return TABLE_ERROR_ARG_NULL;
- }
- if (table_p->ta_magic != TABLE_MAGIC) {
- return TABLE_ERROR_PNT;
- }
- if (linear_p == NULL) {
- return TABLE_ERROR_ARG_NULL;
- }
-
- /* initialize our linear magic number */
- linear_p->tl_magic = LINEAR_MAGIC;
-
- entry_p = first_entry(table_p, linear_p);
- if (entry_p == NULL) {
- return TABLE_ERROR_NOT_FOUND;
- }
-
- SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p));
- SET_POINTER(key_size_p, entry_p->te_key_size);
- if (data_buf_p != NULL) {
- if (entry_p->te_data_size == 0) {
- *data_buf_p = NULL;
- }
- else {
- if (table_p->ta_data_align == 0) {
- *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
- }
- else {
- *data_buf_p = entry_data_buf(table_p, entry_p);
- }
- }
- }
- SET_POINTER(data_size_p, entry_p->te_data_size);
-
- return TABLE_ERROR_NONE;
+ table_entry_t *entry_p;
+
+ if (table_p == NULL) {
+ return TABLE_ERROR_ARG_NULL;
+ }
+ if (table_p->ta_magic != TABLE_MAGIC) {
+ return TABLE_ERROR_PNT;
+ }
+ if (linear_p == NULL) {
+ return TABLE_ERROR_ARG_NULL;
+ }
+
+ /* initialize our linear magic number */
+ linear_p->tl_magic = LINEAR_MAGIC;
+
+ entry_p = first_entry(table_p, linear_p);
+ if (entry_p == NULL) {
+ return TABLE_ERROR_NOT_FOUND;
+ }
+
+ SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p));
+ SET_POINTER(key_size_p, entry_p->te_key_size);
+ if (data_buf_p != NULL) {
+ if (entry_p->te_data_size == 0) {
+ *data_buf_p = NULL;
+ }
+ else {
+ if (table_p->ta_data_align == 0) {
+ *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
+ }
+ else {
+ *data_buf_p = entry_data_buf(table_p, entry_p);
+ }
+ }
+ }
+ SET_POINTER(data_size_p, entry_p->te_data_size);
+
+ return TABLE_ERROR_NONE;
}
/*
* associated with the next key.
*/
int table_next_r(table_t *table_p, table_linear_t *linear_p,
- void **key_buf_p, int *key_size_p,
- void **data_buf_p, int *data_size_p)
+ void **key_buf_p, int *key_size_p,
+ void **data_buf_p, int *data_size_p)
{
- table_entry_t *entry_p;
- int error;
-
- if (table_p == NULL) {
- return TABLE_ERROR_ARG_NULL;
- }
- if (table_p->ta_magic != TABLE_MAGIC) {
- return TABLE_ERROR_PNT;
- }
- if (linear_p == NULL) {
- return TABLE_ERROR_ARG_NULL;
- }
- if (linear_p->tl_magic != LINEAR_MAGIC) {
- return TABLE_ERROR_LINEAR;
- }
-
- /* move to the next entry */
- entry_p = next_entry(table_p, linear_p, &error);
- if (entry_p == NULL) {
- return error;
- }
-
- SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p));
- SET_POINTER(key_size_p, entry_p->te_key_size);
- if (data_buf_p != NULL) {
- if (entry_p->te_data_size == 0) {
- *data_buf_p = NULL;
- }
- else {
- if (table_p->ta_data_align == 0) {
- *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
- }
- else {
- *data_buf_p = entry_data_buf(table_p, entry_p);
- }
- }
- }
- SET_POINTER(data_size_p, entry_p->te_data_size);
-
- return TABLE_ERROR_NONE;
+ table_entry_t *entry_p;
+ int error;
+
+ if (table_p == NULL) {
+ return TABLE_ERROR_ARG_NULL;
+ }
+ if (table_p->ta_magic != TABLE_MAGIC) {
+ return TABLE_ERROR_PNT;
+ }
+ if (linear_p == NULL) {
+ return TABLE_ERROR_ARG_NULL;
+ }
+ if (linear_p->tl_magic != LINEAR_MAGIC) {
+ return TABLE_ERROR_LINEAR;
+ }
+
+ /* move to the next entry */
+ entry_p = next_entry(table_p, linear_p, &error);
+ if (entry_p == NULL) {
+ return error;
+ }
+
+ SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p));
+ SET_POINTER(key_size_p, entry_p->te_key_size);
+ if (data_buf_p != NULL) {
+ if (entry_p->te_data_size == 0) {
+ *data_buf_p = NULL;
+ }
+ else {
+ if (table_p->ta_data_align == 0) {
+ *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
+ }
+ else {
+ *data_buf_p = entry_data_buf(table_p, entry_p);
+ }
+ }
+ }
+ SET_POINTER(data_size_p, entry_p->te_data_size);
+
+ return TABLE_ERROR_NONE;
}
/*
* associated with the current key.
*/
int table_this_r(table_t *table_p, table_linear_t *linear_p,
- void **key_buf_p, int *key_size_p,
- void **data_buf_p, int *data_size_p)
+ void **key_buf_p, int *key_size_p,
+ void **data_buf_p, int *data_size_p)
{
- table_entry_t *entry_p;
- int entry_c;
-
- if (table_p == NULL) {
- return TABLE_ERROR_ARG_NULL;
- }
- if (table_p->ta_magic != TABLE_MAGIC) {
- return TABLE_ERROR_PNT;
- }
- if (linear_p->tl_magic != LINEAR_MAGIC) {
- return TABLE_ERROR_LINEAR;
- }
-
- /* if we removed an item that shorted the bucket list, we may get this */
- if (linear_p->tl_bucket_c >= table_p->ta_bucket_n) {
- /*
- * NOTE: this might happen if we delete an item which shortens the
- * table bucket numbers.
- */
- return TABLE_ERROR_NOT_FOUND;
- }
-
- /* find the entry which is the nth in the list */
- for (entry_c = linear_p->tl_entry_c,
- entry_p = table_p->ta_buckets[linear_p->tl_bucket_c];
- entry_p != NULL && entry_c > 0;
- entry_c--, entry_p = TABLE_POINTER(table_p, table_entry_t *,
- entry_p)->te_next_p) {
- }
-
- if (entry_p == NULL) {
- return TABLE_ERROR_NOT_FOUND;
- }
-
- SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p));
- SET_POINTER(key_size_p, entry_p->te_key_size);
- if (data_buf_p != NULL) {
- if (entry_p->te_data_size == 0) {
- *data_buf_p = NULL;
- }
- else {
- if (table_p->ta_data_align == 0) {
- *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
- }
- else {
- *data_buf_p = entry_data_buf(table_p, entry_p);
- }
- }
- }
- SET_POINTER(data_size_p, entry_p->te_data_size);
-
- return TABLE_ERROR_NONE;
+ table_entry_t *entry_p;
+ int entry_c;
+
+ if (table_p == NULL) {
+ return TABLE_ERROR_ARG_NULL;
+ }
+ if (table_p->ta_magic != TABLE_MAGIC) {
+ return TABLE_ERROR_PNT;
+ }
+ if (linear_p->tl_magic != LINEAR_MAGIC) {
+ return TABLE_ERROR_LINEAR;
+ }
+
+ /* if we removed an item that shorted the bucket list, we may get this */
+ if (linear_p->tl_bucket_c >= table_p->ta_bucket_n) {
+ /*
+ * NOTE: this might happen if we delete an item which shortens the
+ * table bucket numbers.
+ */
+ return TABLE_ERROR_NOT_FOUND;
+ }
+
+ /* find the entry which is the nth in the list */
+ for (entry_c = linear_p->tl_entry_c,
+ entry_p = table_p->ta_buckets[linear_p->tl_bucket_c];
+ entry_p != NULL && entry_c > 0;
+ entry_c--, entry_p = TABLE_POINTER(table_p, table_entry_t *,
+ entry_p)->te_next_p) {
+ }
+
+ if (entry_p == NULL) {
+ return TABLE_ERROR_NOT_FOUND;
+ }
+
+ SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p));
+ SET_POINTER(key_size_p, entry_p->te_key_size);
+ if (data_buf_p != NULL) {
+ if (entry_p->te_data_size == 0) {
+ *data_buf_p = NULL;
+ }
+ else {
+ if (table_p->ta_data_align == 0) {
+ *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
+ }
+ else {
+ *data_buf_p = entry_data_buf(table_p, entry_p);
+ }
+ }
+ }
+ SET_POINTER(data_size_p, entry_p->te_data_size);
+
+ return TABLE_ERROR_NONE;
}
/******************************* mmap routines *******************************/
{
#ifdef NO_MMAP
- /* no mmap support so immediate error */
- SET_POINTER(error_p, TABLE_ERROR_MMAP_NONE);
- return NULL;
+ /* no mmap support so immediate error */
+ SET_POINTER(error_p, TABLE_ERROR_MMAP_NONE);
+ return NULL;
#else
- table_t *table_p;
- struct stat sbuf;
- int fd, state;
-
- table_p = (table_t *)malloc(sizeof(table_t));
- if (table_p == NULL) {
- SET_POINTER(error_p, TABLE_ERROR_ALLOC);
- return NULL;
- }
-
- /* open the mmap file */
- fd = open(path, O_RDONLY, 0);
- if (fd < 0) {
- free(table_p);
- SET_POINTER(error_p, TABLE_ERROR_OPEN);
- return NULL;
- }
-
- /* get the file size */
- if (fstat(fd, &sbuf) != 0) {
- free(table_p);
- SET_POINTER(error_p, TABLE_ERROR_OPEN);
- return NULL;
- }
-
- /* mmap the space and close the file */
+ table_t *table_p;
+ struct stat sbuf;
+ int fd, state;
+
+ table_p = (table_t *)malloc(sizeof(table_t));
+ if (table_p == NULL) {
+ SET_POINTER(error_p, TABLE_ERROR_ALLOC);
+ return NULL;
+ }
+
+ /* open the mmap file */
+ fd = open(path, O_RDONLY, 0);
+ if (fd < 0) {
+ free(table_p);
+ SET_POINTER(error_p, TABLE_ERROR_OPEN);
+ return NULL;
+ }
+
+ /* get the file size */
+ if (fstat(fd, &sbuf) != 0) {
+ free(table_p);
+ SET_POINTER(error_p, TABLE_ERROR_OPEN);
+ return NULL;
+ }
+
+ /* mmap the space and close the file */
#ifdef __alpha
- state = (MAP_SHARED | MAP_FILE | MAP_VARIABLE);
+ state = (MAP_SHARED | MAP_FILE | MAP_VARIABLE);
#else
- state = MAP_SHARED;
+ state = MAP_SHARED;
#endif
- table_p->ta_mmap = (table_t *)mmap((caddr_t)0, sbuf.st_size, PROT_READ,
- state, fd, 0);
- (void)close(fd);
-
- if (table_p->ta_mmap == (table_t *)MAP_FAILED) {
- SET_POINTER(error_p, TABLE_ERROR_MMAP);
- return NULL;
- }
-
- /* is the mmap file contain bad info or maybe another system type? */
- if (table_p->ta_mmap->ta_magic != TABLE_MAGIC) {
- SET_POINTER(error_p, TABLE_ERROR_PNT);
- return NULL;
- }
-
- /* sanity check on the file size */
- if (table_p->ta_mmap->ta_file_size != sbuf.st_size) {
- SET_POINTER(error_p, TABLE_ERROR_SIZE);
- return NULL;
- }
-
- /* copy the fields out of the mmap file into our memory version */
- table_p->ta_magic = TABLE_MAGIC;
- table_p->ta_flags = table_p->ta_mmap->ta_flags;
- table_p->ta_bucket_n = table_p->ta_mmap->ta_bucket_n;
- table_p->ta_entry_n = table_p->ta_mmap->ta_entry_n;
- table_p->ta_data_align = table_p->ta_mmap->ta_data_align;
- table_p->ta_buckets = TABLE_POINTER(table_p, table_entry_t **,
- table_p->ta_mmap->ta_buckets);
- table_p->ta_linear.tl_magic = 0;
- table_p->ta_linear.tl_bucket_c = 0;
- table_p->ta_linear.tl_entry_c = 0;
- /* mmap is already set */
- table_p->ta_file_size = table_p->ta_mmap->ta_file_size;
-
- SET_POINTER(error_p, TABLE_ERROR_NONE);
- return table_p;
+ table_p->ta_mmap = (table_t *)mmap((caddr_t)0, sbuf.st_size, PROT_READ,
+ state, fd, 0);
+ (void)close(fd);
+
+ if (table_p->ta_mmap == (table_t *)MAP_FAILED) {
+ SET_POINTER(error_p, TABLE_ERROR_MMAP);
+ return NULL;
+ }
+
+ /* is the mmap file contain bad info or maybe another system type? */
+ if (table_p->ta_mmap->ta_magic != TABLE_MAGIC) {
+ SET_POINTER(error_p, TABLE_ERROR_PNT);
+ return NULL;
+ }
+
+ /* sanity check on the file size */
+ if (table_p->ta_mmap->ta_file_size != sbuf.st_size) {
+ SET_POINTER(error_p, TABLE_ERROR_SIZE);
+ return NULL;
+ }
+
+ /* copy the fields out of the mmap file into our memory version */
+ table_p->ta_magic = TABLE_MAGIC;
+ table_p->ta_flags = table_p->ta_mmap->ta_flags;
+ table_p->ta_bucket_n = table_p->ta_mmap->ta_bucket_n;
+ table_p->ta_entry_n = table_p->ta_mmap->ta_entry_n;
+ table_p->ta_data_align = table_p->ta_mmap->ta_data_align;
+ table_p->ta_buckets = TABLE_POINTER(table_p, table_entry_t **,
+ table_p->ta_mmap->ta_buckets);
+ table_p->ta_linear.tl_magic = 0;
+ table_p->ta_linear.tl_bucket_c = 0;
+ table_p->ta_linear.tl_entry_c = 0;
+ /* mmap is already set */
+ table_p->ta_file_size = table_p->ta_mmap->ta_file_size;
+
+ SET_POINTER(error_p, TABLE_ERROR_NONE);
+ return table_p;
#endif
}
{
#ifdef NO_MMAP
- /* no mmap support so immediate error */
- return TABLE_ERROR_MMAP_NONE;
+ /* no mmap support so immediate error */
+ return TABLE_ERROR_MMAP_NONE;
#else
- if (table_p == NULL) {
- return TABLE_ERROR_ARG_NULL;
- }
- if (table_p->ta_magic != TABLE_MAGIC) {
- return TABLE_ERROR_PNT;
- }
- if (table_p->ta_mmap == NULL) {
- return TABLE_ERROR_PNT;
- }
-
- (void)munmap((caddr_t)table_p->ta_mmap, table_p->ta_file_size);
- table_p->ta_magic = 0;
- free(table_p);
- return TABLE_ERROR_NONE;
+ if (table_p == NULL) {
+ return TABLE_ERROR_ARG_NULL;
+ }
+ if (table_p->ta_magic != TABLE_MAGIC) {
+ return TABLE_ERROR_PNT;
+ }
+ if (table_p->ta_mmap == NULL) {
+ return TABLE_ERROR_PNT;
+ }
+
+ (void)munmap((caddr_t)table_p->ta_mmap, table_p->ta_file_size);
+ table_p->ta_magic = 0;
+ free(table_p);
+ return TABLE_ERROR_NONE;
#endif
}
*/
table_t *table_read(const char *path, int *error_p)
{
- unsigned int size;
- int fd, ent_size;
- FILE *infile;
- table_entry_t entry, **bucket_p, *entry_p = NULL, *last_p;
- unsigned long pos;
- table_t *table_p;
-
- /* open the file */
- fd = open(path, O_RDONLY, 0);
- if (fd < 0) {
- SET_POINTER(error_p, TABLE_ERROR_OPEN);
- return NULL;
- }
-
- /* allocate a table structure */
- table_p = malloc(sizeof(table_t));
- if (table_p == NULL) {
- SET_POINTER(error_p, TABLE_ERROR_ALLOC);
- return NULL;
- }
-
- /* now open the fd to get buffered i/o */
- infile = fdopen(fd, "r");
- if (infile == NULL) {
- SET_POINTER(error_p, TABLE_ERROR_OPEN);
- return NULL;
- }
-
- /* read the main table struct */
- if (fread(table_p, sizeof(table_t), 1, infile) != 1) {
- SET_POINTER(error_p, TABLE_ERROR_READ);
- free(table_p);
- return NULL;
- }
- table_p->ta_file_size = 0;
-
- /* is the mmap file contain bad info or maybe another system type? */
- if (table_p->ta_magic != TABLE_MAGIC) {
- SET_POINTER(error_p, TABLE_ERROR_PNT);
- return NULL;
- }
-
- /* allocate the buckets */
- table_p->ta_buckets = (table_entry_t **)calloc(table_p->ta_bucket_n,
- sizeof(table_entry_t *));
- if (table_p->ta_buckets == NULL) {
- SET_POINTER(error_p, TABLE_ERROR_ALLOC);
- free(table_p);
- return NULL;
- }
-
- if (fread(table_p->ta_buckets, sizeof(table_entry_t *), table_p->ta_bucket_n,
- infile) != (size_t)table_p->ta_bucket_n) {
- SET_POINTER(error_p, TABLE_ERROR_READ);
- free(table_p->ta_buckets);
- free(table_p);
- return NULL;
- }
-
- /* read in the entries */
- for (bucket_p = table_p->ta_buckets;
- bucket_p < table_p->ta_buckets + table_p->ta_bucket_n;
- bucket_p++) {
+ unsigned int size;
+ int fd, ent_size;
+ FILE *infile;
+ table_entry_t entry, **bucket_p, *entry_p = NULL, *last_p;
+ unsigned long pos;
+ table_t *table_p;
+
+ /* open the file */
+ fd = open(path, O_RDONLY, 0);
+ if (fd < 0) {
+ SET_POINTER(error_p, TABLE_ERROR_OPEN);
+ return NULL;
+ }
+
+ /* allocate a table structure */
+ table_p = malloc(sizeof(table_t));
+ if (table_p == NULL) {
+ SET_POINTER(error_p, TABLE_ERROR_ALLOC);
+ return NULL;
+ }
+
+ /* now open the fd to get buffered i/o */
+ infile = fdopen(fd, "r");
+ if (infile == NULL) {
+ SET_POINTER(error_p, TABLE_ERROR_OPEN);
+ return NULL;
+ }
+
+ /* read the main table struct */
+ if (fread(table_p, sizeof(table_t), 1, infile) != 1) {
+ SET_POINTER(error_p, TABLE_ERROR_READ);
+ free(table_p);
+ return NULL;
+ }
+ table_p->ta_file_size = 0;
+
+ /* is the mmap file contain bad info or maybe another system type? */
+ if (table_p->ta_magic != TABLE_MAGIC) {
+ SET_POINTER(error_p, TABLE_ERROR_PNT);
+ return NULL;
+ }
+
+ /* allocate the buckets */
+ table_p->ta_buckets = (table_entry_t **)calloc(table_p->ta_bucket_n,
+ sizeof(table_entry_t *));
+ if (table_p->ta_buckets == NULL) {
+ SET_POINTER(error_p, TABLE_ERROR_ALLOC);
+ free(table_p);
+ return NULL;
+ }
+
+ if (fread(table_p->ta_buckets, sizeof(table_entry_t *), table_p->ta_bucket_n,
+ infile) != (size_t)table_p->ta_bucket_n) {
+ SET_POINTER(error_p, TABLE_ERROR_READ);
+ free(table_p->ta_buckets);
+ free(table_p);
+ return NULL;
+ }
+
+ /* read in the entries */
+ for (bucket_p = table_p->ta_buckets;
+ bucket_p < table_p->ta_buckets + table_p->ta_bucket_n;
+ bucket_p++) {
- /* skip null buckets */
- if (*bucket_p == NULL) {
- continue;
- }
+ /* skip null buckets */
+ if (*bucket_p == NULL) {
+ continue;
+ }
- /* run through the entry list */
- last_p = NULL;
- for (pos = *(unsigned long *)bucket_p;;
- pos = (unsigned long)entry_p->te_next_p) {
+ /* run through the entry list */
+ last_p = NULL;
+ for (pos = *(unsigned long *)bucket_p;;
+ pos = (unsigned long)entry_p->te_next_p) {
- /* read in the entry */
- if (fseek(infile, pos, SEEK_SET) != 0) {
- SET_POINTER(error_p, TABLE_ERROR_SEEK);
- free(table_p->ta_buckets);
- free(table_p);
- if (entry_p != NULL) {
- free(entry_p);
- }
- /* the other table elements will not be freed */
- return NULL;
- }
- if (fread(&entry, sizeof(struct table_shell_st), 1, infile) != 1) {
- SET_POINTER(error_p, TABLE_ERROR_READ);
- free(table_p->ta_buckets);
- free(table_p);
- if (entry_p != NULL) {
- free(entry_p);
- }
- /* the other table elements will not be freed */
- return NULL;
- }
+ /* read in the entry */
+ if (fseek(infile, pos, SEEK_SET) != 0) {
+ SET_POINTER(error_p, TABLE_ERROR_SEEK);
+ free(table_p->ta_buckets);
+ free(table_p);
+ if (entry_p != NULL) {
+ free(entry_p);
+ }
+ /* the other table elements will not be freed */
+ return NULL;
+ }
+ if (fread(&entry, sizeof(struct table_shell_st), 1, infile) != 1) {
+ SET_POINTER(error_p, TABLE_ERROR_READ);
+ free(table_p->ta_buckets);
+ free(table_p);
+ if (entry_p != NULL) {
+ free(entry_p);
+ }
+ /* the other table elements will not be freed */
+ return NULL;
+ }
- /* make a new entry */
- ent_size = entry_size(table_p, entry.te_key_size, entry.te_data_size);
- entry_p = (table_entry_t *)malloc(ent_size);
- if (entry_p == NULL) {
- SET_POINTER(error_p, TABLE_ERROR_ALLOC);
- free(table_p->ta_buckets);
- free(table_p);
- /* the other table elements will not be freed */
- return NULL;
- }
- entry_p->te_key_size = entry.te_key_size;
- entry_p->te_data_size = entry.te_data_size;
- entry_p->te_next_p = entry.te_next_p;
+ /* make a new entry */
+ ent_size = entry_size(table_p, entry.te_key_size, entry.te_data_size);
+ entry_p = (table_entry_t *)malloc(ent_size);
+ if (entry_p == NULL) {
+ SET_POINTER(error_p, TABLE_ERROR_ALLOC);
+ free(table_p->ta_buckets);
+ free(table_p);
+ /* the other table elements will not be freed */
+ return NULL;
+ }
+ entry_p->te_key_size = entry.te_key_size;
+ entry_p->te_data_size = entry.te_data_size;
+ entry_p->te_next_p = entry.te_next_p;
- if (last_p == NULL) {
- *bucket_p = entry_p;
- }
- else {
- last_p->te_next_p = entry_p;
- }
+ if (last_p == NULL) {
+ *bucket_p = entry_p;
+ }
+ else {
+ last_p->te_next_p = entry_p;
+ }
- /* determine how much more we have to read */
- size = ent_size - sizeof(struct table_shell_st);
- if (fread(ENTRY_KEY_BUF(entry_p), sizeof(char), size, infile) != size) {
- SET_POINTER(error_p, TABLE_ERROR_READ);
- free(table_p->ta_buckets);
- free(table_p);
- free(entry_p);
- /* the other table elements will not be freed */
- return NULL;
- }
+ /* determine how much more we have to read */
+ size = ent_size - sizeof(struct table_shell_st);
+ if (fread(ENTRY_KEY_BUF(entry_p), sizeof(char), size, infile) != size) {
+ SET_POINTER(error_p, TABLE_ERROR_READ);
+ free(table_p->ta_buckets);
+ free(table_p);
+ free(entry_p);
+ /* the other table elements will not be freed */
+ return NULL;
+ }
- /* we are done if the next pointer is null */
- if (entry_p->te_next_p == (unsigned long)0) {
- break;
- }
- last_p = entry_p;
- }
- }
-
- (void)fclose(infile);
-
- SET_POINTER(error_p, TABLE_ERROR_NONE);
- return table_p;
+ /* we are done if the next pointer is null */
+ if (entry_p->te_next_p == (unsigned long)0) {
+ break;
+ }
+ last_p = entry_p;
+ }
+ }
+
+ (void)fclose(infile);
+
+ SET_POINTER(error_p, TABLE_ERROR_NONE);
+ return table_p;
}
/*
*/
int table_write(const table_t *table_p, const char *path, const int mode)
{
- int fd, rem, ent_size;
- unsigned int bucket_c, bucket_size;
- unsigned long size;
- table_entry_t *entry_p, **buckets, **bucket_p, *next_p;
- table_t main_tab;
- FILE *outfile;
-
- if (table_p == NULL) {
- return TABLE_ERROR_ARG_NULL;
- }
- if (table_p->ta_magic != TABLE_MAGIC) {
- return TABLE_ERROR_PNT;
- }
-
- fd = open(path, O_WRONLY | O_CREAT, mode);
- if (fd < 0) {
- return TABLE_ERROR_OPEN;
- }
-
- outfile = fdopen(fd, "w");
- if (outfile == NULL) {
- return TABLE_ERROR_OPEN;
- }
-
- /* allocate a block of sizes for each bucket */
- bucket_size = sizeof(table_entry_t *) * table_p->ta_bucket_n;
- if (table_p->ta_alloc_func == NULL) {
- buckets = (table_entry_t **)malloc(bucket_size);
- }
- else {
- buckets =
- (table_entry_t **)table_p->ta_alloc_func(table_p->ta_mem_pool,
- bucket_size);
- }
- if (buckets == NULL) {
- return TABLE_ERROR_ALLOC;
- }
-
- /* make a copy of the main struct */
- main_tab = *table_p;
-
- /* start counting the bytes */
- size = 0;
- size += sizeof(table_t);
-
- /* buckets go right after main struct */
- main_tab.ta_buckets = (table_entry_t **)size;
- size += sizeof(table_entry_t *) * table_p->ta_bucket_n;
-
- /* run through and count the buckets */
- for (bucket_c = 0; bucket_c < table_p->ta_bucket_n; bucket_c++) {
- bucket_p = table_p->ta_buckets + bucket_c;
- if (*bucket_p == NULL) {
- buckets[bucket_c] = NULL;
- continue;
- }
- buckets[bucket_c] = (table_entry_t *)size;
- for (entry_p = *bucket_p; entry_p != NULL; entry_p = entry_p->te_next_p) {
- size += entry_size(table_p, entry_p->te_key_size, entry_p->te_data_size);
- /*
- * We now have to round the file to the nearest long so the
- * mmaping of the longs in the entry structs will work.
- */
- rem = size & (sizeof(long) - 1);
- if (rem > 0) {
- size += sizeof(long) - rem;
- }
- }
- }
- /* add a \0 at the end to fill the last section */
- size++;
-
- /* set the main fields */
- main_tab.ta_linear.tl_magic = 0;
- main_tab.ta_linear.tl_bucket_c = 0;
- main_tab.ta_linear.tl_entry_c = 0;
- main_tab.ta_mmap = NULL;
- main_tab.ta_file_size = size;
-
- /*
- * Now we can start the writing because we got the bucket offsets.
- */
-
- /* write the main table struct */
- size = 0;
- if (fwrite(&main_tab, sizeof(table_t), 1, outfile) != 1) {
- if (table_p->ta_free_func == NULL) {
- free(buckets);
- }
- else {
- (void)table_p->ta_free_func(table_p->ta_mem_pool, buckets, bucket_size);
- }
- return TABLE_ERROR_WRITE;
- }
- size += sizeof(table_t);
- if (fwrite(buckets, sizeof(table_entry_t *), table_p->ta_bucket_n,
- outfile) != (size_t)table_p->ta_bucket_n) {
- if (table_p->ta_free_func == NULL) {
- free(buckets);
- }
- else {
- (void)table_p->ta_free_func(table_p->ta_mem_pool, buckets, bucket_size);
- }
- return TABLE_ERROR_WRITE;
- }
- size += sizeof(table_entry_t *) * table_p->ta_bucket_n;
-
- /* write out the entries */
- for (bucket_p = table_p->ta_buckets;
- bucket_p < table_p->ta_buckets + table_p->ta_bucket_n;
- bucket_p++) {
- for (entry_p = *bucket_p; entry_p != NULL; entry_p = entry_p->te_next_p) {
-
- ent_size = entry_size(table_p, entry_p->te_key_size,
- entry_p->te_data_size);
- size += ent_size;
- /* round to nearest long here so we can write copy */
- rem = size & (sizeof(long) - 1);
- if (rem > 0) {
- size += sizeof(long) - rem;
- }
- next_p = entry_p->te_next_p;
- if (next_p != NULL) {
- entry_p->te_next_p = (table_entry_t *)size;
- }
-
- /* now write to disk */
- if (fwrite(entry_p, ent_size, 1, outfile) != 1) {
- if (table_p->ta_free_func == NULL) {
- free(buckets);
+ int fd, rem, ent_size;
+ unsigned int bucket_c, bucket_size;
+ unsigned long size;
+ table_entry_t *entry_p, **buckets, **bucket_p, *next_p;
+ table_t main_tab;
+ FILE *outfile;
+
+ if (table_p == NULL) {
+ return TABLE_ERROR_ARG_NULL;
+ }
+ if (table_p->ta_magic != TABLE_MAGIC) {
+ return TABLE_ERROR_PNT;
+ }
+
+ fd = open(path, O_WRONLY | O_CREAT, mode);
+ if (fd < 0) {
+ return TABLE_ERROR_OPEN;
+ }
+
+ outfile = fdopen(fd, "w");
+ if (outfile == NULL) {
+ return TABLE_ERROR_OPEN;
+ }
+
+ /* allocate a block of sizes for each bucket */
+ bucket_size = sizeof(table_entry_t *) * table_p->ta_bucket_n;
+ if (table_p->ta_alloc_func == NULL) {
+ buckets = (table_entry_t **)malloc(bucket_size);
}
else {
- (void)table_p->ta_free_func(table_p->ta_mem_pool, buckets,
- bucket_size);
+ buckets =
+ (table_entry_t **)table_p->ta_alloc_func(table_p->ta_mem_pool,
+ bucket_size);
+ }
+ if (buckets == NULL) {
+ return TABLE_ERROR_ALLOC;
+ }
+
+ /* make a copy of the main struct */
+ main_tab = *table_p;
+
+ /* start counting the bytes */
+ size = 0;
+ size += sizeof(table_t);
+
+ /* buckets go right after main struct */
+ main_tab.ta_buckets = (table_entry_t **)size;
+ size += sizeof(table_entry_t *) * table_p->ta_bucket_n;
+
+ /* run through and count the buckets */
+ for (bucket_c = 0; bucket_c < table_p->ta_bucket_n; bucket_c++) {
+ bucket_p = table_p->ta_buckets + bucket_c;
+ if (*bucket_p == NULL) {
+ buckets[bucket_c] = NULL;
+ continue;
+ }
+ buckets[bucket_c] = (table_entry_t *)size;
+ for (entry_p = *bucket_p; entry_p != NULL; entry_p = entry_p->te_next_p) {
+ size += entry_size(table_p, entry_p->te_key_size, entry_p->te_data_size);
+ /*
+ * We now have to round the file to the nearest long so the
+ * mmaping of the longs in the entry structs will work.
+ */
+ rem = size & (sizeof(long) - 1);
+ if (rem > 0) {
+ size += sizeof(long) - rem;
+ }
+ }
}
- return TABLE_ERROR_WRITE;
- }
+ /* add a \0 at the end to fill the last section */
+ size++;
+
+ /* set the main fields */
+ main_tab.ta_linear.tl_magic = 0;
+ main_tab.ta_linear.tl_bucket_c = 0;
+ main_tab.ta_linear.tl_entry_c = 0;
+ main_tab.ta_mmap = NULL;
+ main_tab.ta_file_size = size;
+
+ /*
+ * Now we can start the writing because we got the bucket offsets.
+ */
+
+ /* write the main table struct */
+ size = 0;
+ if (fwrite(&main_tab, sizeof(table_t), 1, outfile) != 1) {
+ if (table_p->ta_free_func == NULL) {
+ free(buckets);
+ }
+ else {
+ (void)table_p->ta_free_func(table_p->ta_mem_pool, buckets, bucket_size);
+ }
+ return TABLE_ERROR_WRITE;
+ }
+ size += sizeof(table_t);
+ if (fwrite(buckets, sizeof(table_entry_t *), table_p->ta_bucket_n,
+ outfile) != (size_t)table_p->ta_bucket_n) {
+ if (table_p->ta_free_func == NULL) {
+ free(buckets);
+ }
+ else {
+ (void)table_p->ta_free_func(table_p->ta_mem_pool, buckets, bucket_size);
+ }
+ return TABLE_ERROR_WRITE;
+ }
+ size += sizeof(table_entry_t *) * table_p->ta_bucket_n;
+
+ /* write out the entries */
+ for (bucket_p = table_p->ta_buckets;
+ bucket_p < table_p->ta_buckets + table_p->ta_bucket_n;
+ bucket_p++) {
+ for (entry_p = *bucket_p; entry_p != NULL; entry_p = entry_p->te_next_p) {
+
+ ent_size = entry_size(table_p, entry_p->te_key_size,
+ entry_p->te_data_size);
+ size += ent_size;
+ /* round to nearest long here so we can write copy */
+ rem = size & (sizeof(long) - 1);
+ if (rem > 0) {
+ size += sizeof(long) - rem;
+ }
+ next_p = entry_p->te_next_p;
+ if (next_p != NULL) {
+ entry_p->te_next_p = (table_entry_t *)size;
+ }
- /* restore the next pointer */
- if (next_p != NULL) {
- entry_p->te_next_p = next_p;
- }
+ /* now write to disk */
+ if (fwrite(entry_p, ent_size, 1, outfile) != 1) {
+ if (table_p->ta_free_func == NULL) {
+ free(buckets);
+ }
+ else {
+ (void)table_p->ta_free_func(table_p->ta_mem_pool, buckets,
+ bucket_size);
+ }
+ return TABLE_ERROR_WRITE;
+ }
- /* now write the padding information */
- if (rem > 0) {
- rem = sizeof(long) - rem;
+ /* restore the next pointer */
+ if (next_p != NULL) {
+ entry_p->te_next_p = next_p;
+ }
+
+ /* now write the padding information */
+ if (rem > 0) {
+ rem = sizeof(long) - rem;
+ /*
+ * NOTE: this won't leave fseek'd space at the end but we
+ * don't care there because there is no accessed memory
+ * afterwards. We write 1 \0 at the end to make sure.
+ */
+ if (fseek(outfile, rem, SEEK_CUR) != 0) {
+ if (table_p->ta_free_func == NULL) {
+ free(buckets);
+ }
+ else {
+ (void)table_p->ta_free_func(table_p->ta_mem_pool, buckets,
+ bucket_size);
+ }
+ return TABLE_ERROR_SEEK;
+ }
+ }
+ }
+ }
/*
- * NOTE: this won't leave fseek'd space at the end but we
- * don't care there because there is no accessed memory
- * afterwards. We write 1 \0 at the end to make sure.
+ * Write a \0 at the end of the file to make sure that the last
+ * fseek filled with nulls.
*/
- if (fseek(outfile, rem, SEEK_CUR) != 0) {
- if (table_p->ta_free_func == NULL) {
- free(buckets);
- }
- else {
- (void)table_p->ta_free_func(table_p->ta_mem_pool, buckets,
- bucket_size);
- }
- return TABLE_ERROR_SEEK;
- }
- }
- }
- }
- /*
- * Write a \0 at the end of the file to make sure that the last
- * fseek filled with nulls.
- */
- (void)fputc('\0', outfile);
-
- (void)fclose(outfile);
- if (table_p->ta_free_func == NULL) {
- free(buckets);
- }
- else if (! table_p->ta_free_func(table_p->ta_mem_pool, buckets,
- bucket_size)) {
- return TABLE_ERROR_FREE;
- }
-
- return TABLE_ERROR_NONE;
+ (void)fputc('\0', outfile);
+
+ (void)fclose(outfile);
+ if (table_p->ta_free_func == NULL) {
+ free(buckets);
+ }
+ else if (! table_p->ta_free_func(table_p->ta_mem_pool, buckets,
+ bucket_size)) {
+ return TABLE_ERROR_FREE;
+ }
+
+ return TABLE_ERROR_NONE;
}
/******************************** table order ********************************/
* table error code.
*/
table_entry_t **table_order(table_t *table_p, table_compare_t compare,
- int *num_entries_p, int *error_p)
+ int *num_entries_p, int *error_p)
{
- table_entry_t *entry_p, **entries, **entries_p;
- table_linear_t linear;
- compare_t comp_func;
- unsigned int entries_size;
- int ret;
-
- if (table_p == NULL) {
- SET_POINTER(error_p, TABLE_ERROR_ARG_NULL);
- return NULL;
- }
- if (table_p->ta_magic != TABLE_MAGIC) {
- SET_POINTER(error_p, TABLE_ERROR_PNT);
- return NULL;
- }
-
- /* there must be at least 1 element in the table for this to work */
- if (table_p->ta_entry_n == 0) {
- SET_POINTER(error_p, TABLE_ERROR_EMPTY);
- return NULL;
- }
-
- entries_size = table_p->ta_entry_n * sizeof(table_entry_t *);
- if (table_p->ta_alloc_func == NULL) {
- entries = (table_entry_t **)malloc(entries_size);
- }
- else {
- entries =
- (table_entry_t **)table_p->ta_alloc_func(table_p->ta_mem_pool,
- entries_size);
- }
- if (entries == NULL) {
- SET_POINTER(error_p, TABLE_ERROR_ALLOC);
- return NULL;
- }
-
- /* get a pointer to all entries */
- entry_p = first_entry(table_p, &linear);
- if (entry_p == NULL) {
- if (table_p->ta_free_func == NULL) {
- free(entries);
- }
- else {
- (void)table_p->ta_free_func(table_p->ta_mem_pool, entries, entries_size);
- }
- SET_POINTER(error_p, TABLE_ERROR_NOT_FOUND);
- return NULL;
- }
-
- /* add all of the entries to the array */
- for (entries_p = entries;
- entry_p != NULL;
- entry_p = next_entry(table_p, &linear, &ret)) {
- *entries_p++ = entry_p;
- }
-
- if (ret != TABLE_ERROR_NOT_FOUND) {
- if (table_p->ta_free_func == NULL) {
- free(entries);
- }
- else {
- (void)table_p->ta_free_func(table_p->ta_mem_pool, entries, entries_size);
- }
- SET_POINTER(error_p, ret);
- return NULL;
- }
-
- if (compare == NULL) {
- /* this is regardless of the alignment */
- comp_func = local_compare;
- }
- else if (table_p->ta_data_align == 0) {
- comp_func = external_compare;
- }
- else {
- comp_func = external_compare_align;
- }
-
- /* now qsort the entire entries array from first to last element */
- ret = split((unsigned char *)entries,
- (unsigned char *)(entries + table_p->ta_entry_n - 1),
- sizeof(table_entry_t *), comp_func, compare, table_p);
- if (ret != TABLE_ERROR_NONE) {
- if (table_p->ta_free_func == NULL) {
- free(entries);
- }
- else {
- (void)table_p->ta_free_func(table_p->ta_mem_pool, entries, entries_size);
- }
- SET_POINTER(error_p, ret);
- return NULL;
- }
-
- SET_POINTER(num_entries_p, table_p->ta_entry_n);
-
- SET_POINTER(error_p, TABLE_ERROR_NONE);
- return entries;
+ table_entry_t *entry_p, **entries, **entries_p;
+ table_linear_t linear;
+ compare_t comp_func;
+ unsigned int entries_size;
+ int ret;
+
+ if (table_p == NULL) {
+ SET_POINTER(error_p, TABLE_ERROR_ARG_NULL);
+ return NULL;
+ }
+ if (table_p->ta_magic != TABLE_MAGIC) {
+ SET_POINTER(error_p, TABLE_ERROR_PNT);
+ return NULL;
+ }
+
+ /* there must be at least 1 element in the table for this to work */
+ if (table_p->ta_entry_n == 0) {
+ SET_POINTER(error_p, TABLE_ERROR_EMPTY);
+ return NULL;
+ }
+
+ entries_size = table_p->ta_entry_n * sizeof(table_entry_t *);
+ if (table_p->ta_alloc_func == NULL) {
+ entries = (table_entry_t **)malloc(entries_size);
+ }
+ else {
+ entries =
+ (table_entry_t **)table_p->ta_alloc_func(table_p->ta_mem_pool,
+ entries_size);
+ }
+ if (entries == NULL) {
+ SET_POINTER(error_p, TABLE_ERROR_ALLOC);
+ return NULL;
+ }
+
+ /* get a pointer to all entries */
+ entry_p = first_entry(table_p, &linear);
+ if (entry_p == NULL) {
+ if (table_p->ta_free_func == NULL) {
+ free(entries);
+ }
+ else {
+ (void)table_p->ta_free_func(table_p->ta_mem_pool, entries, entries_size);
+ }
+ SET_POINTER(error_p, TABLE_ERROR_NOT_FOUND);
+ return NULL;
+ }
+
+ /* add all of the entries to the array */
+ for (entries_p = entries;
+ entry_p != NULL;
+ entry_p = next_entry(table_p, &linear, &ret)) {
+ *entries_p++ = entry_p;
+ }
+
+ if (ret != TABLE_ERROR_NOT_FOUND) {
+ if (table_p->ta_free_func == NULL) {
+ free(entries);
+ }
+ else {
+ (void)table_p->ta_free_func(table_p->ta_mem_pool, entries, entries_size);
+ }
+ SET_POINTER(error_p, ret);
+ return NULL;
+ }
+
+ if (compare == NULL) {
+ /* this is regardless of the alignment */
+ comp_func = local_compare;
+ }
+ else if (table_p->ta_data_align == 0) {
+ comp_func = external_compare;
+ }
+ else {
+ comp_func = external_compare_align;
+ }
+
+ /* now qsort the entire entries array from first to last element */
+ ret = split((unsigned char *)entries,
+ (unsigned char *)(entries + table_p->ta_entry_n - 1),
+ sizeof(table_entry_t *), comp_func, compare, table_p);
+ if (ret != TABLE_ERROR_NONE) {
+ if (table_p->ta_free_func == NULL) {
+ free(entries);
+ }
+ else {
+ (void)table_p->ta_free_func(table_p->ta_mem_pool, entries, entries_size);
+ }
+ SET_POINTER(error_p, ret);
+ return NULL;
+ }
+
+ SET_POINTER(num_entries_p, table_p->ta_entry_n);
+
+ SET_POINTER(error_p, TABLE_ERROR_NONE);
+ return entries;
}
/*
* table_order or table_order_pos in num_entries_p.
*/
int table_order_free(table_t *table_p, table_entry_t **table_entries,
- const int entry_n)
+ const int entry_n)
{
- int ret, final = TABLE_ERROR_NONE;
-
- if (table_p == NULL) {
- return TABLE_ERROR_ARG_NULL;
- }
- if (table_p->ta_magic != TABLE_MAGIC) {
- return TABLE_ERROR_PNT;
- }
-
- if (table_p->ta_free_func == NULL) {
- free(table_entries);
- }
- else {
- ret = table_p->ta_free_func(table_p->ta_mem_pool, table_entries,
- sizeof(table_entry_t *) * entry_n);
- if (ret != 1) {
- final = TABLE_ERROR_FREE;
- }
- }
-
- return final;
+ int ret, final = TABLE_ERROR_NONE;
+
+ if (table_p == NULL) {
+ return TABLE_ERROR_ARG_NULL;
+ }
+ if (table_p->ta_magic != TABLE_MAGIC) {
+ return TABLE_ERROR_PNT;
+ }
+
+ if (table_p->ta_free_func == NULL) {
+ free(table_entries);
+ }
+ else {
+ ret = table_p->ta_free_func(table_p->ta_mem_pool, table_entries,
+ sizeof(table_entry_t *) * entry_n);
+ if (ret != 1) {
+ final = TABLE_ERROR_FREE;
+ }
+ }
+
+ return final;
}
/*
* to the size of the data that is stored in the table.
*/
int table_entry(table_t *table_p, table_entry_t *entry_p,
- void **key_buf_p, int *key_size_p,
- void **data_buf_p, int *data_size_p)
+ void **key_buf_p, int *key_size_p,
+ void **data_buf_p, int *data_size_p)
{
- if (table_p == NULL) {
- return TABLE_ERROR_ARG_NULL;
- }
- if (table_p->ta_magic != TABLE_MAGIC) {
- return TABLE_ERROR_PNT;
- }
- if (entry_p == NULL) {
- return TABLE_ERROR_ARG_NULL;
- }
-
- SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p));
- SET_POINTER(key_size_p, entry_p->te_key_size);
- if (data_buf_p != NULL) {
- if (entry_p->te_data_size == 0) {
- *data_buf_p = NULL;
- }
- else {
- if (table_p->ta_data_align == 0) {
- *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
- }
- else {
- *data_buf_p = entry_data_buf(table_p, entry_p);
- }
- }
- }
- SET_POINTER(data_size_p, entry_p->te_data_size);
-
- return TABLE_ERROR_NONE;
+ if (table_p == NULL) {
+ return TABLE_ERROR_ARG_NULL;
+ }
+ if (table_p->ta_magic != TABLE_MAGIC) {
+ return TABLE_ERROR_PNT;
+ }
+ if (entry_p == NULL) {
+ return TABLE_ERROR_ARG_NULL;
+ }
+
+ SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p));
+ SET_POINTER(key_size_p, entry_p->te_key_size);
+ if (data_buf_p != NULL) {
+ if (entry_p->te_data_size == 0) {
+ *data_buf_p = NULL;
+ }
+ else {
+ if (table_p->ta_data_align == 0) {
+ *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
+ }
+ else {
+ *data_buf_p = entry_data_buf(table_p, entry_p);
+ }
+ }
+ }
+ SET_POINTER(data_size_p, entry_p->te_data_size);
+
+ return TABLE_ERROR_NONE;
}
/*
* table error code.
*/
table_linear_t *table_order_pos(table_t *table_p, table_compare_t compare,
- int *num_entries_p, int *error_p)
+ int *num_entries_p, int *error_p)
{
- table_entry_t *entry_p;
- table_linear_t linear, *linears, *linears_p;
- compare_t comp_func;
- int ret;
-
- if (table_p == NULL) {
- SET_POINTER(error_p, TABLE_ERROR_ARG_NULL);
- return NULL;
- }
- if (table_p->ta_magic != TABLE_MAGIC) {
- SET_POINTER(error_p, TABLE_ERROR_PNT);
- return NULL;
- }
-
- /* there must be at least 1 element in the table for this to work */
- if (table_p->ta_entry_n == 0) {
- SET_POINTER(error_p, TABLE_ERROR_EMPTY);
- return NULL;
- }
-
- if (table_p->ta_alloc_func == NULL) {
- linears = (table_linear_t *)malloc(table_p->ta_entry_n *
- sizeof(table_linear_t));
- }
- else {
- linears =
- (table_linear_t *)table_p->ta_alloc_func(table_p->ta_mem_pool,
- table_p->ta_entry_n *
- sizeof(table_linear_t));
- }
- if (linears == NULL) {
- SET_POINTER(error_p, TABLE_ERROR_ALLOC);
- return NULL;
- }
-
- /* get a pointer to all entries */
- entry_p = first_entry(table_p, &linear);
- if (entry_p == NULL) {
- SET_POINTER(error_p, TABLE_ERROR_NOT_FOUND);
- return NULL;
- }
-
- /* add all of the entries to the array */
- for (linears_p = linears;
- entry_p != NULL;
- entry_p = next_entry(table_p, &linear, &ret)) {
- *linears_p++ = linear;
- }
-
- if (ret != TABLE_ERROR_NOT_FOUND) {
- SET_POINTER(error_p, ret);
- return NULL;
- }
-
- if (compare == NULL) {
- /* this is regardless of the alignment */
- comp_func = local_compare_pos;
- }
- else if (table_p->ta_data_align == 0) {
- comp_func = external_compare_pos;
- }
- else {
- comp_func = external_compare_align_pos;
- }
-
- /* now qsort the entire entries array from first to last element */
- split((unsigned char *)linears,
- (unsigned char *)(linears + table_p->ta_entry_n - 1),
- sizeof(table_linear_t), comp_func, compare, table_p);
-
- if (num_entries_p != NULL) {
- *num_entries_p = table_p->ta_entry_n;
- }
-
- SET_POINTER(error_p, TABLE_ERROR_NONE);
- return linears;
+ table_entry_t *entry_p;
+ table_linear_t linear, *linears, *linears_p;
+ compare_t comp_func;
+ int ret;
+
+ if (table_p == NULL) {
+ SET_POINTER(error_p, TABLE_ERROR_ARG_NULL);
+ return NULL;
+ }
+ if (table_p->ta_magic != TABLE_MAGIC) {
+ SET_POINTER(error_p, TABLE_ERROR_PNT);
+ return NULL;
+ }
+
+ /* there must be at least 1 element in the table for this to work */
+ if (table_p->ta_entry_n == 0) {
+ SET_POINTER(error_p, TABLE_ERROR_EMPTY);
+ return NULL;
+ }
+
+ if (table_p->ta_alloc_func == NULL) {
+ linears = (table_linear_t *)malloc(table_p->ta_entry_n *
+ sizeof(table_linear_t));
+ }
+ else {
+ linears =
+ (table_linear_t *)table_p->ta_alloc_func(table_p->ta_mem_pool,
+ table_p->ta_entry_n *
+ sizeof(table_linear_t));
+ }
+ if (linears == NULL) {
+ SET_POINTER(error_p, TABLE_ERROR_ALLOC);
+ return NULL;
+ }
+
+ /* get a pointer to all entries */
+ entry_p = first_entry(table_p, &linear);
+ if (entry_p == NULL) {
+ SET_POINTER(error_p, TABLE_ERROR_NOT_FOUND);
+ return NULL;
+ }
+
+ /* add all of the entries to the array */
+ for (linears_p = linears;
+ entry_p != NULL;
+ entry_p = next_entry(table_p, &linear, &ret)) {
+ *linears_p++ = linear;
+ }
+
+ if (ret != TABLE_ERROR_NOT_FOUND) {
+ SET_POINTER(error_p, ret);
+ return NULL;
+ }
+
+ if (compare == NULL) {
+ /* this is regardless of the alignment */
+ comp_func = local_compare_pos;
+ }
+ else if (table_p->ta_data_align == 0) {
+ comp_func = external_compare_pos;
+ }
+ else {
+ comp_func = external_compare_align_pos;
+ }
+
+ /* now qsort the entire entries array from first to last element */
+ split((unsigned char *)linears,
+ (unsigned char *)(linears + table_p->ta_entry_n - 1),
+ sizeof(table_linear_t), comp_func, compare, table_p);
+
+ if (num_entries_p != NULL) {
+ *num_entries_p = table_p->ta_entry_n;
+ }
+
+ SET_POINTER(error_p, TABLE_ERROR_NONE);
+ return linears;
}
/*
* table_order or table_order_pos in num_entries_p.
*/
int table_order_pos_free(table_t *table_p, table_linear_t *table_entries,
- const int entry_n)
+ const int entry_n)
{
- int ret, final = TABLE_ERROR_NONE;
-
- if (table_p == NULL) {
- return TABLE_ERROR_ARG_NULL;
- }
- if (table_p->ta_magic != TABLE_MAGIC) {
- return TABLE_ERROR_PNT;
- }
-
- if (table_p->ta_free_func == NULL) {
- free(table_entries);
- }
- else {
- ret = table_p->ta_free_func(table_p->ta_mem_pool, table_entries,
- sizeof(table_linear_t) * entry_n);
- if (ret != 1) {
- final = TABLE_ERROR_FREE;
- }
- }
-
- return final;
+ int ret, final = TABLE_ERROR_NONE;
+
+ if (table_p == NULL) {
+ return TABLE_ERROR_ARG_NULL;
+ }
+ if (table_p->ta_magic != TABLE_MAGIC) {
+ return TABLE_ERROR_PNT;
+ }
+
+ if (table_p->ta_free_func == NULL) {
+ free(table_entries);
+ }
+ else {
+ ret = table_p->ta_free_func(table_p->ta_mem_pool, table_entries,
+ sizeof(table_linear_t) * entry_n);
+ if (ret != 1) {
+ final = TABLE_ERROR_FREE;
+ }
+ }
+
+ return final;
}
/*
* to the size of the data that is stored in the table.
*/
int table_entry_pos(table_t *table_p, table_linear_t *linear_p,
- void **key_buf_p, int *key_size_p,
- void **data_buf_p, int *data_size_p)
+ void **key_buf_p, int *key_size_p,
+ void **data_buf_p, int *data_size_p)
{
- table_entry_t *entry_p;
- int ret;
-
- if (table_p == NULL) {
- return TABLE_ERROR_ARG_NULL;
- }
- if (table_p->ta_magic != TABLE_MAGIC) {
- return TABLE_ERROR_PNT;
- }
- if (linear_p == NULL) {
- return TABLE_ERROR_ARG_NULL;
- }
-
- /* find the associated entry */
- entry_p = this_entry(table_p, linear_p, &ret);
- if (entry_p == NULL) {
- return ret;
- }
-
- if (key_buf_p != NULL) {
- *key_buf_p = ENTRY_KEY_BUF(entry_p);
- }
- if (key_size_p != NULL) {
- *key_size_p = entry_p->te_key_size;
- }
- if (data_buf_p != NULL) {
- if (entry_p->te_data_size == 0) {
- *data_buf_p = NULL;
- }
- else {
- if (table_p->ta_data_align == 0) {
- *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
- }
- else {
- *data_buf_p = entry_data_buf(table_p, entry_p);
- }
- }
- }
- if (data_size_p != NULL) {
- *data_size_p = entry_p->te_data_size;
- }
-
- return TABLE_ERROR_NONE;
+ table_entry_t *entry_p;
+ int ret;
+
+ if (table_p == NULL) {
+ return TABLE_ERROR_ARG_NULL;
+ }
+ if (table_p->ta_magic != TABLE_MAGIC) {
+ return TABLE_ERROR_PNT;
+ }
+ if (linear_p == NULL) {
+ return TABLE_ERROR_ARG_NULL;
+ }
+
+ /* find the associated entry */
+ entry_p = this_entry(table_p, linear_p, &ret);
+ if (entry_p == NULL) {
+ return ret;
+ }
+
+ if (key_buf_p != NULL) {
+ *key_buf_p = ENTRY_KEY_BUF(entry_p);
+ }
+ if (key_size_p != NULL) {
+ *key_size_p = entry_p->te_key_size;
+ }
+ if (data_buf_p != NULL) {
+ if (entry_p->te_data_size == 0) {
+ *data_buf_p = NULL;
+ }
+ else {
+ if (table_p->ta_data_align == 0) {
+ *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
+ }
+ else {
+ *data_buf_p = entry_data_buf(table_p, entry_p);
+ }
+ }
+ }
+ if (data_size_p != NULL) {
+ *data_size_p = entry_p->te_data_size;
+ }
+
+ return TABLE_ERROR_NONE;
}
/*
*/
const char *table_strerror(const int error)
{
- error_str_t *err_p;
+ error_str_t *err_p;
- for (err_p = errors; err_p->es_error != 0; err_p++) {
- if (err_p->es_error == error) {
- return err_p->es_string;
- }
- }
+ for (err_p = errors; err_p->es_error != 0; err_p++) {
+ if (err_p->es_error == error) {
+ return err_p->es_string;
+ }
+ }
- return INVALID_ERROR;
+ return INVALID_ERROR;
}
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
+ */
#include "table.h"
static char *rcs_id =
- "$Id: table_util.c,v 1.5 2000/03/09 03:30:42 gray Exp $";
+ "$Id: table_util.c,v 1.5 2000/03/09 03:30:42 gray Exp $";
#define WRITE_MODE 0640 /* mode to write out table */
#define SPECIAL_CHARS "e\033^^\"\"''\\\\n\nr\rt\tb\bf\fa\007"
* out_size - size of the output buffer.
*/
int expand_chars(const void *buf, const int buf_size,
- char *out, const int out_size)
+ char *out, const int out_size)
{
- int buf_c;
- const unsigned char *buf_p, *spec_p;
- char *max_p, *out_p = out;
+ int buf_c;
+ const unsigned char *buf_p, *spec_p;
+ char *max_p, *out_p = out;
- /* setup our max pointer */
- max_p = out + out_size;
+ /* setup our max pointer */
+ max_p = out + out_size;
- /* run through the input buffer, counting the characters as we go */
- for (buf_c = 0, buf_p = (const unsigned char *)buf;; buf_c++, buf_p++) {
+ /* run through the input buffer, counting the characters as we go */
+ for (buf_c = 0, buf_p = (const unsigned char *)buf;; buf_c++, buf_p++) {
- /* did we reach the end of the buffer? */
- if (buf_size < 0) {
- if (*buf_p == '\0') {
- break;
- }
- }
- else {
- if (buf_c >= buf_size) {
- break;
- }
- }
+ /* did we reach the end of the buffer? */
+ if (buf_size < 0) {
+ if (*buf_p == '\0') {
+ break;
+ }
+ }
+ else {
+ if (buf_c >= buf_size) {
+ break;
+ }
+ }
- /* search for special characters */
- for (spec_p = (unsigned char *)SPECIAL_CHARS + 1;
- *(spec_p - 1) != '\0';
- spec_p += 2) {
- if (*spec_p == *buf_p) {
- break;
- }
- }
+ /* search for special characters */
+ for (spec_p = (unsigned char *)SPECIAL_CHARS + 1;
+ *(spec_p - 1) != '\0';
+ spec_p += 2) {
+ if (*spec_p == *buf_p) {
+ break;
+ }
+ }
- /* did we find one? */
- if (*(spec_p - 1) != '\0') {
- if (out_p + 2 >= max_p) {
- break;
- }
- (void)sprintf(out_p, "\\%c", *(spec_p - 1));
- out_p += 2;
- continue;
- }
+ /* did we find one? */
+ if (*(spec_p - 1) != '\0') {
+ if (out_p + 2 >= max_p) {
+ break;
+ }
+ (void)sprintf(out_p, "\\%c", *(spec_p - 1));
+ out_p += 2;
+ continue;
+ }
- /* print out any 7-bit printable characters */
- if (*buf_p < 128 && isprint(*buf_p)) {
- if (out_p + 1 >= max_p) {
- break;
- }
- *out_p = *(char *)buf_p;
- out_p += 1;
- }
- else {
- if (out_p + 4 >= max_p) {
- break;
- }
- (void)sprintf(out_p, "\\%03o", *buf_p);
- out_p += 4;
- }
- }
+ /* print out any 7-bit printable characters */
+ if (*buf_p < 128 && isprint(*buf_p)) {
+ if (out_p + 1 >= max_p) {
+ break;
+ }
+ *out_p = *(char *)buf_p;
+ out_p += 1;
+ }
+ else {
+ if (out_p + 4 >= max_p) {
+ break;
+ }
+ (void)sprintf(out_p, "\\%03o", *buf_p);
+ out_p += 4;
+ }
+ }
- return out_p - out;
+ return out_p - out;
}
/*
*/
static void dump_table(table_t *tab_p)
{
- char buf[10240];
- void *key_p, *data_p;
- int ret, key_size, data_size, len, entry_c;
+ char buf[10240];
+ void *key_p, *data_p;
+ int ret, key_size, data_size, len, entry_c;
- for (ret = table_first(tab_p, (void **)&key_p, &key_size,
- (void **)&data_p, &data_size), entry_c = 0;
- ret == TABLE_ERROR_NONE;
- ret = table_next(tab_p, (void **)&key_p, &key_size,
- (void **)&data_p, &data_size), entry_c++) {
- /* expand the key */
- len = expand_chars(key_p, key_size, buf, sizeof(buf));
- (void)printf("%d: key '%.*s' (%d), ", entry_c, len, buf, len);
- /* now dump the data */
- len = expand_chars(data_p, data_size, buf, sizeof(buf));
- (void)printf("data '%.*s' (%d)\n", len, buf, len);
- }
+ for (ret = table_first(tab_p, (void **)&key_p, &key_size,
+ (void **)&data_p, &data_size), entry_c = 0;
+ ret == TABLE_ERROR_NONE;
+ ret = table_next(tab_p, (void **)&key_p, &key_size,
+ (void **)&data_p, &data_size), entry_c++) {
+ /* expand the key */
+ len = expand_chars(key_p, key_size, buf, sizeof(buf));
+ (void)printf("%d: key '%.*s' (%d), ", entry_c, len, buf, len);
+ /* now dump the data */
+ len = expand_chars(data_p, data_size, buf, sizeof(buf));
+ (void)printf("data '%.*s' (%d)\n", len, buf, len);
+ }
}
/*
*/
static void usage(void)
{
- (void)fprintf(stderr,
- "Usage: table_util\n"
- " [-b number] or --buckets num buckets to adjust table\n"
- " [-o file] or --out-file output filename\n"
- " [-v] or --verbose verbose messages\n"
- " file input table filename\n");
- exit(1);
+ (void)fprintf(stderr,
+ "Usage: table_util\n"
+ " [-b number] or --buckets num buckets to adjust table\n"
+ " [-o file] or --out-file output filename\n"
+ " [-v] or --verbose verbose messages\n"
+ " file input table filename\n");
+ exit(1);
}
int main(int argc, char **argv)
{
- table_t *tab_p;
- char do_write = 0, verbose = 0;
- char *out_file = NULL, *in_file;
- int ret, entry_n, bucket_n, num_buckets = 0;
+ table_t *tab_p;
+ char do_write = 0, verbose = 0;
+ char *out_file = NULL, *in_file;
+ int ret, entry_n, bucket_n, num_buckets = 0;
- /* process the args */
- for (argc--, argv++; argc > 0 && **argv == '-'; argc--, argv++) {
+ /* process the args */
+ for (argc--, argv++; argc > 0 && **argv == '-'; argc--, argv++) {
- switch (*(*argv + 1)) {
+ switch (*(*argv + 1)) {
- case 'b':
- argc--, argv++;
- if (argc == 0) {
- usage();
- }
- num_buckets = atoi(*argv);
- break;
+ case 'b':
+ argc--, argv++;
+ if (argc == 0) {
+ usage();
+ }
+ num_buckets = atoi(*argv);
+ break;
- case 'o':
- argc--, argv++;
- if (argc == 0) {
- usage();
- }
- out_file = *argv;
- break;
+ case 'o':
+ argc--, argv++;
+ if (argc == 0) {
+ usage();
+ }
+ out_file = *argv;
+ break;
- case 'v':
- verbose = 1;
- break;
+ case 'v':
+ verbose = 1;
+ break;
- default:
- usage();
- break;
- }
- }
+ default:
+ usage();
+ break;
+ }
+ }
- if (argc != 1) {
- usage();
- }
+ if (argc != 1) {
+ usage();
+ }
- /* take the last argument as the input file */
- in_file = *argv;
+ /* take the last argument as the input file */
+ in_file = *argv;
- /* read in the table from disk */
- tab_p = table_read(in_file, &ret);
- if (tab_p == NULL) {
- (void)fprintf(stderr, "table_util: unable to table_read from '%s': %s\n",
- in_file, table_strerror(ret));
- exit(1);
- }
+ /* read in the table from disk */
+ tab_p = table_read(in_file, &ret);
+ if (tab_p == NULL) {
+ (void)fprintf(stderr, "table_util: unable to table_read from '%s': %s\n",
+ in_file, table_strerror(ret));
+ exit(1);
+ }
- /* get info about the table */
- ret = table_info(tab_p, &bucket_n, &entry_n);
- if (ret != TABLE_ERROR_NONE) {
- (void)fprintf(stderr,
- "table_util: unable to get info on table in '%s': %s\n",
- in_file, table_strerror(ret));
- exit(1);
- }
+ /* get info about the table */
+ ret = table_info(tab_p, &bucket_n, &entry_n);
+ if (ret != TABLE_ERROR_NONE) {
+ (void)fprintf(stderr,
+ "table_util: unable to get info on table in '%s': %s\n",
+ in_file, table_strerror(ret));
+ exit(1);
+ }
- (void)printf("Read table of %d buckets and %d entries from '%s'\n",
- bucket_n, entry_n, in_file);
+ (void)printf("Read table of %d buckets and %d entries from '%s'\n",
+ bucket_n, entry_n, in_file);
- if (verbose) {
- dump_table(tab_p);
- }
+ if (verbose) {
+ dump_table(tab_p);
+ }
- if (num_buckets > 0) {
- /* adjust the table's buckets */
- ret = table_adjust(tab_p, num_buckets);
- if (ret != TABLE_ERROR_NONE) {
- (void)fprintf(stderr,
- "table_util: unable to adjust table to %d buckets: %s\n",
- num_buckets, table_strerror(ret));
- exit(1);
- }
- do_write = 1;
- }
+ if (num_buckets > 0) {
+ /* adjust the table's buckets */
+ ret = table_adjust(tab_p, num_buckets);
+ if (ret != TABLE_ERROR_NONE) {
+ (void)fprintf(stderr,
+ "table_util: unable to adjust table to %d buckets: %s\n",
+ num_buckets, table_strerror(ret));
+ exit(1);
+ }
+ do_write = 1;
+ }
- /* did we modify the table at all */
- if (do_write) {
- if (out_file == NULL) {
- out_file = in_file;
- }
+ /* did we modify the table at all */
+ if (do_write) {
+ if (out_file == NULL) {
+ out_file = in_file;
+ }
- /* write out our table */
- ret = table_write(tab_p, out_file, WRITE_MODE);
- if (ret != TABLE_ERROR_NONE) {
- (void)fprintf(stderr, "table_util: unable to write table to '%s': %s\n",
- out_file, table_strerror(ret));
- exit(1);
- }
+ /* write out our table */
+ ret = table_write(tab_p, out_file, WRITE_MODE);
+ if (ret != TABLE_ERROR_NONE) {
+ (void)fprintf(stderr, "table_util: unable to write table to '%s': %s\n",
+ out_file, table_strerror(ret));
+ exit(1);
+ }
- (void)printf("Wrote table to '%s'\n", out_file);
- }
+ (void)printf("Wrote table to '%s'\n", out_file);
+ }
- /* free the table */
- ret = table_free(tab_p);
- if (ret != TABLE_ERROR_NONE) {
- (void)fprintf(stderr, "table_util: unable to free table: %s\n",
- table_strerror(ret));
- /* NOTE: not a critical error */
- }
+ /* free the table */
+ ret = table_free(tab_p);
+ if (ret != TABLE_ERROR_NONE) {
+ (void)fprintf(stderr, "table_util: unable to free table: %s\n",
+ table_strerror(ret));
+ /* NOTE: not a critical error */
+ }
- exit(0);
+ exit(0);
}
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
+ */