Compare commits

...
2 Commits
Author SHA1 Message Date
liquidaty 80e9bea3a8 Add --strip-comments option 2023-07-09 21:27:08 -05:00
liquidaty b2e7eaff99 Allow, and strip, JSON comments (#, // or /*) 2023-07-09 21:24:48 -05:00
5 changed files with 81 additions and 7 deletions

No files matched your search

+3 -2
View File
@@ -132,7 +132,7 @@ endif
### Tests (make check)
TESTS = tests/optionaltest tests/mantest tests/jqtest tests/onigtest tests/shtest tests/utf8test tests/base64test
TESTS = tests/optionaltest tests/mantest tests/jqtest tests/onigtest tests/shtest tests/utf8test tests/base64test tests/commenttest
TESTS_ENVIRONMENT = NO_VALGRIND=$(NO_VALGRIND)
# This is a magic make variable that causes it to treat tests/man.test as a
@@ -215,7 +215,8 @@ EXTRA_DIST = $(DOC_FILES) $(man_MANS) $(TESTS) $(TEST_LOG_COMPILER) \
tests/optional.test tests/optionaltest \
tests/utf8-truncate.jq tests/utf8test \
tests/base64.test tests/base64test \
tests/jq-f-test.sh tests/shtest
tests/jq-f-test.sh tests/shtest \
tests/commenttest
DISTCHECK_CONFIGURE_FLAGS=--disable-maintainer-mode --with-oniguruma=builtin
+1
View File
@@ -223,6 +223,7 @@ enum {
JV_PARSE_SEQ = 1,
JV_PARSE_STREAMING = 2,
JV_PARSE_STREAM_ERRORS = 4,
JV_PARSE_STRIP_COMMENTS = 8
};
jv jv_parse(const char* string);
+57 -5
View File
@@ -31,6 +31,7 @@ enum last_seen {
};
struct jv_parser {
pfunc (*scan)(struct jv_parser* p, char ch, jv* out);
const char* curr_buf;
int curr_buf_length;
int curr_buf_pos;
@@ -65,9 +66,14 @@ struct jv_parser {
unsigned int last_ch_was_ws:1;
};
static pfunc scan_json(struct jv_parser* p, char ch, jv* out);
static pfunc scan_line_comment(struct jv_parser* p, char ch, jv* out);
static pfunc scan_slash_comment(struct jv_parser* p, char ch, jv* out);
static pfunc scan_c_comment(struct jv_parser* p, char ch, jv* out);
static void parser_init(struct jv_parser* p, int flags) {
p->flags = flags;
p->scan = scan_json;
if ((p->flags & JV_PARSE_STREAMING)) {
p->path = jv_array();
} else {
@@ -613,12 +619,42 @@ static int stream_is_top_num(struct jv_parser* p) {
#define is_top_num(p) \
(((p)->flags & JV_PARSE_STREAMING) ? stream_is_top_num((p)) : parse_is_top_num((p)))
static pfunc scan(struct jv_parser* p, char ch, jv* out) {
p->column++;
if (ch == '\n') {
p->line++;
p->column = 0;
static pfunc scan_line_comment(struct jv_parser* p, char ch, jv* out) {
if(ch == '\n')
p->scan = scan_json;
return OK;
}
static pfunc scan_c_comment_close(struct jv_parser* p, char ch, jv* out) {
if(ch == '/') {
p->scan = scan_json;
} else {
p->scan = scan_c_comment;
}
return OK;
}
static pfunc scan_c_comment(struct jv_parser* p, char ch, jv* out) {
if(ch == '*') {
p->scan = scan_c_comment_close;
}
return OK;
}
static pfunc scan_slash_comment(struct jv_parser* p, char ch, jv* out) {
if(ch == '/') {
p->scan = scan_line_comment;
return OK;
}
if(ch == '*') {
p->scan = scan_c_comment;
return OK;
}
return "Incomplete comment token; slash must be followed by another slash or asterisk";
}
static pfunc scan_json(struct jv_parser* p, char ch, jv* out) {
if (ch == '\036' /* ASCII RS; see draft-ietf-json-sequence-07 */) {
if (check_truncation(p)) {
if (check_literal(p) == 0 && is_top_num(p))
@@ -635,9 +671,15 @@ static pfunc scan(struct jv_parser* p, char ch, jv* out) {
*out = jv_invalid();
return OK;
}
presult answer = 0;
p->last_ch_was_ws = 0;
if (p->st == JV_PARSER_NORMAL) {
if(ch == '/' && (p->flags & JV_PARSE_STRIP_COMMENTS)) {
p->scan = scan_slash_comment;
return OK;
}
chclass cls = classify(ch);
if (cls == WHITESPACE)
p->last_ch_was_ws = 1;
@@ -678,6 +720,16 @@ static pfunc scan(struct jv_parser* p, char ch, jv* out) {
return answer;
}
static pfunc scan(struct jv_parser* p, char ch, jv* out) {
p->column++;
if (ch == '\n') {
p->line++;
p->column = 0;
}
return p->scan(p, ch, out);
}
struct jv_parser* jv_parser_new(int flags) {
struct jv_parser* p = jv_mem_alloc(sizeof(struct jv_parser));
parser_init(p, flags);
+5
View File
@@ -81,6 +81,7 @@ static void usage(int code, int keep_it_short) {
" -M monochrome (don't colorize JSON);\n"
" -S sort keys of objects on output;\n"
" --tab use tabs for indentation;\n"
" --strip-comments accept and strip comments from input;\n"
" --arg a v set variable $a to value <v>;\n"
" --argjson a v set variable $a to JSON value <v>;\n"
" --slurpfile a f set variable $a to an array of JSON texts read from <f>;\n"
@@ -454,6 +455,10 @@ int main(int argc, char* argv[]) {
parser_flags |= JV_PARSE_STREAMING;
continue;
}
if (isoption(argv[i], 0, "strip-comments", &short_opts)) {
parser_flags |= JV_PARSE_STRIP_COMMENTS;
continue;
}
if (isoption(argv[i], 0, "stream-errors", &short_opts)) {
parser_flags |= JV_PARSE_STREAM_ERRORS;
continue;
+15
View File
@@ -0,0 +1,15 @@
#!/bin/sh
. "${0%/*}/setup" "$@"
if [ "$(echo '{"hi":"there"/*comment*/}' | $VALGRIND $Q $JQ --strip-comments '.hi')" != '"there"' ]; then
echo "C-style comment test failed"
exit 1
fi
if [ "$(printf '{"hi"://comment\n"there"}' | $VALGRIND $Q $JQ --strip-comments '.hi')" != '"there"' ]; then
echo "C++-style comment test failed"
exit 1
fi
exit 0