[Pkg-libvirt-commits] [libguestfs] 52/179: mllib: improve JSON: more types, indented output style

Hilko Bengen bengen at moszumanska.debian.org
Fri Oct 31 19:08:05 UTC 2014


This is an automated email from the git hooks/post-receive script.

bengen pushed a commit to branch experimental
in repository libguestfs.

commit 901de75ff42f169880f5c2356483d30c1e1b04eb
Author: Pino Toscano <ptoscano at redhat.com>
Date:   Fri Oct 10 16:55:47 2014 +0200

    mllib: improve JSON: more types, indented output style
    
    Improve the homebrew JSON writer:
    - add more types (including also nested dictionaries and lists)
    - format in a compact way (single line), or indented (multilines)
---
 mllib/JSON.ml  | 118 ++++++++++++++++++++++++++++++++++++++++++++-------------
 mllib/JSON.mli |  16 ++++++--
 2 files changed, 104 insertions(+), 30 deletions(-)

diff --git a/mllib/JSON.ml b/mllib/JSON.ml
index 5e3a879..316b3f2 100644
--- a/mllib/JSON.ml
+++ b/mllib/JSON.ml
@@ -16,38 +16,102 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *)
 
-(* Poor man's JSON generator. *)
-
-open Printf
-
-open Common_utils
+(* Simple JSON generator. *)
 
 type field = string * json_t
-and json_t = String of string | Int of int
+and json_t =
+  | String of string
+  | Int of int
+  | Int64 of int64
+  | Bool of bool
+  | List of json_t list
+  | Dict of field list
 and doc = field list
 
+type output_format =
+  | Compact
+  | Indented
+
+
+let spaces_for_indent level =
+  let len = level * 2 in
+  let s = String.create len in
+  String.fill s 0 len ' ';
+  s
+
+let print_dict_after_start ~fmt ~indent ~size =
+  match size, fmt with
+    | 0, Compact -> ""
+    | _, Compact -> " "
+    | _, Indented -> "\n"
+
+let print_dict_before_end ~fmt ~indent ~size =
+  match size, fmt with
+    | 0, _ -> ""
+    | _, Compact -> " "
+    | _, Indented -> "\n"
+
+let print_indent ~fmt ~indent =
+  match fmt with
+  | Compact -> ""
+  | Indented -> spaces_for_indent indent
+
 (* JSON quoting. *)
-let json_quote str =
-  let str = replace_str str "\\" "\\\\" in
-  let str = replace_str str "\"" "\\\"" in
-  let str = replace_str str "'" "\\'" in
-  let str = replace_str str "\008" "\\b" in
-  let str = replace_str str "\012" "\\f" in
-  let str = replace_str str "\n" "\\n" in
-  let str = replace_str str "\r" "\\r" in
-  let str = replace_str str "\t" "\\t" in
-  let str = replace_str str "\011" "\\v" in
-  str
-
-let string_of_doc fields =
-  "{ " ^
-    String.concat ", " (
+let json_escape_string str =
+  let res = ref "" in
+  for i = 0 to String.length str - 1 do
+    res := !res ^ (match str.[i] with
+      | '"' -> "\\\""
+      | '\\' -> "\\\\"
+      | '\b' -> "\\b"
+      | '\n' -> "\\n"
+      | '\r' -> "\\r"
+      | '\t' -> "\\t"
+      | c -> String.make 1 c)
+  done;
+  !res
+
+let json_quote_string str =
+  "\"" ^ (json_escape_string str) ^ "\""
+
+let rec output_dict fields ~fmt ~indent =
+  let size = List.length fields in
+  let newlinesep =
+    match fmt with
+    | Compact -> ", "
+    | Indented -> ",\n" in
+  "{" ^ (print_dict_after_start ~fmt ~indent ~size) ^
+    String.concat newlinesep (
+      List.map (
+        fun (n, f) ->
+          (print_indent ~fmt ~indent:(indent + 1)) ^ (json_quote_string n)
+          ^ ": " ^ (output_field ~fmt ~indent f)
+      ) fields
+    )
+  ^ (print_dict_before_end ~fmt ~indent ~size) ^ (print_indent ~fmt ~indent) ^ "}"
+
+and output_list fields ~fmt ~indent =
+  let size = List.length fields in
+  let newlinesep =
+    match fmt with
+    | Compact -> ", "
+    | Indented -> ",\n" in
+  "[" ^ (print_dict_after_start ~fmt ~indent ~size) ^
+    String.concat newlinesep (
       List.map (
-        function
-        | (n, String v) ->
-          sprintf "\"%s\" : \"%s\"" n (json_quote v)
-        | (n, Int v) ->
-          sprintf "\"%s\" : %d" n v
+        fun f ->
+          (print_indent ~fmt ~indent:(indent + 1)) ^ (output_field ~fmt ~indent f)
       ) fields
     )
-  ^ " }"
+  ^ (print_dict_before_end ~fmt ~indent ~size) ^ (print_indent ~fmt ~indent) ^ "]"
+
+and output_field ~indent ~fmt = function
+  | String s -> json_quote_string s
+  | Int i -> string_of_int i
+  | Bool b -> if b then "true" else "false"
+  | Int64 i -> Int64.to_string i
+  | List l -> output_list ~indent:(indent + 1) ~fmt l
+  | Dict d -> output_dict ~indent:(indent + 1) ~fmt d
+
+let string_of_doc ?(fmt = Compact) fields =
+  output_dict fields ~fmt ~indent:0
diff --git a/mllib/JSON.mli b/mllib/JSON.mli
index 1e3a1b3..fbaffab 100644
--- a/mllib/JSON.mli
+++ b/mllib/JSON.mli
@@ -16,11 +16,21 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *)
 
-(** Poor man's JSON generator. *)
+(** Simple JSON generator. *)
 
 type field = string * json_t
-and json_t = String of string | Int of int
+and json_t =
+  | String of string
+  | Int of int
+  | Int64 of int64
+  | Bool of bool
+  | List of json_t list
+  | Dict of field list
 and doc = field list
 
-val string_of_doc : doc -> string
+type output_format =
+  | Compact
+  | Indented
+
+val string_of_doc : ?fmt:output_format -> doc -> string
   (** Serialize {!doc} object as a string. *)

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-libvirt/libguestfs.git



More information about the Pkg-libvirt-commits mailing list