BRL-CAD
parse.h
Go to the documentation of this file.
1/* P A R S E . H
2 * BRL-CAD
3 *
4 * Copyright (c) 2004-2023 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_PARSE_H
22#define BU_PARSE_H
23
24#include "common.h"
25#include <stdio.h> /* For FILE */
26#include <stddef.h> /* for size_t */
27
28#include "bu/defines.h"
29#include "bu/magic.h"
30#include "bu/vls.h"
31
32__BEGIN_DECLS
33
34/** @addtogroup bu_parse
35 *
36 * @brief
37 * Definitions and data structures needed for routines that assign
38 * values to elements of arbitrary data structures, the layout of
39 * which is described by tables of "bu_structparse" structures.
40 *
41 * parse.c defines routines to assign values to elements of arbitrary structures. The
42 * layout of a structure to be processed is described by a structure
43 * of type "bu_structparse", giving element names, element formats, an
44 * offset from the beginning of the structure, and a pointer to an
45 * optional "hooked" function that is called whenever that structure
46 * element is changed.
47 */
48/** @{ */
49/** @file bu/parse.h */
50
51/**
52 * The general problem of word-addressed hardware where (int *) and
53 * (char *) have different representations is handled in the parsing
54 * routines that use sp_offset, because of the limitations placed on
55 * compile-time initializers.
56 *
57 * Files using bu_offsetof or bu_offsetofarray will need to include
58 * stddef.h in order to get offsetof()
59 */
60/* FIXME - this is a temporary cast. The bu_structparse sp_offset member
61 * should be a size_t.
62 */
63#ifndef offsetof
64# define offsetof(_t, _m) (size_t)(&(((_t *)0)->_m))
65#endif
66#define bu_offsetof(_t, _m) (size_t)offsetof(_t, _m)
67#define bu_offsetofarray(_t, _a, _d, _i) bu_offsetof(_t, _a) + sizeof(_d) * _i
68
69
70/**
71 * Convert address of global data object into byte "offset" from
72 * address 0.
73 *
74 * Strictly speaking, the C language only permits initializers of the
75 * form: address +- constant, where here the intent is to measure the
76 * byte address of the indicated variable. Matching compensation code
77 * for the CRAY is located in librt/parse.c
78 */
79#if defined(__ia64__) || defined(__x86_64__) || defined(__sparc64__) || defined(_HPUX_SOURCE) || defined(__clang__)
80# define bu_byteoffset(_i) ((size_t)((char *)&(_i)))
81#else
82/* "Conservative" way of finding # bytes as diff of 2 char ptrs */
83# define bu_byteoffset(_i) ((size_t)(((char *)&(_i))-((char *)0)))
84#endif
85
86
87/**
88 * The "bu_structparse" struct describes one element of a structure.
89 * Collections of these are combined to describe entire structures (or at
90 * least those portions for which parse/print/import/export support is
91 * desired.
92 *
93 * Provides a convenient way of describing a C data structure, and
94 * reading and writing it in both human-readable ASCII and efficient
95 * binary forms.
96 *
97 * For example:
98 *
99 * @code
100 *
101 * struct data_structure {
102 * char a_char;
103 * char str[32];
104 * short a_short;
105 * int a_int;
106 * fastf_t a_fastf_t;
107 * double a_double;
108 * }
109 *
110 * struct data_structure default = { 'c', "the default string", 32767, 1, 1.0, 1.0 };
111 *
112 * struct data_structure my_values;
113 *
114 * struct bu_structparse data_sp[] ={
115 * {"%c", 1, "a_char", bu_offsetof(data_structure, a_char), BU_STRUCTPARSE_FUNC_NULL, "a single character", (void*)&default.a_char},
116 * {"%s", 32, "str", bu_offsetofarray(data_structure, str), BU_STRUCTPARSE_FUNC_NULL, "This is a full character string", (void*)default.str},
117 * {"%i", 1, "a_short", bu_offsetof(data_structure, a_short), BU_STRUCTPARSE_FUNC_NULL, "A 16bit integer", (void*)&default.a_short},
118 * {"%d", 1, "a_int", bu_offsetof(data_structure, a_int), BU_STRUCTPARSE_FUNC_NULL, "A full integer", (void*)&default.a_int},
119 * {"%f", 1, "a_fastf_t", bu_offsetof(data_structure, a_fastf_t), BU_STRUCTPARSE_FUNC_NULL, "A variable-precision fasf_t floating point value", (void*)&default.a_fastf_t},
120 * {"%g", 1, "a_double", bu_offsetof(data_structure, a_double), BU_STRUCTPARSE_FUNC_NULL, "A double-precision fasf_t floating point value", (void*)&default.a_double},
121 * { "", 0, (char *)NULL, 0, BU_STRUCTPARSE_FUNC_NULL, (char *)NULL, (void *)NULL}
122 * };
123 *
124 * @endcode
125 *
126 * To parse a string, call:
127 *
128 * bu_struct_parse(vls_string, data_sp, (char *)my_values)
129 *
130 * this will parse the vls string and assign values to the members of
131 * the structure my_values
132 *
133 * A gross hack: To set global variables (or others for that matter)
134 * you can store the actual address of the variable in the sp_offset
135 * field and pass a null pointer as the last argument to
136 * bu_struct_parse. If you don't understand why this would work, you
137 * probably shouldn't use this technique.
138 */
140 const char sp_fmt[4]; /**< "%i" or "%f", etc. */
141 size_t sp_count; /**< number of elements */
142 const char *sp_name; /**< Element's symbolic name */
143 size_t sp_offset; /**< Byte offset in struct */
144 void (*sp_hook)(const struct bu_structparse *,
145 const char *,
146 void *,
147 const char *,
148 void *); /**< Optional hooked function, or indir ptr */
149 const char *sp_desc; /**< description of element */
150 void *sp_default; /**< ptr to default value */
151};
153#define BU_STRUCTPARSE_NULL ((struct bu_structparse *)0)
154
155#define BU_STRUCTPARSE_FUNC_NULL ((void(*)(const struct bu_structparse *, const char *, void *, const char *, void *))0)
156
157/* There are situations (such as the usage pattern in libdm)
158 * where applications may want to associate structparse
159 * functions with variables but not set up a full structparse
160 * table. */
162 const char *sp_name;
163 void (*sp_hook)(const struct bu_structparse *,
164 const char *,
165 void *,
166 const char *,
167 void *); /**< Optional hooked function, or indir ptr */
168};
169
170/**
171 * assert the integrity of a bu_structparse struct.
172 */
173#define BU_CK_STRUCTPARSE(_sp) /* nothing to do */
174
175/**
176 * initialize a bu_structparse struct without allocating any memory.
177 */
178#define BU_STRUCTPARSE_INIT(_sp) { \
179 (_sp)->sp_fmt[0] = (_sp)->sp_fmt[1] = (_sp)->sp_fmt[2] = (_sp)->sp_fmt[3] = '\0'; \
180 (_sp)->sp_count = 0; \
181 (_sp)->sp_name = NULL; \
182 (_sp)->sp_offset = 0; \
183 (_sp)->sp_hook = BU_STRUCTPARSE_FUNC_NULL; \
184 (_sp)->sp_desc = NULL; \
185 (_sp)->sp_default = NULL; \
186 }
187
188/**
189 * macro suitable for declaration statement initialization of a bu_structparse
190 * struct. does not allocate memory.
191 */
192#define BU_STRUCTPARSE_INIT_ZERO { {'\0', '\0', '\0', '\0'}, 0, NULL, 0, BU_STRUCTPARSE_FUNC_NULL, NULL, NULL }
193
194/**
195 * returns truthfully whether a bu_structparse struct has been
196 * initialized. validates whether pointer is non-NULL.
197 */
198#define BU_STRUCTPARSE_IS_INITIALIZED(_sp) ((struct bu_structparse *)(_sp) != BU_STRUCTPARSE_NULL)
199
200
201/*----------------------------------------------------------------------*/
202/**
203 * An "opaque" handle for holding onto objects, typically in some kind
204 * of external form that is not directly usable without passing
205 * through an "importation" function.
206 *
207 * A "bu_external" struct holds the "external binary" representation
208 * of a structure or other block of arbitrary data.
209 */
211 uint32_t ext_magic;
213#if defined(USE_BINARY_ATTRIBUTES)
214 unsigned char widcode; /* needed for decoding binary attributes,
215 * same type as 'struct
216 * db5_raw_internal.a_width' */
217#endif
218 uint8_t *ext_buf;
219};
221#define BU_EXTERNAL_NULL ((struct bu_external *)0)
222
223/**
224 * assert the integrity of a bu_external struct.
225 */
226#define BU_CK_EXTERNAL(_p) BU_CKMAG(_p, BU_EXTERNAL_MAGIC, "bu_external")
227
228/**
229 * initializes a bu_external struct without allocating any memory.
230 */
231#if defined(USE_BINARY_ATTRIBUTES)
232# define BU_EXTERNAL_INIT(_p) { \
233 (_p)->ext_magic = BU_EXTERNAL_MAGIC; \
234 (_p)->ext_nbytes = 0; \
235 (_p)->widcode = 0; \
236 (_p)->ext_buf = NULL; \
237 }
238#else
239# define BU_EXTERNAL_INIT(_p) { \
240 (_p)->ext_magic = BU_EXTERNAL_MAGIC; \
241 (_p)->ext_nbytes = 0; \
242 (_p)->ext_buf = NULL; \
243 }
244#endif
245
246/**
247 * macro suitable for declaration statement initialization of a
248 * bu_external struct. does not allocate memory.
249 */
250#if defined(USE_BINARY_ATTRIBUTES)
251# define BU_EXTERNAL_INIT_ZERO { BU_EXTERNAL_MAGIC, 0, 0, NULL }
252#else
253# define BU_EXTERNAL_INIT_ZERO { BU_EXTERNAL_MAGIC, 0, NULL }
254#endif
255/**
256 * returns truthfully whether a bu_external struct has been
257 * initialized. is not reliable unless the struct has been
258 * initialized with BU_EXTERNAL_INIT().
259 */
260#define BU_EXTERNAL_IS_INITIALIZED(_p) (((struct bu_external *)(_p) != BU_EXTERNAL_NULL) && (_p)->ext_magic == BU_EXTERNAL_MAGIC)
261
262/** @brief routines for parsing arbitrary structures */
263
264/**
265 * ASCII to struct elements.
266 *
267 * Parse the structure element description in the vls string "vls"
268 * according to the structure description in "parsetab"
269 *
270 * @return <0 failure
271 * @return 0 OK
272 */
273BU_EXPORT extern int bu_struct_parse(const struct bu_vls *in_vls,
274 const struct bu_structparse *desc,
275 const char *base,
276 void *data);
277
278/**
279 * struct elements to ASCII.
280 */
281BU_EXPORT extern void bu_struct_print(const char *title,
282 const struct bu_structparse *parsetab,
283 const char *base);
284
285/**
286 * struct elements to machine-independent binary.
287 *
288 * copies ext data to base
289 */
290BU_EXPORT extern int bu_struct_export(struct bu_external *ext,
291 const void *base,
292 const struct bu_structparse *imp);
293
294/**
295 * machine-independent binary to struct elements.
296 *
297 * copies ext data to base
298 */
299BU_EXPORT extern int bu_struct_import(void *base,
300 const struct bu_structparse *imp,
301 const struct bu_external *ext,
302 void *data);
303
304/**
305 * Put a structure in external form to a stdio file. All formatting
306 * must have been accomplished previously.
307 *
308 * Returns number of bytes written. On error, a short byte count (or
309 * zero) is returned. Use feof(3) or ferror(3) to determine which
310 * errors occur.
311 */
312BU_EXPORT extern size_t bu_struct_put(FILE *fp,
313 const struct bu_external *ext);
314
315/**
316 * Obtain the next structure in external form from a stdio file.
317 *
318 * Returns number of bytes read into the bu_external. On error, zero
319 * is returned.
320 */
321BU_EXPORT extern size_t bu_struct_get(struct bu_external *ext,
322 FILE *fp);
323
324/**
325 * Given a buffer with an external representation of a structure
326 * (e.g. the ext_buf portion of the output from bu_struct_export),
327 * check it for damage in shipment, and if it's OK, wrap it up in an
328 * bu_external structure, suitable for passing to bu_struct_import().
329 */
330BU_EXPORT extern void bu_struct_wrap_buf(struct bu_external *ext,
331 void *buf);
332
333/**
334 * This differs from bu_struct_print in that this output is less
335 * readable by humans, but easier to parse with the computer.
336 */
337BU_EXPORT extern void bu_vls_struct_print(struct bu_vls *vls,
338 const struct bu_structparse *sdp,
339 const char *base);
340
341/**
342 * This differs from bu_struct_print in that it prints to a vls.
343 */
344BU_EXPORT extern void bu_vls_struct_print2(struct bu_vls *vls,
345 const char *title,
346 const struct bu_structparse *sdp,
347 const char *base);
348
349/**
350 * Convert a structure element (indicated by sdp) to its ASCII
351 * representation in a VLS.
352 */
353BU_EXPORT extern void bu_vls_struct_item(struct bu_vls *vp,
354 const struct bu_structparse *sdp,
355 const char *base,
356 int sep_char);
357
358/**
359 * Convert a structure element called "name" to an ASCII
360 * representation in a VLS.
361 */
362BU_EXPORT extern int bu_vls_struct_item_named(struct bu_vls *vp,
363 const struct bu_structparse *sdp,
364 const char *name,
365 const char *base,
366 int sep_char);
367
368BU_EXPORT extern int bu_key_eq_to_key_val(const char *in,
369 const char **next,
370 struct bu_vls *vls);
371
372/**
373 * Take an old v4 shader specification of the form
374 *
375 * shadername arg1=value1 arg2=value2 color=1/2/3
376 *
377 * and convert it into the v5 {} list form
378 *
379 * shadername {arg1 value1 arg2 value2 color 1/2/3}
380 *
381 * Note -- the input string is smashed with nulls.
382 *
383 * Note -- the v5 version is used everywhere internally, and in v5
384 * databases.
385 *
386 * @return 1 error
387 * @return 0 OK
388 */
389BU_EXPORT extern int bu_shader_to_list(const char *in, struct bu_vls *vls);
390
391BU_EXPORT extern int bu_shader_to_key_eq(const char *in, struct bu_vls *vls);
392
393/**
394 * Take a block of memory, and write it into a file.
395 *
396 * Caller is responsible for freeing memory of external representation,
397 * using bu_free_external().
398 *
399 * @return <0 error
400 * @return 0 OK
401 */
402BU_EXPORT extern int bu_fwrite_external(FILE *fp,
403 const struct bu_external *ep);
404
405BU_EXPORT extern void bu_hexdump_external(FILE *fp, const struct bu_external *ep,
406 const char *str);
407
408BU_EXPORT extern void bu_free_external(struct bu_external *ep);
409
410BU_EXPORT extern void bu_copy_external(struct bu_external *op,
411 const struct bu_external *ip);
412
413/**
414 * Advance pointer through string over current token,
415 * across white space, to beginning of next token.
416 */
417BU_EXPORT extern char *bu_next_token(char *str);
418
419BU_EXPORT extern void bu_structparse_get_terse_form(struct bu_vls *logstr,
420 const struct bu_structparse *sp);
421
422/**
423 * Support routine for db adjust and db put. Much like the
424 * bu_struct_parse routine which takes its input as a bu_vls. This
425 * routine, however, takes the arguments as lists, a more Tcl-friendly
426 * method. There is a log vls for storing messages.
427 *
428 * Operates on argv[0] and argv[1], then on argv[2] and argv[3], ...
429 *
430 * @param str - vls for dumping info that might have gone to bu_log
431 * @param argc - number of elements in argv
432 * @param argv - contains the keyword-value pairs
433 * @param desc - structure description
434 * @param base - base addr of users struct
435 * @param data - user data to be passed to the sp_hook function
436 *
437 * @retval BRLCAD_OK if successful,
438 * @retval BRLCAD_ERROR on failure
439 */
440BU_EXPORT extern int bu_structparse_argv(struct bu_vls *str,
441 int argc,
442 const char **argv,
443 const struct bu_structparse *desc,
444 char *base,
445 void *data);
446
447/**
448 * Skip the separator(s) (i.e. whitespace and open-braces)
449 *
450 * @param _cp - character pointer
451 */
452#define BU_SP_SKIP_SEP(_cp) { \
453 while (*(_cp) && (*(_cp) == ' ' || *(_cp) == '\n' || \
454 *(_cp) == '\t' || *(_cp) == '{')) ++(_cp); \
455 }
456
457
458/** @} */
459
460__END_DECLS
461
462#endif /* BU_PARSE_H */
463
464/*
465 * Local Variables:
466 * mode: C
467 * tab-width: 8
468 * indent-tabs-mode: t
469 * c-file-style: "stroustrup"
470 * End:
471 * ex: shiftwidth=4 tabstop=8
472 */
Header file for the BRL-CAD common definitions.
int bu_structparse_argv(struct bu_vls *str, int argc, const char **argv, const struct bu_structparse *desc, char *base, void *data)
void bu_struct_wrap_buf(struct bu_external *ext, void *buf)
void bu_copy_external(struct bu_external *op, const struct bu_external *ip)
int bu_vls_struct_item_named(struct bu_vls *vp, const struct bu_structparse *sdp, const char *name, const char *base, int sep_char)
size_t bu_struct_get(struct bu_external *ext, FILE *fp)
int bu_struct_parse(const struct bu_vls *in_vls, const struct bu_structparse *desc, const char *base, void *data)
routines for parsing arbitrary structures
void bu_struct_print(const char *title, const struct bu_structparse *parsetab, const char *base)
void bu_vls_struct_print2(struct bu_vls *vls, const char *title, const struct bu_structparse *sdp, const char *base)
void bu_free_external(struct bu_external *ep)
size_t bu_struct_put(FILE *fp, const struct bu_external *ext)
void bu_vls_struct_item(struct bu_vls *vp, const struct bu_structparse *sdp, const char *base, int sep_char)
void bu_hexdump_external(FILE *fp, const struct bu_external *ep, const char *str)
int bu_shader_to_list(const char *in, struct bu_vls *vls)
void bu_structparse_get_terse_form(struct bu_vls *logstr, const struct bu_structparse *sp)
int bu_key_eq_to_key_val(const char *in, const char **next, struct bu_vls *vls)
int bu_shader_to_key_eq(const char *in, struct bu_vls *vls)
void bu_vls_struct_print(struct bu_vls *vls, const struct bu_structparse *sdp, const char *base)
int bu_struct_export(struct bu_external *ext, const void *base, const struct bu_structparse *imp)
char * bu_next_token(char *str)
int bu_struct_import(void *base, const struct bu_structparse *imp, const struct bu_external *ext, void *data)
int bu_fwrite_external(FILE *fp, const struct bu_external *ep)
Global registry of recognized magic numbers.
size_t ext_nbytes
Definition: parse.h:212
uint8_t * ext_buf
Definition: parse.h:218
uint32_t ext_magic
Definition: parse.h:211
const char * sp_name
Definition: parse.h:162
void(* sp_hook)(const struct bu_structparse *, const char *, void *, const char *, void *)
Definition: parse.h:163
const char sp_fmt[4]
Definition: parse.h:140
size_t sp_count
Definition: parse.h:141
const char * sp_name
Definition: parse.h:142
void(* sp_hook)(const struct bu_structparse *, const char *, void *, const char *, void *)
Definition: parse.h:144
void * sp_default
Definition: parse.h:150
size_t sp_offset
Definition: parse.h:143
const char * sp_desc
Definition: parse.h:149
Definition: vls.h:53