pmt: initial 3.0.2 update
This commit is contained in:
344
include/libgnulib/gl_oset.h
Executable file
344
include/libgnulib/gl_oset.h
Executable file
@@ -0,0 +1,344 @@
|
||||
/* Abstract ordered set data type.
|
||||
Copyright (C) 2006-2007, 2009-2024 Free Software Foundation, Inc.
|
||||
Written by Bruno Haible <bruno@clisp.org>, 2006.
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation; either version 2.1 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _GL_OSET_H
|
||||
#define _GL_OSET_H
|
||||
|
||||
/* This file uses _GL_INLINE_HEADER_BEGIN, _GL_INLINE,
|
||||
_GL_ATTRIBUTE_NODISCARD. */
|
||||
#if !_GL_CONFIG_H_INCLUDED
|
||||
#error "Please include config.h first."
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
_GL_INLINE_HEADER_BEGIN
|
||||
#ifndef GL_OSET_INLINE
|
||||
# define GL_OSET_INLINE _GL_INLINE
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* gl_oset is an abstract ordered set data type. It can contain any number
|
||||
of objects ('void *' or 'const void *' pointers) in the order of a given
|
||||
comparator function. Duplicates (in the sense of the comparator) are
|
||||
forbidden.
|
||||
|
||||
There are several implementations of this ordered set datatype, optimized
|
||||
for different operations or for memory. You can start using the simplest
|
||||
ordered set implementation, GL_ARRAY_OSET, and switch to a different
|
||||
implementation later, when you realize which operations are performed
|
||||
the most frequently. The API of the different implementations is exactly
|
||||
the same; when switching to a different implementation, you only have to
|
||||
change the gl_oset_create call.
|
||||
|
||||
The implementations are:
|
||||
GL_ARRAY_OSET a growable array
|
||||
GL_AVLTREE_OSET a binary tree (AVL tree)
|
||||
GL_RBTREE_OSET a binary tree (red-black tree)
|
||||
|
||||
The memory consumption is asymptotically the same: O(1) for every object
|
||||
in the set. When looking more closely at the average memory consumed
|
||||
for an object, GL_ARRAY_OSET is the most compact representation, and
|
||||
GL_AVLTREE_OSET, GL_RBTREE_OSET need more memory.
|
||||
|
||||
The guaranteed average performance of the operations is, for a set of
|
||||
n elements:
|
||||
|
||||
Operation ARRAY TREE
|
||||
|
||||
gl_oset_size O(1) O(1)
|
||||
gl_oset_add O(n) O(log n)
|
||||
gl_oset_remove O(n) O(log n)
|
||||
gl_oset_update O(n) O(log n)
|
||||
gl_oset_search O(log n) O(log n)
|
||||
gl_oset_search_atleast O(log n) O(log n)
|
||||
gl_oset_iterator O(1) O(log n)
|
||||
gl_oset_iterator_atleast O(log n) O(log n)
|
||||
gl_oset_iterator_next O(1) O(log n)
|
||||
*/
|
||||
|
||||
/* -------------------------- gl_oset_t Data Type -------------------------- */
|
||||
|
||||
/* Type of function used to compare two elements. Same as for qsort().
|
||||
NULL denotes pointer comparison. */
|
||||
typedef int (*gl_setelement_compar_fn) (const void *elt1, const void *elt2);
|
||||
|
||||
#ifndef _GL_SETELEMENT_DISPOSE_FN_DEFINED
|
||||
/* Type of function used to dispose an element once it's removed from a set.
|
||||
NULL denotes a no-op. */
|
||||
typedef void (*gl_setelement_dispose_fn) (const void *elt);
|
||||
# define _GL_SETELEMENT_DISPOSE_FN_DEFINED 1
|
||||
#endif
|
||||
|
||||
/* Type of function used to compare an element with a threshold.
|
||||
Returns true if the element is greater or equal than the threshold. */
|
||||
typedef bool (*gl_setelement_threshold_fn) (const void *elt, const void *threshold);
|
||||
|
||||
struct gl_oset_impl;
|
||||
/* Type representing an entire ordered set. */
|
||||
typedef struct gl_oset_impl * gl_oset_t;
|
||||
|
||||
struct gl_oset_implementation;
|
||||
/* Type representing a ordered set datatype implementation. */
|
||||
typedef const struct gl_oset_implementation * gl_oset_implementation_t;
|
||||
|
||||
#if 0 /* Unless otherwise specified, these are defined inline below. */
|
||||
|
||||
/* Creates an empty set.
|
||||
IMPLEMENTATION is one of GL_ARRAY_OSET, GL_AVLTREE_OSET, GL_RBTREE_OSET.
|
||||
COMPAR_FN is an element comparison function or NULL.
|
||||
DISPOSE_FN is an element disposal function or NULL. */
|
||||
/* declared in gl_xoset.h */
|
||||
extern gl_oset_t gl_oset_create_empty (gl_oset_implementation_t implementation,
|
||||
gl_setelement_compar_fn compar_fn,
|
||||
gl_setelement_dispose_fn dispose_fn)
|
||||
/*_GL_ATTRIBUTE_DEALLOC (gl_oset_free, 1)*/
|
||||
_GL_ATTRIBUTE_RETURNS_NONNULL;
|
||||
/* Likewise. Returns NULL upon out-of-memory. */
|
||||
extern gl_oset_t gl_oset_nx_create_empty (gl_oset_implementation_t implementation,
|
||||
gl_setelement_compar_fn compar_fn,
|
||||
gl_setelement_dispose_fn dispose_fn)
|
||||
/*_GL_ATTRIBUTE_DEALLOC (gl_oset_free, 1)*/;
|
||||
|
||||
/* Returns the current number of elements in an ordered set. */
|
||||
extern size_t gl_oset_size (gl_oset_t set);
|
||||
|
||||
/* Searches whether an element is already in the ordered set.
|
||||
Returns true if found, or false if not present in the set. */
|
||||
extern bool gl_oset_search (gl_oset_t set, const void *elt);
|
||||
|
||||
/* Searches the least element in the ordered set that compares greater or equal
|
||||
to the given THRESHOLD. The representation of the THRESHOLD is defined
|
||||
by the THRESHOLD_FN.
|
||||
Returns true and stores the found element in *ELTP if found, otherwise returns
|
||||
false. */
|
||||
extern bool gl_oset_search_atleast (gl_oset_t set,
|
||||
gl_setelement_threshold_fn threshold_fn,
|
||||
const void *threshold,
|
||||
const void **eltp);
|
||||
|
||||
/* Adds an element to an ordered set.
|
||||
Returns true if it was not already in the set and added, false otherwise. */
|
||||
/* declared in gl_xoset.h */
|
||||
extern bool gl_oset_add (gl_oset_t set, const void *elt);
|
||||
|
||||
/* Likewise. Returns -1 upon out-of-memory. */
|
||||
_GL_ATTRIBUTE_NODISCARD
|
||||
extern int gl_oset_nx_add (gl_oset_t set, const void *elt);
|
||||
|
||||
/* Removes an element from an ordered set.
|
||||
Returns true if it was found and removed. */
|
||||
extern bool gl_oset_remove (gl_oset_t set, const void *elt);
|
||||
|
||||
/* Invokes ACTION (ELT, ACTION_DATA) and updates the given ordered set if,
|
||||
during this invocation, the attributes/properties of the element ELT change
|
||||
in a way that influences the comparison function.
|
||||
Warning: During the invocation of ACTION, the ordered set is inconsistent
|
||||
and must not be accessed!
|
||||
Returns 1 if the position of the element in the ordered set has changed as
|
||||
a consequence, 0 if the element stayed at the same position, or -1 if it
|
||||
collided with another element and was therefore removed. */
|
||||
extern int gl_oset_update (gl_oset_t set, const void *elt,
|
||||
void (*action) (const void *elt, void *action_data),
|
||||
void *action_data);
|
||||
|
||||
/* Frees an entire ordered set.
|
||||
(But this call does not free the elements of the set. It only invokes
|
||||
the DISPOSE_FN on each of the elements of the set.) */
|
||||
extern void gl_oset_free (gl_oset_t set);
|
||||
|
||||
#endif /* End of inline and gl_xoset.h-defined functions. */
|
||||
|
||||
/* --------------------- gl_oset_iterator_t Data Type --------------------- */
|
||||
|
||||
/* Functions for iterating through an ordered set. */
|
||||
|
||||
/* Type of an iterator that traverses an ordered set.
|
||||
This is a fixed-size struct, so that creation of an iterator doesn't need
|
||||
memory allocation on the heap. */
|
||||
typedef struct
|
||||
{
|
||||
/* For fast dispatch of gl_oset_iterator_next. */
|
||||
const struct gl_oset_implementation *vtable;
|
||||
/* For detecting whether the last returned element was removed. */
|
||||
gl_oset_t set;
|
||||
size_t count;
|
||||
/* Other, implementation-private fields. */
|
||||
void *p; void *q;
|
||||
size_t i; size_t j;
|
||||
} gl_oset_iterator_t;
|
||||
|
||||
#if 0 /* These are defined inline below. */
|
||||
|
||||
/* Creates an iterator traversing an ordered set.
|
||||
The set's contents must not be modified while the iterator is in use,
|
||||
except for removing the last returned element. */
|
||||
extern gl_oset_iterator_t gl_oset_iterator (gl_oset_t set);
|
||||
|
||||
/* Creates an iterator traversing the tail of an ordered set, that comprises
|
||||
the elements that compare greater or equal to the given THRESHOLD. The
|
||||
representation of the THRESHOLD is defined by the THRESHOLD_FN. */
|
||||
extern gl_oset_iterator_t gl_oset_iterator_atleast (gl_oset_t set,
|
||||
gl_setelement_threshold_fn threshold_fn,
|
||||
const void *threshold);
|
||||
|
||||
/* If there is a next element, stores the next element in *ELTP, advances the
|
||||
iterator and returns true. Otherwise, returns false. */
|
||||
extern bool gl_oset_iterator_next (gl_oset_iterator_t *iterator,
|
||||
const void **eltp);
|
||||
|
||||
/* Frees an iterator. */
|
||||
extern void gl_oset_iterator_free (gl_oset_iterator_t *iterator);
|
||||
|
||||
#endif /* End of inline functions. */
|
||||
|
||||
/* ------------------------ Implementation Details ------------------------ */
|
||||
|
||||
struct gl_oset_implementation
|
||||
{
|
||||
/* gl_oset_t functions. */
|
||||
gl_oset_t (*nx_create_empty) (gl_oset_implementation_t implementation,
|
||||
gl_setelement_compar_fn compar_fn,
|
||||
gl_setelement_dispose_fn dispose_fn);
|
||||
size_t (*size) (gl_oset_t set);
|
||||
bool (*search) (gl_oset_t set, const void *elt);
|
||||
bool (*search_atleast) (gl_oset_t set,
|
||||
gl_setelement_threshold_fn threshold_fn,
|
||||
const void *threshold, const void **eltp);
|
||||
int (*nx_add) (gl_oset_t set, const void *elt);
|
||||
bool (*remove_elt) (gl_oset_t set, const void *elt);
|
||||
int (*update) (gl_oset_t set, const void *elt,
|
||||
void (*action) (const void * /*elt*/, void * /*action_data*/),
|
||||
void *action_data);
|
||||
void (*oset_free) (gl_oset_t set);
|
||||
/* gl_oset_iterator_t functions. */
|
||||
gl_oset_iterator_t (*iterator) (gl_oset_t set);
|
||||
gl_oset_iterator_t (*iterator_atleast) (gl_oset_t set,
|
||||
gl_setelement_threshold_fn threshold_fn,
|
||||
const void *threshold);
|
||||
bool (*iterator_next) (gl_oset_iterator_t *iterator, const void **eltp);
|
||||
void (*iterator_free) (gl_oset_iterator_t *iterator);
|
||||
};
|
||||
|
||||
struct gl_oset_impl_base
|
||||
{
|
||||
const struct gl_oset_implementation *vtable;
|
||||
gl_setelement_compar_fn compar_fn;
|
||||
gl_setelement_dispose_fn dispose_fn;
|
||||
};
|
||||
|
||||
/* Define all functions of this file as accesses to the
|
||||
struct gl_oset_implementation. */
|
||||
|
||||
GL_OSET_INLINE
|
||||
/*_GL_ATTRIBUTE_DEALLOC (gl_oset_free, 1)*/
|
||||
gl_oset_t
|
||||
gl_oset_nx_create_empty (gl_oset_implementation_t implementation,
|
||||
gl_setelement_compar_fn compar_fn,
|
||||
gl_setelement_dispose_fn dispose_fn)
|
||||
{
|
||||
return implementation->nx_create_empty (implementation, compar_fn,
|
||||
dispose_fn);
|
||||
}
|
||||
|
||||
GL_OSET_INLINE size_t
|
||||
gl_oset_size (gl_oset_t set)
|
||||
{
|
||||
return ((const struct gl_oset_impl_base *) set)->vtable->size (set);
|
||||
}
|
||||
|
||||
GL_OSET_INLINE bool
|
||||
gl_oset_search (gl_oset_t set, const void *elt)
|
||||
{
|
||||
return ((const struct gl_oset_impl_base *) set)->vtable->search (set, elt);
|
||||
}
|
||||
|
||||
GL_OSET_INLINE bool
|
||||
gl_oset_search_atleast (gl_oset_t set,
|
||||
gl_setelement_threshold_fn threshold_fn,
|
||||
const void *threshold, const void **eltp)
|
||||
{
|
||||
return ((const struct gl_oset_impl_base *) set)->vtable
|
||||
->search_atleast (set, threshold_fn, threshold, eltp);
|
||||
}
|
||||
|
||||
_GL_ATTRIBUTE_NODISCARD GL_OSET_INLINE int
|
||||
gl_oset_nx_add (gl_oset_t set, const void *elt)
|
||||
{
|
||||
return ((const struct gl_oset_impl_base *) set)->vtable->nx_add (set, elt);
|
||||
}
|
||||
|
||||
GL_OSET_INLINE bool
|
||||
gl_oset_remove (gl_oset_t set, const void *elt)
|
||||
{
|
||||
return ((const struct gl_oset_impl_base *) set)->vtable
|
||||
->remove_elt (set, elt);
|
||||
}
|
||||
|
||||
GL_OSET_INLINE int
|
||||
gl_oset_update (gl_oset_t set, const void *elt,
|
||||
void (*action) (const void * /*elt*/, void * /*action_data*/),
|
||||
void *action_data)
|
||||
{
|
||||
return ((const struct gl_oset_impl_base *) set)->vtable
|
||||
->update (set, elt, action, action_data);
|
||||
}
|
||||
|
||||
GL_OSET_INLINE void
|
||||
gl_oset_free (gl_oset_t set)
|
||||
{
|
||||
((const struct gl_oset_impl_base *) set)->vtable->oset_free (set);
|
||||
}
|
||||
|
||||
GL_OSET_INLINE gl_oset_iterator_t
|
||||
gl_oset_iterator (gl_oset_t set)
|
||||
{
|
||||
return ((const struct gl_oset_impl_base *) set)->vtable->iterator (set);
|
||||
}
|
||||
|
||||
GL_OSET_INLINE gl_oset_iterator_t
|
||||
gl_oset_iterator_atleast (gl_oset_t set,
|
||||
gl_setelement_threshold_fn threshold_fn,
|
||||
const void *threshold)
|
||||
{
|
||||
return ((const struct gl_oset_impl_base *) set)->vtable
|
||||
->iterator_atleast (set, threshold_fn, threshold);
|
||||
}
|
||||
|
||||
GL_OSET_INLINE bool
|
||||
gl_oset_iterator_next (gl_oset_iterator_t *iterator, const void **eltp)
|
||||
{
|
||||
return iterator->vtable->iterator_next (iterator, eltp);
|
||||
}
|
||||
|
||||
GL_OSET_INLINE void
|
||||
gl_oset_iterator_free (gl_oset_iterator_t *iterator)
|
||||
{
|
||||
iterator->vtable->iterator_free (iterator);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
_GL_INLINE_HEADER_END
|
||||
|
||||
#endif /* _GL_OSET_H */
|
||||
Reference in New Issue
Block a user