BRL-CAD
avs.c
Go to the documentation of this file.
1 /* A V S . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2004-2014 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 #include "common.h"
22 
23 #include <stdio.h>
24 #include <string.h>
25 #include <time.h>
26 
27 #include "bu/avs.h"
28 #include "bu/debug.h"
29 #include "bu/log.h"
30 #include "bu/malloc.h"
31 #include "bu/str.h"
32 
33 #define AVS_ALLOCATION_INCREMENT 32
34 
35 void
37 {
38  avsp->magic = BU_AVS_MAGIC;
39  avsp->count = 0;
40  avsp->max = 0;
41  avsp->readonly_min = avsp->readonly_max = NULL;
42  avsp->avp = (struct bu_attribute_value_pair *)NULL;
43 }
44 
45 
46 void
47 bu_avs_init(struct bu_attribute_value_set *avsp, size_t len, const char *str)
48 {
50  bu_log("bu_avs_init(%p, len=%d, %s)\n", (void *)avsp, len, str);
51 
52  avsp->magic = BU_AVS_MAGIC;
53  if (UNLIKELY(len == 0))
55  avsp->count = 0;
56  avsp->max = len;
57  avsp->readonly_min = avsp->readonly_max = NULL;
58  avsp->avp = (struct bu_attribute_value_pair *)bu_calloc(avsp->max, sizeof(struct bu_attribute_value_pair), str);
59 }
60 
61 
63 bu_avs_new(size_t len, const char *str)
64 {
65  struct bu_attribute_value_set *avsp;
66 
67  BU_ALLOC(avsp, struct bu_attribute_value_set);
68  bu_avs_init(avsp, len, "bu_avs_new");
69 
71  bu_log("bu_avs_new(len=%d, %s) = %p\n", len, str, (void *)avsp);
72 
73  return avsp;
74 }
75 
76 
77 int
78 bu_avs_add(struct bu_attribute_value_set *avsp, const char *name, const char *value)
79 {
80  struct bu_attribute_value_pair *app;
81 
82  if (!avsp) return 0;
83 
84  BU_CK_AVS(avsp);
85 
86  if (UNLIKELY(!name)) {
87  bu_log("WARNING: bu_avs_add() received a null attribute name\n");
88  return 0;
89  }
90 
91  if (UNLIKELY(strlen(name) == 0)) {
92  bu_log("WARNING: bu_avs_add() received an attribute name with zero length\n");
93  return 0;
94  }
95 
96  /* does this attribute already exist? */
97  if (avsp->count) {
98  for (BU_AVS_FOR(app, avsp)) {
99  if (!BU_STR_EQUAL(app->name, name))
100  continue;
101 
102  /* found a match, replace it fully */
103  if (app->name && AVS_IS_FREEABLE(avsp, app->name))
104  bu_free((void *)app->name, "app->name");
105  if (app->value && AVS_IS_FREEABLE(avsp, app->value))
106  bu_free((void *)app->value, "app->value");
107  app->name = bu_strdup(name);
108  if (value) {
109  app->value = bu_strdup(value);
110  } else {
111  app->value = (char *)NULL;
112  }
113  return 1;
114  }
115  }
116 
117  if (avsp->count >= avsp->max) {
118  /* Allocate more space first */
119  avsp->max += AVS_ALLOCATION_INCREMENT;
120  if (avsp->avp) {
121  avsp->avp = (struct bu_attribute_value_pair *)bu_realloc(
122  avsp->avp, avsp->max * sizeof(struct bu_attribute_value_pair),
123  "attribute_value_pair.avp[] (add)");
124  } else {
125  avsp->avp = (struct bu_attribute_value_pair *)bu_calloc(
126  avsp->max, sizeof(struct bu_attribute_value_pair),
127  "attribute_value_pair.avp[] (add)");
128  }
129  }
130 
131  /* add the new attribute */
132  app = &avsp->avp[avsp->count++];
133  app->name = bu_strdup(name);
134  if (value) {
135  app->value = bu_strdup(value);
136  } else {
137  app->value = (char *)NULL;
138  }
139  return 2;
140 }
141 
142 
143 int
144 bu_avs_add_vls(struct bu_attribute_value_set *avsp, const char *name, const struct bu_vls *value_vls)
145 {
146  BU_CK_AVS(avsp);
147  BU_CK_VLS(value_vls);
148 
149  return bu_avs_add(avsp, name, bu_vls_addr(value_vls));
150 }
151 
152 
153 void
155 {
156  struct bu_attribute_value_pair *app;
157 
158  BU_CK_AVS(dest);
159  BU_CK_AVS(src);
160 
161  if (src->count < 1) {
162  return;
163  }
164 
165  for (BU_AVS_FOR(app, src)) {
166  (void)bu_avs_add(dest, app->name, app->value);
167  }
168 }
169 
170 
171 const char *
172 bu_avs_get(const struct bu_attribute_value_set *avsp, const char *name)
173 {
174  struct bu_attribute_value_pair *app;
175 
176  BU_CK_AVS(avsp);
177 
178  if (avsp->count < 1)
179  return NULL;
180 
181  if (!name)
182  return NULL;
183 
184  for (BU_AVS_FOR(app, avsp)) {
185  if (!BU_STR_EQUAL(app->name, name)) {
186  continue;
187  }
188  return app->value;
189  }
190  return NULL;
191 }
192 
193 
194 int
195 bu_avs_remove(struct bu_attribute_value_set *avsp, const char *name)
196 {
197  struct bu_attribute_value_pair *app, *epp;
198 
199  BU_CK_AVS(avsp);
200 
201  if (UNLIKELY(!name)) {
202  return -1;
203  }
204 
205  if (avsp->count < 1) {
206  return -1;
207  }
208 
209  for (BU_AVS_FOR(app, avsp)) {
210  if (!BU_STR_EQUAL(app->name, name))
211  continue;
212  if (app->name && AVS_IS_FREEABLE(avsp, app->name))
213  bu_free((void *)app->name, "app->name");
214  app->name = NULL; /* sanity */
215  if (app->value && AVS_IS_FREEABLE(avsp, app->value))
216  bu_free((void *)app->value, "app->value");
217  app->value = NULL; /* sanity */
218 
219  /* Move last one down to replace it */
220  epp = &avsp->avp[--avsp->count];
221  if (app != epp) {
222  *app = *epp; /* struct copy */
223  }
224 
225  /* sanity */
226  epp->name = NULL;
227  epp->value = NULL;
228  }
229 
230  return 0;
231 }
232 
233 
234 void
236 {
237  struct bu_attribute_value_pair *app;
238 
239  BU_CK_AVS(avsp);
240 
241  if (UNLIKELY(avsp->max < 1))
242  return;
243 
244  if (avsp->count) {
245  for (BU_AVS_FOR(app, avsp)) {
246  if (app->name && AVS_IS_FREEABLE(avsp, app->name)) {
247  bu_free((void *)app->name, "app->name");
248  }
249  app->name = NULL; /* sanity */
250  if (app->value && AVS_IS_FREEABLE(avsp, app->value)) {
251  bu_free((void *)app->value, "app->value");
252  }
253  app->value = NULL; /* sanity */
254  }
255  avsp->count = 0;
256  }
257  if (LIKELY(avsp->avp != NULL)) {
258  bu_free((void *)avsp->avp, "bu_avs_free avsp->avp");
259  avsp->avp = NULL; /* sanity */
260  avsp->max = 0;
261  }
262 }
263 
264 
265 void
266 bu_avs_print(const struct bu_attribute_value_set *avsp, const char *title)
267 {
268  struct bu_attribute_value_pair *avpp;
269  size_t i;
270 
271  BU_CK_AVS(avsp);
272 
273  if (title) {
274  bu_log("%s: %d attributes:\n", title, avsp->count);
275  }
276 
277  avpp = avsp->avp;
278  for (i = 0; i < avsp->count; i++, avpp++) {
279  bu_log(" %s = %s\n",
280  avpp->name ? avpp->name : "NULL",
281  avpp->value ? avpp->value : "NULL");
282  }
283 }
284 
285 
286 void
287 bu_avs_add_nonunique(struct bu_attribute_value_set *avsp, const char *name, const char *value)
288 {
289  struct bu_attribute_value_pair *app;
290 
291  BU_CK_AVS(avsp);
292 
293  /* nothing to do */
294  if (UNLIKELY(name == NULL)) {
295  if (UNLIKELY(value != NULL)) {
296  bu_log("WARNING: bu_avs_add_nonunique given NULL name and non-null value\n");
297  }
298  return;
299  }
300 
301  if (avsp->count >= avsp->max) {
302  /* Allocate more space first */
303  avsp->max += AVS_ALLOCATION_INCREMENT;
304  if (avsp->avp) {
305  avsp->avp = (struct bu_attribute_value_pair *)bu_realloc(
306  avsp->avp, avsp->max * sizeof(struct bu_attribute_value_pair),
307  "attribute_value_pair.avp[] (add)");
308  } else {
309  avsp->avp = (struct bu_attribute_value_pair *)bu_malloc(
310  avsp->max * sizeof(struct bu_attribute_value_pair),
311  "attribute_value_pair.avp[] (add)");
312  }
313  }
314 
315  app = &avsp->avp[avsp->count++];
316  app->name = bu_strdup(name);
317  if (value) {
318  app->value = bu_strdup(value);
319  } else {
320  app->value = (char *)NULL;
321  }
322 }
323 
324 
325 /*
326  * Local Variables:
327  * mode: C
328  * tab-width: 8
329  * indent-tabs-mode: t
330  * c-file-style: "stroustrup"
331  * End:
332  * ex: shiftwidth=4 tabstop=8
333  */
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
#define BU_AVS_MAGIC
Definition: magic.h:46
void bu_avs_init_empty(struct bu_attribute_value_set *avsp)
Definition: avs.c:36
#define LIKELY(expression)
Definition: common.h:261
#define AVS_IS_FREEABLE(_avsp, _p)
Definition: avs.h:150
Definition: clone.c:90
int bu_avs_add(struct bu_attribute_value_set *avsp, const char *name, const char *value)
Definition: avs.c:78
void bu_avs_merge(struct bu_attribute_value_set *dest, const struct bu_attribute_value_set *src)
Definition: avs.c:154
void * readonly_min
Definition: avs.h:87
void * readonly_max
Definition: avs.h:88
Header file for the BRL-CAD common definitions.
const char * value
Definition: avs.h:62
void * bu_malloc(size_t siz, const char *str)
Definition: malloc.c:314
const char * bu_avs_get(const struct bu_attribute_value_set *avsp, const char *name)
Definition: avs.c:172
#define BU_CK_VLS(_vp)
Definition: vls.h:69
struct bu_attribute_value_pair * avp
Definition: avs.h:89
#define BU_ALLOC(_ptr, _type)
Definition: malloc.h:223
void * bu_calloc(size_t nelem, size_t elsize, const char *str)
Definition: malloc.c:321
int bu_avs_remove(struct bu_attribute_value_set *avsp, const char *name)
Definition: avs.c:195
void bu_avs_add_nonunique(struct bu_attribute_value_set *avsp, const char *name, const char *value)
Definition: avs.c:287
#define BU_AVS_FOR(_pp, _avp)
Definition: avs.h:141
void * bu_realloc(void *ptr, size_t siz, const char *str)
uint32_t magic
Definition: avs.h:84
void bu_avs_init(struct bu_attribute_value_set *avsp, size_t len, const char *str)
Definition: avs.c:47
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
#define AVS_ALLOCATION_INCREMENT
Definition: avs.c:33
#define BU_DEBUG_AVS
Definition: debug.h:65
int bu_debug
Definition: globals.c:87
struct bu_attribute_value_set * bu_avs_new(size_t len, const char *str)
Definition: avs.c:63
int bu_avs_add_vls(struct bu_attribute_value_set *avsp, const char *name, const struct bu_vls *value_vls)
Definition: avs.c:144
const char * name
Definition: avs.h:61
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
void bu_avs_print(const struct bu_attribute_value_set *avsp, const char *title)
Definition: avs.c:266
Definition: vls.h:56
#define BU_CK_AVS(_ap)
Definition: avs.h:97
void bu_avs_free(struct bu_attribute_value_set *avsp)
Definition: avs.c:235
#define bu_strdup(s)
Definition: str.h:71
#define UNLIKELY(expression)
Definition: common.h:282
#define BU_STR_EQUAL(s1, s2)
Definition: str.h:126