debugging
[rrq/rrqmisc.git] / vector / vector.h
1 #ifndef vector_H
2 #define vector_H
3
4 /**
5  * A vector is a dynamic pointer array implemented as an access tree
6  * of index pages. The indexing is done using "unsigned long" indexes.
7  */
8
9 /*!
10  * Macro: VECTOR_LEVEL_BITS
11  * This defines the number of bits in the indexing bit field.
12  */
13 #define VECTOR_LEVEL_BITS 4
14
15 /*!
16  * Type: vector_index
17  * This is the general indexing used for vector access.
18  */
19 typedef unsigned long vector_index;
20
21 /*!
22  * Macro: VECTOR_INDEX_BITS
23  * This defines the number of bits of a vector index
24  */
25 #define VECTOR_INDEX_BITS ( sizeof( vector_index ) * 8 )
26
27 /*!
28  * Macro: VECTOR_INDEX_FIELDS
29  * This defines the number of bit fields in an vector index
30  */
31 #define VECTOR_INDEX_FIELDS \
32     ( ( VECTOR_INDEX_BITS - 1 ) / VECTOR_LEVEL_BITS + 1 )
33
34 /*!
35  * Macro: VECTOR_SLOTS
36  * This defines the number of slots spanned by an index level
37  */
38 #define VECTOR_SLOTS ( 1 << VECTOR_LEVEL_BITS )
39
40 /*!
41  * Type: vector_page
42  *
43  * A vector_page is an array of 16 void* items.
44  */
45 typedef void* vector_page[ VECTOR_SLOTS ];
46
47 /*!
48  * Type: vector
49  *
50  * A vector is a compound of a size and a vector_page pointer, which
51  * when non-null points out the top-most page of the vector. The
52  * number of levels is derived from its size with level 0 being the
53  * leaf level of actual content. E.g., a vector larger than 16
54  * items, has at least two levels, and generally N levels may span up
55  * to 16^N content entries.
56  */
57 typedef struct _vector {
58     vector_index size;     //!< Limit for the logical entries[]
59     vector_page *entries; //!< Pointer to entries indexing
60 } vector;
61
62 /*!
63  * Find the next used slot at given index or later. With a reclaim
64  * function, it will be invoked for verifying that the item is
65  * actually in use, in which case it returns 1. Otherwise it should
66  * reclaim any memory for the item and return 0;
67  */
68 void **vector_next_used(
69     vector *pv,vector_index *index,
70     int (*reclaim)(vector *pv,vector_index index,void *item,void *data),
71     void *data );
72
73 /*!
74  * Function: int vector_resize(
75  *              vector *pv,vector_index new_size,
76  *              int (*reclaim)(vector *,vector_index,void *item,void *data),
77  *              void *data )
78  * \param pv
79  * \param new_size
80  * \param reclaim
81  * \param data
82  *
83  * Tries to resize the given vector to a new size. This may result in
84  * the introduction or removal of indexing pages, so that the leveling
85  * is consistent with the vector size. Thus, if it grows into a new
86  * 16^N level, then one or more new upper level pages are inserted as
87  * needed. If it shrinks below the current level, then top-level pages
88  * are remove.
89  *
90  * Also, if the new size is smaller than currently, then the now
91  * excess tail of entries is scanned for any used slots and the given
92  * reclaim function is invoked successively for these. The reclaim
93  * function must, in addition to memory-managing the entry, return 0
94  * upon success and non-zero to veto the attempted vector size
95  * change. The data argument is passed on to the reclaim function.
96  *
97  * The vector_resize function returns 0 on success, with the size
98  * duly changed. Otherwise the function retains the current size and
99  * returns -index-1 for the index of the veto-ed entry.
100  */
101 int vector_resize(
102     vector *pv, vector_index new_size,
103     int (*reclaim)(vector *pv,vector_index index,void *item,void *data),
104     void *data );
105
106 /*!
107  * Function: void **vector_entry(vector *pv,vector_index index)
108  * \param pv - the vector record
109  * \param index - the slot index
110  *
111  * [pgix,epix] = modulo( index, pv->page );
112  *
113  * \returns a direct pointer to the slot of the given index in the
114  * array, or 0 if the index is beyond the array limits (0-limit). Note
115  * that slot pointers are only valid while the vector size is
116  * unchanged.
117  */
118 extern void **vector_entry(vector *pv,vector_index index); 
119
120 /*!
121  * Function: vector_index vector_size(vector *pv)
122  * \param pv - the vector record
123  * \returns the size of the vector.
124  */
125 inline vector_index vector_size(vector *pv) {
126     return pv->size;
127 }
128
129 void vector_set(vector *pv,vector_index index,void *value);
130
131 void *vector_get(vector *pv,vector_index index);
132
133 void vector_append(vector *pv,void *value);
134
135 void vector_copy(vector *dst,vector_index di,
136                   vector *src,vector_index si,vector_index n);
137
138 void vector_dump(vector *pv,
139                   int (*itemdump)(const vector_index ,const void *));
140
141 void vector_qsort(vector *pv,int (*compar)(const void *,const void *));
142
143 void vector_iterate(vector *pv,
144                      int (*itemfn)(vector_index,void*,void*),
145                      void*);
146
147 #endif