2 * Copyright (c) 2014-2015, Juniper Networks, Inc.
4 * This SOFTWARE is licensed under the LICENSE provided in the
5 * ../Copyright file. By downloading, installing, copying, or otherwise
6 * using the SOFTWARE, you agree to be bound by the terms of that
8 * Phil Shafer, July 2014
12 * libxo provides a means of generating text, XML, JSON, and HTML output
13 * using a single set of function calls, maximizing the value of output
14 * while minimizing the cost/impact on the code.
16 * Full documentation is available in ./doc/libxo.txt or online at:
17 * http://juniper.github.io/libxo/libxo-manual.html
24 #include <sys/types.h>
30 #define NORETURN __dead2
36 * Normally we'd use the HAVE_PRINTFLIKE define triggered by the
37 * --enable-printflike option to configure, but we don't install
38 * our internal "xoconfig.h", and I'd rather not. Taking the
39 * coward's path, we'll turn it on inside a #if that allows
40 * others to turn it off where needed. Not ideal, but functional.
42 #if !defined(NO_PRINTFLIKE) && !defined(__linux__)
43 #define PRINTFLIKE(_x, _y) __printflike(_x, _y)
45 #define PRINTFLIKE(_x, _y)
46 #endif /* NO_PRINTFLIKE */
48 /** Formatting types */
49 typedef unsigned short xo_style_t;
50 #define XO_STYLE_TEXT 0 /** Generate text output */
51 #define XO_STYLE_XML 1 /** Generate XML output */
52 #define XO_STYLE_JSON 2 /** Generate JSON output */
53 #define XO_STYLE_HTML 3 /** Generate HTML output */
54 #define XO_STYLE_SDPARAMS 4 /* Generate syslog structured data params */
55 #define XO_STYLE_ENCODER 5 /* Generate calls to external encoder */
57 /** Flags for libxo */
58 typedef unsigned long long xo_xof_flags_t;
59 #define XOF_BIT(_n) ((xo_xof_flags_t) 1 << (_n))
60 #define XOF_CLOSE_FP XOF_BIT(0) /** Close file pointer on xo_close() */
61 #define XOF_PRETTY XOF_BIT(1) /** Make 'pretty printed' output */
62 #define XOF_LOG_SYSLOG XOF_BIT(2) /** Log (on stderr) our syslog content */
63 #define XOF_RESV3 XOF_BIT(3) /* Unused */
65 #define XOF_WARN XOF_BIT(4) /** Generate warnings for broken calls */
66 #define XOF_XPATH XOF_BIT(5) /** Emit XPath attributes in HTML */
67 #define XOF_INFO XOF_BIT(6) /** Emit additional info fields (HTML) */
68 #define XOF_WARN_XML XOF_BIT(7) /** Emit warnings in XML (on stdout) */
70 #define XOF_NO_ENV XOF_BIT(8) /** Don't look at LIBXO_OPTIONS env var */
71 #define XOF_NO_VA_ARG XOF_BIT(9) /** Don't advance va_list w/ va_arg() */
72 #define XOF_DTRT XOF_BIT(10) /** Enable "do the right thing" mode */
73 #define XOF_KEYS XOF_BIT(11) /** Flag 'key' fields for xml and json */
75 #define XOF_IGNORE_CLOSE XOF_BIT(12) /** Ignore errors on close tags */
76 #define XOF_NOT_FIRST XOF_BIT(13) /* Not the first item (JSON) */
77 #define XOF_NO_LOCALE XOF_BIT(14) /** Don't bother with locale */
78 #define XOF_RESV15 XOF_BIT(15) /* Unused */
80 #define XOF_NO_TOP XOF_BIT(16) /** Don't emit the top braces in JSON */
81 #define XOF_RESV17 XOF_BIT(17) /* Unused */
82 #define XOF_UNITS XOF_BIT(18) /** Encode units in XML */
83 #define XOF_RESV19 XOF_BIT(19) /* Unused */
85 #define XOF_UNDERSCORES XOF_BIT(20) /** Replace dashes with underscores (JSON)*/
86 #define XOF_COLUMNS XOF_BIT(21) /** xo_emit should return a column count */
87 #define XOF_FLUSH XOF_BIT(22) /** Flush after each xo_emit call */
88 #define XOF_FLUSH_LINE XOF_BIT(23) /** Flush after each newline */
90 #define XOF_NO_CLOSE XOF_BIT(24) /** xo_finish won't close open elements */
91 #define XOF_COLOR_ALLOWED XOF_BIT(25) /** Allow color/effects to be enabled */
92 #define XOF_COLOR XOF_BIT(26) /** Enable color and effects */
93 #define XOF_NO_HUMANIZE XOF_BIT(27) /** Block the {h:} modifier */
95 #define XOF_LOG_GETTEXT XOF_BIT(28) /** Log (stderr) gettext lookup strings */
96 #define XOF_UTF8 XOF_BIT(29) /** Force text output to be UTF8 */
97 #define XOF_RETAIN_ALL XOF_BIT(30) /** Force use of XOEF_RETAIN */
98 #define XOF_RETAIN_NONE XOF_BIT(31) /** Prevent use of XOEF_RETAIN */
100 typedef unsigned xo_emit_flags_t; /* Flags to xo_emit() and friends */
101 #define XOEF_RETAIN (1<<0) /* Retain parsed formatting information */
104 * The xo_info_t structure provides a mapping between names and
105 * additional data emitted via HTML.
107 typedef struct xo_info_s {
108 const char *xi_name; /* Name of the element */
109 const char *xi_type; /* Type of field */
110 const char *xi_help; /* Description of field */
113 #define XO_INFO_NULL NULL, NULL, NULL /* Use '{ XO_INFO_NULL }' to end lists */
115 struct xo_handle_s; /* Opaque structure forward */
116 typedef struct xo_handle_s xo_handle_t; /* Handle for XO output */
118 typedef int (*xo_write_func_t)(void *, const char *);
119 typedef void (*xo_close_func_t)(void *);
120 typedef int (*xo_flush_func_t)(void *);
121 typedef void *(*xo_realloc_func_t)(void *, size_t);
122 typedef void (*xo_free_func_t)(void *);
125 * The formatter function mirrors "vsnprintf", with an additional argument
126 * of the xo handle. The caller should return the number of bytes _needed_
127 * to fit the data, even if this exceeds 'len'.
129 typedef int (*xo_formatter_t)(xo_handle_t *, char *, int,
130 const char *, va_list);
131 typedef void (*xo_checkpointer_t)(xo_handle_t *, va_list, int);
134 xo_create (xo_style_t style, xo_xof_flags_t flags);
137 xo_create_to_file (FILE *fp, xo_style_t style, xo_xof_flags_t flags);
140 xo_destroy (xo_handle_t *xop);
143 xo_set_writer (xo_handle_t *xop, void *opaque, xo_write_func_t write_func,
144 xo_close_func_t close_func, xo_flush_func_t flush_func);
147 xo_set_allocator (xo_realloc_func_t realloc_func, xo_free_func_t free_func);
150 xo_set_style (xo_handle_t *xop, xo_style_t style);
153 xo_get_style (xo_handle_t *xop);
156 xo_set_style_name (xo_handle_t *xop, const char *style);
159 xo_set_options (xo_handle_t *xop, const char *input);
162 xo_get_flags (xo_handle_t *xop);
165 xo_set_flags (xo_handle_t *xop, xo_xof_flags_t flags);
168 xo_clear_flags (xo_handle_t *xop, xo_xof_flags_t flags);
171 xo_set_file_h (xo_handle_t *xop, FILE *fp);
174 xo_set_file (FILE *fp);
177 xo_set_info (xo_handle_t *xop, xo_info_t *infop, int count);
180 xo_set_formatter (xo_handle_t *xop, xo_formatter_t func, xo_checkpointer_t);
183 xo_set_depth (xo_handle_t *xop, int depth);
186 xo_emit_hv (xo_handle_t *xop, const char *fmt, va_list vap);
189 xo_emit_h (xo_handle_t *xop, const char *fmt, ...);
192 xo_emit (const char *fmt, ...);
195 xo_emit_hvf (xo_handle_t *xop, xo_emit_flags_t flags,
196 const char *fmt, va_list vap);
199 xo_emit_hf (xo_handle_t *xop, xo_emit_flags_t flags, const char *fmt, ...);
202 xo_emit_f (xo_emit_flags_t flags, const char *fmt, ...);
206 xo_emit_hvp (xo_handle_t *xop, const char *fmt, va_list vap)
208 return xo_emit_hv(xop, fmt, vap);
213 xo_emit_hp (xo_handle_t *xop, const char *fmt, ...)
217 int rc = xo_emit_hv(xop, fmt, vap);
224 xo_emit_p (const char *fmt, ...)
228 int rc = xo_emit_hv(NULL, fmt, vap);
235 xo_emit_hvfp (xo_handle_t *xop, xo_emit_flags_t flags,
236 const char *fmt, va_list vap)
238 return xo_emit_hvf(xop, flags, fmt, vap);
243 xo_emit_hfp (xo_handle_t *xop, xo_emit_flags_t flags, const char *fmt, ...)
247 int rc = xo_emit_hvf(xop, flags, fmt, vap);
254 xo_emit_fp (xo_emit_flags_t flags, const char *fmt, ...)
258 int rc = xo_emit_hvf(NULL, flags, fmt, vap);
264 xo_open_container_h (xo_handle_t *xop, const char *name);
267 xo_open_container (const char *name);
270 xo_open_container_hd (xo_handle_t *xop, const char *name);
273 xo_open_container_d (const char *name);
276 xo_close_container_h (xo_handle_t *xop, const char *name);
279 xo_close_container (const char *name);
282 xo_close_container_hd (xo_handle_t *xop);
285 xo_close_container_d (void);
288 xo_open_list_h (xo_handle_t *xop, const char *name);
291 xo_open_list (const char *name);
294 xo_open_list_hd (xo_handle_t *xop, const char *name);
297 xo_open_list_d (const char *name);
300 xo_close_list_h (xo_handle_t *xop, const char *name);
303 xo_close_list (const char *name);
306 xo_close_list_hd (xo_handle_t *xop);
309 xo_close_list_d (void);
312 xo_open_instance_h (xo_handle_t *xop, const char *name);
315 xo_open_instance (const char *name);
318 xo_open_instance_hd (xo_handle_t *xop, const char *name);
321 xo_open_instance_d (const char *name);
324 xo_close_instance_h (xo_handle_t *xop, const char *name);
327 xo_close_instance (const char *name);
330 xo_close_instance_hd (xo_handle_t *xop);
333 xo_close_instance_d (void);
336 xo_open_marker_h (xo_handle_t *xop, const char *name);
339 xo_open_marker (const char *name);
342 xo_close_marker_h (xo_handle_t *xop, const char *name);
345 xo_close_marker (const char *name);
348 xo_attr_h (xo_handle_t *xop, const char *name, const char *fmt, ...);
351 xo_attr_hv (xo_handle_t *xop, const char *name, const char *fmt, va_list vap);
354 xo_attr (const char *name, const char *fmt, ...);
357 xo_error_hv (xo_handle_t *xop, const char *fmt, va_list vap);
360 xo_error_h (xo_handle_t *xop, const char *fmt, ...);
363 xo_error (const char *fmt, ...);
366 xo_flush_h (xo_handle_t *xop);
372 xo_finish_h (xo_handle_t *xop);
378 xo_finish_atexit (void);
381 xo_set_leading_xpath (xo_handle_t *xop, const char *path);
384 xo_warn_hc (xo_handle_t *xop, int code, const char *fmt, ...) PRINTFLIKE(3, 4);
387 xo_warn_c (int code, const char *fmt, ...) PRINTFLIKE(2, 3);
390 xo_warn (const char *fmt, ...) PRINTFLIKE(1, 2);
393 xo_warnx (const char *fmt, ...) PRINTFLIKE(1, 2);
396 xo_err (int eval, const char *fmt, ...) NORETURN PRINTFLIKE(2, 3);
399 xo_errx (int eval, const char *fmt, ...) NORETURN PRINTFLIKE(2, 3);
402 xo_errc (int eval, int code, const char *fmt, ...) NORETURN PRINTFLIKE(3, 4);
405 xo_message_hcv (xo_handle_t *xop, int code, const char *fmt, va_list vap) PRINTFLIKE(3, 0);
408 xo_message_hc (xo_handle_t *xop, int code, const char *fmt, ...) PRINTFLIKE(3, 4);
411 xo_message_c (int code, const char *fmt, ...) PRINTFLIKE(2, 3);
414 xo_message_e (const char *fmt, ...) PRINTFLIKE(1, 2);
417 xo_message (const char *fmt, ...) PRINTFLIKE(1, 2);
420 xo_emit_warn_hcv (xo_handle_t *xop, int as_warning, int code,
421 const char *fmt, va_list vap);
424 xo_emit_warn_hc (xo_handle_t *xop, int code, const char *fmt, ...);
427 xo_emit_warn_c (int code, const char *fmt, ...);
430 xo_emit_warn (const char *fmt, ...);
433 xo_emit_warnx (const char *fmt, ...);
436 xo_emit_err (int eval, const char *fmt, ...) NORETURN;
439 xo_emit_errx (int eval, const char *fmt, ...) NORETURN;
442 xo_emit_errc (int eval, int code, const char *fmt, ...) NORETURN;
446 xo_emit_warn_hcvp (xo_handle_t *xop, int as_warning, int code,
447 const char *fmt, va_list vap)
449 xo_emit_warn_hcv(xop, as_warning, code, fmt, vap);
454 xo_emit_warn_hcp (xo_handle_t *xop, int code, const char *fmt, ...)
458 xo_emit_warn_hcv(xop, 1, code, fmt, vap);
464 xo_emit_warn_cp (int code, const char *fmt, ...)
468 xo_emit_warn_hcv(NULL, 1, code, fmt, vap);
474 xo_emit_warn_p (const char *fmt, ...)
479 xo_emit_warn_hcv(NULL, 1, code, fmt, vap);
485 xo_emit_warnx_p (const char *fmt, ...)
489 xo_emit_warn_hcv(NULL, 1, -1, fmt, vap);
493 NORETURN PRINTFLIKE(2, 3)
495 xo_emit_err_p (int eval, const char *fmt, ...)
500 xo_emit_warn_hcv(NULL, 0, code, fmt, vap);
508 xo_emit_errx_p (int eval, const char *fmt, ...)
512 xo_emit_warn_hcv(NULL, 0, -1, fmt, vap);
519 xo_emit_errc_p (int eval, int code, const char *fmt, ...)
523 xo_emit_warn_hcv(NULL, 0, code, fmt, vap);
529 xo_emit_err_v (int eval, int code, const char *fmt, va_list vap) NORETURN PRINTFLIKE(3, 0);
532 xo_no_setlocale (void);
535 * @brief Lift libxo-specific arguments from a set of arguments
537 * libxo-enable programs typically use command line options to enable
538 * all the nifty-cool libxo features. xo_parse_args() makes this simple
539 * by pre-processing the command line arguments given to main(), handling
540 * and removing the libxo-specific ones, meaning anything starting with
541 * "--libxo". A full description of these arguments is in the base
543 * @param[in] argc Number of arguments (ala #main())
544 * @param[in] argc Array of argument strings (ala #main())
545 * @return New number of arguments, or -1 for failure.
548 xo_parse_args (int argc, char **argv);
551 * This is the "magic" number returned by libxo-supporting commands
552 * when passed the equally magic "--libxo-check" option. If you
553 * return this, we can (unsafely) assume that since you know the magic
554 * handshake, you'll happily handle future --libxo options and not do
555 * something violent like reboot the box or create another hole in the
558 #define XO_HAS_LIBXO 121
561 * externs for libxo's version number strings
563 extern const char xo_version[]; /** Base version triple string */
564 extern const char xo_version_extra[]; /** Extra version magic content */
567 * @brief Dump the internal stack of a libxo handle.
569 * This diagnostic function is something I will ask you to call from
570 * your program when you write to tell me libxo has gone bat-stink
571 * crazy and has discarded your list or container or content. Output
572 * content will be what we lovingly call "developer entertainment".
573 * @param[in] xop A valid libxo handle, or NULL for the default handle
576 xo_dump_stack (xo_handle_t *xop);
579 * @brief Recode the name of the program, suitable for error output.
581 * libxo will record the given name for use while generating error
582 * messages. The contents are not copied, so the value must continue
583 * to point to a valid memory location. This allows the caller to change
584 * the value, but requires the caller to manage the memory. Typically
585 * this is called with argv[0] from main().
586 * @param[in] name The name of the current application program
589 xo_set_program (const char *name);
592 * @brief Add a version string to the output, where possible.
594 * Adds a version number to the output, suitable for tracking
595 * changes in the content. This is only important for the "encoding"
596 * format styles (XML and JSON) and allows a user of the data to
597 * discern which version of the data model is in use.
598 * @param[in] version The version number, encoded as a string
601 xo_set_version (const char *version);
604 * #xo_set_version with a handle.
605 * @param[in] xop A valid libxo handle, or NULL for the default handle
606 * @param[in] version The version number, encoded as a string
609 xo_set_version_h (xo_handle_t *xop, const char *version);
612 xo_open_log (const char *ident, int logopt, int facility);
618 xo_set_logmask (int maskpri);
621 xo_set_unit_test_mode (int value);
624 xo_syslog (int priority, const char *name, const char *message, ...);
627 xo_vsyslog (int priority, const char *name, const char *message, va_list args);
629 typedef void (*xo_syslog_open_t)(void);
630 typedef void (*xo_syslog_send_t)(const char *full_msg,
631 const char *v0_hdr, const char *text_only);
632 typedef void (*xo_syslog_close_t)(void);
635 xo_set_syslog_handler (xo_syslog_open_t open_func, xo_syslog_send_t send_func,
636 xo_syslog_close_t close_func);
639 xo_set_syslog_enterprise_id (unsigned short eid);
641 typedef void (*xo_simplify_field_func_t)(const char *, unsigned, int);
644 xo_simplify_format (xo_handle_t *xop, const char *fmt, int with_numbers,
645 xo_simplify_field_func_t field_cb);
648 xo_emit_field_hv (xo_handle_t *xop, const char *rolmod, const char *contents,
649 const char *fmt, const char *efmt,
653 xo_emit_field_h (xo_handle_t *xop, const char *rolmod, const char *contents,
654 const char *fmt, const char *efmt, ...);
657 xo_emit_field (const char *rolmod, const char *contents,
658 const char *fmt, const char *efmt, ...);
661 xo_retain_clear_all (void);
664 xo_retain_clear (const char *fmt);
666 #endif /* INCLUDE_XO_H */