shithub: json2awk

ref: f8d74ea182246209e30cb5e90e7697a5ad99a407
dir: /json2awk.c/

View raw version
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <json.h>

typedef struct Level Level;
struct Level {
	int	noquote;
	char	*name;
	Level	*next;
	Level	*prev;
};

Level *head = nil;
Level *tail = nil;

void
lappend(int q, char *s)
{
	Level *new;

	if((new = mallocz(sizeof(Level), 1)) == nil)
		sysfatal("mallocz: %r");
	new->noquote = !q;
	new->name = s;
	if(!head)
		head = new;
	if(tail)
		tail->next = new;
	new->prev = tail;
	tail = new;
}

void
lremove(void)
{
	void *v;

	v = tail;
	tail = tail->prev;
	free(v);
	if(tail == nil)
		head = nil;
	else
		tail->next = nil;
}

#pragma	varargck	type	"L"	Level*
int
Lfmt(Fmt *f)
{
	Level *l;

	l = va_arg(f->args, Level*);
	while(l != nil){
		if(l->noquote){
			if(fmtprint(f, "%s", l->name) < 0)
				return -1;
		}else
			if(fmtprint(f, "\"%s\"", l->name) < 0)
				return -1;
		
		if(l->next != nil && fmtprint(f, ", ") < 0)
				return -1;
		l = l->next;
	}
	return 0;
}

void
json2awk(JSON *j)
{
	JSONEl *e;
	char *s;
	int i;

	switch(j->t){
	case JSONArray:
		e = j->first;
		for(i = 0; e; i++){
			s = smprint("%d", i);
			lappend(0, s);
			json2awk(e->val);
			lremove();
			e = e->next;
			free(s);
		}
		break;
	case JSONObject:
		e = j->first;
		do{
			lappend(1, e->name);
			json2awk(e->val);
			lremove();
		}while(e = e->next);
		break;
	case JSONBool:
		print("json[%L] = %d;\n", head, (int)j->n);
		break;
	case JSONNumber:
		print("json[%L] = %g;\n", head, j->n);
		break;
	case JSONString:
		print("json[%L] = \"%s\";\n", head, j->s);
		break;
	case JSONNull:
		break;
	}
}

void
main(int argc, char **argv)
{
	Level *l, *ln;
	Biobuf *b;
	JSON *J;
	char *j;
	int fd;

	switch(argc){
	case 1:
		fd = 0;
		break;
	case 2:
		fd = open(argv[1], OREAD);
		break;
	default:
		fprint(2, "usage: json2awk [file]");
		exits("usage");
	}

	/* read it all into j */
	fmtinstall('L', Lfmt);
	b = Bfdopen(fd, OREAD);
	if((j = Brdstr(b, '\0', '\0')) == nil)
		exits(0);
	if((J = jsonparse(j)) == nil)
		sysfatal("jsonparse: %r");

	json2awk(J);

	jsonfree(J);
	free(j);
	free(b);
	for(l = head; l != nil; l = ln){
		ln = l->next;
		free(l);
	}

	exits(0);
}