jshn: add functionality to read big JSON
The existing read functionality feeds the complete JSON to jshn as a cmdline argument, leading to `-ash: jshn: Argument list too long` errors for JSONs bigger than ca. 100KB. This commit adds the ability to read the JSON directly from a file if wanted, removing this shell-imposed size limit. Tested on x86-64 and ar71xx. An mmap()-based solution was also evaluated, but found to make no performance difference on either platform. Signed-off-by: Christian Beier <dontmind@freeshell.org>
This commit is contained in:
parent
1c08e80313
commit
9c4aeda962
2 changed files with 37 additions and 2 deletions
35
jshn.c
35
jshn.c
|
@ -25,6 +25,8 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
|
||||||
#include "avl.h"
|
#include "avl.h"
|
||||||
|
@ -305,7 +307,7 @@ out:
|
||||||
|
|
||||||
static int usage(const char *progname)
|
static int usage(const char *progname)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: %s [-n] [-i] -r <message>|-w\n", progname);
|
fprintf(stderr, "Usage: %s [-n] [-i] -r <message>|-R <file>|-w\n", progname);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,6 +340,10 @@ int main(int argc, char **argv)
|
||||||
struct env_var *vars;
|
struct env_var *vars;
|
||||||
int i;
|
int i;
|
||||||
int ch;
|
int ch;
|
||||||
|
int fd;
|
||||||
|
struct stat sb;
|
||||||
|
char *fbuf;
|
||||||
|
int ret;
|
||||||
|
|
||||||
avl_init(&env_vars, avl_strcmp_var, false, NULL);
|
avl_init(&env_vars, avl_strcmp_var, false, NULL);
|
||||||
for (i = 0; environ[i]; i++);
|
for (i = 0; environ[i]; i++);
|
||||||
|
@ -359,7 +365,7 @@ int main(int argc, char **argv)
|
||||||
avl_insert(&env_vars, &vars[i].avl);
|
avl_insert(&env_vars, &vars[i].avl);
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((ch = getopt(argc, argv, "p:nir:w")) != -1) {
|
while ((ch = getopt(argc, argv, "p:nir:R:w")) != -1) {
|
||||||
switch(ch) {
|
switch(ch) {
|
||||||
case 'p':
|
case 'p':
|
||||||
var_prefix = optarg;
|
var_prefix = optarg;
|
||||||
|
@ -367,6 +373,31 @@ int main(int argc, char **argv)
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
return jshn_parse(optarg);
|
return jshn_parse(optarg);
|
||||||
|
case 'R':
|
||||||
|
if ((fd = open(optarg, O_RDONLY)) == -1) {
|
||||||
|
fprintf(stderr, "Error opening %s\n", optarg);
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
if (fstat(fd, &sb) == -1) {
|
||||||
|
fprintf(stderr, "Error getting size of %s\n", optarg);
|
||||||
|
close(fd);
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
if (!(fbuf = malloc(sb.st_size))) {
|
||||||
|
fprintf(stderr, "Error allocating memory for %s\n", optarg);
|
||||||
|
close(fd);
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
if (read(fd, fbuf, sb.st_size) != sb.st_size) {
|
||||||
|
fprintf(stderr, "Error reading %s\n", optarg);
|
||||||
|
free(fbuf);
|
||||||
|
close(fd);
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
ret = jshn_parse(fbuf);
|
||||||
|
free(fbuf);
|
||||||
|
close(fd);
|
||||||
|
return ret;
|
||||||
case 'w':
|
case 'w':
|
||||||
return jshn_format(no_newline, indent);
|
return jshn_format(no_newline, indent);
|
||||||
case 'n':
|
case 'n':
|
||||||
|
|
|
@ -180,6 +180,10 @@ json_load() {
|
||||||
eval "`jshn -r "$1"`"
|
eval "`jshn -r "$1"`"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
json_load_file() {
|
||||||
|
eval "`jshn -R "$1"`"
|
||||||
|
}
|
||||||
|
|
||||||
json_dump() {
|
json_dump() {
|
||||||
jshn "$@" ${JSON_PREFIX:+-p "$JSON_PREFIX"} -w
|
jshn "$@" ${JSON_PREFIX:+-p "$JSON_PREFIX"} -w
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue