add -r flag to allow printing all control-characters - json2tsv - JSON to TSV converter
 (HTM) git clone git://git.codemadness.org/json2tsv
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 33d5e77ed74ebe2ac9495ca3f4dbde493b26b69f
 (DIR) parent a8950873f2e40fe767530b8e58b723c8b56abc33
 (HTM) Author: Hiltjo Posthuma <hiltjo@codemadness.org>
       Date:   Tue,  5 Nov 2019 20:46:45 +0100
       
       add -r flag to allow printing all control-characters
       
       No performance change with -O2 or higher with gcc or clang using no flags set.
       
       Minor tweaks:
       - rename showindices to nflag variable.
       - reword and improve formatting of man page.
       - improve parsing of options.
       
       Diffstat:
         M json2tsv.1                          |      24 ++++++++++++++++--------
         M json2tsv.c                          |      21 ++++++++++++++++-----
       
       2 files changed, 32 insertions(+), 13 deletions(-)
       ---
 (DIR) diff --git a/json2tsv.1 b/json2tsv.1
       @@ -1,4 +1,4 @@
       -.Dd October 20, 2019
       +.Dd November 5, 2019
        .Dt JSON2TSV 1
        .Os
        .Sh NAME
       @@ -7,13 +7,19 @@
        .Sh SYNOPSIS
        .Nm
        .Op Fl n
       +.Op Fl r
        .Sh DESCRIPTION
        .Nm
        reads JSON data from stdin.
        It outputs each JSON type to a TAB-Separated Value format per line.
       -The
       -.Fl n
       -flag can be used to show the indices for array types (by default off).
       +.Pp
       +The options are as follows:
       +.Bl -tag -width Ds
       +.It Fl n
       +Show the indices for array types (by default off).
       +.It Fl r
       +Show all control-characters (by default off).
       +.El
        .Sh TAB-SEPARATED VALUE FORMAT
        The output format per line is:
        .Bd -literal
       @@ -21,8 +27,10 @@ nodename<TAB>type<TAB>value<LF>
        .Ed
        .Pp
        Control-characters such as a newline, TAB and backslash (\\n, \\t and \\\\) are
       -escaped in the nodename and value fields.
       -Other control-characters are removed.
       +always escaped in the nodename and value fields.
       +Other control-characters are removed, unless the option
       +.Fl r
       +is set.
        .Pp
        The type field is a single byte and can be:
        .Bl -tag -width Ds
       @@ -49,8 +57,8 @@ Characters in object keys such as a dot or brackets are not escaped in the TSV
        output, this can change the meaning of the nodename field.
        .It
        The JSON parser handles all valid JSON.
       -It also allows some invalid JSON extension: it does not do a complete
       -validation on numbers and is not strict with unicode input.
       +It also allows some invalid JSON extensions: it does not do a complete
       +validation on numbers and is not strict with handling unicode input.
        See also RFC8259 section 9. Parsers.
        .It
        The maximum depth of objects or arrays is hard-coded to 64 levels deep.
 (DIR) diff --git a/json2tsv.c b/json2tsv.c
       @@ -13,7 +13,8 @@
        
        #include "json.h"
        
       -static int showindices = 0; /* -n flag: show indices count for arrays */
       +static int nflag = 0; /* -n flag: show indices count for arrays */
       +static int rflag = 0; /* -r flag: show all control-characters */
        
        void
        printvalue(const char *s)
       @@ -26,7 +27,7 @@ printvalue(const char *s)
                        case '\t': putchar('\\'); putchar('t'); break;
                        default:
                                /* ignore other control chars */
       -                        if (iscntrl((unsigned char)*s))
       +                        if (!rflag && iscntrl((unsigned char)*s))
                                        continue;
                                putchar(*s);
                        }
       @@ -48,7 +49,7 @@ processnode(struct json_node *nodes, size_t depth, const char *value)
                        if (nodes[i].type == TYPE_OBJECT) {
                                putchar('.');
                        } else if (nodes[i].type == TYPE_ARRAY) {
       -                        if (showindices) {
       +                        if (nflag) {
                                        printf("[%zu]", nodes[i].index);
                                } else {
                                        putchar('[');
       @@ -67,13 +68,23 @@ processnode(struct json_node *nodes, size_t depth, const char *value)
        int
        main(int argc, char *argv[])
        {
       +        int i, j;
       +
                if (pledge("stdio", NULL) == -1) {
                        fprintf(stderr, "pledge stdio: %s\n", strerror(errno));
                        return 1;
                }
        
       -        if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'n')
       -                showindices = 1;
       +        for (i = 1; i < argc; i++) {
       +                if (argv[i][0] != '-')
       +                        continue;
       +                for (j = 1; argv[i][j]; j++) {
       +                        switch (argv[i][j]) {
       +                        case 'n': nflag = 1; break;
       +                        case 'r': rflag = 1; break;
       +                        }
       +                }
       +        }
        
                switch (parsejson(processnode)) {
                case JSON_ERROR_MEM: