shithub: riscv

Download patch

ref: a53ae2782a6e8b1996c1d5dea4190eb11d06d056
parent: f6e8b115d49e8aec463e3a495d53ee11031a4db6
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Tue Dec 22 13:12:56 EST 2015

libjson: added printing support (thanks spew)

--- a/sys/include/json.h
+++ b/sys/include/json.h
@@ -4,6 +4,8 @@
 typedef struct JSONEl JSONEl;
 typedef struct JSON JSON;
 
+#pragma varargck type "J" JSON*
+
 enum {
 	JSONNull,
 	JSONBool,
@@ -33,3 +35,5 @@
 void	jsonfree(JSON *);
 JSON*	jsonbyname(JSON *, char *);
 char*	jsonstr(JSON *);
+int	JSONfmt(Fmt*);
+void	JSONfmtinstall(void);
--- a/sys/man/2/json
+++ b/sys/man/2/json
@@ -40,10 +40,12 @@
 	};
 };
 
-JSON*	jsonparse(char *);
-void	jsonfree(JSON *);
-JSON*	jsonbyname(JSON *, char *);
-char*	jsonstr(JSON *);
+JSON*	jsonparse(char *s);
+void	jsonfree(JSON *j);
+JSON*	jsonbyname(JSON *j, char *s);
+char*	jsonstr(JSON *j);
+int	JSONfmt(Fmt *f)
+void	JSONfmtinstall(void);
 .EE
 .SH DESCRIPTION
 The
@@ -76,7 +78,7 @@
 member set to the key of the association.
 .P
 A json object is parsed by calling
-.B jsonparse
+.I jsonparse
 with a
 .B UTF-8
 string of the json encoded data. On success, a non-nil pointer to a
@@ -84,26 +86,41 @@
 .B JSON
 structure is returned.
 To free the parsed objects,
-.B jsonfree
+.I jsonfree
 has to be called.
 .P
 The
-.B jsonbyname
+.I jsonbyname
 function returns the associated value of a dictionary item.
 .P
 The function
-.B jsonstr
+.I jsonstr
 returns the string value of a json object or
 .B nil
 for any other object type.
+.P
+.I JSONfmt
+is a
+.IR print (2)
+formatting routine that prints a well-formatted JSON structure.
+It can be installed by hand but
+.I JSONfmtinstall
+installs it under the standard format character J. The header
+.B <json.h>
+contains a #pragma statement so the compiler can
+type-check uses of
+.B %J
+in
+.IR print (2)
+format strings.
 .SH SOURCE
 .B /sys/src/libjson
 .SH DIAGNOSTICS
 The functions
-.IB jsonparse ,
-.B jsonbyname
+.I jsonparse,
+.I jsonbyname
 and
-.B jsonstr
+.I jsonstr
 return
 .B nil
 on error and set an error string (see
--- a/sys/src/libjson/mkfile
+++ b/sys/src/libjson/mkfile
@@ -2,7 +2,8 @@
 
 LIB=/$objtype/lib/libjson.a
 OFILES=\
-	json.$O
+	json.$O\
+	printjson.$O
 
 HFILES=\
 	/sys/include/json.h
--- /dev/null
+++ b/sys/src/libjson/printjson.c
@@ -1,0 +1,93 @@
+#include <u.h>
+#include <libc.h>
+#include <json.h>
+
+static int printjson(Fmt*, JSON*, int);
+static int printarray(Fmt*, JSON*, int);
+static int printobject(Fmt*, JSON*, int);
+
+static int
+printarray(Fmt *f, JSON *j, int indent)
+{
+	JSONEl *jl;
+	int i, r;
+
+	if(j->first == nil){
+		return fmtprint(f, "[]");
+	}
+	r = fmtprint(f, "[\n");
+	for(jl = j->first; jl != nil; jl = jl->next){
+		for(i = 0; i < indent; i++)
+			r += fmtprint(f, "\t");
+		r += printjson(f, jl->val, indent);
+		r += fmtprint(f, "%s\n", jl->next != nil ? "," : "");
+	}
+	for(i = 0; i < indent-1; i++)
+		r += fmtprint(f, "\t");
+	r += fmtprint(f, "]");
+	return r;
+}
+
+static int
+printobject(Fmt *f, JSON *j, int indent)
+{
+	JSONEl *jl;
+	int i, r;
+
+	if(j->first == nil){
+		return fmtprint(f, "{}");
+	}
+	r = fmtprint(f, "{\n");
+	for(jl = j->first; jl != nil; jl = jl->next){
+		for(i = 0; i < indent; i++)
+			fmtprint(f, "\t");
+		r += fmtprint(f, "\"%s\": ", jl->name);
+		r += printjson(f, jl->val, indent);
+		r += fmtprint(f, "%s\n", jl->next != nil ? "," : "");
+	}
+	for(i = 0; i < indent-1; i++)
+		r += fmtprint(f, "\t");
+	r += fmtprint(f, "}");
+	return r;
+}
+
+static int
+printjson(Fmt *f, JSON *j, int indent)
+{
+	switch(j->t){
+	case JSONNull:
+		return fmtprint(f, "null");
+		break;
+	case JSONBool:
+		return fmtprint(f, "%s", j->n ? "true" : "false");
+		break;
+	case JSONNumber:
+		return fmtprint(f, "%f", j->n);
+		break;
+	case JSONString:
+		return fmtprint(f, "\"%s\"", j->s);
+		break;
+	case JSONArray:
+		return printarray(f, j, indent+1);
+		break;
+	case JSONObject:
+		return printobject(f, j, indent+1);
+		break;
+	}
+	return 0;
+}
+
+int
+JSONfmt(Fmt *f)
+{
+	JSON *j;
+
+	j = va_arg(f->args, JSON*);
+	return printjson(f, j, 0);
+}
+
+void
+JSONfmtinstall(void)
+{
+	fmtinstall('J', JSONfmt);
+}