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-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_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  */
139 struct bu_structparse {
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 };
152 typedef struct bu_structparse bu_structparse_t;
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. */
161 struct bu_structparse_map {
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  */
210 struct bu_external {
211  uint32_t ext_magic;
212  size_t ext_nbytes;
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 };
220 typedef struct bu_external bu_external_t;
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  */
273 BU_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  */
281 BU_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  */
290 BU_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  */
299 BU_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  */
312 BU_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  */
321 BU_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  */
330 BU_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  */
337 BU_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  */
344 BU_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  */
353 BU_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  */
362 BU_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 
368 BU_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  */
389 BU_EXPORT extern int bu_shader_to_list(const char *in, struct bu_vls *vls);
390 
391 BU_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  */
402 BU_EXPORT extern int bu_fwrite_external(FILE *fp,
403  const struct bu_external *ep);
404 
405 BU_EXPORT extern void bu_hexdump_external(FILE *fp, const struct bu_external *ep,
406  const char *str);
407 
408 BU_EXPORT extern void bu_free_external(struct bu_external *ep);
409 
410 BU_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  */
417 BU_EXPORT extern char *bu_next_token(char *str);
418 
419 BU_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  */
440 BU_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)
char * bu_next_token(char *str)
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)
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:213
uint8_t * ext_buf
Definition: parse.h:219
uint32_t ext_magic
Definition: parse.h:212
const char * sp_name
Definition: parse.h:163
void(* sp_hook)(const struct bu_structparse *, const char *, void *, const char *, void *)
Definition: parse.h:164
const char sp_fmt[4]
Definition: parse.h:141
size_t sp_count
Definition: parse.h:142
const char * sp_name
Definition: parse.h:143
void(* sp_hook)(const struct bu_structparse *, const char *, void *, const char *, void *)
Definition: parse.h:145
void * sp_default
Definition: parse.h:151
size_t sp_offset
Definition: parse.h:144
const char * sp_desc
Definition: parse.h:150
Definition: vls.h:53