Import libxo 1.3.0
This commit is contained in:
parent
9e479b3455
commit
0922e92a30
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/vendor/Juniper/libxo/dist/; revision=354425 svn path=/vendor/Juniper/libxo/1.3.0/; revision=354426; tag=vendor/Juniper/libxo/1.3.0
23
Makefile.am
23
Makefile.am
@ -32,7 +32,6 @@ errors:
|
||||
docs:
|
||||
@(cd doc ; ${MAKE} docs)
|
||||
|
||||
|
||||
DIST_FILES_DIR = ~/Dropbox/dist-files/
|
||||
GH_PAGES_DIR = gh-pages/
|
||||
GH_PAGES_DIR_VER = gh-pages/${PACKAGE_VERSION}
|
||||
@ -49,18 +48,20 @@ upload: dist upload-docs upload-xohtml-files
|
||||
@echo "Remember to run:"
|
||||
@echo " gt tag ${PACKAGE_VERSION}"
|
||||
|
||||
upload-docs: docs
|
||||
@echo "Uploading libxo-manual.html ... "
|
||||
@-[ -d ${GH_PAGES_DIR} ] \
|
||||
&& echo "Updating manual on gh-pages ..." \
|
||||
&& mkdir -p ${GH_PAGES_DIR_VER} \
|
||||
&& cp doc/libxo-manual.html ${GH_PAGES_DIR} \
|
||||
&& cp doc/libxo-manual.html ${GH_PAGES_DIR_VER} \
|
||||
upload-docs: docs upload-html
|
||||
|
||||
upload-html:
|
||||
@echo "Uploading html ... "
|
||||
@-[ -d ${GH_PAGES_DIR} -a -d doc/html ] \
|
||||
&& echo "Updating html on gh-pages ..." \
|
||||
&& mkdir -p ${GH_PAGES_DIR_VER}/html \
|
||||
&& cp doc/top-link.html ${GH_PAGES_DIR}/libxo.html \
|
||||
&& cp -r doc/html/* ${GH_PAGES_DIR_VER}/html/ \
|
||||
&& (cd ${GH_PAGES_DIR} \
|
||||
&& git add ${PACKAGE_VERSION} \
|
||||
&& git add libxo-manual.html \
|
||||
&& git add libxo.html \
|
||||
&& git add ${PACKAGE_VERSION}/html \
|
||||
&& git commit -m 'new docs' \
|
||||
libxo-manual.html ${PACKAGE_VERSION} \
|
||||
libxo.html ${PACKAGE_VERSION}/html \
|
||||
&& git push origin gh-pages ) ; true
|
||||
|
||||
upload-xohtml-files:
|
||||
|
@ -10,6 +10,9 @@ application calls a function "xo_emit" to product output that is
|
||||
described in a format string. A "field descriptor" tells libxo what
|
||||
the field is and what it means.
|
||||
|
||||
Imagine a simplified ``wc`` that emits its output fields in a single
|
||||
xo_emit call:
|
||||
|
||||
```
|
||||
xo_emit(" {:lines/%7ju/%ju} {:words/%7ju/%ju} "
|
||||
"{:characters/%7ju/%ju}{d:filename/%s}\n",
|
||||
|
@ -12,7 +12,7 @@
|
||||
#
|
||||
|
||||
AC_PREREQ(2.2)
|
||||
AC_INIT([libxo], [1.0.4], [phil@juniper.net])
|
||||
AC_INIT([libxo], [1.3.0], [phil@juniper.net])
|
||||
AM_INIT_AUTOMAKE([-Wall -Werror foreign -Wno-portability])
|
||||
|
||||
# Support silent build rules. Requires at least automake-1.11.
|
||||
@ -452,6 +452,7 @@ AC_CONFIG_FILES([
|
||||
libxo/add.man
|
||||
encoder/Makefile
|
||||
encoder/cbor/Makefile
|
||||
encoder/csv/Makefile
|
||||
encoder/test/Makefile
|
||||
xo/Makefile
|
||||
xolint/Makefile
|
||||
@ -459,6 +460,7 @@ AC_CONFIG_FILES([
|
||||
xopo/Makefile
|
||||
packaging/libxo.pc
|
||||
doc/Makefile
|
||||
doc/top-link.html
|
||||
tests/Makefile
|
||||
tests/core/Makefile
|
||||
tests/gettext/Makefile
|
||||
|
@ -8,68 +8,22 @@
|
||||
# using the SOFTWARE, you agree to be bound by the terms of that
|
||||
# LICENSE.
|
||||
|
||||
if HAVE_OXTRADOC
|
||||
OXTRADOC_DIR = ${SLAX_OXTRADOCDIR}
|
||||
OXTRADOC_PREFIX = ${OXTRADOC_DIR}
|
||||
OXTRADOC = ${OXTRADOC_DIR}/oxtradoc
|
||||
SLAXPROC_BINDIR = ${SLAX_BINDIR}
|
||||
doc docs: xolint.rst html
|
||||
|
||||
XML2RFC = ${OXTRADOC_DIR}/xml2rfc.tcl
|
||||
XML2HTMLDIR = ${OXTRADOC_DIR}
|
||||
XML2HTMLBIN = ${XML2HTMLDIR}/rfc2629-to-html.slax
|
||||
SLAXPROC = ${SLAX_BINDIR}/slaxproc
|
||||
#
|
||||
# The contents of xolint.rst is generated based on xolint.pl, since we
|
||||
# really want this to be self-documenting. But readthedocs.org needs this
|
||||
# data to be _in_ repo. So we generate this file on command only, and
|
||||
# the developer needs to commit any changes.
|
||||
#
|
||||
|
||||
SLAXPROC_ARGS = \
|
||||
-a oxtradoc-dir ${OXTRADOC_DIR} \
|
||||
-a oxtradoc-install-dir ${OXTRADOC_DIR} \
|
||||
-a anchor-prefix docs
|
||||
xolint.rst: ${top_srcdir}/xolint/xolint.pl
|
||||
perl ${top_srcdir}/xolint/xolint.pl -D > ${top_srcdir}/doc/xolint.rst
|
||||
|
||||
SLAXPROC_ARGS_INLINE = \
|
||||
-a oxtradoc-inline yes
|
||||
|
||||
SLAXPROC_ARGS += ${SLAXPROC_ARGS_INLINE}
|
||||
|
||||
XML2HTML = \
|
||||
${SLAXPROC} -g -e -I ${OXTRADOC_DIR} -I . \
|
||||
${SLAXPROC_ARGS} \
|
||||
${XML2HTMLBIN}
|
||||
|
||||
OX_ARGS = -P ${OXTRADOC_PREFIX} -L ${OXTRADOC_PREFIX}
|
||||
OX_ARGS += -S ${SLAXPROC} -p doc
|
||||
OX_CMD = ${PERL} ${PERLOPTS} ${OXTRADOC} ${OX_ARGS}
|
||||
OXTRADOC_CMD = ${OX_CMD}
|
||||
|
||||
OUTPUT = libxo-manual
|
||||
INPUT = libxo
|
||||
|
||||
EXTRA_DIST = \
|
||||
${INPUT}.txt \
|
||||
${OUTPUT}.html \
|
||||
${OUTPUT}.txt
|
||||
|
||||
doc docs: ${OUTPUT}.txt ${OUTPUT}.html
|
||||
|
||||
${OUTPUT}.txt: ${INPUT}.txt ${OXTRADOC} xolint.txt
|
||||
${OXTRADOC_CMD} -m text -o $@ $<
|
||||
|
||||
${OUTPUT}.html: ${INPUT}.txt ${OXTRADOC} ${XML2HTMLBIN} xolint.txt
|
||||
${OXTRADOC_CMD} -m html -o $@ $<
|
||||
|
||||
xolint.txt: ${top_srcdir}/xolint/xolint.pl
|
||||
perl ${top_srcdir}/xolint/xolint.pl -D > xolint.txt
|
||||
|
||||
CLEANFILES = \
|
||||
xolint.txt \
|
||||
${INPUT}.xml \
|
||||
${INPUT}.fxml \
|
||||
${OUTPUT}.txt \
|
||||
${OUTPUT}.html
|
||||
else
|
||||
doc docs:
|
||||
@${ECHO} "The 'oxtradoc' tool is not installed; see libslax.org"
|
||||
endif
|
||||
|
||||
SPHINX = python3.4 -msphinx
|
||||
SPHINX = python3 -msphinx
|
||||
|
||||
html sphinx sphinx-html:
|
||||
${SPHINX} -M html ${srcdir} .
|
||||
${SPHINX} -M html ${srcdir} . -N -E
|
||||
|
||||
singlehtml:
|
||||
${SPHINX} -M singlehtml ${srcdir} . -N -E
|
||||
|
196
doc/api.rst
196
doc/api.rst
@ -1,4 +1,4 @@
|
||||
.. index: API
|
||||
.. index:: API
|
||||
|
||||
The libxo API
|
||||
=============
|
||||
@ -155,14 +155,14 @@ Output Styles (XO_STYLE\_\*)
|
||||
|
||||
The libxo functions accept a set of output styles:
|
||||
|
||||
=============== =========================
|
||||
Flag Description
|
||||
=============== =========================
|
||||
XO_STYLE_TEXT Traditional text output
|
||||
XO_STYLE_XML XML encoded data
|
||||
XO_STYLE_JSON JSON encoded data
|
||||
XO_STYLE_HTML HTML encoded data
|
||||
=============== =========================
|
||||
=============== =========================
|
||||
Flag Description
|
||||
=============== =========================
|
||||
XO_STYLE_TEXT Traditional text output
|
||||
XO_STYLE_XML XML encoded data
|
||||
XO_STYLE_JSON JSON encoded data
|
||||
XO_STYLE_HTML HTML encoded data
|
||||
=============== =========================
|
||||
|
||||
The "XML", "JSON", and "HTML" output styles all use the UTF-8
|
||||
character encoding. "TEXT" using locale-based encoding.
|
||||
@ -256,26 +256,26 @@ Flags (XOF\_\*)
|
||||
|
||||
The set of valid flags include:
|
||||
|
||||
=================== =========================================
|
||||
Flag Description
|
||||
=================== =========================================
|
||||
XOF_CLOSE_FP Close file pointer on `xo_destroy`
|
||||
XOF_COLOR Enable color and effects in output
|
||||
XOF_COLOR_ALLOWED Allow color/effect for terminal output
|
||||
XOF_DTRT Enable "do the right thing" mode
|
||||
XOF_INFO Display info data attributes (HTML)
|
||||
XOF_KEYS Emit the key attribute (XML)
|
||||
XOF_NO_ENV Do not use the :ref:`libxo-options` env var
|
||||
XOF_NO_HUMANIZE Display humanization (TEXT, HTML)
|
||||
XOF_PRETTY Make "pretty printed" output
|
||||
XOF_UNDERSCORES Replaces hyphens with underscores
|
||||
XOF_UNITS Display units (XML, HMTL)
|
||||
XOF_WARN Generate warnings for broken calls
|
||||
XOF_WARN_XML Generate warnings in XML on stdout
|
||||
XOF_XPATH Emit XPath expressions (HTML)
|
||||
XOF_COLUMNS Force xo_emit to return columns used
|
||||
XOF_FLUSH Flush output after each `xo_emit` call
|
||||
=================== =========================================
|
||||
=================== =========================================
|
||||
Flag Description
|
||||
=================== =========================================
|
||||
XOF_CLOSE_FP Close file pointer on `xo_destroy`
|
||||
XOF_COLOR Enable color and effects in output
|
||||
XOF_COLOR_ALLOWED Allow color/effect for terminal output
|
||||
XOF_DTRT Enable "do the right thing" mode
|
||||
XOF_INFO Display info data attributes (HTML)
|
||||
XOF_KEYS Emit the key attribute (XML)
|
||||
XOF_NO_ENV Do not use the :ref:`libxo-options` env var
|
||||
XOF_NO_HUMANIZE Display humanization (TEXT, HTML)
|
||||
XOF_PRETTY Make "pretty printed" output
|
||||
XOF_UNDERSCORES Replaces hyphens with underscores
|
||||
XOF_UNITS Display units (XML, HMTL)
|
||||
XOF_WARN Generate warnings for broken calls
|
||||
XOF_WARN_XML Generate warnings in XML on stdout
|
||||
XOF_XPATH Emit XPath expressions (HTML)
|
||||
XOF_COLUMNS Force xo_emit to return columns used
|
||||
XOF_FLUSH Flush output after each `xo_emit` call
|
||||
=================== =========================================
|
||||
|
||||
The `XOF_CLOSE_FP` flag will trigger the call of the *close_func*
|
||||
(provided via `xo_set_writer`) when the handle is destroyed.
|
||||
@ -300,12 +300,12 @@ regardless of whether warnings are enabled.
|
||||
If the style is `XO_STYLE_HTML`, the following additional flags can be
|
||||
used:
|
||||
|
||||
=============== =========================================
|
||||
Flag Description
|
||||
=============== =========================================
|
||||
XOF_XPATH Emit "data-xpath" attributes
|
||||
XOF_INFO Emit additional info fields
|
||||
=============== =========================================
|
||||
=============== =========================================
|
||||
Flag Description
|
||||
=============== =========================================
|
||||
XOF_XPATH Emit "data-xpath" attributes
|
||||
XOF_INFO Emit additional info fields
|
||||
=============== =========================================
|
||||
|
||||
The `XOF_XPATH` flag enables the emission of XPath expressions detailing
|
||||
the hierarchy of XML elements used to encode the data field, if the
|
||||
@ -317,11 +317,11 @@ output. See :ref:`field-information` for details.
|
||||
If the style is `XO_STYLE_XML`, the following additional flags can be
|
||||
used:
|
||||
|
||||
=============== =========================================
|
||||
Flag Description
|
||||
=============== =========================================
|
||||
XOF_KEYS Flag "key" fields for XML
|
||||
=============== =========================================
|
||||
=============== =========================================
|
||||
Flag Description
|
||||
=============== =========================================
|
||||
XOF_KEYS Flag "key" fields for XML
|
||||
=============== =========================================
|
||||
|
||||
The `XOF_KEYS` flag adds "key" attribute to the XML encoding for
|
||||
field definitions that use the "k" modifier. The key attribute has
|
||||
@ -1308,52 +1308,52 @@ These values are defined in <syslog.h>.
|
||||
The priority value indicates the importance and potential impact of
|
||||
each message:
|
||||
|
||||
============= =======================================================
|
||||
Priority Description
|
||||
============= =======================================================
|
||||
LOG_EMERG A panic condition, normally broadcast to all users
|
||||
LOG_ALERT A condition that should be corrected immediately
|
||||
LOG_CRIT Critical conditions
|
||||
LOG_ERR Generic errors
|
||||
LOG_WARNING Warning messages
|
||||
LOG_NOTICE Non-error conditions that might need special handling
|
||||
LOG_INFO Informational messages
|
||||
LOG_DEBUG Developer-oriented messages
|
||||
============= =======================================================
|
||||
============= =======================================================
|
||||
Priority Description
|
||||
============= =======================================================
|
||||
LOG_EMERG A panic condition, normally broadcast to all users
|
||||
LOG_ALERT A condition that should be corrected immediately
|
||||
LOG_CRIT Critical conditions
|
||||
LOG_ERR Generic errors
|
||||
LOG_WARNING Warning messages
|
||||
LOG_NOTICE Non-error conditions that might need special handling
|
||||
LOG_INFO Informational messages
|
||||
LOG_DEBUG Developer-oriented messages
|
||||
============= =======================================================
|
||||
|
||||
The facility value indicates the source of message, in fairly generic
|
||||
terms:
|
||||
|
||||
=============== =======================================================
|
||||
Facility Description
|
||||
=============== =======================================================
|
||||
LOG_AUTH The authorization system (e.g. :manpage:`login(1)`)
|
||||
LOG_AUTHPRIV As LOG_AUTH, but logged to a privileged file
|
||||
LOG_CRON The cron daemon: :manpage:`cron(8)`
|
||||
LOG_DAEMON System daemons, not otherwise explicitly listed
|
||||
LOG_FTP The file transfer protocol daemons
|
||||
LOG_KERN Messages generated by the kernel
|
||||
LOG_LPR The line printer spooling system
|
||||
LOG_MAIL The mail system
|
||||
LOG_NEWS The network news system
|
||||
LOG_SECURITY Security subsystems, such as :manpage:`ipfw(4)`
|
||||
LOG_SYSLOG Messages generated internally by :manpage:`syslogd(8)`
|
||||
LOG_USER Messages generated by user processes (default)
|
||||
LOG_UUCP The uucp system
|
||||
LOG_LOCAL0..7 Reserved for local use
|
||||
=============== =======================================================
|
||||
=============== =======================================================
|
||||
Facility Description
|
||||
=============== =======================================================
|
||||
LOG_AUTH The authorization system (e.g. :manpage:`login(1)`)
|
||||
LOG_AUTHPRIV As LOG_AUTH, but logged to a privileged file
|
||||
LOG_CRON The cron daemon: :manpage:`cron(8)`
|
||||
LOG_DAEMON System daemons, not otherwise explicitly listed
|
||||
LOG_FTP The file transfer protocol daemons
|
||||
LOG_KERN Messages generated by the kernel
|
||||
LOG_LPR The line printer spooling system
|
||||
LOG_MAIL The mail system
|
||||
LOG_NEWS The network news system
|
||||
LOG_SECURITY Security subsystems, such as :manpage:`ipfw(4)`
|
||||
LOG_SYSLOG Messages generated internally by :manpage:`syslogd(8)`
|
||||
LOG_USER Messages generated by user processes (default)
|
||||
LOG_UUCP The uucp system
|
||||
LOG_LOCAL0..7 Reserved for local use
|
||||
=============== =======================================================
|
||||
|
||||
In addition to the values listed above, xo_open_log accepts a set of
|
||||
addition flags requesting specific logging behaviors:
|
||||
|
||||
============ ====================================================
|
||||
Flag Description
|
||||
============ ====================================================
|
||||
LOG_CONS If syslogd fails, attempt to write to /dev/console
|
||||
LOG_NDELAY Open the connection to :manpage:`syslogd(8)` immediately
|
||||
LOG_PERROR Write the message also to standard error output
|
||||
LOG_PID Log the process id with each message
|
||||
============ ====================================================
|
||||
============ ====================================================
|
||||
Flag Description
|
||||
============ ====================================================
|
||||
LOG_CONS If syslogd fails, attempt to write to /dev/console
|
||||
LOG_NDELAY Open the connection to :manpage:`syslogd(8)` immediately
|
||||
LOG_PERROR Write the message also to standard error output
|
||||
LOG_PID Log the process id with each message
|
||||
============ ====================================================
|
||||
|
||||
.. index:: xo_syslog
|
||||
|
||||
@ -1588,26 +1588,26 @@ processing model of libxo. Content is formatted within libxo, and
|
||||
callbacks are made to the encoder's handler function when data is
|
||||
ready to be processed:
|
||||
|
||||
======================= =======================================
|
||||
Operation Meaning (Base function)
|
||||
======================= =======================================
|
||||
XO_OP_CREATE Called when the handle is created
|
||||
XO_OP_OPEN_CONTAINER Container opened (xo_open_container)
|
||||
XO_OP_CLOSE_CONTAINER Container closed (xo_close_container)
|
||||
XO_OP_OPEN_LIST List opened (xo_open_list)
|
||||
XO_OP_CLOSE_LIST List closed (xo_close_list)
|
||||
XO_OP_OPEN_LEAF_LIST Leaf list opened (xo_open_leaf_list)
|
||||
XO_OP_CLOSE_LEAF_LIST Leaf list closed (xo_close_leaf_list)
|
||||
XO_OP_OPEN_INSTANCE Instance opened (xo_open_instance)
|
||||
XO_OP_CLOSE_INSTANCE Instance closed (xo_close_instance)
|
||||
XO_OP_STRING Field with Quoted UTF-8 string
|
||||
XO_OP_CONTENT Field with content
|
||||
XO_OP_FINISH Finish any pending output
|
||||
XO_OP_FLUSH Flush any buffered output
|
||||
XO_OP_DESTROY Clean up resources
|
||||
XO_OP_ATTRIBUTE An attribute name/value pair
|
||||
XO_OP_VERSION A version string
|
||||
======================= =======================================
|
||||
======================= =======================================
|
||||
Operation Meaning (Base function)
|
||||
======================= =======================================
|
||||
XO_OP_CREATE Called when the handle is created
|
||||
XO_OP_OPEN_CONTAINER Container opened (xo_open_container)
|
||||
XO_OP_CLOSE_CONTAINER Container closed (xo_close_container)
|
||||
XO_OP_OPEN_LIST List opened (xo_open_list)
|
||||
XO_OP_CLOSE_LIST List closed (xo_close_list)
|
||||
XO_OP_OPEN_LEAF_LIST Leaf list opened (xo_open_leaf_list)
|
||||
XO_OP_CLOSE_LEAF_LIST Leaf list closed (xo_close_leaf_list)
|
||||
XO_OP_OPEN_INSTANCE Instance opened (xo_open_instance)
|
||||
XO_OP_CLOSE_INSTANCE Instance closed (xo_close_instance)
|
||||
XO_OP_STRING Field with Quoted UTF-8 string
|
||||
XO_OP_CONTENT Field with content
|
||||
XO_OP_FINISH Finish any pending output
|
||||
XO_OP_FLUSH Flush any buffered output
|
||||
XO_OP_DESTROY Clean up resources
|
||||
XO_OP_ATTRIBUTE An attribute name/value pair
|
||||
XO_OP_VERSION A version string
|
||||
======================= =======================================
|
||||
|
||||
For all the open and close operations, the name parameter holds the
|
||||
name of the construct. For string, content, and attribute operations,
|
||||
|
14
doc/conf.py
14
doc/conf.py
@ -21,6 +21,14 @@
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
import subprocess
|
||||
|
||||
#
|
||||
# Instead of hardcoding the version number here, we read it from the
|
||||
# project's configure script
|
||||
#
|
||||
vers_cmd = "grep AC_INIT ../configure.ac | awk '{ print substr($2, 2, length($2) - 3);}'"
|
||||
version = subprocess.check_output(vers_cmd, shell=True).decode("utf-8")
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
@ -47,7 +55,7 @@
|
||||
|
||||
# General information about the project.
|
||||
project = 'libxo'
|
||||
copyright = '2017, Juniper Networks'
|
||||
copyright = '2017-2019, Juniper Networks Inc'
|
||||
author = 'Phil Shafer'
|
||||
default_role = 'code'
|
||||
primary_domain = 'c'
|
||||
@ -58,9 +66,9 @@
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.8.4'
|
||||
#version = 'develop'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.8.4'
|
||||
release = version
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
269
doc/encoders.rst
Normal file
269
doc/encoders.rst
Normal file
@ -0,0 +1,269 @@
|
||||
.. index:: encoder
|
||||
|
||||
Encoders
|
||||
========
|
||||
|
||||
This section gives an overview of encoders, details on the encoders
|
||||
that ship with libxo, and documentation for developers of future
|
||||
encoders.
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
The libxo library contains software to generate four "built-in"
|
||||
formats: text, XML, JSON, and HTML. These formats are common and
|
||||
useful, but there are other common and useful formats that users will
|
||||
want, and including them all in the libxo software would be difficult
|
||||
and cumbersome.
|
||||
|
||||
To allow support for additional encodings, libxo includes a
|
||||
"pluggable" extension mechanism for dynamically loading new encoders.
|
||||
libxo-based applications can automatically use any installed encoder.
|
||||
|
||||
Use the "encoder=XXX" option to access encoders. The following
|
||||
example uses the "cbor" encoder, saving the output into a file::
|
||||
|
||||
df --libxo encoder=cbor > df-output.cbor
|
||||
|
||||
Encoders can support specific options that can be accessed by
|
||||
following the encoder name with a colon (':') and one of more options,
|
||||
separated by a plus sign "+"::
|
||||
|
||||
df --libxo encoder=csv:path=filesystem+leaf=name+no-header
|
||||
|
||||
This example instructs libxo to load the "csv" encoder and pass the
|
||||
following options::
|
||||
|
||||
path=filesystem
|
||||
leaf=name
|
||||
no-header
|
||||
|
||||
Each of these option is interpreted by the encoder, and all such
|
||||
options names and semantics are specific to the particular encoder.
|
||||
Refer to the intended encoder for documentation on its options.
|
||||
|
||||
.. _csv_encoder:
|
||||
|
||||
CSV - Comma Separated Values
|
||||
----------------------------
|
||||
|
||||
libxo ships with a custom encoder for "CSV" files, a common format for
|
||||
comma separated values. The output of the CSV encoder can be loaded
|
||||
directly into spreadsheets or similar applications.
|
||||
|
||||
A standard for CSV files is provided in :RFC:`4180`, but since the
|
||||
format predates that standard by decades, there are many minor
|
||||
differences in CSV file consumers and their expectations. The CSV
|
||||
encoder has a number of options to tailor output to those
|
||||
expectations.
|
||||
|
||||
Consider the following XML::
|
||||
|
||||
% list-items --libxo xml,pretty
|
||||
<top>
|
||||
<data test="value">
|
||||
<item test2="value2">
|
||||
<sku test3="value3" key="key">GRO-000-415</sku>
|
||||
<name key="key">gum</name>
|
||||
<sold>1412</sold>
|
||||
<in-stock>54</in-stock>
|
||||
<on-order>10</on-order>
|
||||
</item>
|
||||
<item>
|
||||
<sku test3="value3" key="key">HRD-000-212</sku>
|
||||
<name key="key">rope</name>
|
||||
<sold>85</sold>
|
||||
<in-stock>4</in-stock>
|
||||
<on-order>2</on-order>
|
||||
</item>
|
||||
<item>
|
||||
<sku test3="value3" key="key">HRD-000-517</sku>
|
||||
<name key="key">ladder</name>
|
||||
<sold>0</sold>
|
||||
<in-stock>2</in-stock>
|
||||
<on-order>1</on-order>
|
||||
</item>
|
||||
</data>
|
||||
</top>
|
||||
|
||||
This output is a list of `instances` (named "item"), each containing a
|
||||
set of `leafs` ("sku", "name", etc).
|
||||
|
||||
The CSV encoder will emit the leaf values in this output as `fields`
|
||||
inside a CSV `record`, which is a line containing a set of
|
||||
comma-separated values::
|
||||
|
||||
% list-items --libxo encoder=csv
|
||||
sku,name,sold,in-stock,on-order
|
||||
GRO-000-415,gum,1412,54,10
|
||||
HRD-000-212,rope,85,4,2
|
||||
HRD-000-517,ladder,0,2,1
|
||||
|
||||
Be aware that since the CSV encoder looks for data instances, when
|
||||
used with :ref:`xo`, the `--instance` option will be needed::
|
||||
|
||||
% xo --libxo encoder=csv --instance foo 'The {:product} is {:status}\n' stereo "in route"
|
||||
product,status
|
||||
stereo,in route
|
||||
|
||||
.. _csv_path:
|
||||
|
||||
The `path` Option
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
By default, the CSV encoder will attempt to emit any list instance
|
||||
generated by the application. In some cases, this may be
|
||||
unacceptable, and a specific list may be desired.
|
||||
|
||||
Use the "path" option to limit the processing of output to a specific
|
||||
hierarchy. The path should be one or more names of containers or
|
||||
lists.
|
||||
|
||||
For example, if the "list-items" application generates other lists,
|
||||
the user can give "path=top/data/item" as a path::
|
||||
|
||||
% list-items --libxo encoder=csv:path=top/data/item
|
||||
sku,name,sold,in-stock,on-order
|
||||
GRO-000-415,gum,1412,54,10
|
||||
HRD-000-212,rope,85,4,2
|
||||
HRD-000-517,ladder,0,2,1
|
||||
|
||||
Paths are "relative", meaning they need not be a complete set
|
||||
of names to the list. This means that "path=item" may be sufficient
|
||||
for the above example.
|
||||
|
||||
.. _csv_leafs:
|
||||
|
||||
The `leafs` Option
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The CSV encoding requires that all lines of output have the same
|
||||
number of fields with the same order. In contrast, XML and JSON allow
|
||||
any order (though libxo forces key leafs to appear before other
|
||||
leafs).
|
||||
|
||||
To maintain a consistent set of fields inside the CSV file, the same
|
||||
set of leafs must be selected from each list item. By default, the
|
||||
CSV encoder records the set of leafs that appear in the first list
|
||||
instance it processes, and extract only those leafs from future
|
||||
instances. If the first instance is missing a leaf that is desired by
|
||||
the consumer, the "leaf" option can be used to ensure that an empty
|
||||
value is recorded for instances that lack a particular leaf.
|
||||
|
||||
The "leafs" option can also be used to exclude leafs, limiting the
|
||||
output to only those leafs provided.
|
||||
|
||||
In addition, the order of the output fields follows the order in which
|
||||
the leafs are listed. "leafs=one.two" and "leafs=two.one" give
|
||||
distinct output.
|
||||
|
||||
So the "leafs" option can be used to expand, limit, and order the set
|
||||
of leafs.
|
||||
|
||||
The value of the leafs option should be one or more leaf names,
|
||||
separated by a period (".")::
|
||||
|
||||
% list-items --libxo encoder=csv:leafs=sku.on-order
|
||||
sku,on-order
|
||||
GRO-000-415,10
|
||||
HRD-000-212,2
|
||||
HRD-000-517,1
|
||||
% list-items -libxo encoder=csv:leafs=on-order.sku
|
||||
on-order,sku
|
||||
10,GRO-000-415
|
||||
2,HRD-000-212
|
||||
1,HRD-000-517
|
||||
|
||||
Note that since libxo uses terminology from YANG (:RFC:`7950`), the
|
||||
data modeling language for NETCONF (:RFC:`6241`), which uses "leafs"
|
||||
as the plural form of "leaf". libxo follows that convention.
|
||||
|
||||
.. _csv_no_header:
|
||||
|
||||
The `no-header` Option
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
CSV files typical begin with a line that defines the fields included
|
||||
in that file, in an attempt to make the contents self-defining::
|
||||
|
||||
sku,name,sold,in-stock,on-order
|
||||
GRO-000-415,gum,1412,54,10
|
||||
HRD-000-212,rope,85,4,2
|
||||
HRD-000-517,ladder,0,2,1
|
||||
|
||||
There is no reliable mechanism for determining whether this header
|
||||
line is included, so the consumer must make an assumption.
|
||||
|
||||
The csv encoder defaults to producing the header line, but the
|
||||
"no-header" option can be included to avoid the header line.
|
||||
|
||||
.. _csv_no_quotes:
|
||||
|
||||
The `no-quotes` Option
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:RFC:`4180` specifies that fields containing spaces should be quoted, but
|
||||
many CSV consumers do not handle quotes. The "no-quotes" option
|
||||
instruct the CSV encoder to avoid the use of quotes.
|
||||
|
||||
.. _csv_dos:
|
||||
|
||||
The `dos` Option
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
:RFC:`4180` defines the end-of-line marker as a carriage return
|
||||
followed by a newline. This `CRLF` convention dates from the distant
|
||||
past, but its use was anchored in the 1980s by the `DOS` operating
|
||||
system.
|
||||
|
||||
The CSV encoder defaults to using the standard Unix end-of-line
|
||||
marker, a simple newline. Use the "dos" option to use the `CRLF`
|
||||
convention.
|
||||
|
||||
The Encoder API
|
||||
---------------
|
||||
|
||||
The encoder API consists of three distinct phases:
|
||||
|
||||
- loading the encoder
|
||||
- initializing the encoder
|
||||
- feeding operations to the encoder
|
||||
|
||||
To load the encoder, libxo will open a shared library named:
|
||||
|
||||
${prefix}/lib/libxo/encoder/${name}.enc
|
||||
|
||||
This file is typically a symbolic link to a dynamic library, suitable
|
||||
for `dlopen`(). libxo looks for a symbol called
|
||||
`xo_encoder_library_init` inside that library and calls it with the
|
||||
arguments defined in the header file "xo_encoder.h". This function
|
||||
should look as follows::
|
||||
|
||||
int
|
||||
xo_encoder_library_init (XO_ENCODER_INIT_ARGS)
|
||||
{
|
||||
arg->xei_version = XO_ENCODER_VERSION;
|
||||
arg->xei_handler = test_handler;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Several features here allow for future compatibility: the macro
|
||||
XO_ENCODER_INIT_ARGS allows the arguments to this function change over
|
||||
time, and the XO_ENCODER_VERSION allows the library to tell libxo
|
||||
which version of the API it was compiled with.
|
||||
|
||||
The function places in xei_handler should be have the signature::
|
||||
|
||||
static int
|
||||
test_handler (XO_ENCODER_HANDLER_ARGS)
|
||||
{
|
||||
...
|
||||
|
||||
This function will be called with the "op" codes defined in
|
||||
"xo_encoder.h". Each op code represents a distinct event in the libxo
|
||||
processing model. For example OP_OPEN_CONTAINER tells the encoder
|
||||
that a new container has been opened, and the encoder can behave in an
|
||||
appropriate manner.
|
||||
|
||||
|
@ -202,8 +202,7 @@ will lead users to ask the difference between the two fields. If
|
||||
there is no difference, use only one of the field names. If there is
|
||||
a difference, change the names to make that difference more obvious.
|
||||
|
||||
.. ignore for now, since we want can't have generated content
|
||||
What does this message mean?
|
||||
----------------------------
|
||||
What does this message mean?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
!!include-file xolint.txt
|
||||
.. include:: xolint.rst
|
||||
|
@ -53,48 +53,48 @@ removed eventually.
|
||||
|
||||
The format character is described in the following table:
|
||||
|
||||
===== ================= ======================
|
||||
Ltr Argument Type Format
|
||||
===== ================= ======================
|
||||
d int base 10 (decimal)
|
||||
i int base 10 (decimal)
|
||||
o int base 8 (octal)
|
||||
u unsigned base 10 (decimal)
|
||||
x unsigned base 16 (hex)
|
||||
X unsigned long base 16 (hex)
|
||||
D long base 10 (decimal)
|
||||
O unsigned long base 8 (octal)
|
||||
U unsigned long base 10 (decimal)
|
||||
e double [-]d.ddde+-dd
|
||||
E double [-]d.dddE+-dd
|
||||
f double [-]ddd.ddd
|
||||
F double [-]ddd.ddd
|
||||
g double as 'e' or 'f'
|
||||
G double as 'E' or 'F'
|
||||
a double [-]0xh.hhhp[+-]d
|
||||
A double [-]0Xh.hhhp[+-]d
|
||||
c unsigned char a character
|
||||
C wint_t a character
|
||||
s char \* a UTF-8 string
|
||||
S wchar_t \* a unicode/WCS string
|
||||
p void \* '%#lx'
|
||||
===== ================= ======================
|
||||
===== ================= ======================
|
||||
Ltr Argument Type Format
|
||||
===== ================= ======================
|
||||
d int base 10 (decimal)
|
||||
i int base 10 (decimal)
|
||||
o int base 8 (octal)
|
||||
u unsigned base 10 (decimal)
|
||||
x unsigned base 16 (hex)
|
||||
X unsigned long base 16 (hex)
|
||||
D long base 10 (decimal)
|
||||
O unsigned long base 8 (octal)
|
||||
U unsigned long base 10 (decimal)
|
||||
e double [-]d.ddde+-dd
|
||||
E double [-]d.dddE+-dd
|
||||
f double [-]ddd.ddd
|
||||
F double [-]ddd.ddd
|
||||
g double as 'e' or 'f'
|
||||
G double as 'E' or 'F'
|
||||
a double [-]0xh.hhhp[+-]d
|
||||
A double [-]0Xh.hhhp[+-]d
|
||||
c unsigned char a character
|
||||
C wint_t a character
|
||||
s char \* a UTF-8 string
|
||||
S wchar_t \* a unicode/WCS string
|
||||
p void \* '%#lx'
|
||||
===== ================= ======================
|
||||
|
||||
The 'h' and 'l' modifiers affect the size and treatment of the
|
||||
argument:
|
||||
|
||||
===== ============= ====================
|
||||
Mod d, i o, u, x, X
|
||||
===== ============= ====================
|
||||
hh signed char unsigned char
|
||||
h short unsigned short
|
||||
l long unsigned long
|
||||
ll long long unsigned long long
|
||||
j intmax_t uintmax_t
|
||||
t ptrdiff_t ptrdiff_t
|
||||
z size_t size_t
|
||||
q quad_t u_quad_t
|
||||
===== ============= ====================
|
||||
===== ============= ====================
|
||||
Mod d, i o, u, x, X
|
||||
===== ============= ====================
|
||||
hh signed char unsigned char
|
||||
h short unsigned short
|
||||
l long unsigned long
|
||||
ll long long unsigned long long
|
||||
j intmax_t uintmax_t
|
||||
t ptrdiff_t ptrdiff_t
|
||||
z size_t size_t
|
||||
q quad_t u_quad_t
|
||||
===== ============= ====================
|
||||
|
||||
.. index:: UTF-8
|
||||
.. index:: Locale
|
||||
@ -122,14 +122,14 @@ style::
|
||||
xo_emit("All strings are utf-8 content {:tag/%ls}",
|
||||
L"except for wide strings");
|
||||
|
||||
======== ================== ===============================
|
||||
Format Argument Type Argument Contents
|
||||
======== ================== ===============================
|
||||
%s const char \* UTF-8 string
|
||||
%S const char \* UTF-8 string (alias for '%ls')
|
||||
%ls const wchar_t \* Wide character UNICODE string
|
||||
%hs const char * locale-based string
|
||||
======== ================== ===============================
|
||||
======== ================== ===============================
|
||||
Format Argument Type Argument Contents
|
||||
======== ================== ===============================
|
||||
%s const char \* UTF-8 string
|
||||
%S const char \* UTF-8 string (alias for '%ls')
|
||||
%ls const wchar_t \* Wide character UNICODE string
|
||||
%hs const char * locale-based string
|
||||
======== ================== ===============================
|
||||
|
||||
.. admonition:: "Long", not "locale"
|
||||
|
||||
@ -266,21 +266,21 @@ incompatible with printf-like testing:
|
||||
If none of these features are in use by your code, then using the "_p"
|
||||
variants might be wise:
|
||||
|
||||
================== ========================
|
||||
Function printf-like Equivalent
|
||||
================== ========================
|
||||
xo_emit_hv xo_emit_hvp
|
||||
xo_emit_h xo_emit_hp
|
||||
xo_emit xo_emit_p
|
||||
xo_emit_warn_hcv xo_emit_warn_hcvp
|
||||
xo_emit_warn_hc xo_emit_warn_hcp
|
||||
xo_emit_warn_c xo_emit_warn_cp
|
||||
xo_emit_warn xo_emit_warn_p
|
||||
xo_emit_warnx xo_emit_warnx_p
|
||||
xo_emit_err xo_emit_err_p
|
||||
xo_emit_errx xo_emit_errx_p
|
||||
xo_emit_errc xo_emit_errc_p
|
||||
================== ========================
|
||||
================== ========================
|
||||
Function printf-like Equivalent
|
||||
================== ========================
|
||||
xo_emit_hv xo_emit_hvp
|
||||
xo_emit_h xo_emit_hp
|
||||
xo_emit xo_emit_p
|
||||
xo_emit_warn_hcv xo_emit_warn_hcvp
|
||||
xo_emit_warn_hc xo_emit_warn_hcp
|
||||
xo_emit_warn_c xo_emit_warn_cp
|
||||
xo_emit_warn xo_emit_warn_p
|
||||
xo_emit_warnx xo_emit_warnx_p
|
||||
xo_emit_err xo_emit_err_p
|
||||
xo_emit_errx xo_emit_errx_p
|
||||
xo_emit_errc xo_emit_errc_p
|
||||
================== ========================
|
||||
|
||||
.. index:: performance
|
||||
.. index:: XOEF_RETAIN
|
||||
@ -305,16 +305,16 @@ xo_emit_f() function. A complete set of xo_emit_f functions exist to
|
||||
match all the xo_emit function signatures (with handles, varadic
|
||||
argument, and printf-like flags):
|
||||
|
||||
================== ========================
|
||||
Function Flags Equivalent
|
||||
================== ========================
|
||||
xo_emit_hv xo_emit_hvf
|
||||
xo_emit_h xo_emit_hf
|
||||
xo_emit xo_emit_f
|
||||
xo_emit_hvp xo_emit_hvfp
|
||||
xo_emit_hp xo_emit_hfp
|
||||
xo_emit_p xo_emit_fp
|
||||
================== ========================
|
||||
================== ========================
|
||||
Function Flags Equivalent
|
||||
================== ========================
|
||||
xo_emit_hv xo_emit_hvf
|
||||
xo_emit_h xo_emit_hf
|
||||
xo_emit xo_emit_f
|
||||
xo_emit_hvp xo_emit_hvfp
|
||||
xo_emit_hp xo_emit_hfp
|
||||
xo_emit_p xo_emit_fp
|
||||
================== ========================
|
||||
|
||||
The format string must be immutable across multiple calls to xo_emit_f(),
|
||||
since the library retains the string. Typically this is done by using
|
||||
|
@ -8,26 +8,26 @@ Field Modifiers
|
||||
Field modifiers are flags which modify the way content emitted for
|
||||
particular output styles:
|
||||
|
||||
=== =============== ===================================================
|
||||
M Name Description
|
||||
=== =============== ===================================================
|
||||
a argument The content appears as a 'const char \*' argument
|
||||
c colon A colon (":") is appended after the label
|
||||
d display Only emit field for display styles (text/HTML)
|
||||
e encoding Only emit for encoding styles (XML/JSON)
|
||||
g gettext Call gettext on field's render content
|
||||
h humanize (hn) Format large numbers in human-readable style
|
||||
\ hn-space Humanize: Place space between numeric and unit
|
||||
\ hn-decimal Humanize: Add a decimal digit, if number < 10
|
||||
\ hn-1000 Humanize: Use 1000 as divisor instead of 1024
|
||||
k key Field is a key, suitable for XPath predicates
|
||||
l leaf-list Field is a leaf-list
|
||||
n no-quotes Do not quote the field when using JSON style
|
||||
p plural Gettext: Use comma-separated plural form
|
||||
q quotes Quote the field when using JSON style
|
||||
t trim Trim leading and trailing whitespace
|
||||
w white A blank (" ") is appended after the label
|
||||
=== =============== ===================================================
|
||||
=== =============== ===================================================
|
||||
M Name Description
|
||||
=== =============== ===================================================
|
||||
a argument The content appears as a 'const char \*' argument
|
||||
c colon A colon (":") is appended after the label
|
||||
d display Only emit field for display styles (text/HTML)
|
||||
e encoding Only emit for encoding styles (XML/JSON)
|
||||
g gettext Call gettext on field's render content
|
||||
h humanize (hn) Format large numbers in human-readable style
|
||||
\ hn-space Humanize: Place space between numeric and unit
|
||||
\ hn-decimal Humanize: Add a decimal digit, if number < 10
|
||||
\ hn-1000 Humanize: Use 1000 as divisor instead of 1024
|
||||
k key Field is a key, suitable for XPath predicates
|
||||
l leaf-list Field is a leaf-list
|
||||
n no-quotes Do not quote the field when using JSON style
|
||||
p plural Gettext: Use comma-separated plural form
|
||||
q quotes Quote the field when using JSON style
|
||||
t trim Trim leading and trailing whitespace
|
||||
w white A blank (" ") is appended after the label
|
||||
=== =============== ===================================================
|
||||
|
||||
Roles and modifiers can also use more verbose names, when preceded by
|
||||
a comma. For example, the modifier string "Lwc" (or "L,white,colon")
|
||||
|
@ -8,23 +8,25 @@ Field Roles
|
||||
Field roles are optional, and indicate the role and formatting of the
|
||||
content. The roles are listed below; only one role is permitted:
|
||||
|
||||
=== ============== =================================================
|
||||
R Name Description
|
||||
=== ============== =================================================
|
||||
C color Field has color and effect controls
|
||||
D decoration Field is non-text (e.g., colon, comma)
|
||||
E error Field is an error message
|
||||
G gettext Call gettext(3) on the format string
|
||||
L label Field is text that prefixes a value
|
||||
N note Field is text that follows a value
|
||||
P padding Field is spaces needed for vertical alignment
|
||||
T title Field is a title value for headings
|
||||
U units Field is the units for the previous value field
|
||||
V value Field is the name of field (the default)
|
||||
W warning Field is a warning message
|
||||
[ start-anchor Begin a section of anchored variable-width text
|
||||
] stop-anchor End a section of anchored variable-width text
|
||||
=== ============== =================================================
|
||||
=== ============== =================================================
|
||||
R Name Description
|
||||
=== ============== =================================================
|
||||
C color Field has color and effect controls
|
||||
D decoration Field is non-text (e.g., colon, comma)
|
||||
E error Field is an error message
|
||||
G gettext Call gettext(3) on the format string
|
||||
L label Field is text that prefixes a value
|
||||
N note Field is text that follows a value
|
||||
P padding Field is spaces needed for vertical alignment
|
||||
T title Field is a title value for headings
|
||||
U units Field is the units for the previous value field
|
||||
V value Field is the name of field (the default)
|
||||
W warning Field is a warning message
|
||||
[ start-anchor Begin a section of anchored variable-width text
|
||||
] stop-anchor End a section of anchored variable-width text
|
||||
=== ============== =================================================
|
||||
|
||||
::
|
||||
|
||||
EXAMPLE:
|
||||
xo_emit("{L:Free}{D::}{P: }{:free/%u} {U:Blocks}\n",
|
||||
@ -80,36 +82,36 @@ foreground and background colors, respectively::
|
||||
|
||||
The following table lists the supported effects:
|
||||
|
||||
=============== =================================================
|
||||
Name Description
|
||||
=============== =================================================
|
||||
bg-XXXXX Change background color
|
||||
bold Start bold text effect
|
||||
fg-XXXXX Change foreground color
|
||||
inverse Start inverse (aka reverse) text effect
|
||||
no-bold Stop bold text effect
|
||||
no-inverse Stop inverse (aka reverse) text effect
|
||||
no-underline Stop underline text effect
|
||||
normal Reset effects (only)
|
||||
reset Reset colors and effects (restore defaults)
|
||||
underline Start underline text effect
|
||||
=============== =================================================
|
||||
=============== =================================================
|
||||
Name Description
|
||||
=============== =================================================
|
||||
bg-XXXXX Change background color
|
||||
bold Start bold text effect
|
||||
fg-XXXXX Change foreground color
|
||||
inverse Start inverse (aka reverse) text effect
|
||||
no-bold Stop bold text effect
|
||||
no-inverse Stop inverse (aka reverse) text effect
|
||||
no-underline Stop underline text effect
|
||||
normal Reset effects (only)
|
||||
reset Reset colors and effects (restore defaults)
|
||||
underline Start underline text effect
|
||||
=============== =================================================
|
||||
|
||||
The following color names are supported:
|
||||
|
||||
========= ============================================
|
||||
Name Description
|
||||
========= ============================================
|
||||
black
|
||||
blue
|
||||
cyan
|
||||
default Default color for foreground or background
|
||||
green
|
||||
magenta
|
||||
red
|
||||
white
|
||||
yellow
|
||||
========= ============================================
|
||||
========= ============================================
|
||||
Name Description
|
||||
========= ============================================
|
||||
black
|
||||
blue
|
||||
cyan
|
||||
default Default color for foreground or background
|
||||
green
|
||||
magenta
|
||||
red
|
||||
white
|
||||
yellow
|
||||
========= ============================================
|
||||
|
||||
When using colors, the developer should remember that users will
|
||||
change the foreground and background colors of terminal session
|
||||
|
@ -38,6 +38,7 @@ libxo ships as part of FreeBSD.
|
||||
field-modifiers
|
||||
field-formatting
|
||||
api
|
||||
encoders
|
||||
xo
|
||||
xolint
|
||||
xohtml
|
||||
|
27436
doc/libxo-manual.html
27436
doc/libxo-manual.html
File diff suppressed because it is too large
Load Diff
3995
doc/libxo.txt
3995
doc/libxo.txt
File diff suppressed because it is too large
Load Diff
102
doc/options.rst
102
doc/options.rst
@ -33,36 +33,36 @@ Option Keywords
|
||||
Options is a comma-separated list of tokens that correspond to output
|
||||
styles, flags, or features:
|
||||
|
||||
=============== =======================================================
|
||||
Token Action
|
||||
=============== =======================================================
|
||||
color Enable colors/effects for display styles (TEXT, HTML)
|
||||
colors=xxxx Adjust color output values
|
||||
dtrt Enable "Do The Right Thing" mode
|
||||
flush Flush after every libxo function call
|
||||
flush-line Flush after every line (line-buffered)
|
||||
html Emit HTML output
|
||||
indent=xx Set the indentation level
|
||||
info Add info attributes (HTML)
|
||||
json Emit JSON output
|
||||
keys Emit the key attribute for keys (XML)
|
||||
log-gettext Log (via stderr) each gettext(3) string lookup
|
||||
log-syslog Log (via stderr) each syslog message (via xo_syslog)
|
||||
no-humanize Ignore the {h:} modifier (TEXT, HTML)
|
||||
no-locale Do not initialize the locale setting
|
||||
no-retain Prevent retaining formatting information
|
||||
no-top Do not emit a top set of braces (JSON)
|
||||
not-first Pretend the 1st output item was not 1st (JSON)
|
||||
pretty Emit pretty-printed output
|
||||
retain Force retaining formatting information
|
||||
text Emit TEXT output
|
||||
underscores Replace XML-friendly "-"s with JSON friendly "_"s
|
||||
units Add the 'units' (XML) or 'data-units (HTML) attribute
|
||||
warn Emit warnings when libxo detects bad calls
|
||||
warn-xml Emit warnings in XML
|
||||
xml Emit XML output
|
||||
xpath Add XPath expressions (HTML)
|
||||
=============== =======================================================
|
||||
=============== =======================================================
|
||||
Token Action
|
||||
=============== =======================================================
|
||||
color Enable colors/effects for display styles (TEXT, HTML)
|
||||
colors=xxxx Adjust color output values
|
||||
dtrt Enable "Do The Right Thing" mode
|
||||
flush Flush after every libxo function call
|
||||
flush-line Flush after every line (line-buffered)
|
||||
html Emit HTML output
|
||||
indent=xx Set the indentation level
|
||||
info Add info attributes (HTML)
|
||||
json Emit JSON output
|
||||
keys Emit the key attribute for keys (XML)
|
||||
log-gettext Log (via stderr) each gettext(3) string lookup
|
||||
log-syslog Log (via stderr) each syslog message (via xo_syslog)
|
||||
no-humanize Ignore the {h:} modifier (TEXT, HTML)
|
||||
no-locale Do not initialize the locale setting
|
||||
no-retain Prevent retaining formatting information
|
||||
no-top Do not emit a top set of braces (JSON)
|
||||
not-first Pretend the 1st output item was not 1st (JSON)
|
||||
pretty Emit pretty-printed output
|
||||
retain Force retaining formatting information
|
||||
text Emit TEXT output
|
||||
underscores Replace XML-friendly "-"s with JSON friendly "_"s
|
||||
units Add the 'units' (XML) or 'data-units (HTML) attribute
|
||||
warn Emit warnings when libxo detects bad calls
|
||||
warn-xml Emit warnings in XML
|
||||
xml Emit XML output
|
||||
xpath Add XPath expressions (HTML)
|
||||
=============== =======================================================
|
||||
|
||||
Most of these option are simple and direct, but some require
|
||||
additional details:
|
||||
@ -94,25 +94,25 @@ Brief Options
|
||||
The brief options are simple single-letter aliases to the normal
|
||||
keywords, as detailed below:
|
||||
|
||||
======== =============================================
|
||||
Option Action
|
||||
======== =============================================
|
||||
c Enable color/effects for TEXT/HTML
|
||||
F Force line-buffered flushing
|
||||
H Enable HTML output (XO_STYLE_HTML)
|
||||
I Enable info output (XOF_INFO)
|
||||
i<num> Indent by <number>
|
||||
J Enable JSON output (XO_STYLE_JSON)
|
||||
k Add keys to XPATH expressions in HTML
|
||||
n Disable humanization (TEXT, HTML)
|
||||
P Enable pretty-printed output (XOF_PRETTY)
|
||||
T Enable text output (XO_STYLE_TEXT)
|
||||
U Add units to HTML output
|
||||
u Change "-"s to "_"s in element names (JSON)
|
||||
W Enable warnings (XOF_WARN)
|
||||
X Enable XML output (XO_STYLE_XML)
|
||||
x Enable XPath data (XOF_XPATH)
|
||||
======== =============================================
|
||||
======== =============================================
|
||||
Option Action
|
||||
======== =============================================
|
||||
c Enable color/effects for TEXT/HTML
|
||||
F Force line-buffered flushing
|
||||
H Enable HTML output (XO_STYLE_HTML)
|
||||
I Enable info output (XOF_INFO)
|
||||
i<num> Indent by <number>
|
||||
J Enable JSON output (XO_STYLE_JSON)
|
||||
k Add keys to XPATH expressions in HTML
|
||||
n Disable humanization (TEXT, HTML)
|
||||
P Enable pretty-printed output (XOF_PRETTY)
|
||||
T Enable text output (XO_STYLE_TEXT)
|
||||
U Add units to HTML output
|
||||
u Change "-"s to "_"s in element names (JSON)
|
||||
W Enable warnings (XOF_WARN)
|
||||
X Enable XML output (XO_STYLE_XML)
|
||||
x Enable XPath data (XOF_XPATH)
|
||||
======== =============================================
|
||||
|
||||
.. index:: Colors
|
||||
|
||||
@ -145,7 +145,7 @@ For example consider the following xo_emit call::
|
||||
xo_emit("{C:fg-red,bg-green}Merry XMas!!{C:}\n");
|
||||
|
||||
To turn all colored output to red-on-blue, use eight pairs of
|
||||
"red/blue" mappings separated by "+"s::
|
||||
"red/blue" mappings separated by plus signs ("+")::
|
||||
|
||||
--libxo colors=red/blue+red/blue+red/blue+red/blue+\
|
||||
red/blue+red/blue+red/blue+red/blue
|
||||
@ -159,6 +159,6 @@ to green (the third mapping)::
|
||||
Consider the common situation where blue output looks unreadable on a
|
||||
terminal session with a black background. To turn both "blue"
|
||||
foreground and background output to "yellow", give only the fifth
|
||||
mapping, skipping the first four mappings with bare "+"s::
|
||||
mapping, skipping the first four mappings with bare plus signs ("+")::
|
||||
|
||||
--libxo colors=++++yellow/yellow
|
||||
|
9
doc/top-link.html.in
Normal file
9
doc/top-link.html.in
Normal file
@ -0,0 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Refresh" content="0; url=@LIBXO_VERSION@/html/index.html" />
|
||||
</head>
|
||||
<body>
|
||||
<p>The current libxo version is <a href="@LIBXO_VERSION@/html/index.html">@LIBXO_VERSION@</a>.</p>
|
||||
</body>
|
||||
</html>
|
41
doc/xo.rst
41
doc/xo.rst
@ -1,5 +1,5 @@
|
||||
|
||||
.. index:: --libxo, xo
|
||||
.. _xo:
|
||||
|
||||
The "xo" Utility
|
||||
================
|
||||
@ -12,9 +12,7 @@ The style of output can be selected using a specific option: "-X" for
|
||||
XML, "-J" for JSON, "-H" for HTML, or "-T" for TEXT, which is the
|
||||
default. The "--style <style>" option can also be used. The standard
|
||||
set of "--libxo" options are available (see :ref:`options`), as well
|
||||
as the `LIBXO_OPTIONS`_ environment variable.
|
||||
|
||||
.. _`LIBXO_OPTIONS`: :ref:`libxo-options`
|
||||
as the :ref:`LIBXO_OPTIONS <libxo-options>` environment variable.
|
||||
|
||||
The `xo` utility accepts a format string suitable for `xo_emit` and
|
||||
a set of zero or more arguments used to supply data for that string::
|
||||
@ -23,12 +21,15 @@ a set of zero or more arguments used to supply data for that string::
|
||||
|
||||
TEXT:
|
||||
The fish weighs 6 pounds.
|
||||
|
||||
XML:
|
||||
<name>fish</name>
|
||||
<weight>6</weight>
|
||||
|
||||
JSON:
|
||||
"name": "fish",
|
||||
"weight": 6
|
||||
|
||||
HTML:
|
||||
<div class="line">
|
||||
<div class="text">The </div>
|
||||
@ -54,6 +55,7 @@ by the '/' character::
|
||||
</b>
|
||||
</a>
|
||||
</top>
|
||||
|
||||
JSON:
|
||||
"top": {
|
||||
"a": {
|
||||
@ -72,17 +74,19 @@ then close tags. The `--depth` option may be used to set the
|
||||
depth for indentation. The `--leading-xpath` may be used to
|
||||
prepend data to the XPath values used for HTML output style::
|
||||
|
||||
EXAMPLE;
|
||||
EXAMPLE:
|
||||
#!/bin/sh
|
||||
xo --open top/data
|
||||
xo --depth 2 '{:tag}' value
|
||||
xo --close top/data
|
||||
|
||||
XML:
|
||||
<top>
|
||||
<data>
|
||||
<tag>value</tag>
|
||||
</data>
|
||||
</top>
|
||||
|
||||
JSON:
|
||||
"top": {
|
||||
"data": {
|
||||
@ -102,14 +106,18 @@ Use the `--top-wrap` option to ensure any top-level object details are
|
||||
handled correctly, e.g. wrap the entire output in a top-level set of
|
||||
braces for JSON output.
|
||||
|
||||
EXAMPLE;
|
||||
::
|
||||
|
||||
EXAMPLE:
|
||||
#!/bin/sh
|
||||
xo --top-wrap --open top/data
|
||||
xo --depth 2 'First {:tag} ' value1
|
||||
xo --depth 2 --continuation 'and then {:tag}\n' value2
|
||||
xo --top-wrap --close top/data
|
||||
|
||||
TEXT:
|
||||
First value1 and then value2
|
||||
|
||||
HTML:
|
||||
<div class="line">
|
||||
<div class="text">First </div>
|
||||
@ -118,6 +126,7 @@ braces for JSON output.
|
||||
<div class="text">and then </div>
|
||||
<div class="data" data-tag="tag">value2</div>
|
||||
</div>
|
||||
|
||||
XML:
|
||||
<top>
|
||||
<data>
|
||||
@ -125,6 +134,7 @@ braces for JSON output.
|
||||
<tag>value2</tag>
|
||||
</data>
|
||||
</top>
|
||||
|
||||
JSON:
|
||||
{
|
||||
"top": {
|
||||
@ -150,7 +160,7 @@ them. Each of these options take a `name` parameter, providing the
|
||||
name of the list and instance.
|
||||
|
||||
In the following example, a list named "machine" is created with three
|
||||
instances:
|
||||
instances::
|
||||
|
||||
opts="--json"
|
||||
xo $opts --open-list machine
|
||||
@ -168,6 +178,15 @@ transitions, but since each `xo` command is invoked independent of the
|
||||
previous calls, the state must be passed in explicitly via these
|
||||
command line options.
|
||||
|
||||
The `--instance` option can be used to treat a single `xo` invocation
|
||||
as an instance with the given set of fields::
|
||||
|
||||
% xo --libxo:XP --instance foo 'The {:product} is {:status}\n' stereo "in route"
|
||||
<foo>
|
||||
<product>stereo</product>
|
||||
<status>in route</status>
|
||||
</foo>
|
||||
|
||||
Command Line Options
|
||||
--------------------
|
||||
|
||||
@ -181,6 +200,7 @@ Command Line Options
|
||||
--depth <num> Set the depth for pretty printing
|
||||
--help Display this help text
|
||||
--html OR -H Generate HTML output
|
||||
--instance OR -I <name> Wrap in an instance of the given name
|
||||
--json OR -J Generate JSON output
|
||||
--leading-xpath <path> Add a prefix to generated XPaths (HTML)
|
||||
--not-first Indicate this object is not the first (JSON)
|
||||
@ -197,7 +217,7 @@ Command Line Options
|
||||
--warn-xml Display warnings in xml on stdout
|
||||
--wrap <path> Wrap output in a set of containers
|
||||
--xml OR -X Generate XML output
|
||||
--xpath Add XPath data to HTML output);
|
||||
--xpath Add XPath data to HTML output)
|
||||
|
||||
Example
|
||||
-------
|
||||
@ -206,6 +226,9 @@ Example
|
||||
|
||||
% xo 'The {:product} is {:status}\n' stereo "in route"
|
||||
The stereo is in route
|
||||
% ./xo/xo -p -X 'The {:product} is {:status}\n' stereo "in route"
|
||||
% xo -p -X 'The {:product} is {:status}\n' stereo "in route"
|
||||
<product>stereo</product>
|
||||
<status>in route</status>
|
||||
% xo --libxo xml,pretty 'The {:product} is {:status}\n' stereo "in route"
|
||||
<product>stereo</product>
|
||||
<status>in route</status>
|
||||
|
@ -17,13 +17,13 @@ supporting CSS and Javascript files, and written to standard output or
|
||||
the file given in the "-f" option. The "-b" option can be used to
|
||||
provide an alternative base path for the support files:
|
||||
|
||||
============== ===================================================
|
||||
Option Meaning
|
||||
============== ===================================================
|
||||
-b <base> Base path for finding css/javascript files
|
||||
-c <command> Command to execute
|
||||
-f <file> Output file name
|
||||
============== ===================================================
|
||||
============== ===================================================
|
||||
Option Meaning
|
||||
============== ===================================================
|
||||
-b <base> Base path for finding css/javascript files
|
||||
-c <command> Command to execute
|
||||
-f <file> Output file name
|
||||
============== ===================================================
|
||||
|
||||
The "-c" option takes a full command with arguments, including
|
||||
any libxo options needed to generate html (`--libxo=html`). This
|
||||
|
466
doc/xolint.rst
466
doc/xolint.rst
@ -1,40 +1,444 @@
|
||||
'A percent sign appearing in text is a literal'
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
xolint
|
||||
======
|
||||
The message "A percent sign appearing in text is a literal" can be caused by code like:
|
||||
|
||||
`xolint` is a tool for reporting common mistakes in format strings
|
||||
in source code that invokes `xo_emit`. It allows these errors
|
||||
to be diagnosed at build time, rather than waiting until runtime.
|
||||
::
|
||||
|
||||
`xolint` takes the one or more C files as arguments, and reports
|
||||
and errors, warning, or informational messages as needed:
|
||||
xo_emit("cost: %d", cost);
|
||||
|
||||
============ ===================================================
|
||||
Option Meaning
|
||||
============ ===================================================
|
||||
-c Invoke 'cpp' against the input file
|
||||
-C <flags> Flags that are passed to 'cpp
|
||||
-d Enable debug output
|
||||
-D Generate documentation for all xolint messages
|
||||
-I Generate info table code
|
||||
-p Print the offending lines after the message
|
||||
-V Print vocabulary of all field names
|
||||
-X Extract samples from xolint, suitable for testing
|
||||
============ ===================================================
|
||||
This code should be replaced with code like:
|
||||
|
||||
The output message will contain the source filename and line number, the
|
||||
class of the message, the message, and, if -p is given, the
|
||||
line that contains the error::
|
||||
::
|
||||
|
||||
% xolint.pl -t xolint.c
|
||||
xolint.c: 16: error: anchor format should be "%d"
|
||||
16 xo_emit("{[:/%s}");
|
||||
xo_emit("{L:cost}: {:cost/%d}", cost);
|
||||
|
||||
The "-I" option will generate a table of `xo_info_t`_ structures,
|
||||
suitable for inclusion in source code.
|
||||
This can be a bit surprising and could be a field that was not
|
||||
properly converted to a libxo-style format string.
|
||||
|
||||
.. _xo_info_t: :ref:`field-information`
|
||||
|
||||
The "-V" option does not report errors, but prints a complete list of
|
||||
all field names, sorted alphabetically. The output can help spot
|
||||
inconsistencies and spelling errors.
|
||||
'Unknown long name for role/modifier'
|
||||
+++++++++++++++++++++++++++++++++++++
|
||||
|
||||
The message "Unknown long name for role/modifier" can be caused by code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{,humanization:value}", value);
|
||||
|
||||
This code should be replaced with code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{,humanize:value}", value);
|
||||
|
||||
The hn-* modifiers (hn-decimal, hn-space, hn-1000)
|
||||
are only valid for fields with the {h:} modifier.
|
||||
|
||||
|
||||
'Last character before field definition is a field type'
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
The message "Last character before field definition is a field type" can be caused by code like:
|
||||
A common typo:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{T:Min} T{:Max}");
|
||||
|
||||
This code should be replaced with code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{T:Min} {T:Max}");
|
||||
|
||||
Twiddling the "{" and the field role is a common typo.
|
||||
|
||||
|
||||
'Encoding format uses different number of arguments'
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
The message "Encoding format uses different number of arguments" can be caused by code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{:name/%6.6s %%04d/%s}", name, number);
|
||||
|
||||
This code should be replaced with code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{:name/%6.6s %04d/%s-%d}", name, number);
|
||||
|
||||
Both format should consume the same number of arguments off the stack
|
||||
|
||||
|
||||
'Only one field role can be used'
|
||||
+++++++++++++++++++++++++++++++++
|
||||
|
||||
The message "Only one field role can be used" can be caused by code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{LT:Max}");
|
||||
|
||||
This code should be replaced with code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{T:Max}");
|
||||
|
||||
'Potential missing slash after C, D, N, L, or T with format'
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
The message "Potential missing slash after C, D, N, L, or T with format" can be caused by code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{T:%6.6s}\n", "Max");
|
||||
|
||||
This code should be replaced with code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{T:/%6.6s}\n", "Max");
|
||||
|
||||
The "%6.6s" will be a literal, not a field format. While
|
||||
it's possibly valid, it's likely a missing "/".
|
||||
|
||||
|
||||
'An encoding format cannot be given (roles: DNLT)'
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
The message "An encoding format cannot be given (roles: DNLT)" can be caused by code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{T:Max//%s}", "Max");
|
||||
|
||||
Fields with the C, D, N, L, and T roles are not emitted in
|
||||
the 'encoding' style (JSON, XML), so an encoding format
|
||||
would make no sense.
|
||||
|
||||
|
||||
'Format cannot be given when content is present (roles: CDLN)'
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
The message "Format cannot be given when content is present (roles: CDLN)" can be caused by code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{N:Max/%6.6s}", "Max");
|
||||
|
||||
Fields with the C, D, L, or N roles can't have both
|
||||
static literal content ("{L:Label}") and a
|
||||
format ("{L:/%s}").
|
||||
This error will also occur when the content has a backslash
|
||||
in it, like "{N:Type of I/O}"; backslashes should be escaped,
|
||||
like "{N:Type of I\\/O}". Note the double backslash, one for
|
||||
handling 'C' strings, and one for libxo.
|
||||
|
||||
|
||||
'Field has color without fg- or bg- (role: C)'
|
||||
++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
The message "Field has color without fg- or bg- (role: C)" can be caused by code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{C:green}{:foo}{C:}", x);
|
||||
|
||||
This code should be replaced with code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{C:fg-green}{:foo}{C:}", x);
|
||||
|
||||
Colors must be prefixed by either "fg-" or "bg-".
|
||||
|
||||
|
||||
'Field has invalid color or effect (role: C)'
|
||||
+++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
The message "Field has invalid color or effect (role: C)" can be caused by code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{C:fg-purple,bold}{:foo}{C:gween}", x);
|
||||
|
||||
This code should be replaced with code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{C:fg-red,bold}{:foo}{C:fg-green}", x);
|
||||
|
||||
The list of colors and effects are limited. The
|
||||
set of colors includes default, black, red, green,
|
||||
yellow, blue, magenta, cyan, and white, which must
|
||||
be prefixed by either "fg-" or "bg-". Effects are
|
||||
limited to bold, no-bold, underline, no-underline,
|
||||
inverse, no-inverse, normal, and reset. Values must
|
||||
be separated by commas.
|
||||
|
||||
|
||||
'Field has humanize modifier but no format string'
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
The message "Field has humanize modifier but no format string" can be caused by code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{h:value}", value);
|
||||
|
||||
This code should be replaced with code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{h:value/%d}", value);
|
||||
|
||||
Humanization is only value for numbers, which are not
|
||||
likely to use the default format ("%s").
|
||||
|
||||
|
||||
'Field has hn-* modifier but not 'h' modifier'
|
||||
++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
The message "Field has hn-* modifier but not 'h' modifier" can be caused by code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{,hn-1000:value}", value);
|
||||
|
||||
This code should be replaced with code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{h,hn-1000:value}", value);
|
||||
|
||||
The hn-* modifiers (hn-decimal, hn-space, hn-1000)
|
||||
are only valid for fields with the {h:} modifier.
|
||||
|
||||
|
||||
'Value field must have a name (as content)")'
|
||||
+++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
The message "Value field must have a name (as content)")" can be caused by code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{:/%s}", "value");
|
||||
|
||||
This code should be replaced with code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{:tag-name/%s}", "value");
|
||||
|
||||
The field name is used for XML and JSON encodings. These
|
||||
tags names are static and must appear directly in the
|
||||
field descriptor.
|
||||
|
||||
|
||||
'Use hyphens, not underscores, for value field name'
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
The message "Use hyphens, not underscores, for value field name" can be caused by code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{:no_under_scores}", "bad");
|
||||
|
||||
This code should be replaced with code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{:no-under-scores}", "bad");
|
||||
|
||||
Use of hyphens is traditional in XML, and the XOF_UNDERSCORES
|
||||
flag can be used to generate underscores in JSON, if desired.
|
||||
But the raw field name should use hyphens.
|
||||
|
||||
|
||||
'Value field name cannot start with digit'
|
||||
++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
The message "Value field name cannot start with digit" can be caused by code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{:10-gig/}");
|
||||
|
||||
This code should be replaced with code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{:ten-gig/}");
|
||||
|
||||
XML element names cannot start with a digit.
|
||||
|
||||
|
||||
'Value field name should be lower case'
|
||||
+++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
The message "Value field name should be lower case" can be caused by code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{:WHY-ARE-YOU-SHOUTING}", "NO REASON");
|
||||
|
||||
This code should be replaced with code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{:why-are-you-shouting}", "no reason");
|
||||
|
||||
Lower case is more civilized. Even TLAs should be lower case
|
||||
to avoid scenarios where the differences between "XPath" and
|
||||
"Xpath" drive your users crazy. Lower case rules the seas.
|
||||
|
||||
|
||||
'Value field name should be longer than two characters'
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
The message "Value field name should be longer than two characters" can be caused by code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{:x}", "mumble");
|
||||
|
||||
This code should be replaced with code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{:something-meaningful}", "mumble");
|
||||
|
||||
Field names should be descriptive, and it's hard to
|
||||
be descriptive in less than two characters. Consider
|
||||
your users and try to make something more useful.
|
||||
Note that this error often occurs when the field type
|
||||
is placed after the colon ("{:T/%20s}"), instead of before
|
||||
it ("{T:/20s}").
|
||||
|
||||
|
||||
'Value field name contains invalid character'
|
||||
+++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
The message "Value field name contains invalid character" can be caused by code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{:cost-in-$$/%u}", 15);
|
||||
|
||||
This code should be replaced with code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{:cost-in-dollars/%u}", 15);
|
||||
|
||||
An invalid character is often a sign of a typo, like "{:]}"
|
||||
instead of "{]:}". Field names are restricted to lower-case
|
||||
characters, digits, and hyphens.
|
||||
|
||||
|
||||
'decoration field contains invalid character'
|
||||
+++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
The message "decoration field contains invalid character" can be caused by code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{D:not good}");
|
||||
|
||||
This code should be replaced with code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{D:((}{:good}{D:))}", "yes");
|
||||
|
||||
This is minor, but fields should use proper roles. Decoration
|
||||
fields are meant to hold punctuation and other characters used
|
||||
to decorate the content, typically to make it more readable
|
||||
to human readers.
|
||||
|
||||
|
||||
'Anchor content should be decimal width'
|
||||
++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
The message "Anchor content should be decimal width" can be caused by code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{[:mumble}");
|
||||
|
||||
This code should be replaced with code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{[:32}");
|
||||
|
||||
Anchors need an integer value to specify the width of
|
||||
the set of anchored fields. The value can be positive
|
||||
(for left padding/right justification) or negative (for
|
||||
right padding/left justification) and can appear in
|
||||
either the start or stop anchor field descriptor.
|
||||
|
||||
|
||||
'Anchor format should be "%d"'
|
||||
++++++++++++++++++++++++++++++
|
||||
|
||||
The message "Anchor format should be "%d"" can be caused by code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{[:/%s}");
|
||||
|
||||
This code should be replaced with code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{[:/%d}");
|
||||
|
||||
Anchors only grok integer values, and if the value is not static,
|
||||
if must be in an 'int' argument, represented by the "%d" format.
|
||||
Anything else is an error.
|
||||
|
||||
|
||||
'Anchor cannot have both format and encoding format")'
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
The message "Anchor cannot have both format and encoding format")" can be caused by code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{[:32/%d}");
|
||||
|
||||
This code should be replaced with code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{[:32}");
|
||||
|
||||
Anchors can have a static value or argument for the width,
|
||||
but cannot have both.
|
||||
|
||||
|
||||
'Max width only valid for strings'
|
||||
++++++++++++++++++++++++++++++++++
|
||||
|
||||
The message "Max width only valid for strings" can be caused by code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{:tag/%2.4.6d}", 55);
|
||||
|
||||
This code should be replaced with code like:
|
||||
|
||||
::
|
||||
|
||||
xo_emit("{:tag/%2.6d}", 55);
|
||||
|
||||
libxo allows a true 'max width' in addition to the traditional
|
||||
printf-style 'max number of bytes to use for input'. But this
|
||||
is supported only for string values, since it makes no sense
|
||||
for non-strings. This error may occur from a typo,
|
||||
like "{:tag/%6..6d}" where only one period should be used.
|
||||
|
14
doc/xopo.rst
14
doc/xopo.rst
@ -20,13 +20,13 @@ In the second mode, a simple message given using the "-s" option on
|
||||
the command, and the simplified version of that message is printed on
|
||||
stdout:
|
||||
|
||||
=========== =================================
|
||||
Option Meaning
|
||||
=========== =================================
|
||||
-o <file> Output file name
|
||||
-f <file> Use the given .po file as input
|
||||
-s <text> Simplify a format string
|
||||
=========== =================================
|
||||
=========== =================================
|
||||
Option Meaning
|
||||
=========== =================================
|
||||
-o <file> Output file name
|
||||
-f <file> Use the given .po file as input
|
||||
-s <text> Simplify a format string
|
||||
=========== =================================
|
||||
|
||||
::
|
||||
|
||||
|
@ -1,9 +1,12 @@
|
||||
#
|
||||
# Copyright 2015, Juniper Networks, Inc.
|
||||
# Copyright 2015-2019, Juniper Networks, Inc.
|
||||
# All rights reserved.
|
||||
# This SOFTWARE is licensed under the LICENSE provided in the
|
||||
# ../Copyright file. By downloading, installing, copying, or otherwise
|
||||
# using the SOFTWARE, you agree to be bound by the terms of that
|
||||
# LICENSE.
|
||||
|
||||
SUBDIRS = cbor test
|
||||
SUBDIRS = \
|
||||
cbor \
|
||||
csv \
|
||||
test
|
||||
|
@ -208,9 +208,9 @@ cbor_content (xo_handle_t *xop, cbor_private_t *cbor, xo_buffer_t *xbp,
|
||||
|
||||
unsigned offset = xo_buf_offset(xbp);
|
||||
|
||||
if (value == NULL || *value == '\0' || strcmp(value, "true") == 0)
|
||||
if (value == NULL || *value == '\0' || xo_streq(value, "true"))
|
||||
cbor_append(xop, cbor, &cbor->c_data, CBOR_TRUE, 0, NULL);
|
||||
else if (strcmp(value, "false") == 0)
|
||||
else if (xo_streq(value, "false"))
|
||||
cbor_append(xop, cbor, &cbor->c_data, CBOR_FALSE, 0, NULL);
|
||||
else {
|
||||
int negative = 0;
|
||||
@ -360,6 +360,7 @@ int
|
||||
xo_encoder_library_init (XO_ENCODER_INIT_ARGS)
|
||||
{
|
||||
arg->xei_handler = cbor_handler;
|
||||
arg->xei_version = XO_ENCODER_VERSION;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
51
encoder/csv/Makefile.am
Normal file
51
encoder/csv/Makefile.am
Normal file
@ -0,0 +1,51 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Copyright 2015-2019, Juniper Networks, Inc.
|
||||
# All rights reserved.
|
||||
# This SOFTWARE is licensed under the LICENSE provided in the
|
||||
# ../Copyright file. By downloading, installing, copying, or otherwise
|
||||
# using the SOFTWARE, you agree to be bound by the terms of that
|
||||
# LICENSE.
|
||||
|
||||
if LIBXO_WARNINGS_HIGH
|
||||
LIBXO_WARNINGS = HIGH
|
||||
endif
|
||||
if HAVE_GCC
|
||||
GCC_WARNINGS = yes
|
||||
endif
|
||||
include ${top_srcdir}/warnings.mk
|
||||
|
||||
enc_csvincdir = ${includedir}/libxo
|
||||
|
||||
AM_CFLAGS = \
|
||||
-I${top_srcdir}/libxo \
|
||||
-I${top_builddir}/libxo \
|
||||
${WARNINGS}
|
||||
|
||||
LIBNAME = libenc_csv
|
||||
pkglib_LTLIBRARIES = libenc_csv.la
|
||||
LIBS = \
|
||||
-L${top_builddir}/libxo -lxo
|
||||
|
||||
LDADD = ${top_builddir}/libxo/libxo.la
|
||||
|
||||
libenc_csv_la_SOURCES = \
|
||||
enc_csv.c
|
||||
|
||||
pkglibdir = ${XO_ENCODERDIR}
|
||||
|
||||
UGLY_NAME = csv.enc
|
||||
|
||||
install-exec-hook:
|
||||
@DLNAME=`sh -c '. ./libenc_csv.la ; echo $$dlname'` ; \
|
||||
if [ x"$$DLNAME" = x ]; \
|
||||
then DLNAME=${LIBNAME}.${XO_LIBEXT}; fi ; \
|
||||
if [ "$(build_os)" = "cygwin" ]; \
|
||||
then DLNAME="../bin/$$DLNAME"; fi ; \
|
||||
echo Install link $$DLNAME "->" ${UGLY_NAME} "..." ; \
|
||||
mkdir -p ${DESTDIR}${XO_ENCODERDIR} ; \
|
||||
cd ${DESTDIR}${XO_ENCODERDIR} \
|
||||
&& chmod +w . \
|
||||
&& rm -f ${UGLY_NAME} \
|
||||
&& ${LN_S} $$DLNAME ${UGLY_NAME}
|
826
encoder/csv/enc_csv.c
Normal file
826
encoder/csv/enc_csv.c
Normal file
@ -0,0 +1,826 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Juniper Networks, Inc.
|
||||
* All rights reserved.
|
||||
* This SOFTWARE is licensed under the LICENSE provided in the
|
||||
* ../Copyright file. By downloading, installing, copying, or otherwise
|
||||
* using the SOFTWARE, you agree to be bound by the terms of that
|
||||
* LICENSE.
|
||||
* Phil Shafer, August 2015
|
||||
*/
|
||||
|
||||
/*
|
||||
* CSV encoder generates comma-separated value files for specific
|
||||
* subsets of data. This is not (and cannot be) a generalized
|
||||
* facility, but for specific subsets of data, CSV data can be
|
||||
* reasonably generated. For example, the df XML content:
|
||||
* <filesystem>
|
||||
* <name>procfs</name>
|
||||
* <total-blocks>4</total-blocks>
|
||||
* <used-blocks>4</used-blocks>
|
||||
* <available-blocks>0</available-blocks>
|
||||
* <used-percent>100</used-percent>
|
||||
* <mounted-on>/proc</mounted-on>
|
||||
* </filesystem>
|
||||
*
|
||||
* could be represented as:
|
||||
*
|
||||
* #+name,total-blocks,used-blocks,available-blocks,used-percent,mounted-on
|
||||
* procfs,4,4,0,100,/proc
|
||||
*
|
||||
* Data is then constrained to be sibling leaf values. In addition,
|
||||
* singular leafs can also be matched. The costs include recording
|
||||
* the specific leaf names (to ensure consistency) and some
|
||||
* buffering.
|
||||
*
|
||||
* Some escaping is needed for CSV files, following the rules of RFC4180:
|
||||
*
|
||||
* - Fields containing a line-break, double-quote or commas should be
|
||||
* quoted. (If they are not, the file will likely be impossible to
|
||||
* process correctly).
|
||||
* - A (double) quote character in a field must be represented by two
|
||||
* (double) quote characters.
|
||||
* - Leading and trialing whitespace require fields be quoted.
|
||||
*
|
||||
* Cheesy, but simple. The RFC also requires MS-DOS end-of-line, which
|
||||
* we only do with the "dos" option. Strange that we still live in a
|
||||
* DOS-friendly world, but then again, we make spaceships based on the
|
||||
* horse butts (http://www.astrodigital.org/space/stshorse.html).
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "xo.h"
|
||||
#include "xo_encoder.h"
|
||||
#include "xo_buf.h"
|
||||
|
||||
#ifndef UNUSED
|
||||
#define UNUSED __attribute__ ((__unused__))
|
||||
#endif /* UNUSED */
|
||||
|
||||
/*
|
||||
* The CSV encoder has three moving parts:
|
||||
*
|
||||
* - The path holds the path we are matching against
|
||||
* - This is given as input via "options" and does not change
|
||||
*
|
||||
* - The stack holds the current names of the open elements
|
||||
* - The "open" operations push, while the "close" pop
|
||||
* - Turns out, at this point, the stack is unused, but I've
|
||||
* left "drippings" in the code because I see this as useful
|
||||
* for future features (under CSV_STACK_IS_NEEDED).
|
||||
*
|
||||
* - The leafs record the current set of leaf
|
||||
* - A key from the parent list counts as a leaf (unless CF_NO_KEYS)
|
||||
* - Once the path is matched, all other leafs at that level are leafs
|
||||
* - Leafs are recorded to get the header comment accurately recorded
|
||||
* - Once the first line is emited, the set of leafs _cannot_ change
|
||||
*
|
||||
* We use offsets into the buffers, since we know they can be
|
||||
* realloc'd out from under us, as the size increases. The 'path'
|
||||
* is fixed, we allocate it once, so it doesn't need offsets.
|
||||
*/
|
||||
typedef struct path_frame_s {
|
||||
char *pf_name; /* Path member name; points into c_path_buf */
|
||||
uint32_t pf_flags; /* Flags for this path element (PFF_*) */
|
||||
} path_frame_t;
|
||||
|
||||
typedef struct stack_frame_s {
|
||||
ssize_t sf_off; /* Element name; offset in c_stack_buf */
|
||||
uint32_t sf_flags; /* Flags for this frame (SFF_*) */
|
||||
} stack_frame_t;
|
||||
|
||||
/* Flags for sf_flags */
|
||||
|
||||
typedef struct leaf_s {
|
||||
ssize_t f_name; /* Name of leaf; offset in c_name_buf */
|
||||
ssize_t f_value; /* Value of leaf; offset in c_value_buf */
|
||||
uint32_t f_flags; /* Flags for this value (FF_*) */
|
||||
#ifdef CSV_STACK_IS_NEEDED
|
||||
ssize_t f_depth; /* Depth of stack when leaf was recorded */
|
||||
#endif /* CSV_STACK_IS_NEEDED */
|
||||
} leaf_t;
|
||||
|
||||
/* Flags for f_flags */
|
||||
#define LF_KEY (1<<0) /* Leaf is a key */
|
||||
#define LF_HAS_VALUE (1<<1) /* Value has been set */
|
||||
|
||||
typedef struct csv_private_s {
|
||||
uint32_t c_flags; /* Flags for this encoder */
|
||||
|
||||
/* The path for which we select leafs */
|
||||
char *c_path_buf; /* Buffer containing path members */
|
||||
path_frame_t *c_path; /* Array of path members */
|
||||
ssize_t c_path_max; /* Depth of c_path[] */
|
||||
ssize_t c_path_cur; /* Current depth in c_path[] */
|
||||
|
||||
/* A stack of open elements (xo_op_list, xo_op_container) */
|
||||
#if CSV_STACK_IS_NEEDED
|
||||
xo_buffer_t c_stack_buf; /* Buffer used for stack content */
|
||||
stack_frame_t *c_stack; /* Stack of open tags */
|
||||
ssize_t c_stack_max; /* Maximum stack depth */
|
||||
#endif /* CSV_STACK_IS_NEEDED */
|
||||
ssize_t c_stack_depth; /* Current stack depth */
|
||||
|
||||
/* List of leafs we are emitting (to ensure consistency) */
|
||||
xo_buffer_t c_name_buf; /* String buffer for leaf names */
|
||||
xo_buffer_t c_value_buf; /* String buffer for leaf values */
|
||||
leaf_t *c_leaf; /* List of leafs */
|
||||
ssize_t c_leaf_depth; /* Current depth of c_leaf[] (next free) */
|
||||
ssize_t c_leaf_max; /* Max depth of c_leaf[] */
|
||||
|
||||
xo_buffer_t c_data; /* Buffer for creating data */
|
||||
} csv_private_t;
|
||||
|
||||
#define C_STACK_MAX 32 /* default c_stack_max */
|
||||
#define C_LEAF_MAX 32 /* default c_leaf_max */
|
||||
|
||||
/* Flags for this structure */
|
||||
#define CF_HEADER_DONE (1<<0) /* Have already written the header */
|
||||
#define CF_NO_HEADER (1<<1) /* Do not generate header */
|
||||
#define CF_NO_KEYS (1<<2) /* Do not generate excess keys */
|
||||
#define CF_VALUE_ONLY (1<<3) /* Only generate the value */
|
||||
|
||||
#define CF_DOS_NEWLINE (1<<4) /* Generate CR-NL, just like MS-DOS */
|
||||
#define CF_LEAFS_DONE (1<<5) /* Leafs are already been recorded */
|
||||
#define CF_NO_QUOTES (1<<6) /* Do not generate quotes */
|
||||
#define CF_RECORD_DATA (1<<7) /* Record all sibling leafs */
|
||||
|
||||
#define CF_DEBUG (1<<8) /* Make debug output */
|
||||
#define CF_HAS_PATH (1<<9) /* A "path" option was provided */
|
||||
|
||||
/*
|
||||
* A simple debugging print function, similar to psu_dbg. Controlled by
|
||||
* the undocumented "debug" option.
|
||||
*/
|
||||
static void
|
||||
csv_dbg (xo_handle_t *xop UNUSED, csv_private_t *csv UNUSED,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
if (csv == NULL || !(csv->c_flags & CF_DEBUG))
|
||||
return;
|
||||
|
||||
va_list vap;
|
||||
|
||||
va_start(vap, fmt);
|
||||
vfprintf(stderr, fmt, vap);
|
||||
va_end(vap);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the private data for this handle, initialize it, and record
|
||||
* the pointer in the handle.
|
||||
*/
|
||||
static int
|
||||
csv_create (xo_handle_t *xop)
|
||||
{
|
||||
csv_private_t *csv = xo_realloc(NULL, sizeof(*csv));
|
||||
if (csv == NULL)
|
||||
return -1;
|
||||
|
||||
bzero(csv, sizeof(*csv));
|
||||
xo_buf_init(&csv->c_data);
|
||||
xo_buf_init(&csv->c_name_buf);
|
||||
xo_buf_init(&csv->c_value_buf);
|
||||
#ifdef CSV_STACK_IS_NEEDED
|
||||
xo_buf_init(&csv->c_stack_buf);
|
||||
#endif /* CSV_STACK_IS_NEEDED */
|
||||
|
||||
xo_set_private(xop, csv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up and release any data in use by this handle
|
||||
*/
|
||||
static void
|
||||
csv_destroy (xo_handle_t *xop UNUSED, csv_private_t *csv)
|
||||
{
|
||||
/* Clean up */
|
||||
xo_buf_cleanup(&csv->c_data);
|
||||
xo_buf_cleanup(&csv->c_name_buf);
|
||||
xo_buf_cleanup(&csv->c_value_buf);
|
||||
#ifdef CSV_STACK_IS_NEEDED
|
||||
xo_buf_cleanup(&csv->c_stack_buf);
|
||||
#endif /* CSV_STACK_IS_NEEDED */
|
||||
|
||||
if (csv->c_leaf)
|
||||
xo_free(csv->c_leaf);
|
||||
if (csv->c_path_buf)
|
||||
xo_free(csv->c_path_buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the element name at the top of the path stack. This is the
|
||||
* item that we are currently trying to match on.
|
||||
*/
|
||||
static const char *
|
||||
csv_path_top (csv_private_t *csv, ssize_t delta)
|
||||
{
|
||||
if (!(csv->c_flags & CF_HAS_PATH) || csv->c_path == NULL)
|
||||
return NULL;
|
||||
|
||||
ssize_t cur = csv->c_path_cur + delta;
|
||||
|
||||
if (cur < 0)
|
||||
return NULL;
|
||||
|
||||
return csv->c_path[cur].pf_name;
|
||||
}
|
||||
|
||||
/*
|
||||
* Underimplemented stack functionality
|
||||
*/
|
||||
static inline void
|
||||
csv_stack_push (csv_private_t *csv UNUSED, const char *name UNUSED)
|
||||
{
|
||||
#ifdef CSV_STACK_IS_NEEDED
|
||||
csv->c_stack_depth += 1;
|
||||
#endif /* CSV_STACK_IS_NEEDED */
|
||||
}
|
||||
|
||||
/*
|
||||
* Underimplemented stack functionality
|
||||
*/
|
||||
static inline void
|
||||
csv_stack_pop (csv_private_t *csv UNUSED, const char *name UNUSED)
|
||||
{
|
||||
#ifdef CSV_STACK_IS_NEEDED
|
||||
csv->c_stack_depth -= 1;
|
||||
#endif /* CSV_STACK_IS_NEEDED */
|
||||
}
|
||||
|
||||
/* Flags for csv_quote_flags */
|
||||
#define QF_NEEDS_QUOTES (1<<0) /* Needs to be quoted */
|
||||
#define QF_NEEDS_ESCAPE (1<<1) /* Needs to be escaped */
|
||||
|
||||
/*
|
||||
* Determine how much quote processing is needed. The details of the
|
||||
* quoting rules are given at the top of this file. We return a set
|
||||
* of flags, indicating what's needed.
|
||||
*/
|
||||
static uint32_t
|
||||
csv_quote_flags (xo_handle_t *xop UNUSED, csv_private_t *csv UNUSED,
|
||||
const char *value)
|
||||
{
|
||||
static const char quoted[] = "\n\r\",";
|
||||
static const char escaped[] = "\"";
|
||||
|
||||
if (csv->c_flags & CF_NO_QUOTES) /* User doesn't want quotes */
|
||||
return 0;
|
||||
|
||||
size_t len = strlen(value);
|
||||
uint32_t rc = 0;
|
||||
|
||||
if (strcspn(value, quoted) != len)
|
||||
rc |= QF_NEEDS_QUOTES;
|
||||
else if (isspace((int) value[0])) /* Leading whitespace */
|
||||
rc |= QF_NEEDS_QUOTES;
|
||||
else if (isspace((int) value[len - 1])) /* Trailing whitespace */
|
||||
rc |= QF_NEEDS_QUOTES;
|
||||
|
||||
if (strcspn(value, escaped) != len)
|
||||
rc |= QF_NEEDS_ESCAPE;
|
||||
|
||||
csv_dbg(xop, csv, "csv: quote flags [%s] -> %x (%zu/%zu)\n",
|
||||
value, rc, len, strcspn(value, quoted));
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Escape the string, following the rules in RFC4180
|
||||
*/
|
||||
static void
|
||||
csv_escape (xo_buffer_t *xbp, const char *value, size_t len)
|
||||
{
|
||||
const char *cp, *ep, *np;
|
||||
|
||||
for (cp = value, ep = value + len; cp && cp < ep; cp = np) {
|
||||
np = strchr(cp, '"');
|
||||
if (np) {
|
||||
np += 1;
|
||||
xo_buf_append(xbp, cp, np - cp);
|
||||
xo_buf_append(xbp, "\"", 1);
|
||||
} else
|
||||
xo_buf_append(xbp, cp, ep - cp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Append a newline to the buffer, following the settings of the "dos"
|
||||
* flag.
|
||||
*/
|
||||
static void
|
||||
csv_append_newline (xo_buffer_t *xbp, csv_private_t *csv)
|
||||
{
|
||||
if (csv->c_flags & CF_DOS_NEWLINE)
|
||||
xo_buf_append(xbp, "\r\n", 2);
|
||||
else
|
||||
xo_buf_append(xbp, "\n", 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a 'record' of 'fields' from our recorded leaf values. If
|
||||
* this is the first line and "no-header" isn't given, make a record
|
||||
* containing the leaf names.
|
||||
*/
|
||||
static void
|
||||
csv_emit_record (xo_handle_t *xop, csv_private_t *csv)
|
||||
{
|
||||
csv_dbg(xop, csv, "csv: emit: ...\n");
|
||||
|
||||
ssize_t fnum;
|
||||
uint32_t quote_flags;
|
||||
leaf_t *lp;
|
||||
|
||||
/* If we have no data, then don't bother */
|
||||
if (csv->c_leaf_depth == 0)
|
||||
return;
|
||||
|
||||
if (!(csv->c_flags & (CF_HEADER_DONE | CF_NO_HEADER))) {
|
||||
csv->c_flags |= CF_HEADER_DONE;
|
||||
|
||||
for (fnum = 0; fnum < csv->c_leaf_depth; fnum++) {
|
||||
lp = &csv->c_leaf[fnum];
|
||||
const char *name = xo_buf_data(&csv->c_name_buf, lp->f_name);
|
||||
|
||||
if (fnum != 0)
|
||||
xo_buf_append(&csv->c_data, ",", 1);
|
||||
|
||||
xo_buf_append(&csv->c_data, name, strlen(name));
|
||||
}
|
||||
|
||||
csv_append_newline(&csv->c_data, csv);
|
||||
}
|
||||
|
||||
for (fnum = 0; fnum < csv->c_leaf_depth; fnum++) {
|
||||
lp = &csv->c_leaf[fnum];
|
||||
const char *value;
|
||||
|
||||
if (lp->f_flags & LF_HAS_VALUE) {
|
||||
value = xo_buf_data(&csv->c_value_buf, lp->f_value);
|
||||
} else {
|
||||
value = "";
|
||||
}
|
||||
|
||||
quote_flags = csv_quote_flags(xop, csv, value);
|
||||
|
||||
if (fnum != 0)
|
||||
xo_buf_append(&csv->c_data, ",", 1);
|
||||
|
||||
if (quote_flags & QF_NEEDS_QUOTES)
|
||||
xo_buf_append(&csv->c_data, "\"", 1);
|
||||
|
||||
if (quote_flags & QF_NEEDS_ESCAPE)
|
||||
csv_escape(&csv->c_data, value, strlen(value));
|
||||
else
|
||||
xo_buf_append(&csv->c_data, value, strlen(value));
|
||||
|
||||
if (quote_flags & QF_NEEDS_QUOTES)
|
||||
xo_buf_append(&csv->c_data, "\"", 1);
|
||||
}
|
||||
|
||||
csv_append_newline(&csv->c_data, csv);
|
||||
|
||||
/* We flush if either flush flag is set */
|
||||
if (xo_get_flags(xop) & (XOF_FLUSH | XOF_FLUSH_LINE))
|
||||
xo_flush_h(xop);
|
||||
|
||||
/* Clean out values from leafs */
|
||||
for (fnum = 0; fnum < csv->c_leaf_depth; fnum++) {
|
||||
lp = &csv->c_leaf[fnum];
|
||||
|
||||
lp->f_flags &= ~LF_HAS_VALUE;
|
||||
lp->f_value = 0;
|
||||
}
|
||||
|
||||
xo_buf_reset(&csv->c_value_buf);
|
||||
|
||||
/*
|
||||
* Once we emit the first line, our set of leafs is locked and
|
||||
* cannot be changed.
|
||||
*/
|
||||
csv->c_flags |= CF_LEAFS_DONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Open a "level" of hierarchy, either a container or an instance. Look
|
||||
* for a match in the path=x/y/z hierarchy, and ignore if not a match.
|
||||
* If we're at the end of the path, start recording leaf values.
|
||||
*/
|
||||
static int
|
||||
csv_open_level (xo_handle_t *xop UNUSED, csv_private_t *csv,
|
||||
const char *name, int instance)
|
||||
{
|
||||
/* An new "open" event means we stop recording */
|
||||
if (csv->c_flags & CF_RECORD_DATA) {
|
||||
csv->c_flags &= ~CF_RECORD_DATA;
|
||||
csv_emit_record(xop, csv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *path_top = csv_path_top(csv, 0);
|
||||
|
||||
/* If the top of the stack does not match the name, then ignore */
|
||||
if (path_top == NULL) {
|
||||
if (instance && !(csv->c_flags & CF_HAS_PATH)) {
|
||||
csv_dbg(xop, csv, "csv: recording (no-path) ...\n");
|
||||
csv->c_flags |= CF_RECORD_DATA;
|
||||
}
|
||||
|
||||
} else if (xo_streq(path_top, name)) {
|
||||
csv->c_path_cur += 1; /* Advance to next path member */
|
||||
|
||||
csv_dbg(xop, csv, "csv: match: [%s] (%zd/%zd)\n", name,
|
||||
csv->c_path_cur, csv->c_path_max);
|
||||
|
||||
/* If we're all the way thru the path members, start recording */
|
||||
if (csv->c_path_cur == csv->c_path_max) {
|
||||
csv_dbg(xop, csv, "csv: recording ...\n");
|
||||
csv->c_flags |= CF_RECORD_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
/* Push the name on the stack */
|
||||
csv_stack_push(csv, name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Close a "level", either a container or an instance.
|
||||
*/
|
||||
static int
|
||||
csv_close_level (xo_handle_t *xop UNUSED, csv_private_t *csv, const char *name)
|
||||
{
|
||||
/* If we're recording, a close triggers an emit */
|
||||
if (csv->c_flags & CF_RECORD_DATA) {
|
||||
csv->c_flags &= ~CF_RECORD_DATA;
|
||||
csv_emit_record(xop, csv);
|
||||
}
|
||||
|
||||
const char *path_top = csv_path_top(csv, -1);
|
||||
csv_dbg(xop, csv, "csv: close: [%s] [%s] (%zd)\n", name,
|
||||
path_top ?: "", csv->c_path_cur);
|
||||
|
||||
/* If the top of the stack does not match the name, then ignore */
|
||||
if (path_top != NULL && xo_streq(path_top, name)) {
|
||||
csv->c_path_cur -= 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Pop the name off the stack */
|
||||
csv_stack_pop(csv, name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the index of a given leaf in the c_leaf[] array, where we
|
||||
* record leaf values. If the leaf is new and we haven't stopped recording
|
||||
* leafs, then make a new slot for it and record the name.
|
||||
*/
|
||||
static int
|
||||
csv_leaf_num (xo_handle_t *xop UNUSED, csv_private_t *csv,
|
||||
const char *name, xo_xff_flags_t flags)
|
||||
{
|
||||
ssize_t fnum;
|
||||
leaf_t *lp;
|
||||
xo_buffer_t *xbp = &csv->c_name_buf;
|
||||
|
||||
for (fnum = 0; fnum < csv->c_leaf_depth; fnum++) {
|
||||
lp = &csv->c_leaf[fnum];
|
||||
|
||||
const char *fname = xo_buf_data(xbp, lp->f_name);
|
||||
if (xo_streq(fname, name))
|
||||
return fnum;
|
||||
}
|
||||
|
||||
/* If we're done with adding new leafs, then bail */
|
||||
if (csv->c_flags & CF_LEAFS_DONE)
|
||||
return -1;
|
||||
|
||||
/* This leaf does not exist yet, so we need to create it */
|
||||
/* Start by checking if there's enough room */
|
||||
if (csv->c_leaf_depth + 1 >= csv->c_leaf_max) {
|
||||
/* Out of room; realloc it */
|
||||
ssize_t new_max = csv->c_leaf_max * 2;
|
||||
if (new_max == 0)
|
||||
new_max = C_LEAF_MAX;
|
||||
|
||||
lp = xo_realloc(csv->c_leaf, new_max * sizeof(*lp));
|
||||
if (lp == NULL)
|
||||
return -1; /* No luck; bail */
|
||||
|
||||
/* Zero out the new portion */
|
||||
bzero(&lp[csv->c_leaf_max], csv->c_leaf_max * sizeof(*lp));
|
||||
|
||||
/* Update csv data */
|
||||
csv->c_leaf = lp;
|
||||
csv->c_leaf_max = new_max;
|
||||
}
|
||||
|
||||
lp = &csv->c_leaf[csv->c_leaf_depth++];
|
||||
#ifdef CSV_STACK_IS_NEEDED
|
||||
lp->f_depth = csv->c_stack_depth;
|
||||
#endif /* CSV_STACK_IS_NEEDED */
|
||||
|
||||
lp->f_name = xo_buf_offset(xbp);
|
||||
|
||||
char *cp = xo_buf_cur(xbp);
|
||||
xo_buf_append(xbp, name, strlen(name) + 1);
|
||||
|
||||
if (flags & XFF_KEY)
|
||||
lp->f_flags |= LF_KEY;
|
||||
|
||||
csv_dbg(xop, csv, "csv: leaf: name: %zd [%s] [%s] %x\n",
|
||||
fnum, name, cp, lp->f_flags);
|
||||
|
||||
return fnum;
|
||||
}
|
||||
|
||||
/*
|
||||
* Record a new value for a leaf
|
||||
*/
|
||||
static void
|
||||
csv_leaf_set (xo_handle_t *xop UNUSED, csv_private_t *csv, leaf_t *lp,
|
||||
const char *value)
|
||||
{
|
||||
xo_buffer_t *xbp = &csv->c_value_buf;
|
||||
|
||||
lp->f_value = xo_buf_offset(xbp);
|
||||
lp->f_flags |= LF_HAS_VALUE;
|
||||
|
||||
char *cp = xo_buf_cur(xbp);
|
||||
xo_buf_append(xbp, value, strlen(value) + 1);
|
||||
|
||||
csv_dbg(xop, csv, "csv: leaf: value: [%s] [%s] %x\n",
|
||||
value, cp, lp->f_flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Record the requested set of leaf names. The input should be a set
|
||||
* of leaf names, separated by periods.
|
||||
*/
|
||||
static int
|
||||
csv_record_leafs (xo_handle_t *xop, csv_private_t *csv, const char *leafs_raw)
|
||||
{
|
||||
char *cp, *ep, *np;
|
||||
ssize_t len = strlen(leafs_raw);
|
||||
char *leafs_buf = alloca(len + 1);
|
||||
|
||||
memcpy(leafs_buf, leafs_raw, len + 1); /* Make local copy */
|
||||
|
||||
for (cp = leafs_buf, ep = leafs_buf + len; cp && cp < ep; cp = np) {
|
||||
np = strchr(cp, '.');
|
||||
if (np)
|
||||
*np++ = '\0';
|
||||
|
||||
if (*cp == '\0') /* Skip empty names */
|
||||
continue;
|
||||
|
||||
csv_dbg(xop, csv, "adding leaf: [%s]\n", cp);
|
||||
csv_leaf_num(xop, csv, cp, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Since we've been told explicitly what leafs matter, ignore the rest
|
||||
*/
|
||||
csv->c_flags |= CF_LEAFS_DONE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Record the requested path elements. The input should be a set of
|
||||
* container or instances names, separated by slashes.
|
||||
*/
|
||||
static int
|
||||
csv_record_path (xo_handle_t *xop, csv_private_t *csv, const char *path_raw)
|
||||
{
|
||||
int count;
|
||||
char *cp, *ep, *np;
|
||||
ssize_t len = strlen(path_raw);
|
||||
char *path_buf = xo_realloc(NULL, len + 1);
|
||||
|
||||
memcpy(path_buf, path_raw, len + 1);
|
||||
|
||||
for (cp = path_buf, ep = path_buf + len, count = 2;
|
||||
cp && cp < ep; cp = np) {
|
||||
np = strchr(cp, '/');
|
||||
if (np) {
|
||||
np += 1;
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
path_frame_t *path = xo_realloc(NULL, sizeof(path[0]) * count);
|
||||
if (path == NULL) {
|
||||
xo_failure(xop, "allocation failure for path '%s'", path_buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bzero(path, sizeof(path[0]) * count);
|
||||
|
||||
for (count = 0, cp = path_buf; cp && cp < ep; cp = np) {
|
||||
path[count++].pf_name = cp;
|
||||
|
||||
np = strchr(cp, '/');
|
||||
if (np)
|
||||
*np++ = '\0';
|
||||
csv_dbg(xop, csv, "path: [%s]\n", cp);
|
||||
}
|
||||
|
||||
path[count].pf_name = NULL;
|
||||
|
||||
if (csv->c_path) /* In case two paths are given */
|
||||
xo_free(csv->c_path);
|
||||
if (csv->c_path_buf) /* In case two paths are given */
|
||||
xo_free(csv->c_path_buf);
|
||||
|
||||
csv->c_path_buf = path_buf;
|
||||
csv->c_path = path;
|
||||
csv->c_path_max = count;
|
||||
csv->c_path_cur = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract the option values. The format is:
|
||||
* -libxo encoder=csv:kw=val+kw=val+kw=val,pretty,etc
|
||||
*/
|
||||
static int
|
||||
csv_options (xo_handle_t *xop, csv_private_t *csv, const char *raw_opts)
|
||||
{
|
||||
ssize_t len = strlen(raw_opts);
|
||||
char *options = alloca(len + 1);
|
||||
memcpy(options, raw_opts, len);
|
||||
options[len] = '\0';
|
||||
|
||||
char *cp, *ep, *np, *vp;
|
||||
for (cp = options, ep = options + len + 1; cp && cp < ep; cp = np) {
|
||||
np = strchr(cp, '+');
|
||||
if (np)
|
||||
*np++ = '\0';
|
||||
|
||||
vp = strchr(cp, '=');
|
||||
if (vp)
|
||||
*vp++ = '\0';
|
||||
|
||||
if (xo_streq(cp, "path")) {
|
||||
/* Record the path */
|
||||
if (vp != NULL && csv_record_path(xop, csv, vp))
|
||||
return -1;
|
||||
|
||||
csv->c_flags |= CF_HAS_PATH; /* Yup, we have an explicit path now */
|
||||
|
||||
} else if (xo_streq(cp, "leafs")
|
||||
|| xo_streq(cp, "leaf")
|
||||
|| xo_streq(cp, "leaves")) {
|
||||
/* Record the leafs */
|
||||
if (vp != NULL && csv_record_leafs(xop, csv, vp))
|
||||
return -1;
|
||||
|
||||
} else if (xo_streq(cp, "no-keys")) {
|
||||
csv->c_flags |= CF_NO_KEYS;
|
||||
} else if (xo_streq(cp, "no-header")) {
|
||||
csv->c_flags |= CF_NO_HEADER;
|
||||
} else if (xo_streq(cp, "value-only")) {
|
||||
csv->c_flags |= CF_VALUE_ONLY;
|
||||
} else if (xo_streq(cp, "dos")) {
|
||||
csv->c_flags |= CF_DOS_NEWLINE;
|
||||
} else if (xo_streq(cp, "no-quotes")) {
|
||||
csv->c_flags |= CF_NO_QUOTES;
|
||||
} else if (xo_streq(cp, "debug")) {
|
||||
csv->c_flags |= CF_DEBUG;
|
||||
} else {
|
||||
xo_warn_hc(xop, -1,
|
||||
"unknown encoder option value: '%s'", cp);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handler for incoming data values. We just record each leaf name and
|
||||
* value. The values are emittd when the instance is closed.
|
||||
*/
|
||||
static int
|
||||
csv_data (xo_handle_t *xop UNUSED, csv_private_t *csv UNUSED,
|
||||
const char *name, const char *value,
|
||||
xo_xof_flags_t flags)
|
||||
{
|
||||
csv_dbg(xop, csv, "data: [%s]=[%s] %llx\n", name, value, (unsigned long long) flags);
|
||||
|
||||
if (!(csv->c_flags & CF_RECORD_DATA))
|
||||
return 0;
|
||||
|
||||
/* Find the leaf number */
|
||||
int fnum = csv_leaf_num(xop, csv, name, flags);
|
||||
if (fnum < 0)
|
||||
return 0; /* Don't bother recording */
|
||||
|
||||
leaf_t *lp = &csv->c_leaf[fnum];
|
||||
csv_leaf_set(xop, csv, lp, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The callback from libxo, passing us operations/events as they
|
||||
* happen.
|
||||
*/
|
||||
static int
|
||||
csv_handler (XO_ENCODER_HANDLER_ARGS)
|
||||
{
|
||||
int rc = 0;
|
||||
csv_private_t *csv = private;
|
||||
xo_buffer_t *xbp = csv ? &csv->c_data : NULL;
|
||||
|
||||
csv_dbg(xop, csv, "op %s: [%s] [%s]\n", xo_encoder_op_name(op),
|
||||
name ?: "", value ?: "");
|
||||
fflush(stdout);
|
||||
|
||||
/* If we don't have private data, we're sunk */
|
||||
if (csv == NULL && op != XO_OP_CREATE)
|
||||
return -1;
|
||||
|
||||
switch (op) {
|
||||
case XO_OP_CREATE: /* Called when the handle is init'd */
|
||||
rc = csv_create(xop);
|
||||
break;
|
||||
|
||||
case XO_OP_OPTIONS:
|
||||
rc = csv_options(xop, csv, value);
|
||||
break;
|
||||
|
||||
case XO_OP_OPEN_LIST:
|
||||
case XO_OP_CLOSE_LIST:
|
||||
break; /* Ignore these ops */
|
||||
|
||||
case XO_OP_OPEN_CONTAINER:
|
||||
case XO_OP_OPEN_LEAF_LIST:
|
||||
rc = csv_open_level(xop, csv, name, 0);
|
||||
break;
|
||||
|
||||
case XO_OP_OPEN_INSTANCE:
|
||||
rc = csv_open_level(xop, csv, name, 1);
|
||||
break;
|
||||
|
||||
case XO_OP_CLOSE_CONTAINER:
|
||||
case XO_OP_CLOSE_LEAF_LIST:
|
||||
case XO_OP_CLOSE_INSTANCE:
|
||||
rc = csv_close_level(xop, csv, name);
|
||||
break;
|
||||
|
||||
case XO_OP_STRING: /* Quoted UTF-8 string */
|
||||
case XO_OP_CONTENT: /* Other content */
|
||||
rc = csv_data(xop, csv, name, value, flags);
|
||||
break;
|
||||
|
||||
case XO_OP_FINISH: /* Clean up function */
|
||||
break;
|
||||
|
||||
case XO_OP_FLUSH: /* Clean up function */
|
||||
rc = write(1, xbp->xb_bufp, xbp->xb_curp - xbp->xb_bufp);
|
||||
if (rc > 0)
|
||||
rc = 0;
|
||||
|
||||
xo_buf_reset(xbp);
|
||||
break;
|
||||
|
||||
case XO_OP_DESTROY: /* Clean up function */
|
||||
csv_destroy(xop, csv);
|
||||
break;
|
||||
|
||||
case XO_OP_ATTRIBUTE: /* Attribute name/value */
|
||||
break;
|
||||
|
||||
case XO_OP_VERSION: /* Version string */
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback when our encoder is loaded.
|
||||
*/
|
||||
int
|
||||
xo_encoder_library_init (XO_ENCODER_INIT_ARGS)
|
||||
{
|
||||
arg->xei_handler = csv_handler;
|
||||
arg->xei_version = XO_ENCODER_VERSION;
|
||||
|
||||
return 0;
|
||||
}
|
@ -15,7 +15,7 @@ static int
|
||||
test_handler (XO_ENCODER_HANDLER_ARGS)
|
||||
{
|
||||
printf("op %s: [%s] [%s] [%#llx]\n", xo_encoder_op_name(op),
|
||||
name ?: "", value ?: "", flags);
|
||||
name ?: "", value ?: "", (unsigned long long) flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ uses
|
||||
version @LIBXO_VERSION@.
|
||||
Complete documentation can be found on github:
|
||||
.Bd -literal -offset indent
|
||||
http://juniper.github.io/libxo/@LIBXO_VERSION@/libxo\-manual.html
|
||||
https://juniper.github.io/libxo/@LIBXO_VERSION@/html/index.html
|
||||
.Ed
|
||||
.Pp
|
||||
.Nm libxo
|
||||
|
160
libxo/libxo.c
160
libxo/libxo.c
@ -293,39 +293,6 @@ struct xo_handle_s {
|
||||
#define XOIF_INIT_IN_PROGRESS XOF_BIT(5) /* Init of handle is in progress */
|
||||
#define XOIF_MADE_OUTPUT XOF_BIT(6) /* Have already made output */
|
||||
|
||||
/* Flags for formatting functions */
|
||||
typedef unsigned long xo_xff_flags_t;
|
||||
#define XFF_COLON (1<<0) /* Append a ":" */
|
||||
#define XFF_COMMA (1<<1) /* Append a "," iff there's more output */
|
||||
#define XFF_WS (1<<2) /* Append a blank */
|
||||
#define XFF_ENCODE_ONLY (1<<3) /* Only emit for encoding styles (XML, JSON) */
|
||||
|
||||
#define XFF_QUOTE (1<<4) /* Force quotes */
|
||||
#define XFF_NOQUOTE (1<<5) /* Force no quotes */
|
||||
#define XFF_DISPLAY_ONLY (1<<6) /* Only emit for display styles (text, html) */
|
||||
#define XFF_KEY (1<<7) /* Field is a key (for XPath) */
|
||||
|
||||
#define XFF_XML (1<<8) /* Force XML encoding style (for XPath) */
|
||||
#define XFF_ATTR (1<<9) /* Escape value using attribute rules (XML) */
|
||||
#define XFF_BLANK_LINE (1<<10) /* Emit a blank line */
|
||||
#define XFF_NO_OUTPUT (1<<11) /* Do not make any output */
|
||||
|
||||
#define XFF_TRIM_WS (1<<12) /* Trim whitespace off encoded values */
|
||||
#define XFF_LEAF_LIST (1<<13) /* A leaf-list (list of values) */
|
||||
#define XFF_UNESCAPE (1<<14) /* Need to printf-style unescape the value */
|
||||
#define XFF_HUMANIZE (1<<15) /* Humanize the value (for display styles) */
|
||||
|
||||
#define XFF_HN_SPACE (1<<16) /* Humanize: put space before suffix */
|
||||
#define XFF_HN_DECIMAL (1<<17) /* Humanize: add one decimal place if <10 */
|
||||
#define XFF_HN_1000 (1<<18) /* Humanize: use 1000, not 1024 */
|
||||
#define XFF_GT_FIELD (1<<19) /* Call gettext() on a field */
|
||||
|
||||
#define XFF_GT_PLURAL (1<<20) /* Call dngettext to find plural form */
|
||||
#define XFF_ARGUMENT (1<<21) /* Content provided via argument */
|
||||
|
||||
/* Flags to turn off when we don't want i18n processing */
|
||||
#define XFF_GT_FLAGS (XFF_GT_FIELD | XFF_GT_PLURAL)
|
||||
|
||||
/*
|
||||
* Normal printf has width and precision, which for strings operate as
|
||||
* min and max number of columns. But this depends on the idea that
|
||||
@ -435,9 +402,6 @@ xo_realloc_func_t xo_realloc = realloc;
|
||||
xo_free_func_t xo_free = free;
|
||||
|
||||
/* Forward declarations */
|
||||
static void
|
||||
xo_failure (xo_handle_t *xop, const char *fmt, ...);
|
||||
|
||||
static ssize_t
|
||||
xo_transition (xo_handle_t *xop, xo_xof_flags_t flags, const char *name,
|
||||
xo_state_t new_state);
|
||||
@ -660,13 +624,18 @@ xo_init_handle (xo_handle_t *xop)
|
||||
if (!xo_locale_inited) {
|
||||
xo_locale_inited = 1; /* Only do this once */
|
||||
|
||||
const char *cp = getenv("LC_CTYPE");
|
||||
#ifdef __FreeBSD__ /* Who does The Right Thing */
|
||||
const char *cp = "";
|
||||
#else /* __FreeBSD__ */
|
||||
const char *cp = getenv("LC_ALL");
|
||||
if (cp == NULL)
|
||||
cp = getenv("LC_CTYPE");
|
||||
if (cp == NULL)
|
||||
cp = getenv("LANG");
|
||||
if (cp == NULL)
|
||||
cp = getenv("LC_ALL");
|
||||
if (cp == NULL)
|
||||
cp = "C"; /* Default for C programs */
|
||||
#endif /* __FreeBSD__ */
|
||||
|
||||
(void) setlocale(LC_CTYPE, cp);
|
||||
}
|
||||
|
||||
@ -1871,7 +1840,7 @@ xo_message (const char *fmt, ...)
|
||||
va_end(vap);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
xo_failure (xo_handle_t *xop, const char *fmt, ...)
|
||||
{
|
||||
if (!XOF_ISSET(xop, XOF_WARN))
|
||||
@ -2042,17 +2011,17 @@ xo_get_style (xo_handle_t *xop)
|
||||
static int
|
||||
xo_name_to_style (const char *name)
|
||||
{
|
||||
if (strcmp(name, "xml") == 0)
|
||||
if (xo_streq(name, "xml"))
|
||||
return XO_STYLE_XML;
|
||||
else if (strcmp(name, "json") == 0)
|
||||
else if (xo_streq(name, "json"))
|
||||
return XO_STYLE_JSON;
|
||||
else if (strcmp(name, "encoder") == 0)
|
||||
else if (xo_streq(name, "encoder"))
|
||||
return XO_STYLE_ENCODER;
|
||||
else if (strcmp(name, "text") == 0)
|
||||
else if (xo_streq(name, "text"))
|
||||
return XO_STYLE_TEXT;
|
||||
else if (strcmp(name, "html") == 0)
|
||||
else if (xo_streq(name, "html"))
|
||||
return XO_STYLE_HTML;
|
||||
else if (strcmp(name, "sdparams") == 0)
|
||||
else if (xo_streq(name, "sdparams"))
|
||||
return XO_STYLE_SDPARAMS;
|
||||
|
||||
return -1;
|
||||
@ -2230,7 +2199,7 @@ xo_set_color_map (xo_handle_t *xop, char *value)
|
||||
}
|
||||
|
||||
/* If no color initialization happened, then we don't need the map */
|
||||
if (num > 0)
|
||||
if (num > 1)
|
||||
XOF_SET(xop, XOF_COLOR_MAP);
|
||||
else
|
||||
XOF_CLEAR(xop, XOF_COLOR_MAP);
|
||||
@ -2261,7 +2230,7 @@ xo_set_options_simple (xo_handle_t *xop, const char *input)
|
||||
if (vp)
|
||||
*vp++ = '\0';
|
||||
|
||||
if (strcmp("colors", cp) == 0) {
|
||||
if (xo_streq("colors", cp)) {
|
||||
xo_set_color_map(xop, vp);
|
||||
continue;
|
||||
}
|
||||
@ -2269,7 +2238,7 @@ xo_set_options_simple (xo_handle_t *xop, const char *input)
|
||||
new_flag = xo_name_lookup(xo_xof_simple_names, cp, -1);
|
||||
if (new_flag != 0) {
|
||||
XOF_SET(xop, new_flag);
|
||||
} else if (strcmp(cp, "no-color") == 0) {
|
||||
} else if (xo_streq(cp, "no-color")) {
|
||||
XOF_CLEAR(xop, XOF_COLOR_ALLOWED);
|
||||
} else {
|
||||
xo_failure(xop, "unknown simple option: %s", cp);
|
||||
@ -2406,7 +2375,7 @@ xo_set_options (xo_handle_t *xop, const char *input)
|
||||
if (vp)
|
||||
*vp++ = '\0';
|
||||
|
||||
if (strcmp("colors", cp) == 0) {
|
||||
if (xo_streq("colors", cp)) {
|
||||
xo_set_color_map(xop, vp);
|
||||
continue;
|
||||
}
|
||||
@ -2425,21 +2394,20 @@ xo_set_options (xo_handle_t *xop, const char *input)
|
||||
new_flag = xo_name_to_flag(cp);
|
||||
if (new_flag != 0)
|
||||
XOF_SET(xop, new_flag);
|
||||
else if (strcmp(cp, "no-color") == 0)
|
||||
else if (xo_streq(cp, "no-color"))
|
||||
XOF_CLEAR(xop, XOF_COLOR_ALLOWED);
|
||||
else if (strcmp(cp, "indent") == 0) {
|
||||
else if (xo_streq(cp, "indent")) {
|
||||
if (vp)
|
||||
xop->xo_indent_by = atoi(vp);
|
||||
else
|
||||
xo_failure(xop, "missing value for indent option");
|
||||
} else if (strcmp(cp, "encoder") == 0) {
|
||||
} else if (xo_streq(cp, "encoder")) {
|
||||
if (vp == NULL)
|
||||
xo_failure(xop, "missing value for encoder option");
|
||||
else {
|
||||
if (xo_encoder_init(xop, vp)) {
|
||||
xo_failure(xop, "encoder not found: %s", vp);
|
||||
rc = -1;
|
||||
}
|
||||
rc = xo_encoder_init(xop, vp);
|
||||
if (rc)
|
||||
xo_warnx("error initializing encoder: %s", vp);
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -3356,7 +3324,7 @@ xo_do_format_field (xo_handle_t *xop, xo_buffer_t *xbp,
|
||||
cp += 1;
|
||||
continue;
|
||||
|
||||
} if (cp + 1 < ep && cp[1] == '%') {
|
||||
} else if (cp + 1 < ep && cp[1] == '%') {
|
||||
cp += 1;
|
||||
goto add_one;
|
||||
}
|
||||
@ -4733,7 +4701,7 @@ xo_color_find (const char *str)
|
||||
int i;
|
||||
|
||||
for (i = 0; xo_color_names[i]; i++) {
|
||||
if (strcmp(xo_color_names[i], str) == 0)
|
||||
if (xo_streq(xo_color_names[i], str))
|
||||
return i;
|
||||
}
|
||||
|
||||
@ -4784,7 +4752,7 @@ xo_effect_find (const char *str)
|
||||
int i;
|
||||
|
||||
for (i = 0; xo_effect_names[i]; i++) {
|
||||
if (strcmp(xo_effect_names[i], str) == 0)
|
||||
if (xo_streq(xo_effect_names[i], str))
|
||||
return i;
|
||||
}
|
||||
|
||||
@ -5653,6 +5621,7 @@ xo_gettext_finish_numbering_fields (xo_handle_t *xop UNUSED,
|
||||
xo_field_info_t *xfip;
|
||||
unsigned fnum, max_fields;
|
||||
uint64_t bits = 0;
|
||||
const uint64_t one = 1; /* Avoid "1ULL" */
|
||||
|
||||
/* First make a list of add the explicitly used bits */
|
||||
for (xfip = fields, fnum = 0; xfip->xfi_ftype; xfip++) {
|
||||
@ -5669,7 +5638,7 @@ xo_gettext_finish_numbering_fields (xo_handle_t *xop UNUSED,
|
||||
break;
|
||||
|
||||
if (xfip->xfi_fnum)
|
||||
bits |= 1 << xfip->xfi_fnum;
|
||||
bits |= one << xfip->xfi_fnum;
|
||||
}
|
||||
|
||||
max_fields = fnum;
|
||||
@ -5687,14 +5656,14 @@ xo_gettext_finish_numbering_fields (xo_handle_t *xop UNUSED,
|
||||
continue;
|
||||
|
||||
/* Find the next unassigned field */
|
||||
for (fnum++; bits & (1 << fnum); fnum++)
|
||||
for (fnum++; bits & (one << fnum); fnum++)
|
||||
continue;
|
||||
|
||||
if (fnum > max_fields)
|
||||
break;
|
||||
|
||||
xfip->xfi_fnum = fnum; /* Mark the field number */
|
||||
bits |= 1 << fnum; /* Mark it used */
|
||||
bits |= one << fnum; /* Mark it used */
|
||||
}
|
||||
}
|
||||
|
||||
@ -5709,6 +5678,7 @@ xo_parse_field_numbers (xo_handle_t *xop, const char *fmt,
|
||||
xo_field_info_t *xfip;
|
||||
unsigned field, fnum;
|
||||
uint64_t bits = 0;
|
||||
const uint64_t one = 1; /* Avoid 1ULL */
|
||||
|
||||
for (xfip = fields, field = 0; field < num_fields; xfip++, field++) {
|
||||
/* Fields default to 1:1 with natural position */
|
||||
@ -5721,12 +5691,12 @@ xo_parse_field_numbers (xo_handle_t *xop, const char *fmt,
|
||||
|
||||
fnum = xfip->xfi_fnum - 1; /* Move to zero origin */
|
||||
if (fnum < 64) { /* Only test what fits */
|
||||
if (bits & (1 << fnum)) {
|
||||
if (bits & (one << fnum)) {
|
||||
xo_failure(xop, "field number %u reused: '%s'",
|
||||
xfip->xfi_fnum, fmt);
|
||||
return -1;
|
||||
}
|
||||
bits |= 1 << fnum;
|
||||
bits |= one << fnum;
|
||||
}
|
||||
}
|
||||
|
||||
@ -5786,9 +5756,10 @@ xo_parse_fields (xo_handle_t *xop, xo_field_info_t *fields,
|
||||
xfip->xfi_len = sp - xfip->xfi_start + 1;
|
||||
|
||||
/* Move along the string, but don't run off the end */
|
||||
if (*sp == '}' && sp[1] == '}')
|
||||
if (*sp == '}' && sp[1] == '}') /* Paranoid; must be true */
|
||||
sp += 2;
|
||||
cp = *sp ? sp : sp;
|
||||
|
||||
cp = sp;
|
||||
xfip->xfi_next = cp;
|
||||
continue;
|
||||
}
|
||||
@ -6186,7 +6157,7 @@ xo_gettext_build_format (xo_handle_t *xop,
|
||||
goto bail2;
|
||||
|
||||
const char *gtfmt = xo_dgettext(xop, xb.xb_bufp);
|
||||
if (gtfmt == NULL || gtfmt == fmt || strcmp(gtfmt, fmt) == 0)
|
||||
if (gtfmt == NULL || gtfmt == fmt || xo_streq(gtfmt, fmt))
|
||||
goto bail2;
|
||||
|
||||
char *new_fmt = xo_strndup(gtfmt, -1);
|
||||
@ -6875,7 +6846,7 @@ xo_depth_change (xo_handle_t *xop, const char *name,
|
||||
xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth];
|
||||
if (XOF_ISSET(xop, XOF_WARN)) {
|
||||
const char *top = xsp->xs_name;
|
||||
if (top != NULL && name != NULL && strcmp(name, top) != 0) {
|
||||
if (top != NULL && name != NULL && !xo_streq(name, top)) {
|
||||
xo_failure(xop, "incorrect close: '%s' .vs. '%s'",
|
||||
name, top);
|
||||
return;
|
||||
@ -7074,7 +7045,6 @@ xo_do_close_container (xo_handle_t *xop, const char *name)
|
||||
xo_stack_set_flags(xop);
|
||||
|
||||
pre_nl = XOF_ISSET(xop, XOF_PRETTY) ? "\n" : "";
|
||||
ppn = (xop->xo_depth <= 1) ? pre_nl : "";
|
||||
ppn = "";
|
||||
|
||||
xo_depth_change(xop, name, -1, -1, XSS_CLOSE_CONTAINER, 0);
|
||||
@ -7622,7 +7592,7 @@ xo_do_close (xo_handle_t *xop, const char *name, xo_state_t new_state)
|
||||
if (xsp->xs_state != need_state)
|
||||
continue;
|
||||
|
||||
if (name && xsp->xs_name && strcmp(name, xsp->xs_name) != 0)
|
||||
if (name && xsp->xs_name && !xo_streq(name, xsp->xs_name))
|
||||
continue;
|
||||
|
||||
limit = xsp;
|
||||
@ -7680,13 +7650,6 @@ xo_transition (xo_handle_t *xop, xo_xof_flags_t flags, const char *name,
|
||||
break;
|
||||
|
||||
case XSS_TRANSITION(XSS_OPEN_LIST, XSS_OPEN_CONTAINER):
|
||||
if (on_marker)
|
||||
goto marker_prevents_close;
|
||||
rc = xo_do_close_list(xop, NULL);
|
||||
if (rc >= 0)
|
||||
goto open_container;
|
||||
break;
|
||||
|
||||
case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_OPEN_CONTAINER):
|
||||
if (on_marker)
|
||||
goto marker_prevents_close;
|
||||
@ -7695,18 +7658,13 @@ xo_transition (xo_handle_t *xop, xo_xof_flags_t flags, const char *name,
|
||||
goto open_container;
|
||||
break;
|
||||
|
||||
/*close_container:*/
|
||||
case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_CLOSE_CONTAINER):
|
||||
if (on_marker)
|
||||
goto marker_prevents_close;
|
||||
rc = xo_do_close(xop, name, new_state);
|
||||
break;
|
||||
|
||||
case XSS_TRANSITION(XSS_INIT, XSS_CLOSE_CONTAINER):
|
||||
/* This is an exception for "xo --close" */
|
||||
rc = xo_do_close_container(xop, name);
|
||||
break;
|
||||
|
||||
/*close_container:*/
|
||||
case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_CLOSE_CONTAINER):
|
||||
case XSS_TRANSITION(XSS_OPEN_LIST, XSS_CLOSE_CONTAINER):
|
||||
case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_CLOSE_CONTAINER):
|
||||
if (on_marker)
|
||||
@ -8062,7 +8020,7 @@ xo_error_hv (xo_handle_t *xop, const char *fmt, va_list vap)
|
||||
char *newfmt = alloca(len + 2);
|
||||
memcpy(newfmt, fmt, len);
|
||||
newfmt[len] = '\n';
|
||||
newfmt[len] = '\0';
|
||||
newfmt[len + 1] = '\0';
|
||||
fmt = newfmt;
|
||||
}
|
||||
|
||||
@ -8145,7 +8103,16 @@ xo_parse_args (int argc, char **argv)
|
||||
xo_program = argv[0];
|
||||
cp = strrchr(xo_program, '/');
|
||||
if (cp)
|
||||
xo_program = cp + 1;
|
||||
xo_program = ++cp;
|
||||
|
||||
/* GNU tools add an annoying ".test" as the program extension; remove it */
|
||||
size_t len = strlen(xo_program);
|
||||
static const char gnu_ext[] = ".test";
|
||||
if (len >= sizeof(gnu_ext)) {
|
||||
cp = &cp[len + 1 - sizeof(gnu_ext)];
|
||||
if (xo_streq(cp, gnu_ext))
|
||||
*cp = '\0';
|
||||
}
|
||||
|
||||
xo_handle_t *xop = xo_default(NULL);
|
||||
|
||||
@ -8178,7 +8145,7 @@ xo_parse_args (int argc, char **argv)
|
||||
|
||||
} else if (*cp == '-') {
|
||||
cp += 1;
|
||||
if (strcmp(cp, "check") == 0) {
|
||||
if (xo_streq(cp, "check")) {
|
||||
exit(XO_HAS_LIBXO);
|
||||
|
||||
} else {
|
||||
@ -8386,9 +8353,8 @@ xo_emit_err (int eval, const char *fmt, ...)
|
||||
int code = errno;
|
||||
va_list vap;
|
||||
va_start(vap, fmt);
|
||||
xo_emit_err_v(0, code, fmt, vap);
|
||||
va_end(vap);
|
||||
exit(eval);
|
||||
xo_emit_err_v(eval, code, fmt, vap);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
void
|
||||
@ -8397,10 +8363,8 @@ xo_emit_errx (int eval, const char *fmt, ...)
|
||||
va_list vap;
|
||||
|
||||
va_start(vap, fmt);
|
||||
xo_emit_err_v(0, -1, fmt, vap);
|
||||
va_end(vap);
|
||||
xo_finish();
|
||||
exit(eval);
|
||||
xo_emit_err_v(eval, -1, fmt, vap); /* This will exit */
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
void
|
||||
@ -8409,10 +8373,8 @@ xo_emit_errc (int eval, int code, const char *fmt, ...)
|
||||
va_list vap;
|
||||
|
||||
va_start(vap, fmt);
|
||||
xo_emit_warn_hcv(NULL, 0, code, fmt, vap);
|
||||
va_end(vap);
|
||||
xo_finish();
|
||||
exit(eval);
|
||||
xo_emit_err_v(eval, code, fmt, vap); /* This will exit */
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -72,14 +72,14 @@ xo_buf_is_empty (xo_buffer_t *xbp)
|
||||
/*
|
||||
* Return the current offset
|
||||
*/
|
||||
static inline unsigned
|
||||
static inline ssize_t
|
||||
xo_buf_offset (xo_buffer_t *xbp)
|
||||
{
|
||||
return xbp ? (xbp->xb_curp - xbp->xb_bufp) : 0;
|
||||
}
|
||||
|
||||
static inline char *
|
||||
xo_buf_data (xo_buffer_t *xbp, unsigned offset)
|
||||
xo_buf_data (xo_buffer_t *xbp, ssize_t offset)
|
||||
{
|
||||
if (xbp == NULL)
|
||||
return NULL;
|
||||
|
@ -199,7 +199,7 @@ xo_encoder_find (const char *name)
|
||||
xo_encoder_list_init(&xo_encoders);
|
||||
|
||||
XO_ENCODER_LIST_FOREACH(xep, &xo_encoders) {
|
||||
if (strcmp(xep->xe_name, name) == 0)
|
||||
if (xo_streq(xep->xe_name, name))
|
||||
return xep;
|
||||
}
|
||||
|
||||
@ -290,9 +290,26 @@ xo_encoder_init (xo_handle_t *xop, const char *name)
|
||||
{
|
||||
xo_encoder_setup();
|
||||
|
||||
const char *opts = strchr(name, ':');
|
||||
if (opts) {
|
||||
/* Make a writable copy of the name */
|
||||
size_t len = strlen(name);
|
||||
char *copy = alloca(len + 1);
|
||||
memcpy(copy, name, len);
|
||||
copy[len] = '\0';
|
||||
|
||||
char *opts_copy = copy + (opts - name); /* Move to ':' */
|
||||
*opts_copy++ = '\0'; /* Trim it off */
|
||||
|
||||
opts = opts_copy; /* Use copy as options */
|
||||
name = copy; /* Use trimmed copy as name */
|
||||
}
|
||||
|
||||
/* Can't have names containing '/' or ':' */
|
||||
if (strchr(name, '/') != NULL || strchr(name, ':') != NULL)
|
||||
if (strchr(name, '/') != NULL || strchr(name, ':') != NULL) {
|
||||
xo_failure(xop, "invalid encoder name: %s", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* First we look on the list of known (registered) encoders.
|
||||
@ -302,13 +319,20 @@ xo_encoder_init (xo_handle_t *xop, const char *name)
|
||||
xo_encoder_node_t *xep = xo_encoder_find(name);
|
||||
if (xep == NULL) {
|
||||
xep = xo_encoder_discover(name);
|
||||
if (xep == NULL)
|
||||
if (xep == NULL) {
|
||||
xo_failure(xop, "encoder not founde: %s", name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
xo_set_encoder(xop, xep->xe_handler);
|
||||
|
||||
return xo_encoder_handle(xop, XO_OP_CREATE, NULL, NULL, 0);
|
||||
int rc = xo_encoder_handle(xop, XO_OP_CREATE, name, NULL, 0);
|
||||
if (rc == 0 && opts != NULL) {
|
||||
rc = xo_encoder_handle(xop, XO_OP_OPTIONS, name, opts, 0);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -334,7 +358,7 @@ xo_encoder_create (const char *name, xo_xof_flags_t flags)
|
||||
|
||||
int
|
||||
xo_encoder_handle (xo_handle_t *xop, xo_encoder_op_t op,
|
||||
const char *name, const char *value, xo_xof_flags_t flags)
|
||||
const char *name, const char *value, xo_xff_flags_t flags)
|
||||
{
|
||||
void *private = xo_get_private(xop);
|
||||
xo_encoder_func_t func = xo_get_encoder(xop);
|
||||
@ -366,6 +390,7 @@ xo_encoder_op_name (xo_encoder_op_t op)
|
||||
/* 14 */ "destroy",
|
||||
/* 15 */ "attr",
|
||||
/* 16 */ "version",
|
||||
/* 17 */ "options",
|
||||
};
|
||||
|
||||
if (op > sizeof(names) / sizeof(names[0]))
|
||||
|
@ -18,12 +18,57 @@
|
||||
#ifndef XO_ENCODER_H
|
||||
#define XO_ENCODER_H
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* Expose libxo's memory allocation functions
|
||||
*/
|
||||
extern xo_realloc_func_t xo_realloc;
|
||||
extern xo_free_func_t xo_free;
|
||||
|
||||
/*
|
||||
* Simple string comparison function (without the temptation
|
||||
* to forget the "== 0").
|
||||
*/
|
||||
static inline int
|
||||
xo_streq (const char *one, const char *two)
|
||||
{
|
||||
return strcmp(one, two) == 0;
|
||||
}
|
||||
|
||||
/* Flags for formatting functions */
|
||||
typedef unsigned long xo_xff_flags_t;
|
||||
#define XFF_COLON (1<<0) /* Append a ":" */
|
||||
#define XFF_COMMA (1<<1) /* Append a "," iff there's more output */
|
||||
#define XFF_WS (1<<2) /* Append a blank */
|
||||
#define XFF_ENCODE_ONLY (1<<3) /* Only emit for encoding styles (XML, JSON) */
|
||||
|
||||
#define XFF_QUOTE (1<<4) /* Force quotes */
|
||||
#define XFF_NOQUOTE (1<<5) /* Force no quotes */
|
||||
#define XFF_DISPLAY_ONLY (1<<6) /* Only emit for display styles (text, html) */
|
||||
#define XFF_KEY (1<<7) /* Field is a key (for XPath) */
|
||||
|
||||
#define XFF_XML (1<<8) /* Force XML encoding style (for XPath) */
|
||||
#define XFF_ATTR (1<<9) /* Escape value using attribute rules (XML) */
|
||||
#define XFF_BLANK_LINE (1<<10) /* Emit a blank line */
|
||||
#define XFF_NO_OUTPUT (1<<11) /* Do not make any output */
|
||||
|
||||
#define XFF_TRIM_WS (1<<12) /* Trim whitespace off encoded values */
|
||||
#define XFF_LEAF_LIST (1<<13) /* A leaf-list (list of values) */
|
||||
#define XFF_UNESCAPE (1<<14) /* Need to printf-style unescape the value */
|
||||
#define XFF_HUMANIZE (1<<15) /* Humanize the value (for display styles) */
|
||||
|
||||
#define XFF_HN_SPACE (1<<16) /* Humanize: put space before suffix */
|
||||
#define XFF_HN_DECIMAL (1<<17) /* Humanize: add one decimal place if <10 */
|
||||
#define XFF_HN_1000 (1<<18) /* Humanize: use 1000, not 1024 */
|
||||
#define XFF_GT_FIELD (1<<19) /* Call gettext() on a field */
|
||||
|
||||
#define XFF_GT_PLURAL (1<<20) /* Call dngettext to find plural form */
|
||||
#define XFF_ARGUMENT (1<<21) /* Content provided via argument */
|
||||
|
||||
/* Flags to turn off when we don't want i18n processing */
|
||||
#define XFF_GT_FLAGS (XFF_GT_FIELD | XFF_GT_PLURAL)
|
||||
|
||||
typedef unsigned xo_encoder_op_t;
|
||||
|
||||
/* Encoder operations; names are in xo_encoder.c:xo_encoder_op_name() */
|
||||
@ -44,6 +89,7 @@ typedef unsigned xo_encoder_op_t;
|
||||
#define XO_OP_DESTROY 14 /* Clean up function */
|
||||
#define XO_OP_ATTRIBUTE 15 /* Attribute name/value */
|
||||
#define XO_OP_VERSION 16 /* Version string */
|
||||
#define XO_OP_OPTIONS 17 /* Additional command line options */
|
||||
|
||||
#define XO_ENCODER_HANDLER_ARGS \
|
||||
xo_handle_t *xop __attribute__ ((__unused__)), \
|
||||
@ -51,7 +97,7 @@ typedef unsigned xo_encoder_op_t;
|
||||
const char *name __attribute__ ((__unused__)), \
|
||||
const char *value __attribute__ ((__unused__)), \
|
||||
void *private __attribute__ ((__unused__)), \
|
||||
xo_xof_flags_t flags __attribute__ ((__unused__))
|
||||
xo_xff_flags_t flags __attribute__ ((__unused__))
|
||||
|
||||
typedef int (*xo_encoder_func_t)(XO_ENCODER_HANDLER_ARGS);
|
||||
|
||||
@ -106,7 +152,7 @@ xo_encoder_create (const char *name, xo_xof_flags_t flags);
|
||||
|
||||
int
|
||||
xo_encoder_handle (xo_handle_t *xop, xo_encoder_op_t op,
|
||||
const char *name, const char *value, xo_xof_flags_t flags);
|
||||
const char *name, const char *value, xo_xff_flags_t flags);
|
||||
|
||||
void
|
||||
xo_encoders_clean (void);
|
||||
@ -114,4 +160,10 @@ xo_encoders_clean (void);
|
||||
const char *
|
||||
xo_encoder_op_name (xo_encoder_op_t op);
|
||||
|
||||
/*
|
||||
* xo_failure is used to announce internal failures, when "warn" is on
|
||||
*/
|
||||
void
|
||||
xo_failure (xo_handle_t *xop, const char *fmt, ...);
|
||||
|
||||
#endif /* XO_ENCODER_H */
|
||||
|
@ -86,6 +86,11 @@ TEST_JIG = \
|
||||
${DIFF} -Nu ${srcdir}/saved/$$base.$$fmt.out out/$$base.$$fmt.out ${S2O} ; \
|
||||
${DIFF} -Nu ${srcdir}/saved/$$base.$$fmt.err out/$$base.$$fmt.err ${S2O}
|
||||
|
||||
TEST_JIG2 = \
|
||||
echo "... $$test ... $$fmt ..."; \
|
||||
xoopts==warn,encoder=csv$$csv ; \
|
||||
${TEST_JIG}; true;
|
||||
|
||||
TEST_FORMATS = T XP JP HP X J H HIPx
|
||||
|
||||
test tests: ${bin_PROGRAMS}
|
||||
@ -105,6 +110,12 @@ test tests: ${bin_PROGRAMS}
|
||||
true; \
|
||||
done) \
|
||||
done)
|
||||
-@ (${TEST_TRACE} test=test_01.c; base=test_01; \
|
||||
( fmt=Ecsv1; csv= ; ${TEST_JIG2} ); \
|
||||
( fmt=Ecsv2; csv=:path=top/data/item+no-header ; ${TEST_JIG2} ); \
|
||||
( fmt=Ecsv3; csv=:path=item+leafs=sku.sold+no-quotes ; ${TEST_JIG2} ); \
|
||||
)
|
||||
|
||||
|
||||
one:
|
||||
-@(test=${TEST_CASE}; data=${TEST_DATA}; ${TEST_ONE} ; true)
|
||||
@ -112,12 +123,17 @@ one:
|
||||
accept:
|
||||
-@(for test in ${TEST_CASES} ; do \
|
||||
base=`${BASENAME} $$test .c` ; \
|
||||
(for fmt in ${TEST_FORMATS} E; do \
|
||||
(for fmt in ${TEST_FORMATS} E ; do \
|
||||
echo "... $$test ... $$fmt ..."; \
|
||||
${CP} out/$$base.$$fmt.out ${srcdir}/saved/$$base.$$fmt.out ; \
|
||||
${CP} out/$$base.$$fmt.err ${srcdir}/saved/$$base.$$fmt.err ; \
|
||||
done) \
|
||||
done)
|
||||
-@(test=test_01.c; base=test_01; for fmt in Ecsv1 Ecsv2 Ecsv3 ; do \
|
||||
echo "... $$test ... $$fmt ..."; \
|
||||
${CP} out/$$base.$$fmt.out ${srcdir}/saved/$$base.$$fmt.out ; \
|
||||
${CP} out/$$base.$$fmt.err ${srcdir}/saved/$$base.$$fmt.err ; \
|
||||
done)
|
||||
|
||||
.c.test:
|
||||
$(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -o $@ $<
|
||||
|
@ -1,4 +1,4 @@
|
||||
op create: [] [] [0]
|
||||
op create: [test] [] [0]
|
||||
op open_container: [top] [] [0x810]
|
||||
op string: [type] [ethernet] [0]
|
||||
op content: [type] [bridge] [0]
|
||||
@ -133,6 +133,55 @@ op attr: [test4] [value4] [0]
|
||||
op string: [item] [water] [0x2000]
|
||||
op close_list: [item] [] [0]
|
||||
op close_container: [data4] [] [0]
|
||||
op attr: [test] [value] [0]
|
||||
op open_container: [data] [] [0x810]
|
||||
op open_list: [item] [] [0]
|
||||
op attr: [test2] [value2] [0]
|
||||
op open_instance: [item] [] [0x810]
|
||||
op attr: [test3] [value3] [0]
|
||||
op string: [sku] [GRO-000-415] [0x98]
|
||||
op string: [name] [gum] [0x80]
|
||||
op content: [sold] [1412] [0x20]
|
||||
op content: [on-order] [10] [0]
|
||||
op content: [in-stock] [54] [0]
|
||||
op close_instance: [item] [] [0]
|
||||
op open_instance: [item] [] [0x810]
|
||||
op attr: [test3] [value3] [0]
|
||||
op string: [sku] [HRD-000-212] [0x98]
|
||||
op string: [name] [rope] [0x80]
|
||||
op content: [sold] [85] [0x20]
|
||||
op string: [extra] [special] [0]
|
||||
op content: [on-order] [2] [0]
|
||||
op content: [in-stock] [4] [0]
|
||||
op close_instance: [item] [] [0]
|
||||
op open_instance: [item] [] [0x810]
|
||||
op attr: [test3] [value3] [0]
|
||||
op string: [sku] [HRD-000-517] [0x98]
|
||||
op string: [name] [ladder] [0x80]
|
||||
op content: [sold] [0] [0x20]
|
||||
op string: [extra] [special] [0]
|
||||
op content: [on-order] [1] [0]
|
||||
op content: [in-stock] [2] [0]
|
||||
op close_instance: [item] [] [0]
|
||||
op open_instance: [item] [] [0x810]
|
||||
op attr: [test3] [value3] [0]
|
||||
op string: [sku] [HRD-000-632] [0x98]
|
||||
op string: [name] [bolt] [0x80]
|
||||
op content: [sold] [4123] [0x20]
|
||||
op content: [on-order] [42] [0]
|
||||
op content: [in-stock] [144] [0]
|
||||
op close_instance: [item] [] [0]
|
||||
op open_instance: [item] [] [0x810]
|
||||
op attr: [test3] [value3] [0]
|
||||
op string: [sku] [GRO-000-2331] [0x98]
|
||||
op string: [name] [water] [0x80]
|
||||
op content: [sold] [17] [0x20]
|
||||
op string: [extra] [special] [0]
|
||||
op content: [on-order] [2] [0]
|
||||
op content: [in-stock] [14] [0]
|
||||
op close_instance: [item] [] [0]
|
||||
op close_list: [item] [] [0]
|
||||
op close_container: [data] [] [0]
|
||||
op content: [cost] [425] [0]
|
||||
op content: [cost] [455] [0]
|
||||
op string: [mode] [mode] [0x8]
|
||||
|
0
tests/core/saved/test_01.Ecsv1.err
Normal file
0
tests/core/saved/test_01.Ecsv1.err
Normal file
17
tests/core/saved/test_01.Ecsv1.out
Normal file
17
tests/core/saved/test_01.Ecsv1.out
Normal file
@ -0,0 +1,17 @@
|
||||
sku,name,sold,in-stock,on-order
|
||||
GRO-000-415,gum,1412,54,10
|
||||
HRD-000-212,rope,85,4,2
|
||||
HRD-000-517,ladder,0,2,1
|
||||
HRD-000-632,bolt,4123,144,42
|
||||
GRO-000-2331,water,17,14,2
|
||||
GRO-000-415,gum,1412.0,54,10
|
||||
HRD-000-212,rope,85.0,4,2
|
||||
HRD-000-517,ladder,0,2,1
|
||||
HRD-000-632,bolt,4123.0,144,42
|
||||
GRO-000-2331,water,17.0,14,2
|
||||
GRO-000-533,fish,1321.0,45,1
|
||||
GRO-000-415,gum,1412,54,10
|
||||
HRD-000-212,rope,85,4,2
|
||||
HRD-000-517,ladder,0,2,1
|
||||
HRD-000-632,bolt,4123,144,42
|
||||
GRO-000-2331,water,17,14,2
|
0
tests/core/saved/test_01.Ecsv2.err
Normal file
0
tests/core/saved/test_01.Ecsv2.err
Normal file
10
tests/core/saved/test_01.Ecsv2.out
Normal file
10
tests/core/saved/test_01.Ecsv2.out
Normal file
@ -0,0 +1,10 @@
|
||||
GRO-000-415,gum,1412,54,10
|
||||
HRD-000-212,rope,85,4,2
|
||||
HRD-000-517,ladder,0,2,1
|
||||
HRD-000-632,bolt,4123,144,42
|
||||
GRO-000-2331,water,17,14,2
|
||||
GRO-000-415,gum,1412,54,10
|
||||
HRD-000-212,rope,85,4,2
|
||||
HRD-000-517,ladder,0,2,1
|
||||
HRD-000-632,bolt,4123,144,42
|
||||
GRO-000-2331,water,17,14,2
|
0
tests/core/saved/test_01.Ecsv3.err
Normal file
0
tests/core/saved/test_01.Ecsv3.err
Normal file
17
tests/core/saved/test_01.Ecsv3.out
Normal file
17
tests/core/saved/test_01.Ecsv3.out
Normal file
@ -0,0 +1,17 @@
|
||||
sku,sold
|
||||
GRO-000-415,1412
|
||||
HRD-000-212,85
|
||||
HRD-000-517,0
|
||||
HRD-000-632,4123
|
||||
GRO-000-2331,17
|
||||
GRO-000-415,1412.0
|
||||
HRD-000-212,85.0
|
||||
HRD-000-517,0
|
||||
HRD-000-632,4123.0
|
||||
GRO-000-2331,17.0
|
||||
GRO-000-533,1321.0
|
||||
GRO-000-415,1412
|
||||
HRD-000-212,85
|
||||
HRD-000-517,0
|
||||
HRD-000-632,4123
|
||||
GRO-000-2331,17
|
File diff suppressed because one or more lines are too long
@ -329,6 +329,58 @@
|
||||
<div class="padding"> </div>
|
||||
<div class="data" data-tag="item" data-xpath="/top/data4/item">water</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="title">Item </div>
|
||||
<div class="title"> Total Sold</div>
|
||||
<div class="title"> In Stock</div>
|
||||
<div class="title"> On Order</div>
|
||||
<div class="title"> SKU</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="data" data-tag="name" data-xpath="/top/data/item/name" data-type="string" data-help="Name of the item" data-key="key">gum </div>
|
||||
<div class="data" data-tag="sold" data-xpath="/top/data/item[sku = 'GRO-000-415'][name = 'gum']/sold" data-type="number" data-help="Number of items sold"> 1412</div>
|
||||
<div class="data" data-tag="on-order" data-xpath="/top/data/item[sku = 'GRO-000-415'][name = 'gum']/on-order" data-type="number" data-help="Number of items on order"> 10</div>
|
||||
<div class="data" data-tag="in-stock" data-xpath="/top/data/item[sku = 'GRO-000-415'][name = 'gum']/in-stock" data-type="number" data-help="Number of items in stock"> 54</div>
|
||||
<div class="data" data-tag="sku" data-xpath="/top/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key"> GRO-000-415</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="data" data-tag="name" data-xpath="/top/data/item/name" data-type="string" data-help="Name of the item" data-key="key">rope </div>
|
||||
<div class="data" data-tag="sold" data-xpath="/top/data/item[sku = 'HRD-000-212'][name = 'rope']/sold" data-type="number" data-help="Number of items sold"> 85</div>
|
||||
<div class="text">Extra: </div>
|
||||
<div class="data" data-tag="extra" data-xpath="/top/data/item[sku = 'HRD-000-212'][name = 'rope']/extra">special</div>
|
||||
<div class="data" data-tag="on-order" data-xpath="/top/data/item[sku = 'HRD-000-212'][name = 'rope']/on-order" data-type="number" data-help="Number of items on order"> 2</div>
|
||||
<div class="data" data-tag="in-stock" data-xpath="/top/data/item[sku = 'HRD-000-212'][name = 'rope']/in-stock" data-type="number" data-help="Number of items in stock"> 4</div>
|
||||
<div class="data" data-tag="sku" data-xpath="/top/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key"> HRD-000-212</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="data" data-tag="name" data-xpath="/top/data/item/name" data-type="string" data-help="Name of the item" data-key="key">ladder </div>
|
||||
<div class="data" data-tag="sold" data-xpath="/top/data/item[sku = 'HRD-000-517'][name = 'ladder']/sold" data-type="number" data-help="Number of items sold"> 0</div>
|
||||
<div class="text">Extra: </div>
|
||||
<div class="data" data-tag="extra" data-xpath="/top/data/item[sku = 'HRD-000-517'][name = 'ladder']/extra">special</div>
|
||||
<div class="data" data-tag="on-order" data-xpath="/top/data/item[sku = 'HRD-000-517'][name = 'ladder']/on-order" data-type="number" data-help="Number of items on order"> 1</div>
|
||||
<div class="data" data-tag="in-stock" data-xpath="/top/data/item[sku = 'HRD-000-517'][name = 'ladder']/in-stock" data-type="number" data-help="Number of items in stock"> 2</div>
|
||||
<div class="data" data-tag="sku" data-xpath="/top/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key"> HRD-000-517</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="data" data-tag="name" data-xpath="/top/data/item/name" data-type="string" data-help="Name of the item" data-key="key">bolt </div>
|
||||
<div class="data" data-tag="sold" data-xpath="/top/data/item[sku = 'HRD-000-632'][name = 'bolt']/sold" data-type="number" data-help="Number of items sold"> 4123</div>
|
||||
<div class="data" data-tag="on-order" data-xpath="/top/data/item[sku = 'HRD-000-632'][name = 'bolt']/on-order" data-type="number" data-help="Number of items on order"> 42</div>
|
||||
<div class="data" data-tag="in-stock" data-xpath="/top/data/item[sku = 'HRD-000-632'][name = 'bolt']/in-stock" data-type="number" data-help="Number of items in stock"> 144</div>
|
||||
<div class="data" data-tag="sku" data-xpath="/top/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key"> HRD-000-632</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="data" data-tag="name" data-xpath="/top/data/item/name" data-type="string" data-help="Name of the item" data-key="key">water </div>
|
||||
<div class="data" data-tag="sold" data-xpath="/top/data/item[sku = 'GRO-000-2331'][name = 'water']/sold" data-type="number" data-help="Number of items sold"> 17</div>
|
||||
<div class="text">Extra: </div>
|
||||
<div class="data" data-tag="extra" data-xpath="/top/data/item[sku = 'GRO-000-2331'][name = 'water']/extra">special</div>
|
||||
<div class="data" data-tag="on-order" data-xpath="/top/data/item[sku = 'GRO-000-2331'][name = 'water']/on-order" data-type="number" data-help="Number of items on order"> 2</div>
|
||||
<div class="data" data-tag="in-stock" data-xpath="/top/data/item[sku = 'GRO-000-2331'][name = 'water']/in-stock" data-type="number" data-help="Number of items in stock"> 14</div>
|
||||
<div class="data" data-tag="sku" data-xpath="/top/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key"> GRO-000-2331</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
</div>
|
||||
<div class="line">
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">X</div>
|
||||
<div class="text">X</div>
|
||||
|
@ -329,6 +329,58 @@
|
||||
<div class="padding"> </div>
|
||||
<div class="data" data-tag="item">water</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="title">Item </div>
|
||||
<div class="title"> Total Sold</div>
|
||||
<div class="title"> In Stock</div>
|
||||
<div class="title"> On Order</div>
|
||||
<div class="title"> SKU</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="data" data-tag="name" data-key="key">gum </div>
|
||||
<div class="data" data-tag="sold"> 1412</div>
|
||||
<div class="data" data-tag="on-order"> 10</div>
|
||||
<div class="data" data-tag="in-stock"> 54</div>
|
||||
<div class="data" data-tag="sku" data-key="key"> GRO-000-415</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="data" data-tag="name" data-key="key">rope </div>
|
||||
<div class="data" data-tag="sold"> 85</div>
|
||||
<div class="text">Extra: </div>
|
||||
<div class="data" data-tag="extra">special</div>
|
||||
<div class="data" data-tag="on-order"> 2</div>
|
||||
<div class="data" data-tag="in-stock"> 4</div>
|
||||
<div class="data" data-tag="sku" data-key="key"> HRD-000-212</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="data" data-tag="name" data-key="key">ladder </div>
|
||||
<div class="data" data-tag="sold"> 0</div>
|
||||
<div class="text">Extra: </div>
|
||||
<div class="data" data-tag="extra">special</div>
|
||||
<div class="data" data-tag="on-order"> 1</div>
|
||||
<div class="data" data-tag="in-stock"> 2</div>
|
||||
<div class="data" data-tag="sku" data-key="key"> HRD-000-517</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="data" data-tag="name" data-key="key">bolt </div>
|
||||
<div class="data" data-tag="sold"> 4123</div>
|
||||
<div class="data" data-tag="on-order"> 42</div>
|
||||
<div class="data" data-tag="in-stock"> 144</div>
|
||||
<div class="data" data-tag="sku" data-key="key"> HRD-000-632</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="data" data-tag="name" data-key="key">water </div>
|
||||
<div class="data" data-tag="sold"> 17</div>
|
||||
<div class="text">Extra: </div>
|
||||
<div class="data" data-tag="extra">special</div>
|
||||
<div class="data" data-tag="on-order"> 2</div>
|
||||
<div class="data" data-tag="in-stock"> 14</div>
|
||||
<div class="data" data-tag="sku" data-key="key"> GRO-000-2331</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
</div>
|
||||
<div class="line">
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">X</div>
|
||||
<div class="text">X</div>
|
||||
|
@ -1 +1 @@
|
||||
{"top": {"type":"ethernet","type":"bridge","type":"18u","type":24,"address":"0x0","port":1,"address":"0x0","port":1,"address":"0x0","port":1,"used-percent":12,"kve_start":"0xdeadbeef","kve_end":"0xcabb1e","host":"my-box","domain":"example.com","host":"my-box","domain":"example.com","label":"value","max-chaos":"very","min-chaos":42,"some-chaos":"[42]","host":"my-box","domain":"example.com", "data": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412,"in-stock":54,"on-order":10}, {"sku":"HRD-000-212","name":"rope","sold":85,"in-stock":4,"on-order":2}, {"sku":"HRD-000-517","name":"ladder","sold":0,"in-stock":2,"on-order":1}, {"sku":"HRD-000-632","name":"bolt","sold":4123,"in-stock":144,"on-order":42}, {"sku":"GRO-000-2331","name":"water","sold":17,"in-stock":14,"on-order":2}]}, "data2": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412.0,"in-stock":54,"on-order":10}, {"sku":"HRD-000-212","name":"rope","sold":85.0,"in-stock":4,"on-order":2}, {"sku":"HRD-000-517","name":"ladder","sold":0,"in-stock":2,"on-order":1}, {"sku":"HRD-000-632","name":"bolt","sold":4123.0,"in-stock":144,"on-order":42}, {"sku":"GRO-000-2331","name":"water","sold":17.0,"in-stock":14,"on-order":2}]}, "data3": {"item": [{"sku":"GRO-000-533","name":"fish","sold":1321.0,"in-stock":45,"on-order":1}]}, "data4": {"item": ["gum","rope","ladder","bolt","water"]},"cost":425,"cost":455,"mode":"mode","mode_octal":"octal","links":"links","user":"user","group":"group","pre":"that","links":3,"post":"this","mode":"/some/file","mode_octal":640,"links":1,"user":"user","group":"group"}}
|
||||
{"top": {"type":"ethernet","type":"bridge","type":"18u","type":24,"address":"0x0","port":1,"address":"0x0","port":1,"address":"0x0","port":1,"used-percent":12,"kve_start":"0xdeadbeef","kve_end":"0xcabb1e","host":"my-box","domain":"example.com","host":"my-box","domain":"example.com","label":"value","max-chaos":"very","min-chaos":42,"some-chaos":"[42]","host":"my-box","domain":"example.com", "data": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412,"in-stock":54,"on-order":10}, {"sku":"HRD-000-212","name":"rope","sold":85,"in-stock":4,"on-order":2}, {"sku":"HRD-000-517","name":"ladder","sold":0,"in-stock":2,"on-order":1}, {"sku":"HRD-000-632","name":"bolt","sold":4123,"in-stock":144,"on-order":42}, {"sku":"GRO-000-2331","name":"water","sold":17,"in-stock":14,"on-order":2}]}, "data2": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412.0,"in-stock":54,"on-order":10}, {"sku":"HRD-000-212","name":"rope","sold":85.0,"in-stock":4,"on-order":2}, {"sku":"HRD-000-517","name":"ladder","sold":0,"in-stock":2,"on-order":1}, {"sku":"HRD-000-632","name":"bolt","sold":4123.0,"in-stock":144,"on-order":42}, {"sku":"GRO-000-2331","name":"water","sold":17.0,"in-stock":14,"on-order":2}]}, "data3": {"item": [{"sku":"GRO-000-533","name":"fish","sold":1321.0,"in-stock":45,"on-order":1}]}, "data4": {"item": ["gum","rope","ladder","bolt","water"]}, "data": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412,"on-order":10,"in-stock":54}, {"sku":"HRD-000-212","name":"rope","sold":85,"extra":"special","on-order":2,"in-stock":4}, {"sku":"HRD-000-517","name":"ladder","sold":0,"extra":"special","on-order":1,"in-stock":2}, {"sku":"HRD-000-632","name":"bolt","sold":4123,"on-order":42,"in-stock":144}, {"sku":"GRO-000-2331","name":"water","sold":17,"extra":"special","on-order":2,"in-stock":14}]},"cost":425,"cost":455,"mode":"mode","mode_octal":"octal","links":"links","user":"user","group":"group","pre":"that","links":3,"post":"this","mode":"/some/file","mode_octal":640,"links":1,"user":"user","group":"group"}}
|
||||
|
@ -121,6 +121,48 @@
|
||||
"water"
|
||||
]
|
||||
},
|
||||
"data": {
|
||||
"item": [
|
||||
{
|
||||
"sku": "GRO-000-415",
|
||||
"name": "gum",
|
||||
"sold": 1412,
|
||||
"on-order": 10,
|
||||
"in-stock": 54
|
||||
},
|
||||
{
|
||||
"sku": "HRD-000-212",
|
||||
"name": "rope",
|
||||
"sold": 85,
|
||||
"extra": "special",
|
||||
"on-order": 2,
|
||||
"in-stock": 4
|
||||
},
|
||||
{
|
||||
"sku": "HRD-000-517",
|
||||
"name": "ladder",
|
||||
"sold": 0,
|
||||
"extra": "special",
|
||||
"on-order": 1,
|
||||
"in-stock": 2
|
||||
},
|
||||
{
|
||||
"sku": "HRD-000-632",
|
||||
"name": "bolt",
|
||||
"sold": 4123,
|
||||
"on-order": 42,
|
||||
"in-stock": 144
|
||||
},
|
||||
{
|
||||
"sku": "GRO-000-2331",
|
||||
"name": "water",
|
||||
"sold": 17,
|
||||
"extra": "special",
|
||||
"on-order": 2,
|
||||
"in-stock": 14
|
||||
}
|
||||
]
|
||||
},
|
||||
"cost": 425,
|
||||
"cost": 455,
|
||||
"mode": "mode",
|
||||
|
@ -50,6 +50,14 @@ Item: rope
|
||||
Item: ladder
|
||||
Item: bolt
|
||||
Item: water
|
||||
Item Total Sold In Stock On Order SKU
|
||||
gum 1412 10 54 GRO-000-415
|
||||
rope 85Extra: special 2 4 HRD-000-212
|
||||
ladder 0Extra: special 1 2 HRD-000-517
|
||||
bolt 4123 42 144 HRD-000-632
|
||||
water 17Extra: special 2 14 GRO-000-2331
|
||||
|
||||
|
||||
XXXXXXXX
|
||||
X XCost: 425
|
||||
X XCost: 455
|
||||
|
@ -1 +1 @@
|
||||
<top><type>ethernet</type><type>bridge</type><type>18u</type><type>24</type><address>0x0</address><port>1</port><address>0x0</address><port>1</port><address>0x0</address><port>1</port><used-percent>12</used-percent><kve_start>0xdeadbeef</kve_start><kve_end>0xcabb1e</kve_end><host>my-box</host><domain>example.com</domain><host>my-box</host><domain>example.com</domain><label>value</label><max-chaos>very</max-chaos><min-chaos>42</min-chaos><some-chaos>[42]</some-chaos><host>my-box</host><domain>example.com</domain><data test="value"><item test2="value2"><sku test3="value3" key="key">GRO-000-415</sku><name key="key">gum</name><sold>1412</sold><in-stock>54</in-stock><on-order>10</on-order></item><item><sku test3="value3" key="key">HRD-000-212</sku><name key="key">rope</name><sold>85</sold><in-stock>4</in-stock><on-order>2</on-order></item><item><sku test3="value3" key="key">HRD-000-517</sku><name key="key">ladder</name><sold>0</sold><in-stock>2</in-stock><on-order>1</on-order></item><item><sku test3="value3" key="key">HRD-000-632</sku><name key="key">bolt</name><sold>4123</sold><in-stock>144</in-stock><on-order>42</on-order></item><item><sku test3="value3" key="key">GRO-000-2331</sku><name key="key">water</name><sold>17</sold><in-stock>14</in-stock><on-order>2</on-order></item></data><data2><item><sku key="key">GRO-000-415</sku><name key="key">gum</name><sold>1412.0</sold><in-stock>54</in-stock><on-order>10</on-order></item><item><sku key="key">HRD-000-212</sku><name key="key">rope</name><sold>85.0</sold><in-stock>4</in-stock><on-order>2</on-order></item><item><sku key="key">HRD-000-517</sku><name key="key">ladder</name><sold>0</sold><in-stock>2</in-stock><on-order>1</on-order></item><item><sku key="key">HRD-000-632</sku><name key="key">bolt</name><sold>4123.0</sold><in-stock>144</in-stock><on-order>42</on-order></item><item><sku key="key">GRO-000-2331</sku><name key="key">water</name><sold>17.0</sold><in-stock>14</in-stock><on-order>2</on-order></item></data2><data3><item><sku key="key">GRO-000-533</sku><name key="key">fish</name><sold>1321.0</sold><in-stock>45</in-stock><on-order>1</on-order></item></data3><data4><item test4="value4">gum</item><item test4="value4">rope</item><item test4="value4">ladder</item><item test4="value4">bolt</item><item test4="value4">water</item></data4><cost>425</cost><cost>455</cost><mode>mode</mode><mode_octal>octal</mode_octal><links>links</links><user>user</user><group>group</group><pre>that</pre><links>3</links><post>this</post><mode>/some/file</mode><mode_octal>640</mode_octal><links>1</links><user>user</user><group>group</group></top>
|
||||
<top><type>ethernet</type><type>bridge</type><type>18u</type><type>24</type><address>0x0</address><port>1</port><address>0x0</address><port>1</port><address>0x0</address><port>1</port><used-percent>12</used-percent><kve_start>0xdeadbeef</kve_start><kve_end>0xcabb1e</kve_end><host>my-box</host><domain>example.com</domain><host>my-box</host><domain>example.com</domain><label>value</label><max-chaos>very</max-chaos><min-chaos>42</min-chaos><some-chaos>[42]</some-chaos><host>my-box</host><domain>example.com</domain><data test="value"><item test2="value2"><sku test3="value3" key="key">GRO-000-415</sku><name key="key">gum</name><sold>1412</sold><in-stock>54</in-stock><on-order>10</on-order></item><item><sku test3="value3" key="key">HRD-000-212</sku><name key="key">rope</name><sold>85</sold><in-stock>4</in-stock><on-order>2</on-order></item><item><sku test3="value3" key="key">HRD-000-517</sku><name key="key">ladder</name><sold>0</sold><in-stock>2</in-stock><on-order>1</on-order></item><item><sku test3="value3" key="key">HRD-000-632</sku><name key="key">bolt</name><sold>4123</sold><in-stock>144</in-stock><on-order>42</on-order></item><item><sku test3="value3" key="key">GRO-000-2331</sku><name key="key">water</name><sold>17</sold><in-stock>14</in-stock><on-order>2</on-order></item></data><data2><item><sku key="key">GRO-000-415</sku><name key="key">gum</name><sold>1412.0</sold><in-stock>54</in-stock><on-order>10</on-order></item><item><sku key="key">HRD-000-212</sku><name key="key">rope</name><sold>85.0</sold><in-stock>4</in-stock><on-order>2</on-order></item><item><sku key="key">HRD-000-517</sku><name key="key">ladder</name><sold>0</sold><in-stock>2</in-stock><on-order>1</on-order></item><item><sku key="key">HRD-000-632</sku><name key="key">bolt</name><sold>4123.0</sold><in-stock>144</in-stock><on-order>42</on-order></item><item><sku key="key">GRO-000-2331</sku><name key="key">water</name><sold>17.0</sold><in-stock>14</in-stock><on-order>2</on-order></item></data2><data3><item><sku key="key">GRO-000-533</sku><name key="key">fish</name><sold>1321.0</sold><in-stock>45</in-stock><on-order>1</on-order></item></data3><data4><item test4="value4">gum</item><item test4="value4">rope</item><item test4="value4">ladder</item><item test4="value4">bolt</item><item test4="value4">water</item></data4><data test="value"><item test2="value2"><sku test3="value3" key="key">GRO-000-415</sku><name key="key">gum</name><sold>1412</sold><on-order>10</on-order><in-stock>54</in-stock></item><item><sku test3="value3" key="key">HRD-000-212</sku><name key="key">rope</name><sold>85</sold><extra>special</extra><on-order>2</on-order><in-stock>4</in-stock></item><item><sku test3="value3" key="key">HRD-000-517</sku><name key="key">ladder</name><sold>0</sold><extra>special</extra><on-order>1</on-order><in-stock>2</in-stock></item><item><sku test3="value3" key="key">HRD-000-632</sku><name key="key">bolt</name><sold>4123</sold><on-order>42</on-order><in-stock>144</in-stock></item><item><sku test3="value3" key="key">GRO-000-2331</sku><name key="key">water</name><sold>17</sold><extra>special</extra><on-order>2</on-order><in-stock>14</in-stock></item></data><cost>425</cost><cost>455</cost><mode>mode</mode><mode_octal>octal</mode_octal><links>links</links><user>user</user><group>group</group><pre>that</pre><links>3</links><post>this</post><mode>/some/file</mode><mode_octal>640</mode_octal><links>1</links><user>user</user><group>group</group></top>
|
@ -112,6 +112,46 @@
|
||||
<item test4="value4">bolt</item>
|
||||
<item test4="value4">water</item>
|
||||
</data4>
|
||||
<data test="value">
|
||||
<item test2="value2">
|
||||
<sku test3="value3" key="key">GRO-000-415</sku>
|
||||
<name key="key">gum</name>
|
||||
<sold>1412</sold>
|
||||
<on-order>10</on-order>
|
||||
<in-stock>54</in-stock>
|
||||
</item>
|
||||
<item>
|
||||
<sku test3="value3" key="key">HRD-000-212</sku>
|
||||
<name key="key">rope</name>
|
||||
<sold>85</sold>
|
||||
<extra>special</extra>
|
||||
<on-order>2</on-order>
|
||||
<in-stock>4</in-stock>
|
||||
</item>
|
||||
<item>
|
||||
<sku test3="value3" key="key">HRD-000-517</sku>
|
||||
<name key="key">ladder</name>
|
||||
<sold>0</sold>
|
||||
<extra>special</extra>
|
||||
<on-order>1</on-order>
|
||||
<in-stock>2</in-stock>
|
||||
</item>
|
||||
<item>
|
||||
<sku test3="value3" key="key">HRD-000-632</sku>
|
||||
<name key="key">bolt</name>
|
||||
<sold>4123</sold>
|
||||
<on-order>42</on-order>
|
||||
<in-stock>144</in-stock>
|
||||
</item>
|
||||
<item>
|
||||
<sku test3="value3" key="key">GRO-000-2331</sku>
|
||||
<name key="key">water</name>
|
||||
<sold>17</sold>
|
||||
<extra>special</extra>
|
||||
<on-order>2</on-order>
|
||||
<in-stock>14</in-stock>
|
||||
</item>
|
||||
</data>
|
||||
<cost>425</cost>
|
||||
<cost>455</cost>
|
||||
<mode>mode</mode>
|
||||
|
@ -1 +1 @@
|
||||
test_02.test: key field emitted after normal value field: 'name'
|
||||
test_02: key field emitted after normal value field: 'name'
|
||||
|
@ -1,4 +1,4 @@
|
||||
op create: [] [] [0]
|
||||
op create: [test] [] [0]
|
||||
op open_container: [top] [] [0x40010]
|
||||
op open_container: [data] [] [0x40010]
|
||||
op string: [name] [em0] [0x1080]
|
||||
|
@ -1 +1 @@
|
||||
test_02.test: key field emitted after normal value field: 'name'
|
||||
test_02: key field emitted after normal value field: 'name'
|
||||
|
@ -1 +1 @@
|
||||
test_02.test: key field emitted after normal value field: 'name'
|
||||
test_02: key field emitted after normal value field: 'name'
|
||||
|
@ -1 +1 @@
|
||||
test_02.test: key field emitted after normal value field: 'name'
|
||||
test_02: key field emitted after normal value field: 'name'
|
||||
|
@ -1 +1 @@
|
||||
test_02.test: key field emitted after normal value field: 'name'
|
||||
test_02: key field emitted after normal value field: 'name'
|
||||
|
@ -1 +1 @@
|
||||
test_02.test: key field emitted after normal value field: 'name'
|
||||
test_02: key field emitted after normal value field: 'name'
|
||||
|
@ -1,2 +1,2 @@
|
||||
test_02.test: key field emitted after normal value field: 'name'
|
||||
test_02: key field emitted after normal value field: 'name'
|
||||
Shut 'er down, Clancey! She's a-pumpin' mud! <>!,"!<>
|
||||
|
@ -1 +1 @@
|
||||
test_02.test: key field emitted after normal value field: 'name'
|
||||
test_02: key field emitted after normal value field: 'name'
|
||||
|
@ -1 +1 @@
|
||||
test_02.test: key field emitted after normal value field: 'name'
|
||||
test_02: key field emitted after normal value field: 'name'
|
||||
|
@ -1,4 +1,4 @@
|
||||
op create: [] [] [0]
|
||||
op create: [test] [] [0]
|
||||
op open_container: [employees] [] [0x10]
|
||||
op open_list: [employee] [] [0]
|
||||
op close_list: [employee] [] [0]
|
||||
|
@ -1,4 +1,4 @@
|
||||
op create: [] [] [0]
|
||||
op create: [test] [] [0]
|
||||
op open_container: [employees] [] [0x10]
|
||||
op open_list: [employee] [] [0]
|
||||
op open_instance: [employee] [] [0x10]
|
||||
|
@ -1,4 +1,4 @@
|
||||
op create: [] [] [0]
|
||||
op create: [test] [] [0]
|
||||
op open_container: [indian-languages] [] [0x200010]
|
||||
op string: [gurmukhi] [ਲਹੌਰ ਪਾਕਿਸਤਾਨੀ ਪੰਜਾਬ ਦੀ ਰਾਜਧਾਨੀ ਹੈ । ਲੋਕ ਗਿਣਤੀ ਦੇ ਨਾਲ ਕਰਾਚੀ ਤੋਂ ਬਾਅਦ ਲਹੌਰ ਦੂਜਾ ਸਭ ਤੋਂ ਵੱਡਾ ਸ਼ਹਿਰ ਹੈ । ਲਹੌਰ ਪਾਕਿਸਤਾਨ ਦਾ ਸਿਆਸੀ, ਰਹਤਲੀ ਤੇ ਪੜ੍ਹਾਈ ਦਾ ਗੜ੍ਹ ਹੈ ਅਤੇ ਇਸ ਲਈ ਇਹਨੂੰ ਪਾਕਿਸਤਾਨ ਦਾ ਦਿਲ ਵੀ ਕਿਹਾ ਜਾਂਦਾ ਹੈ । ਲਹੌਰ ਦਰਿਆ-ਏ-ਰਾਵੀ ਦੇ ਕੰਢੇ ਤੇ ਵਸਦਾ ਹੈ ਤੇ ਇਸਦੀ ਲੋਕ ਗਿਣਤੀ ਇੱਕ ਕਰੋੜ ਦੇ ਨੇੜੇ ਹੈ ।] [0]
|
||||
op string: [shahmukhi] [لہور پاکستانی پنجاب دا دارالحکومت اے۔ لوک گنتی دے نال کراچی توں بعد لہور دوجا سبھ توں وڈا شہر اے۔ لہور پاکستان دا سیاسی، رہتلی تے پڑھائی دا گڑھ اے تے اس لئی ایھنوں پاکستان دا دل وی کیھا جاندا اے۔ لہور دریاۓ راوی دے کنڈھے تے وسدا اے اسدی لوک گنتی اک کروڑ دے نیڑے اے ۔] [0]
|
||||
|
@ -1,4 +1,4 @@
|
||||
op create: [] [] [0]
|
||||
op create: [test] [] [0]
|
||||
op open_container: [employees] [] [0x410]
|
||||
op open_list: [employee] [] [0]
|
||||
op open_instance: [employee] [] [0x410]
|
||||
|
@ -1,4 +1,4 @@
|
||||
op create: [] [] [0]
|
||||
op create: [test] [] [0]
|
||||
op open_container: [employees] [] [0x200010]
|
||||
op open_list: [test] [] [0]
|
||||
op open_instance: [test] [] [0x200010]
|
||||
|
@ -1,4 +1,4 @@
|
||||
op create: [] [] [0]
|
||||
op create: [test] [] [0]
|
||||
op open_container: [top] [] [0x810]
|
||||
op open_container: [data] [] [0x810]
|
||||
op open_container: [contents] [] [0x810]
|
||||
|
@ -1,4 +1,4 @@
|
||||
op create: [] [] [0]
|
||||
op create: [test] [] [0]
|
||||
op open_container: [top] [] [0x810]
|
||||
op open_container: [data] [] [0x810]
|
||||
op open_container: [contents] [] [0x810]
|
||||
|
@ -1,4 +1,4 @@
|
||||
op create: [] [] [0]
|
||||
op create: [test] [] [0]
|
||||
op version: [] [3.1.4] [0]
|
||||
op open_container: [top] [] [0x4000810]
|
||||
op attr: [test] [value] [0]
|
||||
|
@ -1,4 +1,4 @@
|
||||
op create: [] [] [0]
|
||||
op create: [test] [] [0]
|
||||
op version: [] [3.1.4] [0]
|
||||
op open_container: [top] [] [0x10]
|
||||
{{<14>1 2015-06-23T13:47:09.123-0500 worker-host test-program 222 animal-status [animal-status@42 animal="snake" state="loose"] The snake is loose}}
|
||||
|
@ -1,4 +1,4 @@
|
||||
test_12.test: invalid XML tag name: '2by4'
|
||||
test_12.test: invalid XML tag name: '4x4'
|
||||
test_12.test: invalid XML tag name: '2morrow'
|
||||
test_12.test: invalid XML tag name: '2by4'
|
||||
test_12: invalid XML tag name: '2by4'
|
||||
test_12: invalid XML tag name: '4x4'
|
||||
test_12: invalid XML tag name: '2morrow'
|
||||
test_12: invalid XML tag name: '2by4'
|
||||
|
@ -1,4 +1,4 @@
|
||||
op create: [] [] [0]
|
||||
op create: [test] [] [0]
|
||||
op open_container: [top] [] [0x4040010]
|
||||
op open_container: [data] [] [0x4040010]
|
||||
op string: [animal] [fish] [0]
|
||||
|
@ -1,4 +1,4 @@
|
||||
test_12.test: invalid XML tag name: '2by4'
|
||||
test_12.test: invalid XML tag name: '4x4'
|
||||
test_12.test: invalid XML tag name: '2morrow'
|
||||
test_12.test: invalid XML tag name: '2by4'
|
||||
test_12: invalid XML tag name: '2by4'
|
||||
test_12: invalid XML tag name: '4x4'
|
||||
test_12: invalid XML tag name: '2morrow'
|
||||
test_12: invalid XML tag name: '2by4'
|
||||
|
@ -1,4 +1,4 @@
|
||||
test_12.test: invalid XML tag name: '2by4'
|
||||
test_12.test: invalid XML tag name: '4x4'
|
||||
test_12.test: invalid XML tag name: '2morrow'
|
||||
test_12.test: invalid XML tag name: '2by4'
|
||||
test_12: invalid XML tag name: '2by4'
|
||||
test_12: invalid XML tag name: '4x4'
|
||||
test_12: invalid XML tag name: '2morrow'
|
||||
test_12: invalid XML tag name: '2by4'
|
||||
|
@ -1,4 +1,4 @@
|
||||
test_12.test: invalid XML tag name: '2by4'
|
||||
test_12.test: invalid XML tag name: '4x4'
|
||||
test_12.test: invalid XML tag name: '2morrow'
|
||||
test_12.test: invalid XML tag name: '2by4'
|
||||
test_12: invalid XML tag name: '2by4'
|
||||
test_12: invalid XML tag name: '4x4'
|
||||
test_12: invalid XML tag name: '2morrow'
|
||||
test_12: invalid XML tag name: '2by4'
|
||||
|
@ -1,4 +1,4 @@
|
||||
test_12.test: invalid XML tag name: '2by4'
|
||||
test_12.test: invalid XML tag name: '4x4'
|
||||
test_12.test: invalid XML tag name: '2morrow'
|
||||
test_12.test: invalid XML tag name: '2by4'
|
||||
test_12: invalid XML tag name: '2by4'
|
||||
test_12: invalid XML tag name: '4x4'
|
||||
test_12: invalid XML tag name: '2morrow'
|
||||
test_12: invalid XML tag name: '2by4'
|
||||
|
@ -1,4 +1,4 @@
|
||||
test_12.test: invalid XML tag name: '2by4'
|
||||
test_12.test: invalid XML tag name: '4x4'
|
||||
test_12.test: invalid XML tag name: '2morrow'
|
||||
test_12.test: invalid XML tag name: '2by4'
|
||||
test_12: invalid XML tag name: '2by4'
|
||||
test_12: invalid XML tag name: '4x4'
|
||||
test_12: invalid XML tag name: '2morrow'
|
||||
test_12: invalid XML tag name: '2by4'
|
||||
|
@ -1,4 +1,4 @@
|
||||
test_12.test: invalid XML tag name: '2by4'
|
||||
test_12.test: invalid XML tag name: '4x4'
|
||||
test_12.test: invalid XML tag name: '2morrow'
|
||||
test_12.test: invalid XML tag name: '2by4'
|
||||
test_12: invalid XML tag name: '2by4'
|
||||
test_12: invalid XML tag name: '4x4'
|
||||
test_12: invalid XML tag name: '2morrow'
|
||||
test_12: invalid XML tag name: '2by4'
|
||||
|
@ -1,4 +1,4 @@
|
||||
test_12.test: invalid XML tag name: '2by4'
|
||||
test_12.test: invalid XML tag name: '4x4'
|
||||
test_12.test: invalid XML tag name: '2morrow'
|
||||
test_12.test: invalid XML tag name: '2by4'
|
||||
test_12: invalid XML tag name: '2by4'
|
||||
test_12: invalid XML tag name: '4x4'
|
||||
test_12: invalid XML tag name: '2morrow'
|
||||
test_12: invalid XML tag name: '2by4'
|
||||
|
@ -1,4 +1,4 @@
|
||||
test_12.test: invalid XML tag name: '2by4'
|
||||
test_12.test: invalid XML tag name: '4x4'
|
||||
test_12.test: invalid XML tag name: '2morrow'
|
||||
test_12.test: invalid XML tag name: '2by4'
|
||||
test_12: invalid XML tag name: '2by4'
|
||||
test_12: invalid XML tag name: '4x4'
|
||||
test_12: invalid XML tag name: '2morrow'
|
||||
test_12: invalid XML tag name: '2by4'
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "xo.h"
|
||||
#include "xo_encoder.h"
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
@ -55,21 +56,21 @@ main (int argc, char **argv)
|
||||
return 1;
|
||||
|
||||
for (argc = 1; argv[argc]; argc++) {
|
||||
if (strcmp(argv[argc], "xml") == 0)
|
||||
if (xo_streq(argv[argc], "xml"))
|
||||
xo_set_style(NULL, XO_STYLE_XML);
|
||||
else if (strcmp(argv[argc], "json") == 0)
|
||||
else if (xo_streq(argv[argc], "json"))
|
||||
xo_set_style(NULL, XO_STYLE_JSON);
|
||||
else if (strcmp(argv[argc], "text") == 0)
|
||||
else if (xo_streq(argv[argc], "text"))
|
||||
xo_set_style(NULL, XO_STYLE_TEXT);
|
||||
else if (strcmp(argv[argc], "html") == 0)
|
||||
else if (xo_streq(argv[argc], "html"))
|
||||
xo_set_style(NULL, XO_STYLE_HTML);
|
||||
else if (strcmp(argv[argc], "pretty") == 0)
|
||||
else if (xo_streq(argv[argc], "pretty"))
|
||||
xo_set_flags(NULL, XOF_PRETTY);
|
||||
else if (strcmp(argv[argc], "xpath") == 0)
|
||||
else if (xo_streq(argv[argc], "xpath"))
|
||||
xo_set_flags(NULL, XOF_XPATH);
|
||||
else if (strcmp(argv[argc], "info") == 0)
|
||||
else if (xo_streq(argv[argc], "info"))
|
||||
xo_set_flags(NULL, XOF_INFO);
|
||||
else if (strcmp(argv[argc], "error") == 0) {
|
||||
else if (xo_streq(argv[argc], "error")) {
|
||||
close(-1);
|
||||
xo_err(1, "error detected");
|
||||
}
|
||||
@ -186,6 +187,44 @@ main (int argc, char **argv)
|
||||
xo_close_list("item");
|
||||
xo_close_container("data4");
|
||||
|
||||
xo_attr("test", "value");
|
||||
xo_open_container("data");
|
||||
xo_open_list("item");
|
||||
xo_attr("test2", "value2");
|
||||
|
||||
xo_emit("{T:Item/%-10s}{T:Total Sold/%12s}{T:In Stock/%12s}"
|
||||
"{T:On Order/%12s}{T:SKU/%5s}\n");
|
||||
|
||||
for (ip = list; ip->i_title; ip++) {
|
||||
xo_open_instance("item");
|
||||
xo_attr("test3", "value3");
|
||||
|
||||
xo_emit("{keq:sku/%s-%u/%s-000-%u}"
|
||||
"{k:name/%-10s/%s}{n:sold/%12u/%u}",
|
||||
ip->i_sku_base, ip->i_sku_num,
|
||||
ip->i_title, ip->i_sold);
|
||||
|
||||
if (ip->i_onorder < 5)
|
||||
xo_emit("Extra: {:extra}", "special");
|
||||
|
||||
if (ip->i_instock & 1)
|
||||
xo_emit("{:in-stock/%12u/%u}", ip->i_instock);
|
||||
xo_emit("{:on-order/%12u/%u}", ip->i_onorder);
|
||||
if (!(ip->i_instock & 1))
|
||||
xo_emit("{:in-stock/%12u/%u}", ip->i_instock);
|
||||
|
||||
xo_emit("{qkd:sku/%5s-000-%u/%s-000-%u}\n",
|
||||
ip->i_sku_base, ip->i_sku_num);
|
||||
|
||||
xo_close_instance("item");
|
||||
}
|
||||
|
||||
xo_close_list("item");
|
||||
xo_close_container("data");
|
||||
|
||||
xo_emit("\n\n");
|
||||
|
||||
|
||||
xo_emit("X{P:}X", "epic fail");
|
||||
xo_emit("X{T:}X", "epic fail");
|
||||
xo_emit("X{N:}X", "epic fail");
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "xo.h"
|
||||
#include "xo_encoder.h"
|
||||
|
||||
#include "xo_humanize.h"
|
||||
|
||||
@ -25,19 +26,19 @@ main (int argc, char **argv)
|
||||
return 1;
|
||||
|
||||
for (argc = 1; argv[argc]; argc++) {
|
||||
if (strcmp(argv[argc], "xml") == 0)
|
||||
if (xo_streq(argv[argc], "xml"))
|
||||
xo_set_style(NULL, XO_STYLE_XML);
|
||||
else if (strcmp(argv[argc], "json") == 0)
|
||||
else if (xo_streq(argv[argc], "json"))
|
||||
xo_set_style(NULL, XO_STYLE_JSON);
|
||||
else if (strcmp(argv[argc], "text") == 0)
|
||||
else if (xo_streq(argv[argc], "text"))
|
||||
xo_set_style(NULL, XO_STYLE_TEXT);
|
||||
else if (strcmp(argv[argc], "html") == 0)
|
||||
else if (xo_streq(argv[argc], "html"))
|
||||
xo_set_style(NULL, XO_STYLE_HTML);
|
||||
else if (strcmp(argv[argc], "pretty") == 0)
|
||||
else if (xo_streq(argv[argc], "pretty"))
|
||||
xo_set_flags(NULL, XOF_PRETTY);
|
||||
else if (strcmp(argv[argc], "xpath") == 0)
|
||||
else if (xo_streq(argv[argc], "xpath"))
|
||||
xo_set_flags(NULL, XOF_XPATH);
|
||||
else if (strcmp(argv[argc], "info") == 0)
|
||||
else if (xo_streq(argv[argc], "info"))
|
||||
xo_set_flags(NULL, XOF_INFO);
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "xo.h"
|
||||
#include "xo_encoder.h"
|
||||
|
||||
xo_info_t info[] = {
|
||||
{ "employee", "object", "Employee data" },
|
||||
@ -44,10 +45,10 @@ main (int argc, char **argv)
|
||||
return 1;
|
||||
|
||||
for (argc = 1; argv[argc]; argc++) {
|
||||
if (strcmp(argv[argc], "count") == 0) {
|
||||
if (xo_streq(argv[argc], "count")) {
|
||||
if (argv[argc + 1])
|
||||
opt_count = atoi(argv[++argc]);
|
||||
} else if (strcmp(argv[argc], "extra") == 0) {
|
||||
} else if (xo_streq(argv[argc], "extra")) {
|
||||
if (argv[argc + 1])
|
||||
opt_extra = atoi(argv[++argc]);
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <errno.h>
|
||||
|
||||
#include "xo.h"
|
||||
#include "xo_encoder.h"
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
@ -39,21 +40,21 @@ main (int argc, char **argv)
|
||||
return 1;
|
||||
|
||||
for (argc = 1; argv[argc]; argc++) {
|
||||
if (strcmp(argv[argc], "xml") == 0)
|
||||
if (xo_streq(argv[argc], "xml"))
|
||||
xo_set_style(NULL, XO_STYLE_XML);
|
||||
else if (strcmp(argv[argc], "json") == 0)
|
||||
else if (xo_streq(argv[argc], "json"))
|
||||
xo_set_style(NULL, XO_STYLE_JSON);
|
||||
else if (strcmp(argv[argc], "text") == 0)
|
||||
else if (xo_streq(argv[argc], "text"))
|
||||
xo_set_style(NULL, XO_STYLE_TEXT);
|
||||
else if (strcmp(argv[argc], "html") == 0)
|
||||
else if (xo_streq(argv[argc], "html"))
|
||||
xo_set_style(NULL, XO_STYLE_HTML);
|
||||
else if (strcmp(argv[argc], "pretty") == 0)
|
||||
else if (xo_streq(argv[argc], "pretty"))
|
||||
xo_set_flags(NULL, XOF_PRETTY);
|
||||
else if (strcmp(argv[argc], "xpath") == 0)
|
||||
else if (xo_streq(argv[argc], "xpath"))
|
||||
xo_set_flags(NULL, XOF_XPATH);
|
||||
else if (strcmp(argv[argc], "info") == 0)
|
||||
else if (xo_streq(argv[argc], "info"))
|
||||
xo_set_flags(NULL, XOF_INFO);
|
||||
else if (strcmp(argv[argc], "error") == 0) {
|
||||
else if (xo_streq(argv[argc], "error")) {
|
||||
close(-1);
|
||||
xo_err(1, "error detected");
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <errno.h>
|
||||
|
||||
#include "xo.h"
|
||||
#include "xo_encoder.h"
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
@ -39,21 +40,21 @@ main (int argc, char **argv)
|
||||
return 1;
|
||||
|
||||
for (argc = 1; argv[argc]; argc++) {
|
||||
if (strcmp(argv[argc], "xml") == 0)
|
||||
if (xo_streq(argv[argc], "xml"))
|
||||
xo_set_style(NULL, XO_STYLE_XML);
|
||||
else if (strcmp(argv[argc], "json") == 0)
|
||||
else if (xo_streq(argv[argc], "json"))
|
||||
xo_set_style(NULL, XO_STYLE_JSON);
|
||||
else if (strcmp(argv[argc], "text") == 0)
|
||||
else if (xo_streq(argv[argc], "text"))
|
||||
xo_set_style(NULL, XO_STYLE_TEXT);
|
||||
else if (strcmp(argv[argc], "html") == 0)
|
||||
else if (xo_streq(argv[argc], "html"))
|
||||
xo_set_style(NULL, XO_STYLE_HTML);
|
||||
else if (strcmp(argv[argc], "pretty") == 0)
|
||||
else if (xo_streq(argv[argc], "pretty"))
|
||||
xo_set_flags(NULL, XOF_PRETTY);
|
||||
else if (strcmp(argv[argc], "xpath") == 0)
|
||||
else if (xo_streq(argv[argc], "xpath"))
|
||||
xo_set_flags(NULL, XOF_XPATH);
|
||||
else if (strcmp(argv[argc], "info") == 0)
|
||||
else if (xo_streq(argv[argc], "info"))
|
||||
xo_set_flags(NULL, XOF_INFO);
|
||||
else if (strcmp(argv[argc], "error") == 0) {
|
||||
else if (xo_streq(argv[argc], "error")) {
|
||||
close(-1);
|
||||
xo_err(1, "error detected");
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <ctype.h>
|
||||
|
||||
#include "xo.h"
|
||||
#include "xo_encoder.h"
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
@ -58,21 +59,21 @@ main (int argc, char **argv)
|
||||
return 1;
|
||||
|
||||
for (argc = 1; argv[argc]; argc++) {
|
||||
if (strcmp(argv[argc], "xml") == 0)
|
||||
if (xo_streq(argv[argc], "xml"))
|
||||
xo_set_style(NULL, XO_STYLE_XML);
|
||||
else if (strcmp(argv[argc], "json") == 0)
|
||||
else if (xo_streq(argv[argc], "json"))
|
||||
xo_set_style(NULL, XO_STYLE_JSON);
|
||||
else if (strcmp(argv[argc], "text") == 0)
|
||||
else if (xo_streq(argv[argc], "text"))
|
||||
xo_set_style(NULL, XO_STYLE_TEXT);
|
||||
else if (strcmp(argv[argc], "html") == 0)
|
||||
else if (xo_streq(argv[argc], "html"))
|
||||
xo_set_style(NULL, XO_STYLE_HTML);
|
||||
else if (strcmp(argv[argc], "pretty") == 0)
|
||||
else if (xo_streq(argv[argc], "pretty"))
|
||||
xo_set_flags(NULL, XOF_PRETTY);
|
||||
else if (strcmp(argv[argc], "xpath") == 0)
|
||||
else if (xo_streq(argv[argc], "xpath"))
|
||||
xo_set_flags(NULL, XOF_XPATH);
|
||||
else if (strcmp(argv[argc], "info") == 0)
|
||||
else if (xo_streq(argv[argc], "info"))
|
||||
xo_set_flags(NULL, XOF_INFO);
|
||||
else if (strcmp(argv[argc], "error") == 0) {
|
||||
else if (xo_streq(argv[argc], "error")) {
|
||||
close(-1);
|
||||
xo_err(1, "error detected");
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <syslog.h>
|
||||
|
||||
#include "xo.h"
|
||||
#include "xo_encoder.h"
|
||||
|
||||
void
|
||||
test_syslog_open (void)
|
||||
@ -50,11 +51,11 @@ main (int argc, char **argv)
|
||||
return 1;
|
||||
|
||||
for (argc = 1; argv[argc]; argc++) {
|
||||
if (strcmp(argv[argc], "full") == 0)
|
||||
if (xo_streq(argv[argc], "full"))
|
||||
unit_test = 0;
|
||||
else if (strcmp(argv[argc], "fire") == 0)
|
||||
else if (xo_streq(argv[argc], "fire"))
|
||||
fire = 1;
|
||||
else if (strcmp(argv[argc], "tz") == 0)
|
||||
else if (xo_streq(argv[argc], "tz"))
|
||||
tzone = argv[++argc];
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "xo_config.h"
|
||||
#include "xo.h"
|
||||
#include "xo_encoder.h"
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
@ -29,25 +30,25 @@ main (int argc, char **argv)
|
||||
return 1;
|
||||
|
||||
for (argc = 1; argv[argc]; argc++) {
|
||||
if (strcmp(argv[argc], "xml") == 0)
|
||||
if (xo_streq(argv[argc], "xml"))
|
||||
xo_set_style(NULL, XO_STYLE_XML);
|
||||
else if (strcmp(argv[argc], "json") == 0)
|
||||
else if (xo_streq(argv[argc], "json"))
|
||||
xo_set_style(NULL, XO_STYLE_JSON);
|
||||
else if (strcmp(argv[argc], "text") == 0)
|
||||
else if (xo_streq(argv[argc], "text"))
|
||||
xo_set_style(NULL, XO_STYLE_TEXT);
|
||||
else if (strcmp(argv[argc], "html") == 0)
|
||||
else if (xo_streq(argv[argc], "html"))
|
||||
xo_set_style(NULL, XO_STYLE_HTML);
|
||||
else if (strcmp(argv[argc], "no-color") == 0)
|
||||
else if (xo_streq(argv[argc], "no-color"))
|
||||
opt_color = 0;
|
||||
else if (strcmp(argv[argc], "pretty") == 0)
|
||||
else if (xo_streq(argv[argc], "pretty"))
|
||||
xo_set_flags(NULL, XOF_PRETTY);
|
||||
else if (strcmp(argv[argc], "xpath") == 0)
|
||||
else if (xo_streq(argv[argc], "xpath"))
|
||||
xo_set_flags(NULL, XOF_XPATH);
|
||||
else if (strcmp(argv[argc], "info") == 0)
|
||||
else if (xo_streq(argv[argc], "info"))
|
||||
xo_set_flags(NULL, XOF_INFO);
|
||||
else if (strcmp(argv[argc], "no-retain") == 0)
|
||||
else if (xo_streq(argv[argc], "no-retain"))
|
||||
flags &= ~XOEF_RETAIN;
|
||||
else if (strcmp(argv[argc], "big") == 0) {
|
||||
else if (xo_streq(argv[argc], "big")) {
|
||||
if (argv[argc + 1])
|
||||
count = atoi(argv[++argc]);
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <libintl.h>
|
||||
|
||||
#include "xo.h"
|
||||
#include "xo_encoder.h"
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
@ -35,11 +36,11 @@ main (int argc, char **argv)
|
||||
return 1;
|
||||
|
||||
for (argc = 1; argv[argc]; argc++) {
|
||||
if (strcmp(argv[argc], "tz") == 0)
|
||||
if (xo_streq(argv[argc], "tz"))
|
||||
tzone = argv[++argc];
|
||||
else if (strcmp(argv[argc], "lang") == 0)
|
||||
else if (xo_streq(argv[argc], "lang"))
|
||||
lang = argv[++argc];
|
||||
else if (strcmp(argv[argc], "po") == 0)
|
||||
else if (xo_streq(argv[argc], "po"))
|
||||
strlcpy(path, argv[++argc], sizeof(path));
|
||||
}
|
||||
|
||||
|
@ -1 +1 @@
|
||||
<div class="line"><div class="text">Ouryay </div><div class="data" data-tag="noun">ordsway</div><div class="text"> </div><div class="data" data-tag="adjective">amingflay</div><div class="text"> isyay </div><div class="data" data-tag="owner">ymay</div><div class="data" data-tag="target">ouchcay</div><div class="text"> bubbly-bubbly </div><div class="data" data-tag="verb">urningbay</div></div><div class="line"><div class="text">Ethay </div><div class="data" data-tag="noun">ordsway</div><div class="text"> asway '</div><div class="data" data-tag="owner">ymay</div><div class="data" data-tag="adjective">amingflay</div><div class="data" data-tag="target">ouchcay</div><div class="text">' </div><div class="data" data-tag="verb">urningbay</div></div><div class="line"><div class="data" data-tag="bytes">0</div><div class="padding"> </div><div class="note">yebay</div></div><div class="line"><div class="data" data-tag="bytes">1</div><div class="padding"> </div><div class="note">yesbay</div></div><div class="line"><div class="data" data-tag="bytes">2</div><div class="padding"> </div><div class="note">yezbay</div></div><div class="line"><div class="data" data-tag="bytes">3</div><div class="padding"> </div><div class="note">yezbay</div></div><div class="line"><div class="data" data-tag="bytes">4</div><div class="padding"> </div><div class="note">yezbay</div></div><div class="line"><div class="label">otaltay</div><div class="text"> </div><div class="data" data-tag="total">1234</div></div><div class="line"><div class="text">Eceivedray </div><div class="data" data-tag="received">1234</div><div class="text"> </div><div class="note">ldb2</div><div class="text"> omfray </div><div class="data" data-tag="from">foop</div><div class="text">#</div><div class="data" data-tag="port">4321</div><div class="text"> inyay </div><div class="data" data-tag="time">32</div><div class="text"> msyay</div></div><div class="line"><div class="text">Received </div><div class="data" data-tag="received">1234</div><div class="text"> </div><div class="note">yezbay</div><div class="text"> from </div><div class="data" data-tag="from">foop</div><div class="text">#</div><div class="data" data-tag="port">4321</div><div class="text"> in </div><div class="data" data-tag="time">32</div><div class="text"> ms</div></div><div class="line"><div class="text">Eceivedray </div><div class="data" data-tag="received">1234</div><div class="text"> </div><div class="note">ldb2</div><div class="text"> omfray </div><div class="data" data-tag="from">foop</div><div class="text">#</div><div class="data" data-tag="port">4321</div><div class="text"> inyay </div><div class="data" data-tag="time">32</div><div class="text"> msyay</div></div><div class="line"><div class="text">Onlyay </div><div class="data" data-tag="marzlevanes">3</div><div class="text"> </div><div class="note">arzlevanezmay</div><div class="text"> areyay unctioningfay orrectlycay</div></div><div class="line"><div class="text">Ersionvay </div><div class="data" data-tag="date">Tue Jun 23 18:47:09 UTC 2015</div><div class="text"> </div><div class="data" data-tag="version">1.2.3</div></div><div class="line"><div class="data" data-tag="program">gt_01.test</div><div class="decoration">:</div><div class="padding"> </div><div class="text">Nableuay otay </div><div class="data" data-tag="verb">ectulatobjay</div><div class="text"> orwardfay elocipingvay</div><div class="text">: </div><div class="data" data-tag="error">Ermissionpay eniedday</div></div><div class="line"><div class="data" data-tag="program">gt_01.test</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="style">automaticyay</div><div class="text"> ynchronizationsay ofyay </div><div class="data" data-tag="type">ardinalyay</div><div class="text"> </div><div class="data" data-tag="target">ammetersgray</div><div class="text"> ailedfay</div><div class="text">: </div><div class="data" data-tag="error">Ermissionpay eniedday</div></div><div class="line"><div class="label">ydrocoptichay arzlevanesmay</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="marzlevanes">6</div></div><div class="line"><div class="text">Dude, </div><div class="label">Indingsway</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="windings">otuslay-oyay-eltayay</div></div>
|
||||
<div class="line"><div class="text">Ouryay </div><div class="data" data-tag="noun">ordsway</div><div class="text"> </div><div class="data" data-tag="adjective">amingflay</div><div class="text"> isyay </div><div class="data" data-tag="owner">ymay</div><div class="data" data-tag="target">ouchcay</div><div class="text"> bubbly-bubbly </div><div class="data" data-tag="verb">urningbay</div></div><div class="line"><div class="text">Ethay </div><div class="data" data-tag="noun">ordsway</div><div class="text"> asway '</div><div class="data" data-tag="owner">ymay</div><div class="data" data-tag="adjective">amingflay</div><div class="data" data-tag="target">ouchcay</div><div class="text">' </div><div class="data" data-tag="verb">urningbay</div></div><div class="line"><div class="data" data-tag="bytes">0</div><div class="padding"> </div><div class="note">yebay</div></div><div class="line"><div class="data" data-tag="bytes">1</div><div class="padding"> </div><div class="note">yesbay</div></div><div class="line"><div class="data" data-tag="bytes">2</div><div class="padding"> </div><div class="note">yezbay</div></div><div class="line"><div class="data" data-tag="bytes">3</div><div class="padding"> </div><div class="note">yezbay</div></div><div class="line"><div class="data" data-tag="bytes">4</div><div class="padding"> </div><div class="note">yezbay</div></div><div class="line"><div class="label">otaltay</div><div class="text"> </div><div class="data" data-tag="total">1234</div></div><div class="line"><div class="text">Eceivedray </div><div class="data" data-tag="received">1234</div><div class="text"> </div><div class="note">ldb2</div><div class="text"> omfray </div><div class="data" data-tag="from">foop</div><div class="text">#</div><div class="data" data-tag="port">4321</div><div class="text"> inyay </div><div class="data" data-tag="time">32</div><div class="text"> msyay</div></div><div class="line"><div class="text">Received </div><div class="data" data-tag="received">1234</div><div class="text"> </div><div class="note">yezbay</div><div class="text"> from </div><div class="data" data-tag="from">foop</div><div class="text">#</div><div class="data" data-tag="port">4321</div><div class="text"> in </div><div class="data" data-tag="time">32</div><div class="text"> ms</div></div><div class="line"><div class="text">Eceivedray </div><div class="data" data-tag="received">1234</div><div class="text"> </div><div class="note">ldb2</div><div class="text"> omfray </div><div class="data" data-tag="from">foop</div><div class="text">#</div><div class="data" data-tag="port">4321</div><div class="text"> inyay </div><div class="data" data-tag="time">32</div><div class="text"> msyay</div></div><div class="line"><div class="text">Onlyay </div><div class="data" data-tag="marzlevanes">3</div><div class="text"> </div><div class="note">arzlevanezmay</div><div class="text"> areyay unctioningfay orrectlycay</div></div><div class="line"><div class="text">Ersionvay </div><div class="data" data-tag="date">Tue Jun 23 18:47:09 UTC 2015</div><div class="text"> </div><div class="data" data-tag="version">1.2.3</div></div><div class="line"><div class="data" data-tag="program">gt_01</div><div class="decoration">:</div><div class="padding"> </div><div class="text">Nableuay otay </div><div class="data" data-tag="verb">ectulatobjay</div><div class="text"> orwardfay elocipingvay</div><div class="text">: </div><div class="data" data-tag="error">Ermissionpay eniedday</div></div><div class="line"><div class="data" data-tag="program">gt_01</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="style">automaticyay</div><div class="text"> ynchronizationsay ofyay </div><div class="data" data-tag="type">ardinalyay</div><div class="text"> </div><div class="data" data-tag="target">ammetersgray</div><div class="text"> ailedfay</div><div class="text">: </div><div class="data" data-tag="error">Ermissionpay eniedday</div></div><div class="line"><div class="label">ydrocoptichay arzlevanesmay</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="marzlevanes">6</div></div><div class="line"><div class="text">Dude, </div><div class="label">Indingsway</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="windings">otuslay-oyay-eltayay</div></div>
|
@ -102,7 +102,7 @@
|
||||
<div class="data" data-tag="version" data-xpath="/top/version">1.2.3</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="data" data-tag="program" data-xpath="/top/xo_emit_warn_hcv/__warning/program">gt_01.test</div>
|
||||
<div class="data" data-tag="program" data-xpath="/top/xo_emit_warn_hcv/__warning/program">gt_01</div>
|
||||
<div class="decoration">:</div>
|
||||
<div class="padding"> </div>
|
||||
<div class="text">Nableuay otay </div>
|
||||
@ -112,7 +112,7 @@
|
||||
<div class="data" data-tag="error" data-xpath="/top/xo_emit_warn_hcv/__warning/error">Ermissionpay eniedday</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="data" data-tag="program" data-xpath="/top/xo_emit_warn_hcv/__warning/program">gt_01.test</div>
|
||||
<div class="data" data-tag="program" data-xpath="/top/xo_emit_warn_hcv/__warning/program">gt_01</div>
|
||||
<div class="decoration">:</div>
|
||||
<div class="padding"> </div>
|
||||
<div class="data" data-tag="style" data-xpath="/top/xo_emit_warn_hcv/__warning/style">automaticyay</div>
|
||||
|
@ -102,7 +102,7 @@
|
||||
<div class="data" data-tag="version">1.2.3</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="data" data-tag="program">gt_01.test</div>
|
||||
<div class="data" data-tag="program">gt_01</div>
|
||||
<div class="decoration">:</div>
|
||||
<div class="padding"> </div>
|
||||
<div class="text">Nableuay otay </div>
|
||||
@ -112,7 +112,7 @@
|
||||
<div class="data" data-tag="error">Ermissionpay eniedday</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="data" data-tag="program">gt_01.test</div>
|
||||
<div class="data" data-tag="program">gt_01</div>
|
||||
<div class="decoration">:</div>
|
||||
<div class="padding"> </div>
|
||||
<div class="data" data-tag="style">automaticyay</div>
|
||||
|
@ -1 +1 @@
|
||||
{"top": {"adjective":"amingflay","noun":"ordsway","verb":"urningbay","owner":"ymay","target":"ouchcay","adjective":"amingflay","noun":"ordsway","verb":"urningbay","owner":"ymay","target":"ouchcay", "bytes": [0,1,2,3,4],"total":1234,"received":1234,"from":"foop","port":4321,"time":32,"received":1234,"from":"foop","port":4321,"time":32,"received":1234,"from":"foop","port":4321,"time":32,"marzlevanes":3,"version":"1.2.3","date":"Tue Jun 23 18:47:09 UTC 2015", "__warning": {"program":"gt_01.test","message":"Nableuay otay ectulatobjay orwardfay elocipingvay","verb":"ectulatobjay","error":"Ermissionpay eniedday"}, "__warning": {"program":"gt_01.test","message":"automaticyay ynchronizationsay ofyay ardinalyay ammetersgray ailedfay","style":"automaticyay","type":"ardinalyay","target":"ammetersgray","error":"Ermissionpay eniedday"},"marzlevanes":6,"windings":"otuslay-oyay-eltayay"}}
|
||||
{"top": {"adjective":"amingflay","noun":"ordsway","verb":"urningbay","owner":"ymay","target":"ouchcay","adjective":"amingflay","noun":"ordsway","verb":"urningbay","owner":"ymay","target":"ouchcay", "bytes": [0,1,2,3,4],"total":1234,"received":1234,"from":"foop","port":4321,"time":32,"received":1234,"from":"foop","port":4321,"time":32,"received":1234,"from":"foop","port":4321,"time":32,"marzlevanes":3,"version":"1.2.3","date":"Tue Jun 23 18:47:09 UTC 2015", "__warning": {"program":"gt_01","message":"Nableuay otay ectulatobjay orwardfay elocipingvay","verb":"ectulatobjay","error":"Ermissionpay eniedday"}, "__warning": {"program":"gt_01","message":"automaticyay ynchronizationsay ofyay ardinalyay ammetersgray ailedfay","style":"automaticyay","type":"ardinalyay","target":"ammetersgray","error":"Ermissionpay eniedday"},"marzlevanes":6,"windings":"otuslay-oyay-eltayay"}}
|
||||
|
@ -34,13 +34,13 @@
|
||||
"version": "1.2.3",
|
||||
"date": "Tue Jun 23 18:47:09 UTC 2015",
|
||||
"__warning": {
|
||||
"program": "gt_01.test",
|
||||
"program": "gt_01",
|
||||
"message": "Nableuay otay ectulatobjay orwardfay elocipingvay",
|
||||
"verb": "ectulatobjay",
|
||||
"error": "Ermissionpay eniedday"
|
||||
},
|
||||
"__warning": {
|
||||
"program": "gt_01.test",
|
||||
"program": "gt_01",
|
||||
"message": "automaticyay ynchronizationsay ofyay ardinalyay ammetersgray ailedfay",
|
||||
"style": "automaticyay",
|
||||
"type": "ardinalyay",
|
||||
|
@ -11,7 +11,7 @@ Received 1234 yezbay from foop#4321 in 32 ms
|
||||
Eceivedray 1234 ldb2 omfray foop#4321 inyay 32 msyay
|
||||
Onlyay 3 arzlevanezmay areyay unctioningfay orrectlycay
|
||||
Ersionvay Tue Jun 23 18:47:09 UTC 2015 1.2.3
|
||||
gt_01.test: Nableuay otay ectulatobjay orwardfay elocipingvay: Ermissionpay eniedday
|
||||
gt_01.test: automaticyay ynchronizationsay ofyay ardinalyay ammetersgray ailedfay: Ermissionpay eniedday
|
||||
gt_01: Nableuay otay ectulatobjay orwardfay elocipingvay: Ermissionpay eniedday
|
||||
gt_01: automaticyay ynchronizationsay ofyay ardinalyay ammetersgray ailedfay: Ermissionpay eniedday
|
||||
ydrocoptichay arzlevanesmay: 6
|
||||
Dude, Indingsway: otuslay-oyay-eltayay
|
||||
|
@ -1 +1 @@
|
||||
<top><adjective>amingflay</adjective><noun>ordsway</noun><verb>urningbay</verb><owner>ymay</owner><target>ouchcay</target><adjective>amingflay</adjective><noun>ordsway</noun><verb>urningbay</verb><owner>ymay</owner><target>ouchcay</target><bytes>0</bytes><bytes>1</bytes><bytes>2</bytes><bytes>3</bytes><bytes>4</bytes><total>1234</total><received>1234</received><from>foop</from><port>4321</port><time>32</time><received>1234</received><from>foop</from><port>4321</port><time>32</time><received>1234</received><from>foop</from><port>4321</port><time>32</time><marzlevanes>3</marzlevanes><version>1.2.3</version><date>Tue Jun 23 18:47:09 UTC 2015</date><__warning><program>gt_01.test</program><message>Nableuay otay ectulatobjay orwardfay elocipingvay</message><verb>ectulatobjay</verb><error>Ermissionpay eniedday</error></__warning><__warning><program>gt_01.test</program><message>automaticyay ynchronizationsay ofyay ardinalyay ammetersgray ailedfay</message><style>automaticyay</style><type>ardinalyay</type><target>ammetersgray</target><error>Ermissionpay eniedday</error></__warning><marzlevanes>6</marzlevanes><windings>otuslay-oyay-eltayay</windings></top>
|
||||
<top><adjective>amingflay</adjective><noun>ordsway</noun><verb>urningbay</verb><owner>ymay</owner><target>ouchcay</target><adjective>amingflay</adjective><noun>ordsway</noun><verb>urningbay</verb><owner>ymay</owner><target>ouchcay</target><bytes>0</bytes><bytes>1</bytes><bytes>2</bytes><bytes>3</bytes><bytes>4</bytes><total>1234</total><received>1234</received><from>foop</from><port>4321</port><time>32</time><received>1234</received><from>foop</from><port>4321</port><time>32</time><received>1234</received><from>foop</from><port>4321</port><time>32</time><marzlevanes>3</marzlevanes><version>1.2.3</version><date>Tue Jun 23 18:47:09 UTC 2015</date><__warning><program>gt_01</program><message>Nableuay otay ectulatobjay orwardfay elocipingvay</message><verb>ectulatobjay</verb><error>Ermissionpay eniedday</error></__warning><__warning><program>gt_01</program><message>automaticyay ynchronizationsay ofyay ardinalyay ammetersgray ailedfay</message><style>automaticyay</style><type>ardinalyay</type><target>ammetersgray</target><error>Ermissionpay eniedday</error></__warning><marzlevanes>6</marzlevanes><windings>otuslay-oyay-eltayay</windings></top>
|
@ -31,13 +31,13 @@
|
||||
<version>1.2.3</version>
|
||||
<date>Tue Jun 23 18:47:09 UTC 2015</date>
|
||||
<__warning>
|
||||
<program>gt_01.test</program>
|
||||
<program>gt_01</program>
|
||||
<message>Nableuay otay ectulatobjay orwardfay elocipingvay</message>
|
||||
<verb>ectulatobjay</verb>
|
||||
<error>Ermissionpay eniedday</error>
|
||||
</__warning>
|
||||
<__warning>
|
||||
<program>gt_01.test</program>
|
||||
<program>gt_01</program>
|
||||
<message>automaticyay ynchronizationsay ofyay ardinalyay ammetersgray ailedfay</message>
|
||||
<style>automaticyay</style>
|
||||
<type>ardinalyay</type>
|
||||
|
@ -6,6 +6,7 @@ Usage: xo [options] format [fields]
|
||||
--depth <num> Set the depth for pretty printing
|
||||
--help Display this help text
|
||||
--html OR -H Generate HTML output
|
||||
--instance OR -I <name> Wrap in an instance of the given name
|
||||
--json OR -J Generate JSON output
|
||||
--leading-xpath <path> OR -l <path> Add a prefix to generated XPaths (HTML)
|
||||
--not-first Indicate this object is not the first (JSON)
|
||||
|
@ -6,6 +6,7 @@ Usage: xo [options] format [fields]
|
||||
--depth <num> Set the depth for pretty printing
|
||||
--help Display this help text
|
||||
--html OR -H Generate HTML output
|
||||
--instance OR -I <name> Wrap in an instance of the given name
|
||||
--json OR -J Generate JSON output
|
||||
--leading-xpath <path> OR -l <path> Add a prefix to generated XPaths (HTML)
|
||||
--not-first Indicate this object is not the first (JSON)
|
||||
|
@ -6,6 +6,7 @@ Usage: xo [options] format [fields]
|
||||
--depth <num> Set the depth for pretty printing
|
||||
--help Display this help text
|
||||
--html OR -H Generate HTML output
|
||||
--instance OR -I <name> Wrap in an instance of the given name
|
||||
--json OR -J Generate JSON output
|
||||
--leading-xpath <path> OR -l <path> Add a prefix to generated XPaths (HTML)
|
||||
--not-first Indicate this object is not the first (JSON)
|
||||
|
@ -6,6 +6,7 @@ Usage: xo [options] format [fields]
|
||||
--depth <num> Set the depth for pretty printing
|
||||
--help Display this help text
|
||||
--html OR -H Generate HTML output
|
||||
--instance OR -I <name> Wrap in an instance of the given name
|
||||
--json OR -J Generate JSON output
|
||||
--leading-xpath <path> OR -l <path> Add a prefix to generated XPaths (HTML)
|
||||
--not-first Indicate this object is not the first (JSON)
|
||||
|
@ -6,6 +6,7 @@ Usage: xo [options] format [fields]
|
||||
--depth <num> Set the depth for pretty printing
|
||||
--help Display this help text
|
||||
--html OR -H Generate HTML output
|
||||
--instance OR -I <name> Wrap in an instance of the given name
|
||||
--json OR -J Generate JSON output
|
||||
--leading-xpath <path> OR -l <path> Add a prefix to generated XPaths (HTML)
|
||||
--not-first Indicate this object is not the first (JSON)
|
||||
|
@ -6,6 +6,7 @@ Usage: xo [options] format [fields]
|
||||
--depth <num> Set the depth for pretty printing
|
||||
--help Display this help text
|
||||
--html OR -H Generate HTML output
|
||||
--instance OR -I <name> Wrap in an instance of the given name
|
||||
--json OR -J Generate JSON output
|
||||
--leading-xpath <path> OR -l <path> Add a prefix to generated XPaths (HTML)
|
||||
--not-first Indicate this object is not the first (JSON)
|
||||
|
@ -6,6 +6,7 @@ Usage: xo [options] format [fields]
|
||||
--depth <num> Set the depth for pretty printing
|
||||
--help Display this help text
|
||||
--html OR -H Generate HTML output
|
||||
--instance OR -I <name> Wrap in an instance of the given name
|
||||
--json OR -J Generate JSON output
|
||||
--leading-xpath <path> OR -l <path> Add a prefix to generated XPaths (HTML)
|
||||
--not-first Indicate this object is not the first (JSON)
|
||||
|
@ -6,6 +6,7 @@ Usage: xo [options] format [fields]
|
||||
--depth <num> Set the depth for pretty printing
|
||||
--help Display this help text
|
||||
--html OR -H Generate HTML output
|
||||
--instance OR -I <name> Wrap in an instance of the given name
|
||||
--json OR -J Generate JSON output
|
||||
--leading-xpath <path> OR -l <path> Add a prefix to generated XPaths (HTML)
|
||||
--not-first Indicate this object is not the first (JSON)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user