Skip to content

Commit 98e6d9c

Browse files
committed
Add -c for CSV output
1 parent d431c02 commit 98e6d9c

File tree

4 files changed

+58
-17
lines changed

4 files changed

+58
-17
lines changed

jt.1

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@
77
\fBjt\fR \- transform JSON data to tabular format
88
.
99
.SH "SYNOPSIS"
10-
\fBjt\fR [\fB\-h\fR]
10+
\fBjt\fR \fB\-h\fR
1111
.
1212
.br
13-
\fBjt\fR [\fB\-u\fR \fIstring\fR]
13+
\fBjt\fR \fB\-u\fR \fIstring\fR
14+
.
15+
.br
16+
\fBjt\fR \fB\-c\fR [\fB\-js\fR] [\fB\-i\fR \fIfile\fR] [\fB\-o\fR \fIfile\fR] \fBCOMMAND\fR \.\.\.
1417
.
1518
.br
1619
\fBjt\fR [\fB\-js\fR] [\fB\-F\fR \fIchar\fR] [\fB\-R\fR \fIchar\fR] [\fB\-i\fR \fIfile\fR] [\fB\-o\fR \fIfile\fR] \fBCOMMAND\fR \.\.\.
@@ -28,6 +31,10 @@
2831
Print usage info and exit\.
2932
.
3033
.TP
34+
\fB\-c\fR
35+
Print output as CSV with JSON strings unescaped\.
36+
.
37+
.TP
3138
\fB\-j\fR
3239
Inner join mode: discard rows with missing columns\.
3340
.

jt.1.html

Lines changed: 4 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

jt.1.ronn

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ jt(1) -- transform JSON data to tabular format
33

44
## SYNOPSIS
55

6-
`jt` [`-h`]<br>
7-
`jt` [`-u` <string>]<br>
6+
`jt` `-h`<br>
7+
`jt` `-u` <string><br>
8+
`jt` `-c` [`-js`] [`-i` <file>] [`-o` <file>] `COMMAND` ...<br>
89
`jt` [`-js`] [`-F` <char>] [`-R` <char>] [`-i` <file>] [`-o` <file>] `COMMAND` ...
910

1011
## DESCRIPTION
@@ -27,6 +28,9 @@ the tabular data to the final result.
2728
* `-h`:
2829
Print usage info and exit.
2930

31+
* `-c`:
32+
Print output as CSV with JSON strings unescaped.
33+
3034
* `-j`:
3135
Inner join mode: discard rows with missing columns.
3236

jt.c

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
char *colsep = "\t";
1515
char *rowsep = "\n";
1616
int left_join = 1;
17+
int csv_output = 0;
18+
19+
char *unescape_string(char*);
1720

1821
/*
1922
* helpers
@@ -66,13 +69,34 @@ void *jrealloc(void *ptr, size_t size) {
6669
return ret;
6770
}
6871

72+
char *csv_str(char *raw) {
73+
char *in, *inp, *out, *outp;
74+
75+
inp = in = unescape_string(raw);
76+
free(raw);
77+
78+
outp = out = jmalloc(strlen(in) * 2 + 3);
79+
*(outp++) = '"';
80+
81+
while (*inp != '\0') {
82+
*(outp++) = *inp;
83+
if (*(inp++) == '"') *(outp++) = '"';
84+
}
85+
86+
*(outp++) = '"';
87+
*outp = '\0';
88+
free(in);
89+
90+
return out;
91+
}
92+
6993
char *str(const char *fmt, ...) {
70-
char *s;
94+
char *s = NULL;
7195
va_list ap;
7296
va_start(ap, fmt);
7397
if (vasprintf(&s, fmt, ap) < 0) die_mem();
7498
va_end(ap);
75-
return s;
99+
return csv_output ? csv_str(s) : s;
76100
}
77101

78102
FILE *open(const char *path, const char *mode) {
@@ -191,25 +215,24 @@ unsigned long read_code_point(char **s) {
191215
return high;
192216
}
193217

194-
unsigned long utf_tag[7] = { 0x00, 0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc };
218+
unsigned long utf_tag[4] = { 0x00, 0xc0, 0xe0, 0xf0 };
195219

196220
void encode_u_escaped(char **in, char **out) {
197221
unsigned long p = read_code_point(in);
198-
int len = (p < 0x80) ? 1 : (p < 0x800) ? 2 : (p < 0x1000) ? 3 : 4;
199-
222+
int len = (p < 0x80) ? 1 : ((p < 0x800) ? 2 : ((p < 0x1000) ? 3 : 4));
200223
*out += len;
201224
switch (len) {
202225
case 4: *--(*out) = ((p | 0x80) & 0xbf); p >>= 6;
203226
case 3: *--(*out) = ((p | 0x80) & 0xbf); p >>= 6;
204227
case 2: *--(*out) = ((p | 0x80) & 0xbf); p >>= 6;
205-
case 1: *--(*out) = (p | utf_tag[len]);
228+
case 1: *--(*out) = (p | utf_tag[len - 1]);
206229
}
207230
*out += len;
208231
}
209232

210233
char *unescape_string(char *in) {
211234
char *inp = in, *outp, *out;
212-
outp = out = malloc(strlen(in) + 1);
235+
outp = out = jmalloc(strlen(in) + 1);
213236

214237
while (*inp != '\0') {
215238
if (*inp != '\\') {
@@ -401,9 +424,10 @@ int run(char *js, int argc, char *argv[]) {
401424

402425
void usage(int status) {
403426
fprintf(stderr, "jt %s - transform JSON data into tab delimited lines of text.\n\n", JT_VERSION);
404-
fprintf(stderr, "Usage: jt [-h]\n");
405-
fprintf(stderr, " jt [-u <string>]\n");
406-
fprintf(stderr, " jt [-hjs] [-i <file>] [-o <file>] [-F <char>] [-R <char>] [COMMAND ...]\n\n");
427+
fprintf(stderr, "Usage: jt -h\n");
428+
fprintf(stderr, " jt -u <string>\n");
429+
fprintf(stderr, " jt -c [-js] [-i <file>] [-o <file>] COMMAND ...\n");
430+
fprintf(stderr, " jt [-js] [-i <file>] [-o <file>] [-F <char>] [-R <char>] COMMAND ...\n\n");
407431
fprintf(stderr, "Where COMMAND is one of `[', `]', `%%', `?', `^', or a property name.\n");
408432
exit(status);
409433
}
@@ -419,11 +443,15 @@ int main(int argc, char *argv[]) {
419443
infile = stdin;
420444
outfile = stdout;
421445

422-
while ((opt = getopt(argc, argv, "+hjsi:o:u:F:R:")) != -1) {
446+
while ((opt = getopt(argc, argv, "+hjsci:o:u:F:R:")) != -1) {
423447
switch (opt) {
424448
case 'h':
425449
usage(0);
426450
break;
451+
case 'c':
452+
csv_output = 1;
453+
colsep = ",";
454+
break;
427455
case 'j':
428456
left_join = 0;
429457
break;

0 commit comments

Comments
 (0)