Bij.decode starts to work;

more thorough tests (for big int lists)
This commit is contained in:
Simon Cruanes 2013-05-15 10:31:12 +02:00
parent 7628ed9954
commit a41baa1174
2 changed files with 52 additions and 25 deletions

57
bij.ml
View file

@ -219,24 +219,24 @@ module Sexp = struct
let len = ref 0 in let len = ref 0 in
(* current token *) (* current token *)
let rec cur () = let rec cur () =
if !len = 0 if eof ()
then raise (DecodingError "unexpected EOF") then raise (EncodingError "unexpected EOF")
else if !pos = !len else str.[!pos]
then (refill (); cur ()) and eof () = !len = 0
else
str.[!pos]
and refill () = and refill () =
len := source str; len := source str;
pos := 0 pos := 0
and junk () = and junk () =
if !pos = !len then refill () else incr pos incr pos;
if !pos >= !len then refill ()
(* eat whitespace *) (* eat whitespace *)
and whitespace () = and whitespace () =
match cur () with if not (eof ()) then match cur () with
| ' ' | '\t' | '\n' -> junk (); whitespace () | ' ' | '\t' | '\n' -> junk (); whitespace ()
| _ -> () | _ -> ()
in
(* decode using the [bij] *) (* decode using the [bij] *)
and decode : type a. a bij -> int -> int -> a = fun bij i n -> let rec decode : type a. a bij -> a = fun bij ->
whitespace (); whitespace ();
match bij with match bij with
| Unit -> () | Unit -> ()
@ -274,16 +274,13 @@ module Sexp = struct
| Pair (bija, bijb) -> | Pair (bija, bijb) ->
decode_open (); decode_open ();
let a = decode bija in let a = decode bija in
whitespace ();
let b = decode bijb in let b = decode bijb in
decode_close (); decode_close ();
a, b a, b
| Triple (bija, bijb, bijc) -> | Triple (bija, bijb, bijc) ->
decode_open (); decode_open ();
let a = decode bija in let a = decode bija in
whitespace ();
let b = decode bijb in let b = decode bijb in
whitespace ();
let c = decode bijc in let c = decode bijc in
decode_close (); decode_close ();
a, b, c a, b, c
@ -291,26 +288,48 @@ module Sexp = struct
let x = decode bij' in let x = decode bij' in
extract x extract x
| Switch (_, choices) -> decode_switch choices | Switch (_, choices) -> decode_switch choices
and decode_open () = match cur () with and decode_open : unit -> unit = fun () -> match cur () with
| '(' -> junk (); whitespace () | '(' -> junk () (* done *)
| _ -> raise (DecodingError "expected '('") | _ -> raise (DecodingError "expected '('")
and decode_close () = and decode_close : unit -> unit = fun () ->
whitespace (); (* on close, first eat whitespace *) whitespace (); (* on close, first eat whitespace *)
match cur () with match cur () with
| ')' -> junk (); whitespace () | ')' -> junk () (* done *)
| _ -> raise (DecodingError "expected ')'") | _ -> raise (DecodingError "expected ')'")
and decode_int i = match cur () with and decode_int : int -> int = fun i ->
| '-' when i = 0 -> ~- (decode_int 0) (* negative *) if eof () then i
else match cur () with
| '-' when i = 0 -> junk (); ~- (decode_int 0) (* negative *)
| c when Char.code c >= Char.code '0' && Char.code c <= Char.code '9' -> | c when Char.code c >= Char.code '0' && Char.code c <= Char.code '9' ->
junk (); junk ();
decode_int (i * 10 + (Char.code c - Char.code '0')) decode_int (i * 10 + (Char.code c - Char.code '0'))
| _ -> i | _ -> i
and decode_string buf = match cur() with and decode_string : Buffer.t -> string = fun buf ->
if eof () then Buffer.contents buf
else match cur() with
| ' ' | '\t' | '\n' | ')' -> Buffer.contents buf | ' ' | '\t' | '\n' | ')' -> Buffer.contents buf
| '\\' -> junk (); Buffer.add_char buf (cur ()); junk (); decode_string buf | '\\' -> junk (); Buffer.add_char buf (cur ()); junk (); decode_string buf
| c -> Buffer.add_char buf c; junk (); decode_string buf | c -> Buffer.add_char buf c; junk (); decode_string buf
and decode_list : type a. a t -> a list -> a list = fun bij l ->
whitespace ();
match cur() with
| ')' -> List.rev l (* done *)
| _ ->
let x = decode bij in
decode_list bij (x :: l)
and decode_switch : type a. (char * a t) list -> a = fun choices ->
let c = cur () in
junk ();
let bij =
try List.assq c choices
with Not_found ->
try List.assq ' ' choices
with Not_found -> raise (DecodingError "no choice")
in in
decode bij decode bij
in
refill (); (* first input *)
decode bij
let of_string ~bij s = decode ~bij (Source.of_str s) let of_string ~bij s = decode ~bij (Source.of_str s)
end end

View file

@ -13,16 +13,24 @@ let test_escape () =
let s = Sexp.to_string bij (1,("foo()","bar\n hello")) in let s = Sexp.to_string bij (1,("foo()","bar\n hello")) in
OUnit.assert_equal ~printer:(fun x -> x) "(1 (foo(\\) bar\\n\\ hello))" s OUnit.assert_equal ~printer:(fun x -> x) "(1 (foo(\\) bar\\n\\ hello))" s
let test_intlist () = let pp_int_list l =
let b = Buffer.create 4 in
Format.fprintf (Format.formatter_of_buffer b) "%a@?"
(Sequence.pp_seq Format.pp_print_int) (Sequence.of_list l);
Buffer.contents b
let test_intlist n () =
let bij = list_ int_ in let bij = list_ int_ in
let l = Sequence.to_list (Sequence.int_range ~start:0 ~stop:10000) in let l = Sequence.to_list (Sequence.int_range ~start:0 ~stop:n) in
let s = Sexp.to_string ~bij l in let s = Sexp.to_string ~bij l in
let l' = Sexp.of_string ~bij s in let l' = Sexp.of_string ~bij s in
OUnit.assert_equal l l' OUnit.assert_equal ~printer:pp_int_list l l'
let suite = let suite =
"test_bij" >::: "test_bij" >:::
[ "test_int2" >:: test_int2; [ "test_int2" >:: test_int2;
"test_escape" >:: test_escape; "test_escape" >:: test_escape;
"test_intlist" >:: test_intlist; "test_intlist10" >:: test_intlist 10;
"test_intlist100" >:: test_intlist 100;
"test_intlist10_000" >:: test_intlist 10_000;
] ]