2 .\" # Copyright (c) 2014, 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
6 .\" # using the SOFTWARE, you agree to be bound by the terms of that
8 .\" # Phil Shafer, July 2014
15 .Nd content of format descriptors for xo_emit
19 uses format strings to control the rendering of data into
20 various output styles, including
26 Each format string contains a set of zero or more
27 .Dq field descriptions ,
28 which describe independent data fields.
29 Each field description contains a set of
34 .Dq format descriptors .
37 what the field is and how to treat it, while the format descriptors are
38 formatting instructions using
39 .Xr printf 3 Ns -style
40 format strings, telling
42 how to format the field.
43 The field description is placed inside
44 a set of braces, with a colon
46 after the modifiers and a slash
48 before each format descriptors.
49 Text may be intermixed with
50 field descriptions within the format string.
52 The field description is given as follows:
53 .Bd -literal -offset indent
54 '{' [ role | modifier ]* ':' [ content ]
55 [ '/' field-format [ '/' encoding-format ]] '}'
58 The role describes the function of the field, while the modifiers
59 enable optional behaviors.
60 The contents, field-format, and
61 encoding-format are used in varying ways, based on the role.
62 These are described in the following sections.
64 In the following example, three field descriptors appear.
66 is a padding field containing three spaces of padding, the second is a
67 label ("In stock"), and the third is a value field ("in-stock").
68 The in-stock field has a "%u" format that will parse the next argument
71 function as an unsigned integer.
72 .Bd -literal -offset indent
73 xo_emit("{P: }{Lwc:In stock}{:in-stock/%u}\\n", 65);
76 This single line of code can generate text ("In stock: 65\\n"), XML
77 ("<in-stock>65</in-stock>"), JSON ('"in-stock": 65'), or HTML (too
78 lengthy to be listed here).
80 Modifiers are optional, and indicate the role and formatting of the
82 The roles are listed below; only one role is permitted:
84 .Bl -column "M" "Name12341234"
85 .It Sy "M Name Description"
86 .It D "decoration " "Field is non-text (e.g. colon, comma)"
87 .It E "error " "Field is an error message"
88 .It L "label " "Field is text that prefixes a value"
89 .It N "note " "Field is text that follows a value"
90 .It P "padding " "Field is spaces needed for vertical alignment"
91 .It T "title " "Field is a title value for headings"
92 .It U "units " "Field is the units for the previous value field"
93 .It V "value " "Field is the name of field (the default)"
94 .It W "warning " "Field is a warning message"
95 .It \&[ "start anchor" "Begin a section of anchored variable-width text"
96 .It \&] "stop anchor " "End a section of anchored variable-width text"
99 .Ss The Color Role ({C:})
100 Colors and effects control how text values are displayed; they are
101 used for display styles (TEXT and HTML).
102 The color content can be
103 either static, when placed directly within the field descriptor, or a
104 printf-style format descriptor can be used, if preceded by a slash ("/"):
105 .Bd -literal -offset indent
106 xo_emit("{C:bold}{Lwc:Cost}{:cost/%u}{C:reset}\n", cost);
107 xo_emit("{C:/fg-%s,bg-%s}{Lwc:Cost}{:cost/%u}{C:reset}\n",
108 fg_color, bg_color, cost);
111 The content should be a comma-separated list of zero or more colors or
114 Colors and effects remain in effect until modified by other "C" roles.
116 If the content is empty, the "reset" action is performed.
118 .Bl -column "no-underline"
119 .It Sy "Name Description"
120 .It "bg-xxxxx " "Change background color"
121 .It "bold " "Start bold text effect"
122 .It "fg-xxxxx " "Change foreground color"
123 .It "inverse " "Start inverse (aka reverse) text effect"
124 .It "no-bold " "Stop bold text effect"
125 .It "no-inverse " "Stop inverse (aka reverse) text effect"
126 .It "no-underline " "Stop underline text effect"
127 .It "normal " "Reset effects (only)"
128 .It "reset " "Reset colors and effects (restore defaults)"
129 .It "underline " "Start underline text effect"
132 The following color names are supported:
133 .Bl -column "no-underline"
146 Color names are prefixed with either "fg-" or "bg-" to change the
147 foreground and background colors, respectively.
148 .Ss The Decoration Role ({D:})
149 Decorations are typically punctuation marks such as colons,
150 semi-colons, and commas used to decorate the text and make it simpler
152 By marking these distinctly, HTML usage scenarios
153 can use CSS to direct their display parameters.
154 .Bd -literal -offset indent
155 xo_emit("{D:((}{:name}{D:))}\\n", name);
157 .Ss The Label Role ({L:})
158 Labels are text that appears before a value.
159 .Bd -literal -offset indent
160 xo_emit("{Lwc:Cost}{:cost/%u}\\n", cost);
162 .Ss The Note Role ({N:})
163 Notes are text that appears after a value.
164 .Bd -literal -offset indent
165 xo_emit("{:cost/%u} {N:per year}\\n", cost);
167 .Ss The Padding Role ({P:})
168 Padding represents whitespace used before and between fields.
169 The padding content can be either static, when placed directly within
170 the field descriptor, or a printf-style format descriptor can be used,
171 if preceded by a slash ("/"):
172 .Bd -literal -offset indent
173 xo_emit("{P: }{Lwc:Cost}{:cost/%u}\\n", cost);
174 xo_emit("{P:/30s}{Lwc:Cost}{:cost/%u}\\n", "", cost);
176 .Ss The Title Role ({T:})
177 Titles are heading or column headers that are meant to be displayed to
179 The title can be either static, when placed directly within
180 the field descriptor, or a printf-style format descriptor can be used,
181 if preceded by a slash ("/"):
182 .Bd -literal -offset indent
183 xo_emit("{T:Interface Statistics}\\n");
184 xo_emit("{T:/%20.20s}{T:/%6.6s}\\n", "Item Name", "Cost");
186 .Ss The Units Role ({U:})
187 Units are the dimension by which values are measured, such as degrees,
188 miles, bytes, and decibels.
189 The units field carries this information
190 for the previous value field.
191 .Bd -literal -offset indent
192 xo_emit("{Lwc:Distance}{:distance/%u}{Uw:miles}\\n", miles);
195 Note that the sense of the 'w' modifier is reversed for units;
196 a blank is added before the contents, rather than after it.
200 flag is set, units are rendered in XML as the
203 .Bd -literal -offset indent
204 <distance units="miles">50</distance>
207 Units can also be rendered in HTML as the "data-units" attribute:
208 .Bd -literal -offset indent
209 <div class="data" data-tag="distance" data-units="miles"
210 data-xpath="/top/data/distance">50</div>
212 .Ss The Value Role ({V:} and {:})
213 The value role is used to represent the a data value that is
214 interesting for the non-display output styles (XML and JSON).
216 is the default role; if no other role designation is given, the field
218 The field name must appear within the field descriptor,
219 followed by one or two format descriptors.
221 descriptor is used for display styles (TEXT and HTML), while the
222 second one is used for encoding styles (XML and JSON).
224 format is given, the encoding format defaults to the first format,
225 with any minimum width removed.
226 If no first format is given, both
227 format descriptors default to "%s".
228 .Bd -literal -offset indent
229 xo_emit("{:length/%02u}x{:width/%02u}x{:height/%02u}\\n",
230 length, width, height);
231 xo_emit("{:author} wrote \"{:poem}\" in {:year/%4d}\\n,
234 .Ss The Anchor Modifiers ({[:} and {]:})
235 The anchor roles allow a set of strings by be padded as a group,
236 but still be visible to
240 or stop anchor can give a field width and it can be either directly in
241 the descriptor or passed as an argument.
242 Any fields between the start
243 and stop anchor are padded to meet the minimum width given.
245 To give a width directly, encode it as the content of the anchor tag:
246 .Bd -literal -offset indent
247 xo_emit("({[:10}{:min/%d}/{:max/%d}{]:})\\n", min, max);
250 To pass a width as an argument, use "%d" as the format, which must
251 appear after the "/".
252 Note that only "%d" is supported for widths.
253 Using any other value could ruin your day.
254 .Bd -literal -offset indent
255 xo_emit("({[:/%d}{:min/%d}/{:max/%d}{]:})\\n", width, min, max);
258 If the width is negative, padding will be added on the right, suitable
259 for left justification.
260 Otherwise the padding will be added to the
261 left of the fields between the start and stop anchors, suitable for
263 If the width is zero, nothing happens.
265 number of columns of output between the start and stop anchors is less
266 than the absolute value of the given width, nothing happens.
268 Widths over 8k are considered probable errors and not supported.
271 is set, a warning will be generated.
273 The modifiers can also include the following flags, which modify the
274 content emitted for some output styles:
276 .Bl -column M "Name12341234"
277 .It Sy M "Name Description"
278 .It c "colon " "A colon ("":"") is appended after the label"
279 .It d "display " "Only emit field for display styles (text/HTML)"
280 .It e "encoding " "Only emit for encoding styles (XML/JSON)"
281 .It k "key " "Field is a key, suitable for XPath predicates"
282 .It l "leaf " "Field is a leaf-list, a list of leaf values"
283 .It n "no-quotes " "Do not quote the field when using JSON style"
284 .It q "quotes " "Quote the field when using JSON style"
285 .It w "white space " "A blank ("" "") is appended after the label"
288 For example, the modifier string "Lwc" means the field has a label
289 role (text that describes the next field) and should be followed by a
290 colon ('c') and a space ('w').
291 The modifier string "Vkq" means the
292 field has a value role, that it is a key for the current instance, and
293 that the value should be quoted when encoded for JSON.
294 .Ss The Colon Modifier ({c:})
295 The colon modifier appends a single colon to the data value:
296 .Bd -literal -offset indent
298 xo_emit("{Lc:Name}{:name}\\n", "phil");
303 The colon modifier is only used for the TEXT and HTML output
305 It is commonly combined with the space modifier ('{w:}').
306 It is purely a convenience feature.
307 .Ss The Display Modifier ({d:})
308 The display modifier indicated the field should only be generated for
309 the display output styles, TEXT and HTML.
310 .Bd -literal -offset indent
312 xo_emit("{Lcw:Name}{d:name} {:id/%d}\\n", "phil", 1);
319 The display modifier is the opposite of the encoding modifier, and
320 they are often used to give to distinct views of the underlying data.
321 .Ss The Encoding Modifier ({e:})
322 The encoding modifier indicated the field should only be generated for
323 the encoding output styles, such as JSON and XML.
324 .Bd -literal -offset indent
326 xo_emit("{Lcw:Name}{:name} {e:id/%d}\\n", "phil", 1);
330 <name>phil</name><id>1</id>
333 The encoding modifier is the opposite of the display modifier, and
334 they are often used to give to distinct views of the underlying data.
335 .Ss The Key Modifier ({k:})
336 The key modifier is used to indicate that a particular field helps
337 uniquely identify an instance of list data.
338 .Bd -literal -offset indent
340 xo_open_list("user");
341 for (i = 0; i < num_users; i++) {
342 xo_open_instance("user");
343 xo_emit("User {k:name} has {:count} tickets\\n",
344 user[i].u_name, user[i].u_tickets);
345 xo_close_instance("user");
347 xo_close_list("user");
350 Currently the key modifier is only used when generating XPath values
351 for the HTML output style when
353 is set, but other uses are likely in the near future.
354 .Ss The Leaf-List Modifier ({l:})
355 The leaf-list modifier is used to distinguish lists where each
356 instance consists of only a single value. In XML, these are
357 rendered as single elements, where JSON renders them as arrays.
358 .Bd -literal -offset indent
360 xo_open_list("user");
361 for (i = 0; i < num_users; i++) {
362 xo_emit("Member {l:name}\n", user[i].u_name);
364 xo_close_list("user");
369 "user": [ "phil", "pallavi" ]
371 .Ss The No-Quotes Modifier ({n:})
372 The no-quotes modifier (and its twin, the 'quotes' modifier) affect
373 the quoting of values in the JSON output style.
375 string values, but no quotes for numeric, boolean, and null data.
377 applies a simple heuristic to determine whether quotes are
378 needed, but often this needs to be controlled by the caller.
379 .Bd -literal -offset indent
381 const char *bool = is_true ? "true" : "false";
382 xo_emit("{n:fancy/%s}", bool);
386 .Ss The Quotes Modifier ({q:})
387 The quotes modifier (and its twin, the 'no-quotes' modifier) affect
388 the quoting of values in the JSON output style.
390 string values, but no quotes for numeric, boolean, and null data.
392 applies a simple heuristic to determine whether quotes are
393 needed, but often this needs to be controlled by the caller.
394 .Bd -literal -offset indent
396 xo_emit("{q:time/%d}", 2014);
400 .Ss The White Space Modifier ({w:})
401 The white space modifier appends a single space to the data value:
402 .Bd -literal -offset indent
404 xo_emit("{Lw:Name}{:name}\\n", "phil");
409 The white space modifier is only used for the TEXT and HTML output
411 It is commonly combined with the colon modifier ('{c:}').
412 It is purely a convenience feature.
414 Note that the sense of the 'w' modifier is reversed for the units role
415 ({Uw:}); a blank is added before the contents, rather than after it.
417 The field format is similar to the format string for
419 Its use varies based on the role of the field, but generally is used to
420 format the field's contents.
422 If the format string is not provided for a value field, it defaults
425 Note a field definition can contain zero or more printf-style
427 which are sequences that start with a '%' and end with
428 one of following characters: "diouxXDOUeEfFgGaAcCsSp".
430 is matched by one of more arguments to the
434 The format string has the form:
435 .Bd -literal -offset indent
436 '%' format-modifier * format-character
439 The format- modifier can be:
442 a '#' character, indicating the output value should be prefixed with
443 '0x', typically to indicate a base 16 (hex) value.
445 a minus sign ('-'), indicating the output value should be padded on
446 the right instead of the left.
448 a leading zero ('0') indicating the output value should be padded on the
449 left with zeroes instead of spaces (' ').
451 one or more digits ('0' - '9') indicating the minimum width of the
453 If the width in columns of the output value is less than
454 the minimum width, the value will be padded to reach the minimum.
456 a period followed by one or more digits indicating the maximum
457 number of bytes which will be examined for a string argument, or the maximum
458 width for a non-string argument.
459 When handling ASCII strings this
460 functions as the field width but for multi-byte characters, a single
461 character may be composed of multiple bytes.
463 will never dereference memory beyond the given number of bytes.
465 a second period followed by one or more digits indicating the maximum
466 width for a string argument.
467 This modifier cannot be given for non-string arguments.
469 one or more 'h' characters, indicating shorter input data.
471 one or more 'l' characters, indicating longer input data.
473 a 'z' character, indicating a 'size_t' argument.
475 a 't' character, indicating a 'ptrdiff_t' argument.
477 a ' ' character, indicating a space should be emitted before
480 a '+' character, indicating sign should emitted before any number.
483 Note that 'q', 'D', 'O', and 'U' are considered deprecated and will be
486 The format character is described in the following table:
488 .Bl -column C "Argument Type12"
489 .It Sy "C Argument Type Format"
490 .It d "int " "base 10 (decimal)"
491 .It i "int " "base 10 (decimal)"
492 .It o "int " "base 8 (octal)"
493 .It u "unsigned " "base 10 (decimal)"
494 .It x "unsigned " "base 16 (hex)"
495 .It X "unsigned long " "base 16 (hex)"
496 .It D "long " "base 10 (decimal)"
497 .It O "unsigned long " "base 8 (octal)"
498 .It U "unsigned long " "base 10 (decimal)"
499 .It e "double " "[-]d.ddde+-dd"
500 .It E "double " "[-]d.dddE+-dd"
501 .It f "double " "[-]ddd.ddd"
502 .It F "double " "[-]ddd.ddd"
503 .It g "double " "as 'e' or 'f'"
504 .It G "double " "as 'E' or 'F'"
505 .It a "double " "[-]0xh.hhhp[+-]d"
506 .It A "double " "[-]0Xh.hhhp[+-]d"
507 .It c "unsigned char " "a character"
508 .It C "wint_t " "a character"
509 .It s "char * " "a UTF-8 string"
510 .It S "wchar_t * " "a unicode/WCS string"
511 .It p "void * " "'%#lx'"
514 The 'h' and 'l' modifiers affect the size and treatment of the
516 .Bl -column "Mod" "d, i " "o, u, x, X "
517 .It Sy "Mod" "d, i " "o, u, x, X"
518 .It "hh " "signed char " "unsigned char"
519 .It "h " "short " "unsigned short"
520 .It "l " "long " "unsigned long"
521 .It "ll " "long long " "unsigned long long"
522 .It "j " "intmax_t " "uintmax_t"
523 .It "t " "ptrdiff_t " "ptrdiff_t"
524 .It "z " "size_t " "size_t"
525 .It "q " "quad_t " "u_quad_t"
528 .Ss UTF-8 and Locale Strings
533 will handle turning them
534 into locale-based strings for display to the user.
536 For strings, the 'h' and 'l' modifiers affect the interpretation of
537 the bytes pointed to argument.
538 The default '%s' string is a 'char *'
539 pointer to a string encoded as UTF-8.
540 Since UTF-8 is compatible with
546 'wchar_t *' pointer to a wide-character string, encoded as 32-bit
548 '%hs' expects a 'char *' pointer to a multi-byte
549 string encoded with the current locale, as given by the
554 environment variables.
555 The first of this list of
556 variables is used and if none of the variables are set, the locale defaults to
561 convert these arguments as needed to either UTF-8 (for XML, JSON, and
562 HTML styles) or locale-based strings for display in text style.
563 .Bd -literal -offset indent
564 xo_emit("All strings are utf-8 content {:tag/%ls}",
565 L"except for wide strings");
568 "%S" is equivalent to "%ls".
570 For example, a function is passed a locale-base name, a hat size,
572 The hat size is formatted in a UTF-8 (ASCII)
573 string, and the time value is formatted into a wchar_t string.
574 .Bd -literal -offset indent
575 void print_order (const char *name, int size,
578 const char *size_val = "unknown";
581 snprintf(buf, sizeof(buf), "%d", size);
586 wcsftime(when, sizeof(when), L"%d%b%y", timep);
588 xo_emit("The hat for {:name/%hs} is {:size/%s}.\\n",
590 xo_emit("It was ordered on {:order-time/%ls}.\\n",
595 It is important to note that
597 will perform the conversion
598 required to make appropriate output.
599 Text style output uses the
600 current locale (as described above), while XML, JSON, and HTML use
603 UTF-8 and locale-encoded strings can use multiple bytes to encode one
605 The traditional "precision'" (aka "max-width") value
606 for "%s" printf formatting becomes overloaded since it specifies both
607 the number of bytes that can be safely referenced and the maximum
608 number of columns to emit.
610 uses the precision as the former,
611 and adds a third value for specifying the maximum number of columns.
613 In this example, the name field is printed with a minimum of 3 columns
615 Up to ten bytes are in used in filling those columns.
616 .Bd -literal -offset indent
617 xo_emit("{:name/%3.10.6s}", name);
619 .Ss Characters Outside of Field Definitions
620 Characters in the format string that are not part of a field definition are
621 copied to the output for the TEXT style, and are ignored for the JSON
623 For HTML, these characters are placed in a <div> with class "text".
624 .Bd -literal -offset indent
626 xo_emit("The hat is {:size/%s}.\\n", size_val);
628 The hat is extra small.
630 <size>extra small</size>
632 "size": "extra small"
634 <div class="text">The hat is </div>
635 <div class="data" data-tag="size">extra small</div>
636 <div class="text">.</div>
638 .Ss "%n" is Not Supported
640 does not support the '%n' directive.
641 It is a bad idea and we
643 .Ss The Encoding Format (eformat)
644 The "eformat" string is the format string used when encoding the field
646 If not provided, it defaults to the primary format
647 with any minimum width removed.
648 If the primary is not given, both default to "%s".
650 In this example, the value for the number of items in stock is emitted:
651 .Bd -literal -offset indent
652 xo_emit("{P: }{Lwc:In stock}{:in-stock/%u}\\n",
656 This call will generate the following output:
657 .Bd -literal -offset indent
661 <in-stock>144</in-stock>
666 <div class="padding"> </div>
667 <div class="label">In stock</div>
668 <div class="decoration">:</div>
669 <div class="padding"> </div>
670 <div class="data" data-tag="in-stock">144</div>
674 Clearly HTML wins the verbosity award, and this output does
679 data, which would expand the penultimate line to:
680 .Bd -literal -offset indent
681 <div class="data" data-tag="in-stock"
682 data-xpath="/top/data/item/in-stock"
684 data-help="Number of items in stock">144</div>
686 .Sh WHAT MAKES A GOOD FIELD NAME?
687 To make useful, consistent field names, follow these guidelines:
689 .Ss Use lower case, even for TLAs
690 Lower case is more civilized.
691 Even TLAs should be lower case
692 to avoid scenarios where the differences between "XPath" and
693 "Xpath" drive your users crazy.
694 Using "xpath" is simpler and better.
695 .Ss Use hyphens, not underscores
696 Use of hyphens is traditional in XML, and the
698 flag can be used to generate underscores in JSON, if desired.
699 But the raw field name should use hyphens.
701 Do not abbreviate especially when the abbreviation is not obvious or
703 Use "data-size", not "dsz" or "dsize".
705 "interface" instead of "ifname", "if-name", "iface", "if", or "intf".
706 .Ss Use <verb>-<units>
707 Using the form <verb>-<units> or <verb>-<classifier>-<units> helps in
708 making consistent, useful names, avoiding the situation where one app
709 uses "sent-packet" and another "packets-sent" and another
710 "packets-we-have-sent".
711 The <units> can be dropped when it is
712 obvious, as can obvious words in the classification.
713 Use "receive-after-window-packets" instead of
714 "received-packets-of-data-after-window".
715 .Ss Reuse existing field names
716 Nothing is worse than writing expressions like:
717 .Bd -literal -offset indent
718 if ($src1/process[pid == $pid]/name ==
719 $src2/proc-table/proc/p[process-id == $pid]/proc-name) {
724 Find someone else who is expressing similar data and follow their
725 fields and hierarchy.
726 Remember the quote is not
727 .Dq Consistency is the hobgoblin of little minds
729 .Dq A foolish consistency is the hobgoblin of little minds .
730 .Ss Think about your users
731 Have empathy for your users, choosing clear and useful fields that
732 contain clear and useful data.
733 You may need to augment the display content with
735 calls or "{e:}" fields to make the data useful.
736 .Ss Do not use an arbitrary number postfix
737 What does "errors2" mean?
739 "errors-after-restart" would be a better choice.
740 Think of your users, and think of the future.
741 If you make "errors2", the next guy will happily make
742 "errors3" and before you know it, someone will be asking what is the
743 difference between errors37 and errors63.
744 .Ss Be consistent, uniform, unsurprising, and predictable
745 Think of your field vocabulary as an API.
747 expressive, meaningful, direct, and obvious.
749 application's programmer to move between without the need to
750 understand a variety of opinions on how fields are named.
752 see the system as a single cohesive whole, not a sack of cats.
754 Field names constitute the means by which client programmers interact
756 By choosing wise names now, you are making their lives better.
760 to find errors in your field descriptors, use
762 to spell check your field names and to detect different
763 names for the same data.
766 .Dq dropped-too-short
767 are both reasonable names, but using them both will lead users to ask the
768 difference between the two fields.
769 If there is no difference,
770 use only one of the field names.
771 If there is a difference, change the
772 names to make that difference more obvious.
773 .Sh ADDITIONAL DOCUMENTATION
774 Complete documentation can be found on github:
775 .Bd -literal -offset indent
776 http://juniper.github.io/libxo/libxo-manual.html
781 .Bd -literal -offset indent
782 https://github.com/Juniper/libxo
785 The latest release of
788 .Bd -literal -offset indent
789 https://github.com/Juniper/libxo/releases