123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414(* Js_of_ocaml library
* http://www.ocsigen.org/js_of_ocaml/
* Copyright Grégoire Henry 2010.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, with linking exception;
* either version 2.1 of the License, or (at your option) any later version.
*
* 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser 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.
*)(** Json **)open!Deriving_Json_importmoduleLexer=Deriving_Json_lexertype'at={write:Buffer.t->'a->unit;read:Lexer.lexbuf->'a}letmakewriteread={write;read}letreadt=t.readletwritet=t.writeletconverttf1f2={write=(funbufa->t.writebuf(f2a));read=(funbuf->f1(t.readbuf))}letto_stringtv=letbuf=Buffer.create50int.writebufv;Buffer.contentsbuf(*let to_channel t oc v =
let buf = Buffer.create 50 in
t.write buf v;
Buffer.output_buffer oc buf
*)letfrom_stringts=t.read(Lexer.init_lexer(Lexing.from_strings))(*
let from_channel t ic =
t.read (Lexer.init_lexer (Lexing.from_channel ic))
*)(** Deriver **)moduletypeJson_min=sigtypeavalwrite:Buffer.t->a->unitvalread:Lexer.lexbuf->aendmoduletypeJson_min'=sigtypeavalwrite:Buffer.t->a->unitvalread:Lexer.lexbuf->avalmatch_variant:[`Cstofint|`NCstofint]->boolvalread_variant:Lexer.lexbuf->[`Cstofint|`NCstofint]->aendmoduletypeJson_min''=sigtypeavalt:atendmoduletypeJson_converter=sigtypeatypebvalt:atvalfrom_:a->bvalto_:b->aendmoduletypeJson=sigtypeavalt:atvalwrite:Buffer.t->a->unitvalread:Lexer.lexbuf->avalto_string:a->string(* val to_channel: out_channel -> a -> unit *)valfrom_string:string->a(* val from_channel: in_channel -> a *)valmatch_variant:[`Cstofint|`NCstofint]->boolvalread_variant:Lexer.lexbuf->[`Cstofint|`NCstofint]->aendmoduleDefaults(J:Json_min):Jsonwithtypea=J.a=structincludeJlett={write;read}letto_stringv=to_stringtv(* let to_channel oc v = to_channel t oc v *)letfrom_strings=from_stringts(* let from_channel ic = from_channel t ic *)letmatch_variant_hash=assertfalseletread_variant_buf_hash=assertfalseendmoduleDefaults'(J:Json_min'):Jsonwithtypea=J.a=structincludeJlett={write;read}letto_stringv=to_stringtv(* let to_channel oc v = to_channel t oc v *)letfrom_strings=from_stringts(* let from_channel ic = from_channel t ic *)endmoduleDefaults''(J:Json_min''):Jsonwithtypea=J.a=structincludeJletread=t.readletwrite=t.writeletto_stringv=to_stringtv(* let to_channel oc v = to_channel t oc v *)letfrom_strings=from_stringts(* let from_channel ic = from_channel t ic *)letmatch_variant_hash=assertfalseletread_variant_buf_hash=assertfalseendmoduleConvert(J:Json_converter):Jsonwithtypea=J.b=structmoduleTmp:Jsonwithtypea=J.b=Defaults''(structtypea=J.blett=convertJ.tJ.from_J.to_end)includeTmpend(** Predefs *)moduleJson_undef(T:sigtypeaend)=Defaults(structtypea=T.aletwrite_buf_=failwith"Unimplemented"letread_buf=failwith"Unimplemented"end)moduleJson_char=Defaults(structtypea=charletwritebufferc=Buffer.add_stringbuffer(string_of_int(int_of_charc))letreadbuf=char_of_int(Lexer.read_bounded_int~max:255buf)end)moduleJson_bool=Defaults(structtypea=boolletwritebufferb=Buffer.add_charbuffer(ifbthen'1'else'0')letreadbuf=1=Lexer.read_tag_201bufend)moduleJson_unit=Defaults(structtypea=unitletwritebuffer()=Buffer.add_charbuffer'0'letreadbuf=ignore(Lexer.read_tag_10buf)end)moduleJson_int=Defaults(structtypea=intletwritebufferi=Printf.bprintfbuffer"%d"iletreadbuf=Lexer.read_intbufend)moduleJson_int32=Defaults(structtypea=int32letwritebufferi=Printf.bprintfbuffer"%ld"iletreadbuf=Lexer.read_int32bufend)moduleJson_int64=Defaults(structtypea=int64letmask24=Int64.of_int0xffffffletmask16=Int64.of_int0xffffletwritebufferi=Printf.bprintfbuffer"[255,%Ld,%Ld,%Ld]"(Int64.logandimask24)(Int64.logand(Int64.shift_righti24)mask24)(Int64.logand(Int64.shift_righti48)mask16)letreadbuf=Lexer.read_lbracketbuf;ignore(Lexer.read_tag_1255buf);Lexer.read_commabuf;leth1=Lexer.read_int64bufinLexer.read_commabuf;leth2=Int64.shift_left(Lexer.read_int64buf)24inLexer.read_commabuf;leth3=Int64.shift_left(Lexer.read_int64buf)48inLexer.read_rbracketbuf;Int64.logorh3(Int64.logorh2h1)end)moduleJson_nativeint=Json_undef(structtypea=nativeintend)(* module Json_num = Json_undef(struct type a = Num.num end) *)moduleJson_float=Defaults(structtypea=floatletwritebufferf=(* "%.15g" can be (much) shorter; "%.17g" is round-trippable *)lets=Printf.sprintf"%.15g"finifPoly.(float_of_strings=f)thenBuffer.add_stringbufferselsePrintf.bprintfbuffer"%.17g"fletreadbuf=Lexer.read_numberbufend)moduleJson_string=Defaults(struct(* Given that JSON must be valid UTF-8 and that OCaml string are
just a sequence of byte we need to "embed" byte string in an
UTF-8 sequence. Each byte af an OCaml string is considered as
Unicode code point (< 256) and then encoded in UTF-8. Hence,
bytes greater than 127 are "wrapped" in two bytes. *)typea=stringletwritebuffers=Buffer.add_charbuffer'\"';fori=0toString.lengths-1domatchs.[i]with|'\"'->Buffer.add_stringbuffer"\\\""|'\\'->Buffer.add_stringbuffer"\\\\"|'\b'->Buffer.add_stringbuffer"\\b"|'\x0C'->Buffer.add_stringbuffer"\\f"|'\n'->Buffer.add_stringbuffer"\\n"|'\r'->Buffer.add_stringbuffer"\\r"|'\t'->Buffer.add_stringbuffer"\\t"|cwhenPoly.(c<='\x1F')->(* Other control characters are escaped. *)Printf.bprintfbuffer"\\u%04X"(int_of_charc)|cwhenPoly.(c<'\x80')->Buffer.add_charbuffers.[i]|_c(* >= '\x80' *)->(* Bytes greater than 127 are embedded in a UTF-8 sequence. *)Buffer.add_charbuffer(Char.chr(0xC2lor(Char.codes.[i]lsr6)));Buffer.add_charbuffer(Char.chr(0x80lor(Char.codes.[i]land0x3F)))done;Buffer.add_charbuffer'\"'letreadbuf=Lexer.read_stringbufend)letread_listfbuf=letrecauxlc=matchLexer.read_casebufwith|`Cst0->for_i=cdownto1doLexer.read_rbracketbufdone;List.revl|`NCst0->Lexer.read_commabuf;letx=fbufinLexer.read_commabuf;aux(x::l)(succc)|_->Lexer.tag_error~typename:"list"bufinaux[]0letwrite_listfbufferxs=letrecauxlc=matchlwith|[]->Buffer.add_charbuffer'0';for_i=cdownto1doBuffer.add_charbuffer']'done|x::xs->Printf.bprintfbuffer"[0,%a,"fx;auxxs(succc)inauxxs0moduleJson_list(A:Json)=Defaults(structtypea=A.alistletread=read_listA.readletwrite=write_listA.writeend)letread_reffbuf=matchLexer.read_casebufwith|`NCst0->Lexer.read_commabuf;letx=fbufinLexer.read_rbracketbuf;refx|_->Lexer.tag_error~typename:"ref"bufletwrite_reffbufferr=Printf.bprintfbuffer"[0,%a]"f!rmoduleJson_ref(A:Json)=Defaults(structtypea=A.arefletwrite=write_refA.writeletread=read_refA.readend)letread_optionfbuf=matchLexer.read_casebufwith|`Cst0->None|`NCst0->Lexer.read_commabuf;letx=fbufinLexer.read_rbracketbuf;Somex|_->Lexer.tag_error~typename:"option"bufletwrite_optionfbuffero=matchowith|None->Buffer.add_charbuffer'0'|Somex->Printf.bprintfbuffer"[0,%a]"fxmoduleJson_option(A:Json)=Defaults(structtypea=A.aoptionletread=read_optionA.readletwrite=write_optionA.writeend)letread_arrayfbuf=letrecread_listaccbuf=matchLexer.read_comma_or_rbracketbufwith|`RBracket->acc|`Comma->letx=fbufinread_list(x::acc)bufinmatchLexer.read_casebufwith(* We allow the tag 254 in case of float array *)|`NCst0|`NCst254->Array.of_list(List.rev(read_list[]buf))|_->Lexer.tag_error~typename:"array"bufletwrite_arrayfbuffera=Buffer.add_stringbuffer"[0";fori=0toArray.lengtha-1doBuffer.add_charbuffer',';fbuffera.(i)done;Buffer.add_charbuffer']'moduleJson_array(A:Json)=Defaults(structtypea=A.aarrayletread=read_arrayA.readletwrite=write_arrayA.writeend)