xo.h revision 302408
1/* 2 * Copyright (c) 2014-2015, Juniper Networks, Inc. 3 * All rights reserved. 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 7 * LICENSE. 8 * Phil Shafer, July 2014 9 */ 10 11/** 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. 15 * 16 * Full documentation is available in ./doc/libxo.txt or online at: 17 * http://juniper.github.io/libxo/libxo-manual.html 18 */ 19 20#ifndef INCLUDE_XO_H 21#define INCLUDE_XO_H 22 23#include <stdio.h> 24#include <sys/types.h> 25#include <stdarg.h> 26#include <stdlib.h> 27#include <errno.h> 28 29#ifdef __dead2 30#define NORETURN __dead2 31#else 32#define NORETURN 33#endif /* __dead2 */ 34 35/* 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. 41 */ 42#if !defined(NO_PRINTFLIKE) && !defined(__linux__) 43#define PRINTFLIKE(_x, _y) __printflike(_x, _y) 44#else 45#define PRINTFLIKE(_x, _y) 46#endif /* NO_PRINTFLIKE */ 47 48/** Formatting types */ 49typedef 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 */ 56 57/** Flags for libxo */ 58typedef 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 */ 64 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) */ 69 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 */ 74 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 */ 79 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 */ 84 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 */ 89 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 */ 94 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 */ 99 100typedef unsigned xo_emit_flags_t; /* Flags to xo_emit() and friends */ 101#define XOEF_RETAIN (1<<0) /* Retain parsed formatting information */ 102 103/* 104 * The xo_info_t structure provides a mapping between names and 105 * additional data emitted via HTML. 106 */ 107typedef 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 */ 111} xo_info_t; 112 113#define XO_INFO_NULL NULL, NULL, NULL /* Use '{ XO_INFO_NULL }' to end lists */ 114 115struct xo_handle_s; /* Opaque structure forward */ 116typedef struct xo_handle_s xo_handle_t; /* Handle for XO output */ 117 118typedef int (*xo_write_func_t)(void *, const char *); 119typedef void (*xo_close_func_t)(void *); 120typedef int (*xo_flush_func_t)(void *); 121typedef void *(*xo_realloc_func_t)(void *, size_t); 122typedef void (*xo_free_func_t)(void *); 123 124/* 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'. 128 */ 129typedef int (*xo_formatter_t)(xo_handle_t *, char *, int, 130 const char *, va_list); 131typedef void (*xo_checkpointer_t)(xo_handle_t *, va_list, int); 132 133xo_handle_t * 134xo_create (xo_style_t style, xo_xof_flags_t flags); 135 136xo_handle_t * 137xo_create_to_file (FILE *fp, xo_style_t style, xo_xof_flags_t flags); 138 139void 140xo_destroy (xo_handle_t *xop); 141 142void 143xo_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); 145 146void 147xo_set_allocator (xo_realloc_func_t realloc_func, xo_free_func_t free_func); 148 149void 150xo_set_style (xo_handle_t *xop, xo_style_t style); 151 152xo_style_t 153xo_get_style (xo_handle_t *xop); 154 155int 156xo_set_style_name (xo_handle_t *xop, const char *style); 157 158int 159xo_set_options (xo_handle_t *xop, const char *input); 160 161xo_xof_flags_t 162xo_get_flags (xo_handle_t *xop); 163 164void 165xo_set_flags (xo_handle_t *xop, xo_xof_flags_t flags); 166 167void 168xo_clear_flags (xo_handle_t *xop, xo_xof_flags_t flags); 169 170int 171xo_set_file_h (xo_handle_t *xop, FILE *fp); 172 173int 174xo_set_file (FILE *fp); 175 176void 177xo_set_info (xo_handle_t *xop, xo_info_t *infop, int count); 178 179void 180xo_set_formatter (xo_handle_t *xop, xo_formatter_t func, xo_checkpointer_t); 181 182void 183xo_set_depth (xo_handle_t *xop, int depth); 184 185int 186xo_emit_hv (xo_handle_t *xop, const char *fmt, va_list vap); 187 188int 189xo_emit_h (xo_handle_t *xop, const char *fmt, ...); 190 191int 192xo_emit (const char *fmt, ...); 193 194int 195xo_emit_hvf (xo_handle_t *xop, xo_emit_flags_t flags, 196 const char *fmt, va_list vap); 197 198int 199xo_emit_hf (xo_handle_t *xop, xo_emit_flags_t flags, const char *fmt, ...); 200 201int 202xo_emit_f (xo_emit_flags_t flags, const char *fmt, ...); 203 204PRINTFLIKE(2, 0) 205static inline int 206xo_emit_hvp (xo_handle_t *xop, const char *fmt, va_list vap) 207{ 208 return xo_emit_hv(xop, fmt, vap); 209} 210 211PRINTFLIKE(2, 3) 212static inline int 213xo_emit_hp (xo_handle_t *xop, const char *fmt, ...) 214{ 215 va_list vap; 216 va_start(vap, fmt); 217 int rc = xo_emit_hv(xop, fmt, vap); 218 va_end(vap); 219 return rc; 220} 221 222PRINTFLIKE(1, 2) 223static inline int 224xo_emit_p (const char *fmt, ...) 225{ 226 va_list vap; 227 va_start(vap, fmt); 228 int rc = xo_emit_hv(NULL, fmt, vap); 229 va_end(vap); 230 return rc; 231} 232 233PRINTFLIKE(3, 0) 234static inline int 235xo_emit_hvfp (xo_handle_t *xop, xo_emit_flags_t flags, 236 const char *fmt, va_list vap) 237{ 238 return xo_emit_hvf(xop, flags, fmt, vap); 239} 240 241PRINTFLIKE(3, 4) 242static inline int 243xo_emit_hfp (xo_handle_t *xop, xo_emit_flags_t flags, const char *fmt, ...) 244{ 245 va_list vap; 246 va_start(vap, fmt); 247 int rc = xo_emit_hvf(xop, flags, fmt, vap); 248 va_end(vap); 249 return rc; 250} 251 252PRINTFLIKE(2, 3) 253static inline int 254xo_emit_fp (xo_emit_flags_t flags, const char *fmt, ...) 255{ 256 va_list vap; 257 va_start(vap, fmt); 258 int rc = xo_emit_hvf(NULL, flags, fmt, vap); 259 va_end(vap); 260 return rc; 261} 262 263int 264xo_open_container_h (xo_handle_t *xop, const char *name); 265 266int 267xo_open_container (const char *name); 268 269int 270xo_open_container_hd (xo_handle_t *xop, const char *name); 271 272int 273xo_open_container_d (const char *name); 274 275int 276xo_close_container_h (xo_handle_t *xop, const char *name); 277 278int 279xo_close_container (const char *name); 280 281int 282xo_close_container_hd (xo_handle_t *xop); 283 284int 285xo_close_container_d (void); 286 287int 288xo_open_list_h (xo_handle_t *xop, const char *name); 289 290int 291xo_open_list (const char *name); 292 293int 294xo_open_list_hd (xo_handle_t *xop, const char *name); 295 296int 297xo_open_list_d (const char *name); 298 299int 300xo_close_list_h (xo_handle_t *xop, const char *name); 301 302int 303xo_close_list (const char *name); 304 305int 306xo_close_list_hd (xo_handle_t *xop); 307 308int 309xo_close_list_d (void); 310 311int 312xo_open_instance_h (xo_handle_t *xop, const char *name); 313 314int 315xo_open_instance (const char *name); 316 317int 318xo_open_instance_hd (xo_handle_t *xop, const char *name); 319 320int 321xo_open_instance_d (const char *name); 322 323int 324xo_close_instance_h (xo_handle_t *xop, const char *name); 325 326int 327xo_close_instance (const char *name); 328 329int 330xo_close_instance_hd (xo_handle_t *xop); 331 332int 333xo_close_instance_d (void); 334 335int 336xo_open_marker_h (xo_handle_t *xop, const char *name); 337 338int 339xo_open_marker (const char *name); 340 341int 342xo_close_marker_h (xo_handle_t *xop, const char *name); 343 344int 345xo_close_marker (const char *name); 346 347int 348xo_attr_h (xo_handle_t *xop, const char *name, const char *fmt, ...); 349 350int 351xo_attr_hv (xo_handle_t *xop, const char *name, const char *fmt, va_list vap); 352 353int 354xo_attr (const char *name, const char *fmt, ...); 355 356void 357xo_error_hv (xo_handle_t *xop, const char *fmt, va_list vap); 358 359void 360xo_error_h (xo_handle_t *xop, const char *fmt, ...); 361 362void 363xo_error (const char *fmt, ...); 364 365int 366xo_flush_h (xo_handle_t *xop); 367 368int 369xo_flush (void); 370 371int 372xo_finish_h (xo_handle_t *xop); 373 374int 375xo_finish (void); 376 377void 378xo_finish_atexit (void); 379 380void 381xo_set_leading_xpath (xo_handle_t *xop, const char *path); 382 383void 384xo_warn_hc (xo_handle_t *xop, int code, const char *fmt, ...) PRINTFLIKE(3, 4); 385 386void 387xo_warn_c (int code, const char *fmt, ...) PRINTFLIKE(2, 3); 388 389void 390xo_warn (const char *fmt, ...) PRINTFLIKE(1, 2); 391 392void 393xo_warnx (const char *fmt, ...) PRINTFLIKE(1, 2); 394 395void 396xo_err (int eval, const char *fmt, ...) NORETURN PRINTFLIKE(2, 3); 397 398void 399xo_errx (int eval, const char *fmt, ...) NORETURN PRINTFLIKE(2, 3); 400 401void 402xo_errc (int eval, int code, const char *fmt, ...) NORETURN PRINTFLIKE(3, 4); 403 404void 405xo_message_hcv (xo_handle_t *xop, int code, const char *fmt, va_list vap) PRINTFLIKE(3, 0); 406 407void 408xo_message_hc (xo_handle_t *xop, int code, const char *fmt, ...) PRINTFLIKE(3, 4); 409 410void 411xo_message_c (int code, const char *fmt, ...) PRINTFLIKE(2, 3); 412 413void 414xo_message_e (const char *fmt, ...) PRINTFLIKE(1, 2); 415 416void 417xo_message (const char *fmt, ...) PRINTFLIKE(1, 2); 418 419void 420xo_emit_warn_hcv (xo_handle_t *xop, int as_warning, int code, 421 const char *fmt, va_list vap); 422 423void 424xo_emit_warn_hc (xo_handle_t *xop, int code, const char *fmt, ...); 425 426void 427xo_emit_warn_c (int code, const char *fmt, ...); 428 429void 430xo_emit_warn (const char *fmt, ...); 431 432void 433xo_emit_warnx (const char *fmt, ...); 434 435void 436xo_emit_err (int eval, const char *fmt, ...) NORETURN; 437 438void 439xo_emit_errx (int eval, const char *fmt, ...) NORETURN; 440 441void 442xo_emit_errc (int eval, int code, const char *fmt, ...) NORETURN; 443 444PRINTFLIKE(4, 0) 445static inline void 446xo_emit_warn_hcvp (xo_handle_t *xop, int as_warning, int code, 447 const char *fmt, va_list vap) 448{ 449 xo_emit_warn_hcv(xop, as_warning, code, fmt, vap); 450} 451 452PRINTFLIKE(3, 4) 453static inline void 454xo_emit_warn_hcp (xo_handle_t *xop, int code, const char *fmt, ...) 455{ 456 va_list vap; 457 va_start(vap, fmt); 458 xo_emit_warn_hcv(xop, 1, code, fmt, vap); 459 va_end(vap); 460} 461 462PRINTFLIKE(2, 3) 463static inline void 464xo_emit_warn_cp (int code, const char *fmt, ...) 465{ 466 va_list vap; 467 va_start(vap, fmt); 468 xo_emit_warn_hcv(NULL, 1, code, fmt, vap); 469 va_end(vap); 470} 471 472PRINTFLIKE(1, 2) 473static inline void 474xo_emit_warn_p (const char *fmt, ...) 475{ 476 int code = errno; 477 va_list vap; 478 va_start(vap, fmt); 479 xo_emit_warn_hcv(NULL, 1, code, fmt, vap); 480 va_end(vap); 481} 482 483PRINTFLIKE(1, 2) 484static inline void 485xo_emit_warnx_p (const char *fmt, ...) 486{ 487 va_list vap; 488 va_start(vap, fmt); 489 xo_emit_warn_hcv(NULL, 1, -1, fmt, vap); 490 va_end(vap); 491} 492 493NORETURN PRINTFLIKE(2, 3) 494static inline void 495xo_emit_err_p (int eval, const char *fmt, ...) 496{ 497 int code = errno; 498 va_list vap; 499 va_start(vap, fmt); 500 xo_emit_warn_hcv(NULL, 0, code, fmt, vap); 501 va_end(vap); 502 503 exit(eval); 504} 505 506PRINTFLIKE(2, 3) 507static inline void 508xo_emit_errx_p (int eval, const char *fmt, ...) 509{ 510 va_list vap; 511 va_start(vap, fmt); 512 xo_emit_warn_hcv(NULL, 0, -1, fmt, vap); 513 va_end(vap); 514 exit(eval); 515} 516 517PRINTFLIKE(3, 4) 518static inline void 519xo_emit_errc_p (int eval, int code, const char *fmt, ...) 520{ 521 va_list vap; 522 va_start(vap, fmt); 523 xo_emit_warn_hcv(NULL, 0, code, fmt, vap); 524 va_end(vap); 525 exit(eval); 526} 527 528void 529xo_emit_err_v (int eval, int code, const char *fmt, va_list vap) NORETURN PRINTFLIKE(3, 0); 530 531void 532xo_no_setlocale (void); 533 534/** 535 * @brief Lift libxo-specific arguments from a set of arguments 536 * 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 542 * documentation. 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. 546 */ 547int 548xo_parse_args (int argc, char **argv); 549 550/** 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 556 * ozone layer. 557 */ 558#define XO_HAS_LIBXO 121 559 560/** 561 * externs for libxo's version number strings 562 */ 563extern const char xo_version[]; /** Base version triple string */ 564extern const char xo_version_extra[]; /** Extra version magic content */ 565 566/** 567 * @brief Dump the internal stack of a libxo handle. 568 * 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 574 */ 575void 576xo_dump_stack (xo_handle_t *xop); 577 578/** 579 * @brief Recode the name of the program, suitable for error output. 580 * 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 587 */ 588void 589xo_set_program (const char *name); 590 591/** 592 * @brief Add a version string to the output, where possible. 593 * 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 599 */ 600void 601xo_set_version (const char *version); 602 603/** 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 607 */ 608void 609xo_set_version_h (xo_handle_t *xop, const char *version); 610 611void 612xo_open_log (const char *ident, int logopt, int facility); 613 614void 615xo_close_log (void); 616 617int 618xo_set_logmask (int maskpri); 619 620void 621xo_set_unit_test_mode (int value); 622 623void 624xo_syslog (int priority, const char *name, const char *message, ...); 625 626void 627xo_vsyslog (int priority, const char *name, const char *message, va_list args); 628 629typedef void (*xo_syslog_open_t)(void); 630typedef void (*xo_syslog_send_t)(const char *full_msg, 631 const char *v0_hdr, const char *text_only); 632typedef void (*xo_syslog_close_t)(void); 633 634void 635xo_set_syslog_handler (xo_syslog_open_t open_func, xo_syslog_send_t send_func, 636 xo_syslog_close_t close_func); 637 638void 639xo_set_syslog_enterprise_id (unsigned short eid); 640 641typedef void (*xo_simplify_field_func_t)(const char *, unsigned, int); 642 643char * 644xo_simplify_format (xo_handle_t *xop, const char *fmt, int with_numbers, 645 xo_simplify_field_func_t field_cb); 646 647int 648xo_emit_field_hv (xo_handle_t *xop, const char *rolmod, const char *contents, 649 const char *fmt, const char *efmt, 650 va_list vap); 651 652int 653xo_emit_field_h (xo_handle_t *xop, const char *rolmod, const char *contents, 654 const char *fmt, const char *efmt, ...); 655 656int 657xo_emit_field (const char *rolmod, const char *contents, 658 const char *fmt, const char *efmt, ...); 659 660void 661xo_retain_clear_all (void); 662 663void 664xo_retain_clear (const char *fmt); 665 666#endif /* INCLUDE_XO_H */ 667