Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Page
Library
Module
Module type
Parameter
Class
Class type
Source
j.ml1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257(*********************************************************************************) (* OCaml-RDF *) (* *) (* Copyright (C) 2012-2024 Institut National de Recherche en Informatique *) (* et en Automatique. All rights reserved. *) (* *) (* This program is free software; you can redistribute it and/or modify *) (* it under the terms of the GNU Lesser General Public License version *) (* 3 as published by the Free Software Foundation. *) (* *) (* This program is distributed in the hope that it will be useful, *) (* but WITHOUT ANY WARRANTY; without even the implied warranty of *) (* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) (* GNU General Public License for more details. *) (* *) (* You should have received a copy of the GNU General Public License *) (* along with this program; if not, write to the Free Software *) (* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA *) (* 02111-1307 USA *) (* *) (* Contact: Maxence.Guesdon@inria.fr *) (* *) (*********************************************************************************) (** JSON documents. *) type loc = int * int (** 1-based line * 0-based column *) type range = loc * loc let string_of_range ((l1,c1), (l2,c2)) = if l1 = l2 then Printf.sprintf "line %d, characters %d-%d" l1 c1 c2 else Printf.sprintf "line %d, character %d to line %d, character %d" l1 c1 l2 c2 type 'a ranged = { loc : range option ; data : 'a } let ranged ?loc data = { loc ; data } type error = .. type error += Invalid_json of string exception Error of error let error e = raise (Error e) type key = string ranged type map = (key * json) list and json_t = [ | `Obj of (key * json) list | `List of json list | `String of string | `Bool of bool | `Float of float | `Null ] and json = json_t ranged let json ?loc data = { loc ; data } exception Escape of ((int * int) * (int * int)) * Jsonm.error let string_of_error range err = let b = Buffer.create 256 in Buffer.add_string b (string_of_range range) ; Buffer.add_string b ": "; let fmt = Format.formatter_of_buffer b in Jsonm.pp_error fmt err; Format.pp_print_flush fmt (); Buffer.contents b let dec d = match Jsonm.decode d with | `Lexeme l -> l | `Error e -> raise (Escape (Jsonm.decoded_range d, e)) | `End | `Await -> assert false let loc_start d = fst (Jsonm.decoded_range d) let loc_end d = snd (Jsonm.decoded_range d) let range d = Jsonm.decoded_range d let rec value v k d = match v with | `Os -> obj (loc_start d) [] k d | `As -> arr (loc_start d) [] k d | `Null | `Bool _ | `String _ | `Float _ as v -> let v = json ~loc: (range d) v in k v d | _ -> assert false and arr loc_start vs k d = match dec d with | `Ae -> let loc = (loc_start, loc_end d) in let v = json ~loc (`List (List.rev vs)) in k v d | v -> value v (fun v -> arr loc_start (v :: vs) k) d and obj loc_start ms k d = match dec d with | `Oe -> let loc = (loc_start, loc_end d) in let v = json ~loc (`Obj (List.rev ms)) in k v d | `Name n -> let key = ranged n in value (dec d) (fun v -> obj loc_start ((key, v) :: ms) k) d | _ -> assert false let json_of_src ?encoding (src : [`Channel of in_channel | `String of string]) = let d = Jsonm.decoder ?encoding src in try Ok (value (dec d) (fun v _ -> v) d) with | Escape (r, e) -> Error (r, e) let enc e l = ignore (Jsonm.encode e (`Lexeme l)) let rec value v k e = match v with | `List vs -> arr vs k e | `Obj ms -> obj ms k e | `Null | `Bool _ | `Float _ | `String _ as v -> enc e v; k e and arr vs k e = enc e `As; arr_vs vs k e and arr_vs vs k e = match vs with | v :: vs' -> value v.data (arr_vs vs' k) e | [] -> enc e `Ae; k e and obj ms k e = enc e `Os; obj_ms ms k e and obj_ms ms k e = match ms with | (key, v) :: ms -> enc e (`Name key.data); value v.data (obj_ms ms k) e | [] -> enc e `Oe; k e let json_to_dst ~minify (dst : [`Channel of out_channel | `Buffer of Buffer.t ]) (json : json) = let e = Jsonm.encoder ~minify dst in let finish e = ignore (Jsonm.encode e `End) in match json.data with `List _ | `Obj _ as json -> value json finish e | _ -> invalid_arg "invalid json text" let from_string ?encoding s = json_of_src ?encoding (`String s) let from_string_exn ?encoding s = match from_string ?encoding s with | Ok x -> x | Error (range, e) -> error (Invalid_json (string_of_error range e)) let to_string ?(minify=false) json = let b = Buffer.create 256 in (match json.data with | `Null -> Buffer.add_string b "null" | `Bool true -> Buffer.add_string b "true" | `Bool false ->Buffer.add_string b "false" | `Float f -> Printf.bprintf b "%E" f | `String str -> Printf.bprintf b "%S" str | x -> json_to_dst ~minify (`Buffer b) json ); Buffer.contents b let pp ppf j = Format.fprintf ppf "%s" (to_string j) let ppm ppf j = Format.fprintf ppf "%s" (to_string ~minify:true j) let map_get = let rec find k = function | [] -> None | ({ data }, v) :: _ when data = k -> Some v | _ :: q -> find k q in fun fields k -> find k (List.rev fields) let (-->>) = map_get let (-->) fields name = Option.map (fun { data } -> data) (fields-->>name) let (-?>) json name = match json.data with | `Obj fields -> fields-->>name | _ -> None let string ?loc str = json ?loc (`String str) let string_of_opt ?loc str = string ?loc (match str with None -> "None" | Some str -> str) let list ?loc l = json ?loc (`List l) let obj ?loc fields = json ?loc (`Obj fields) let null = json `Null let bool ?loc b = json ?loc (`Bool b) let float ?loc f = json ?loc (`Float f) let rec compare { data = data1 } { data = data2 } = match data1, data2 with | `Null, `Null -> 0 | `Null, _ -> -1 | _, `Null -> 1 | `Float f1, `Float f2 -> Float.compare f1 f2 | `Float _, _ -> -1 | _, `Float _ -> 1 | `Bool b1, `Bool b2 -> Bool.compare b1 b2 | `Bool _, _ -> -1 | _, `Bool _ -> 1 | `String s1, `String s2 -> String.compare s1 s2 | `String _, _ -> -1 | _, `String _ -> 1 | `List l1, `List l2 -> List.compare compare l1 l2 | `List _, _ -> -1 | _, `List _ -> 1 | `Obj o1, `Obj o2 -> map_compare o1 o2 and key_value_compare (k1, v1) (k2, v2) = match String.compare k1.data k2.data with | 0 -> compare v1 v2 | x -> x and map_compare map1 map2 = let map1 = sort_map map1 and map2 = sort_map map2 in List.compare key_value_compare map1 map2 and sort_map map = List.sort key_value_compare map let rec normalize (j:json) = match j.data with | `List l -> list ?loc:j.loc (List.map normalize l) | `Obj map -> let map = List.map (fun (k,v) -> (k, normalize v)) map in obj ?loc:j.loc (sort_map map) | _ -> j let equal j1 j2 = compare j1 j2 = 0 let to_array j = match j.data with | `List _ -> j | _ -> list [j] let values j = match j.data with | `List l -> l | _ -> [j] let is_scalar j = match j.data with | `Obj _ | `List _ | `Null -> false | _ -> true let is_string_array = let pred = function { data = `String _ } -> true | _ -> false in fun j -> match j.data with | `List l -> List.for_all pred l | _ -> false let string_of_json_opt = function None -> "None" | Some j -> to_string j let map_add_value = let rec iter acc k v = function | [] -> (ranged k, v) :: acc | (k1, _) :: q when k1.data = k -> acc @ ((k1, v) :: q) | h :: q -> iter (h::acc) k v q in fun map k v -> iter [] k v map let map_remove_value map k = List.filter (fun (k1, _) -> k1.data <> k) map let map_pp ppf map = Format.fprintf ppf "%s" (to_string (obj map)) let opt_map_pp ppf = function | None -> Format.fprintf ppf "None" | Some map -> map_pp ppf map