jv_print.c (jq-1.5) | : | jv_print.c (jq-1.6) | ||
---|---|---|---|---|
skipping to change at line 15 | skipping to change at line 15 | |||
#ifdef WIN32 | #ifdef WIN32 | |||
#include <windows.h> | #include <windows.h> | |||
#include <io.h> | #include <io.h> | |||
#include <fileapi.h> | #include <fileapi.h> | |||
#endif | #endif | |||
#include "jv.h" | #include "jv.h" | |||
#include "jv_dtoa.h" | #include "jv_dtoa.h" | |||
#include "jv_unicode.h" | #include "jv_unicode.h" | |||
#include "jv_alloc.h" | ||||
#ifndef MAX_PRINT_DEPTH | ||||
#define MAX_PRINT_DEPTH (256) | ||||
#endif | ||||
#define ESC "\033" | #define ESC "\033" | |||
#define COL(c) (ESC "[" c "m") | #define COL(c) (ESC "[" c "m") | |||
#define COLRESET (ESC "[0m") | #define COLRESET (ESC "[0m") | |||
// Colour table. See https://en.wikipedia.org/wiki/ANSI_escape_code#Colors | // Color table. See https://en.wikipedia.org/wiki/ANSI_escape_code#Colors | |||
// for how to choose these. | // for how to choose these. | |||
static const jv_kind colour_kinds[] = | static const jv_kind color_kinds[] = | |||
{JV_KIND_NULL, JV_KIND_FALSE, JV_KIND_TRUE, JV_KIND_NUMBER, | {JV_KIND_NULL, JV_KIND_FALSE, JV_KIND_TRUE, JV_KIND_NUMBER, | |||
JV_KIND_STRING, JV_KIND_ARRAY, JV_KIND_OBJECT}; | JV_KIND_STRING, JV_KIND_ARRAY, JV_KIND_OBJECT}; | |||
static const char* const colours[] = | static char color_bufs[sizeof(color_kinds)/sizeof(color_kinds[0])][16]; | |||
static const char *color_bufps[8]; | ||||
static const char* def_colors[] = | ||||
{COL("1;30"), COL("0;39"), COL("0;39"), COL("0;39"), | {COL("1;30"), COL("0;39"), COL("0;39"), COL("0;39"), | |||
COL("0;32"), COL("1;39"), COL("1;39")}; | COL("0;32"), COL("1;39"), COL("1;39")}; | |||
#define FIELD_COLOUR COL("34;1") | #define FIELD_COLOR COL("34;1") | |||
static const char **colors = def_colors; | ||||
int | ||||
jq_set_colors(const char *c) | ||||
{ | ||||
const char *e; | ||||
size_t i; | ||||
if (c == NULL) | ||||
return 1; | ||||
colors = def_colors; | ||||
memset(color_bufs, 0, sizeof(color_bufs)); | ||||
for (i = 0; i < sizeof(def_colors) / sizeof(def_colors[0]); i++) | ||||
color_bufps[i] = def_colors[i]; | ||||
for (i = 0; i < sizeof(def_colors) / sizeof(def_colors[0]) && *c != '\0'; i++, | ||||
c = e) { | ||||
if ((e = strchr(c, ':')) == NULL) | ||||
e = c + strlen(c); | ||||
if ((size_t)(e - c) > sizeof(color_bufs[i]) - 4 /* ESC [ m NUL */) | ||||
return 0; | ||||
color_bufs[i][0] = ESC[0]; | ||||
color_bufs[i][1] = '['; | ||||
(void) strncpy(&color_bufs[i][2], c, e - c); | ||||
if (strspn(&color_bufs[i][2], "0123456789;") < strlen(&color_bufs[i][2])) | ||||
return 0; | ||||
color_bufs[i][2 + (e - c)] = 'm'; | ||||
color_bufps[i] = color_bufs[i]; | ||||
if (e[0] == ':') | ||||
e++; | ||||
} | ||||
colors = color_bufps; | ||||
return 1; | ||||
} | ||||
static void put_buf(const char *s, int len, FILE *fout, jv *strout, int is_tty) { | static void put_buf(const char *s, int len, FILE *fout, jv *strout, int is_tty) { | |||
if (strout) { | if (strout) { | |||
*strout = jv_string_append_buf(*strout, s, len); | *strout = jv_string_append_buf(*strout, s, len); | |||
} else { | } else { | |||
#ifdef WIN32 | #ifdef WIN32 | |||
/* See util.h */ | /* See util.h */ | |||
if (is_tty) | if (is_tty) { | |||
WriteFile((HANDLE)_get_osfhandle(fileno(fout)), s, len, NULL, NULL); | wchar_t *ws; | |||
else | size_t wl; | |||
if (len == -1) | ||||
len = strlen(s); | ||||
wl = MultiByteToWideChar(CP_UTF8, 0, s, len, NULL, 0); | ||||
ws = jv_mem_calloc((wl + 1), sizeof(*ws)); | ||||
if (!ws) | ||||
return; | ||||
wl = MultiByteToWideChar(CP_UTF8, 0, s, len, ws, wl + 1); | ||||
ws[wl] = 0; | ||||
WriteConsoleW((HANDLE)_get_osfhandle(fileno(fout)), ws, wl, NULL, NULL); | ||||
free(ws); | ||||
} else | ||||
fwrite(s, 1, len, fout); | fwrite(s, 1, len, fout); | |||
#else | #else | |||
fwrite(s, 1, len, fout); | fwrite(s, 1, len, fout); | |||
#endif | #endif | |||
} | } | |||
} | } | |||
static void put_char(char c, FILE* fout, jv* strout, int T) { | static void put_char(char c, FILE* fout, jv* strout, int T) { | |||
put_buf(&c, 1, fout, strout, T); | put_buf(&c, 1, fout, strout, T); | |||
} | } | |||
skipping to change at line 118 | skipping to change at line 169 | |||
} | } | |||
} else { | } else { | |||
if (ascii_only) { | if (ascii_only) { | |||
unicode_escape = 1; | unicode_escape = 1; | |||
} else { | } else { | |||
put_buf(cstart, i - cstart, F, S, T); | put_buf(cstart, i - cstart, F, S, T); | |||
} | } | |||
} | } | |||
if (unicode_escape) { | if (unicode_escape) { | |||
if (c <= 0xffff) { | if (c <= 0xffff) { | |||
sprintf(buf, "\\u%04x", c); | snprintf(buf, sizeof(buf), "\\u%04x", c); | |||
} else { | } else { | |||
c -= 0x10000; | c -= 0x10000; | |||
sprintf(buf, "\\u%04x\\u%04x", | snprintf(buf, sizeof(buf), "\\u%04x\\u%04x", | |||
0xD800 | ((c & 0xffc00) >> 10), | 0xD800 | ((c & 0xffc00) >> 10), | |||
0xDC00 | (c & 0x003ff)); | 0xDC00 | (c & 0x003ff)); | |||
} | } | |||
put_str(buf, F, S, T); | put_str(buf, F, S, T); | |||
} | } | |||
} | } | |||
assert(c != -1); | assert(c != -1); | |||
put_char('"', F, S, T); | put_char('"', F, S, T); | |||
} | } | |||
static void put_refcnt(struct dtoa_context* C, int refcnt, FILE *F, jv* S, int T ){ | static void put_refcnt(struct dtoa_context* C, int refcnt, FILE *F, jv* S, int T ){ | |||
char buf[JVP_DTOA_FMT_MAX_LEN]; | char buf[JVP_DTOA_FMT_MAX_LEN]; | |||
put_char(' ', F, S, T); | put_char(' ', F, S, T); | |||
put_char('(', F, S, T); | put_char('(', F, S, T); | |||
put_str(jvp_dtoa_fmt(C, buf, refcnt), F, S, T); | put_str(jvp_dtoa_fmt(C, buf, refcnt), F, S, T); | |||
put_char(')', F, S, T); | put_char(')', F, S, T); | |||
} | } | |||
static void jv_dump_term(struct dtoa_context* C, jv x, int flags, int indent, FI LE* F, jv* S) { | static void jv_dump_term(struct dtoa_context* C, jv x, int flags, int indent, FI LE* F, jv* S) { | |||
char buf[JVP_DTOA_FMT_MAX_LEN]; | char buf[JVP_DTOA_FMT_MAX_LEN]; | |||
const char* colour = 0; | const char* color = 0; | |||
double refcnt = (flags & JV_PRINT_REFCOUNT) ? jv_get_refcnt(x) - 1 : -1; | double refcnt = (flags & JV_PRINT_REFCOUNT) ? jv_get_refcnt(x) - 1 : -1; | |||
if (flags & JV_PRINT_COLOUR) { | if (flags & JV_PRINT_COLOR) { | |||
for (unsigned i=0; i<sizeof(colour_kinds)/sizeof(colour_kinds[0]); i++) { | for (unsigned i=0; i<sizeof(color_kinds)/sizeof(color_kinds[0]); i++) { | |||
if (jv_get_kind(x) == colour_kinds[i]) { | if (jv_get_kind(x) == color_kinds[i]) { | |||
colour = colours[i]; | color = colors[i]; | |||
put_str(colour, F, S, flags & JV_PRINT_ISATTY); | put_str(color, F, S, flags & JV_PRINT_ISATTY); | |||
break; | break; | |||
} | } | |||
} | } | |||
} | } | |||
switch (jv_get_kind(x)) { | if (indent > MAX_PRINT_DEPTH) { | |||
put_str("<skipped: too deep>", F, S, flags & JV_PRINT_ISATTY); | ||||
} else switch (jv_get_kind(x)) { | ||||
default: | default: | |||
case JV_KIND_INVALID: | case JV_KIND_INVALID: | |||
if (flags & JV_PRINT_INVALID) { | if (flags & JV_PRINT_INVALID) { | |||
jv msg = jv_invalid_get_msg(jv_copy(x)); | jv msg = jv_invalid_get_msg(jv_copy(x)); | |||
if (jv_get_kind(msg) == JV_KIND_STRING) { | if (jv_get_kind(msg) == JV_KIND_STRING) { | |||
put_str("<invalid:", F, S, flags & JV_PRINT_ISATTY); | put_str("<invalid:", F, S, flags & JV_PRINT_ISATTY); | |||
jvp_dump_string(msg, flags | JV_PRINT_ASCII, F, S, flags & JV_PRINT_ISAT TY); | jvp_dump_string(msg, flags | JV_PRINT_ASCII, F, S, flags & JV_PRINT_ISAT TY); | |||
put_str(">", F, S, flags & JV_PRINT_ISATTY); | put_str(">", F, S, flags & JV_PRINT_ISATTY); | |||
} else { | } else { | |||
put_str("<invalid>", F, S, flags & JV_PRINT_ISATTY); | put_str("<invalid>", F, S, flags & JV_PRINT_ISATTY); | |||
skipping to change at line 216 | skipping to change at line 269 | |||
jv_array_foreach(x, i, elem) { | jv_array_foreach(x, i, elem) { | |||
if (i!=0) { | if (i!=0) { | |||
if (flags & JV_PRINT_PRETTY) { | if (flags & JV_PRINT_PRETTY) { | |||
put_str(",\n", F, S, flags & JV_PRINT_ISATTY); | put_str(",\n", F, S, flags & JV_PRINT_ISATTY); | |||
put_indent(indent + 1, flags, F, S, flags & JV_PRINT_ISATTY); | put_indent(indent + 1, flags, F, S, flags & JV_PRINT_ISATTY); | |||
} else { | } else { | |||
put_str(",", F, S, flags & JV_PRINT_ISATTY); | put_str(",", F, S, flags & JV_PRINT_ISATTY); | |||
} | } | |||
} | } | |||
jv_dump_term(C, elem, flags, indent + 1, F, S); | jv_dump_term(C, elem, flags, indent + 1, F, S); | |||
if (colour) put_str(colour, F, S, flags & JV_PRINT_ISATTY); | if (color) put_str(color, F, S, flags & JV_PRINT_ISATTY); | |||
} | } | |||
if (flags & JV_PRINT_PRETTY) { | if (flags & JV_PRINT_PRETTY) { | |||
put_char('\n', F, S, flags & JV_PRINT_ISATTY); | put_char('\n', F, S, flags & JV_PRINT_ISATTY); | |||
put_indent(indent, flags, F, S, flags & JV_PRINT_ISATTY); | put_indent(indent, flags, F, S, flags & JV_PRINT_ISATTY); | |||
} | } | |||
if (colour) put_str(colour, F, S, flags & JV_PRINT_ISATTY); | if (color) put_str(color, F, S, flags & JV_PRINT_ISATTY); | |||
put_char(']', F, S, flags & JV_PRINT_ISATTY); | put_char(']', F, S, flags & JV_PRINT_ISATTY); | |||
if (flags & JV_PRINT_REFCOUNT) | if (flags & JV_PRINT_REFCOUNT) | |||
put_refcnt(C, refcnt, F, S, flags & JV_PRINT_ISATTY); | put_refcnt(C, refcnt, F, S, flags & JV_PRINT_ISATTY); | |||
break; | break; | |||
} | } | |||
case JV_KIND_OBJECT: { | case JV_KIND_OBJECT: { | |||
if (jv_object_length(jv_copy(x)) == 0) { | if (jv_object_length(jv_copy(x)) == 0) { | |||
put_str("{}", F, S, flags & JV_PRINT_ISATTY); | put_str("{}", F, S, flags & JV_PRINT_ISATTY); | |||
break; | break; | |||
} | } | |||
skipping to change at line 275 | skipping to change at line 328 | |||
} | } | |||
if (!first) { | if (!first) { | |||
if (flags & JV_PRINT_PRETTY){ | if (flags & JV_PRINT_PRETTY){ | |||
put_str(",\n", F, S, flags & JV_PRINT_ISATTY); | put_str(",\n", F, S, flags & JV_PRINT_ISATTY); | |||
put_indent(indent + 1, flags, F, S, flags & JV_PRINT_ISATTY); | put_indent(indent + 1, flags, F, S, flags & JV_PRINT_ISATTY); | |||
} else { | } else { | |||
put_str(",", F, S, flags & JV_PRINT_ISATTY); | put_str(",", F, S, flags & JV_PRINT_ISATTY); | |||
} | } | |||
} | } | |||
if (colour) put_str(COLRESET, F, S, flags & JV_PRINT_ISATTY); | if (color) put_str(COLRESET, F, S, flags & JV_PRINT_ISATTY); | |||
first = 0; | first = 0; | |||
if (colour) put_str(FIELD_COLOUR, F, S, flags & JV_PRINT_ISATTY); | if (color) put_str(FIELD_COLOR, F, S, flags & JV_PRINT_ISATTY); | |||
jvp_dump_string(key, flags & JV_PRINT_ASCII, F, S, flags & JV_PRINT_ISATTY ); | jvp_dump_string(key, flags & JV_PRINT_ASCII, F, S, flags & JV_PRINT_ISATTY ); | |||
jv_free(key); | jv_free(key); | |||
if (colour) put_str(COLRESET, F, S, flags & JV_PRINT_ISATTY); | if (color) put_str(COLRESET, F, S, flags & JV_PRINT_ISATTY); | |||
if (colour) put_str(colour, F, S, flags & JV_PRINT_ISATTY); | if (color) put_str(color, F, S, flags & JV_PRINT_ISATTY); | |||
put_str((flags & JV_PRINT_PRETTY) ? ": " : ":", F, S, flags & JV_PRINT_ISA TTY); | put_str((flags & JV_PRINT_PRETTY) ? ": " : ":", F, S, flags & JV_PRINT_ISA TTY); | |||
if (colour) put_str(COLRESET, F, S, flags & JV_PRINT_ISATTY); | if (color) put_str(COLRESET, F, S, flags & JV_PRINT_ISATTY); | |||
jv_dump_term(C, value, flags, indent + 1, F, S); | jv_dump_term(C, value, flags, indent + 1, F, S); | |||
if (colour) put_str(colour, F, S, flags & JV_PRINT_ISATTY); | if (color) put_str(color, F, S, flags & JV_PRINT_ISATTY); | |||
} | } | |||
if (flags & JV_PRINT_PRETTY) { | if (flags & JV_PRINT_PRETTY) { | |||
put_char('\n', F, S, flags & JV_PRINT_ISATTY); | put_char('\n', F, S, flags & JV_PRINT_ISATTY); | |||
put_indent(indent, flags, F, S, flags & JV_PRINT_ISATTY); | put_indent(indent, flags, F, S, flags & JV_PRINT_ISATTY); | |||
} | } | |||
if (colour) put_str(colour, F, S, flags & JV_PRINT_ISATTY); | if (color) put_str(color, F, S, flags & JV_PRINT_ISATTY); | |||
put_char('}', F, S, flags & JV_PRINT_ISATTY); | put_char('}', F, S, flags & JV_PRINT_ISATTY); | |||
if (flags & JV_PRINT_REFCOUNT) | if (flags & JV_PRINT_REFCOUNT) | |||
put_refcnt(C, refcnt, F, S, flags & JV_PRINT_ISATTY); | put_refcnt(C, refcnt, F, S, flags & JV_PRINT_ISATTY); | |||
} | } | |||
} | } | |||
jv_free(x); | jv_free(x); | |||
if (colour) { | if (color) { | |||
put_str(COLRESET, F, S, flags & JV_PRINT_ISATTY); | put_str(COLRESET, F, S, flags & JV_PRINT_ISATTY); | |||
} | } | |||
} | } | |||
void jv_dumpf(jv x, FILE *f, int flags) { | void jv_dumpf(jv x, FILE *f, int flags) { | |||
struct dtoa_context C; | struct dtoa_context C; | |||
jvp_dtoa_context_init(&C); | jvp_dtoa_context_init(&C); | |||
jv_dump_term(&C, x, flags, 0, f, 0); | jv_dump_term(&C, x, flags, 0, f, 0); | |||
jvp_dtoa_context_free(&C); | jvp_dtoa_context_free(&C); | |||
} | } | |||
void jv_dump(jv x, int flags) { | void jv_dump(jv x, int flags) { | |||
jv_dumpf(x, stdout, flags); | jv_dumpf(x, stdout, flags); | |||
} | } | |||
/* This one is nice for use in debuggers */ | /* This one is nice for use in debuggers */ | |||
void jv_show(jv x, int flags) { | void jv_show(jv x, int flags) { | |||
if (flags == -1) | if (flags == -1) | |||
flags = JV_PRINT_PRETTY | JV_PRINT_COLOUR | JV_PRINT_INDENT_FLAGS(2); | flags = JV_PRINT_PRETTY | JV_PRINT_COLOR | JV_PRINT_INDENT_FLAGS(2); | |||
jv_dumpf(jv_copy(x), stderr, flags | JV_PRINT_INVALID); | jv_dumpf(jv_copy(x), stderr, flags | JV_PRINT_INVALID); | |||
fflush(stderr); | fflush(stderr); | |||
} | } | |||
jv jv_dump_string(jv x, int flags) { | jv jv_dump_string(jv x, int flags) { | |||
struct dtoa_context C; | struct dtoa_context C; | |||
jvp_dtoa_context_init(&C); | jvp_dtoa_context_init(&C); | |||
jv s = jv_string(""); | jv s = jv_string(""); | |||
jv_dump_term(&C, x, flags, 0, 0, &s); | jv_dump_term(&C, x, flags, 0, 0, &s); | |||
jvp_dtoa_context_free(&C); | jvp_dtoa_context_free(&C); | |||
End of changes. 22 change blocks. | ||||
27 lines changed or deleted | 81 lines changed or added |