b41b151f19f5e1616fec110973a216bcc07ef36f
[rrq/rrqmisc.git] / pvector / pvector.h
1 #ifndef pvector_H
2 #define pvector_H
3
4 /**
5  * A pvector is a dynamic pointer array implemented as an access tree
6  * of index pages of 256 pointers.
7  */
8
9 //#include <stdint.h>
10
11 /*!
12  * Type: pvector_page
13  *
14  * A pvector_page is an array of 256 void* items.
15  */
16 typedef void* pvector_page[256];
17
18 /*!
19  * Type: pvector_index
20  *
21  * A pvector index is ether viewed in whole as an unsigned 64-bit
22  * integer, or in levels as 8 unsigned char level indexes. This
23  * implementation assumes LE integer layout.
24  */
25 typedef union {
26     unsigned long whole; // 64-bit unsigned integer
27     unsigned char level[8];
28 } pvector_index;
29
30 /*!
31  * Type: pvector
32  *
33  * A pvector is a compound of a size and a pvector_page pointer, which
34  * when non-null points out the top-most page of the pvector. The
35  * number of levels is derived from its size with level 0 being the
36  * leaf level of actual content. E.g., a pvector larger than 256
37  * items, has at least two levels, and generally N levels may span up
38  * to 256^N content entries.
39  */
40 typedef struct _pvector {
41     unsigned long size;     //!< Limit for the logical entries[]
42     pvector_page *entries; //!< Pointer to entries indexing
43 } pvector;
44
45 // Number of page levels for size S
46 #define PV_LEVELS(S) ((int)(( 39 - __builtin_clz( ((S)-1) | 1) ) / 8 ))
47
48 #define PV_LEVEL_SIZE(S) ((int)(exp( 256, (S) )))
49
50 // The indexing part for level part p in index i
51 #define PV_PART(p,i) (((unsigned char*)&i)[p])
52
53 /*!
54  * Find the next used slot at given index or later. With a reclaim
55  * function, it will be invoked for verifying that the item is
56  * actually in use, in which case it returns 1. Otherwise it should
57  * reclaim any memory for the item and return 0;
58  */
59 void **pvector_next_used(
60     pvector *pv,unsigned long *index,
61     int (*reclaim)(pvector *pv,unsigned long index,void *item,void *data),
62     void *data );
63
64 /*!
65  * Function: int pvector_resize(
66  *              pvector *pv,unsigned long new_size,
67  *              int (*reclaim)(pvector *,unsigned long,void *item,void *data),
68  *              void *data )
69  * \param pv
70  * \param new_size
71  * \param reclaim
72  * \param data
73  *
74  * Tries to resize the given pvector to a new size. This may result in
75  * the introduction or removal of indexing pages, so that the leveling
76  * is consistent with the pvector size. Thus, if it grows into a new
77  * 256^N level, then one or more new upper level pages are inserted as
78  * needed. If it shrinks below the current level, then top-level pages
79  * are remove.
80  *
81  * Also, if the new size is smaller than currently, then the now
82  * excess tail of entries is scanned for any used slots and the given
83  * reclaim function is invoked successively for these. The reclaim
84  * function must, in addition to memory-managing the entry, return 0
85  * upon success and non-zero to veto the attempted pvector size
86  * change. The data argument is passed on to the reclaim function.
87  *
88  * The pvector_resize function returns 0 on success, with the size
89  * duly changed. Otherwise the function retains the current size and
90  * returns -index-1 for the index of the veto-ed entry.
91  */
92 int pvector_resize(
93     pvector *pv, unsigned long new_size,
94     int (*reclaim)(pvector *pv,unsigned long index,void *item,void *data),
95     void *data );
96
97 /*!
98  * Function: void **pvector_entry(pvector *pv,unsigned long index)
99  * \param pv - the pvector record
100  * \param index - the slot index
101  *
102  * [pgix,epix] = modulo( index, pv->page );
103  *
104  * \returns a direct pointer to the slot of the given index in the
105  * array, or 0 if the index is beyond the array limits (0-limit). Note
106  * that slot pointers are only valid while the pvector size is
107  * unchanged.
108  */
109 extern void **pvector_entry(pvector *pv,unsigned long index); 
110
111 /*!
112  * Function: unsigned long pvector_size(pvector *pv)
113  * \param pv - the pvector record
114  * \returns the size of the pvector.
115  */
116 inline unsigned long pvector_size(pvector *pv) {
117     return pv->size;
118 }
119
120 void pvector_set(pvector *pv,unsigned long index,void *value);
121
122 void *pvector_get(pvector *pv,unsigned long index);
123
124 void pvector_append(pvector *pv,void *value);
125
126 void pvector_copy(pvector *dst,unsigned long di,
127                   pvector *src,unsigned long si,unsigned long n);
128
129 void pvector_dump(pvector *pv,int (*itemdump)(unsigned long ,void *));
130
131 void pvector_qsort(pvector *pv,int (*compar)(void *,void *));
132
133 #endif