BRL-CAD
ptbl.h
Go to the documentation of this file.
1 /* P T B L . H
2  * BRL-CAD
3  *
4  * Copyright (c) 2004-2024 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 
21 #ifndef BU_PTBL_H
22 #define BU_PTBL_H
23 
24 #include "common.h"
25 
26 #include <stddef.h> /* for size_t */
27 
28 #include "bu/defines.h"
29 #include "bu/magic.h"
30 #include "bu/list.h"
31 
32 __BEGIN_DECLS
33 
34 /** @addtogroup bu_ptbl
35  *
36  * @brief
37  * Support for generalized "pointer tables", kept compactly in a
38  * dynamic array.
39  *
40  * The table is currently un-ordered, and is merely an array of
41  * pointers. The support routines BU_*PTBL* and bu_ptbl* manipulate the
42  * array for you. Pointers to be operated on (inserted, deleted, searched
43  * for) are passed as a "pointer to long".
44  *
45  */
46 /** @{ */
47 /** @file bu/ptbl.h*/
48 
49 
50 /**
51  * Support for generalized "pointer tables".
52  */
53 struct bu_ptbl {
54  struct bu_list l; /**< linked list for caller's use */
55  size_t end; /**< index into buffer of first available location */
56  size_t blen; /**< # of (long *)'s worth of storage at *buffer */
57  long **buffer; /**< data storage area */
58 };
59 typedef struct bu_ptbl bu_ptbl_t;
60 #define BU_PTBL_NULL ((struct bu_ptbl *)0)
61 
62 /**
63  * assert the integrity of a bu_ptbl struct pointer.
64  */
65 #define BU_CK_PTBL(_p) BU_CKMAG(_p, BU_PTBL_MAGIC, "bu_ptbl")
66 
67 /**
68  * initialize a bu_ptbl struct without allocating any memory. this
69  * macro is not suitable for initializing a list head node.
70  */
71 #define BU_PTBL_INIT(_p) { \
72  BU_LIST_INIT_MAGIC(&(_p)->l, BU_PTBL_MAGIC); \
73  (_p)->end = 0; \
74  (_p)->blen = 0; \
75  (_p)->buffer = NULL; \
76  }
77 
78 /**
79  * macro suitable for declaration statement initialization of a
80  * bu_ptbl struct. does not allocate memory. not suitable for
81  * initializing a list head node.
82  */
83 #define BU_PTBL_INIT_ZERO { {BU_PTBL_MAGIC, BU_LIST_NULL, BU_LIST_NULL}, 0, 0, NULL }
84 
85 /**
86  * returns truthfully whether a bu_ptbl has been initialized via
87  * BU_PTBL_INIT() or BU_PTBL_INIT_ZERO.
88  */
89 #define BU_PTBL_IS_INITIALIZED(_p) (((struct bu_ptbl *)(_p) != BU_PTBL_NULL) && LIKELY((_p)->l.magic == BU_PTBL_MAGIC))
90 
91 
92 /*
93  * For those routines that have to "peek" into the ptbl a little bit.
94  */
95 #define BU_PTBL_LEN(ptbl) (((uintptr_t)(ptbl) != (uintptr_t)NULL)?(ptbl)->end:0)
96 #define BU_PTBL_TEST(ptbl) (((uintptr_t)(ptbl) != (uintptr_t)NULL)?(ptbl)->l.magic == BU_PTBL_MAGIC:0)
97 #define BU_PTBL_GET(ptbl, i) ((ptbl)->buffer[(i)])
98 #define BU_PTBL_SET(ptbl, i, val) ((ptbl)->buffer[(i)] = (long*)(val))
99 
100 /** DEPRECATED */
101 #define BU_PTBL_END(ptbl) ((ptbl)->end)
102 /** DEPRECATED */
103 #define BU_PTBL_BASEADDR(ptbl) (((uintptr_t)(ptbl) != (uintptr_t)NULL)?(ptbl)->buffer:NULL)
104 /** DEPRECATED */
105 #define BU_PTBL_LASTADDR(ptbl) (((uintptr_t)(ptbl) != (uintptr_t)NULL)?(ptbl)->buffer + (ptbl)->end - 1:NULL)
106 
107 /**
108  * A handy way to visit all the elements of the table is:
109  *
110  * struct edgeuse **eup;
111  * for (eup = (struct edgeuse **)BU_PTBL_LASTADDR(&eutab); eup >= (struct edgeuse **)BU_PTBL_BASEADDR(&eutab); eup--) {
112  * NMG_CK_EDGEUSE(*eup);
113  * }
114  * --- OR ---
115  * for (BU_PTBL_FOR(eup, (struct edgeuse **), &eutab)) {
116  * NMG_CK_EDGEUSE(*eup);
117  * }
118  */
119 #define BU_PTBL_FOR(ip, cast, ptbl) \
120  ip = cast BU_PTBL_LASTADDR(ptbl); ip >= cast BU_PTBL_BASEADDR(ptbl); ip--
121 
122 /**
123  * This collection of routines implements a "pointer table" data
124  * structure providing a convenient mechanism for managing a collection
125  * of pointers to objects. This is useful where the size of the array
126  * is not known in advance and may change with time. It's convenient
127  * to be able to write code that can say "remember this object", and
128  * then later on iterate through the collection of remembered objects.
129  *
130  * When combined with the concept of placing "magic numbers" as the
131  * first field of each data structure, the pointers to the objects
132  * become automatically typed.
133  */
134 
135 /**
136  * Initialize struct & get storage for table.
137  * Recommend 8 or 64 for initial len.
138  */
139 BU_EXPORT extern void bu_ptbl_init(struct bu_ptbl *b,
140  size_t len,
141  const char *str);
142 
143 /**
144  * Reset the table to have no elements, but retain any existing
145  * storage.
146  */
147 BU_EXPORT extern void bu_ptbl_reset(struct bu_ptbl *b);
148 
149 /**
150  * Append/Insert a (long *) item to/into the table.
151  */
152 BU_EXPORT extern size_t bu_ptbl_ins(struct bu_ptbl *b, long *p);
153 
154 /**
155  * locate a (long *) in an existing table
156  *
157  *
158  * @return index of first matching element in array, if found
159  * @return -1 if not found
160  *
161  * We do this a great deal, so make it go as fast as possible. this
162  * is the biggest argument I can make for changing to an ordered list.
163  * Someday....
164  */
165 BU_EXPORT extern intmax_t bu_ptbl_locate(const struct bu_ptbl *b, const long *p);
166 
167 /**
168  * Set all occurrences of "p" in the table to zero. This is different
169  * than deleting them.
170  */
171 BU_EXPORT extern void bu_ptbl_zero(struct bu_ptbl *b,
172  const long *p);
173 
174 /**
175  * Append item to table, if not already present. Unique insert.
176  *
177  * @return index of first matching element in array, if found. (table unchanged)
178  * @return -1 if table extended to hold new element
179  *
180  * We do this a great deal, so make it go as fast as possible. this
181  * is the biggest argument I can make for changing to an ordered list.
182  * Someday....
183  */
184 BU_EXPORT extern intmax_t bu_ptbl_ins_unique(struct bu_ptbl *b, long *p);
185 
186 /**
187  * Remove all occurrences of an item from a table
188  *
189  * @return Number of copies of 'p' that were removed from the table.
190  * @return 0 if none found.
191  *
192  * we go backwards down the table looking for occurrences of p to
193  * delete. We do it backwards to reduce the amount of data moved when
194  * there is more than one occurrence of p in the table. A pittance
195  * savings, unless you're doing a lot of it.
196  */
197 BU_EXPORT extern size_t bu_ptbl_rm(struct bu_ptbl *b, const long *p);
198 
199 /**
200  * Catenate one table onto end of another. There is no checking for
201  * duplication.
202  */
203 BU_EXPORT extern void bu_ptbl_cat(struct bu_ptbl *dest,
204  const struct bu_ptbl *src);
205 
206 /**
207  * Catenate one table onto end of another, ensuring that no entry is
208  * duplicated. Duplications between multiple items in 'src' are not
209  * caught. The search is a nasty n**2 one. The tables are expected
210  * to be short.
211  */
212 BU_EXPORT extern void bu_ptbl_cat_uniq(struct bu_ptbl *dest,
213  const struct bu_ptbl *src);
214 
215 /**
216  * Deallocate dynamic buffer associated with a table, and render this
217  * table unusable without a subsequent bu_ptbl_init().
218  */
219 BU_EXPORT extern void bu_ptbl_free(struct bu_ptbl *b);
220 
221 /**
222  * Print a bu_ptbl array for inspection.
223  */
224 BU_EXPORT extern void bu_pr_ptbl(const char *title,
225  const struct bu_ptbl *tbl,
226  int verbose);
227 
228 /**
229  * truncate a bu_ptbl to the specified size.
230  */
231 BU_EXPORT extern void bu_ptbl_trunc(struct bu_ptbl *tbl, size_t end);
232 
233 /** @} */
234 
235 __END_DECLS
236 
237 #endif /* BU_PTBL_H */
238 
239 /*
240  * Local Variables:
241  * mode: C
242  * tab-width: 8
243  * indent-tabs-mode: t
244  * c-file-style: "stroustrup"
245  * End:
246  * ex: shiftwidth=4 tabstop=8
247  */
Header file for the BRL-CAD common definitions.
void bu_ptbl_cat(struct bu_ptbl *dest, const struct bu_ptbl *src)
size_t bu_ptbl_rm(struct bu_ptbl *b, const long *p)
void bu_ptbl_free(struct bu_ptbl *b)
intmax_t bu_ptbl_locate(const struct bu_ptbl *b, const long *p)
void bu_ptbl_trunc(struct bu_ptbl *tbl, size_t end)
void bu_ptbl_reset(struct bu_ptbl *b)
void bu_ptbl_cat_uniq(struct bu_ptbl *dest, const struct bu_ptbl *src)
size_t bu_ptbl_ins(struct bu_ptbl *b, long *p)
intmax_t bu_ptbl_ins_unique(struct bu_ptbl *b, long *p)
void bu_ptbl_init(struct bu_ptbl *b, size_t len, const char *str)
void bu_pr_ptbl(const char *title, const struct bu_ptbl *tbl, int verbose)
void bu_ptbl_zero(struct bu_ptbl *b, const long *p)
Global registry of recognized magic numbers.
Definition: list.h:132
Definition: ptbl.h:53
size_t blen
Definition: ptbl.h:56
long ** buffer
Definition: ptbl.h:57
struct bu_list l
Definition: ptbl.h:54
size_t end
Definition: ptbl.h:55