Commits

Dmitry Grebeniuk  committed 60b9467

iteratees: + signed ints, + tests

  • Participants
  • Parent commits 5c29f80

Comments (0)

Files changed (4)

       list (iteratee 'a 'b) -> iteratee 'a 'b
     ;
 
+    value junk : iteratee 'el unit
+    ;
+
     module Ops
      :
       sig

File dumbstreaming_it.ml

-value dbg fmt = Printf.eprintf fmt
+value dbgn fmt = Printf.ksprintf (fun s -> Printf.eprintf "%s%!" s) fmt
+;
+value dbg fmt = Printf.ksprintf (fun s -> Printf.eprintf "DBG: %s\n%!" s) fmt
 ;
 (*
 value dbg fmt = Printf.ifprintf stdout fmt
 
     (* for tests: *)
     value read_uint : I.iteratee char int;
+    value read_uint_nz : I.iteratee char int;
+    value read_int : I.iteratee char int;
+    value read_int_nz : I.iteratee char int;
 
-    (* for tests: *)
-    value read_uint_nz : I.iteratee char int;
+    value read_uint32 : I.iteratee char int32;
+    value read_uint32_nz : I.iteratee char int32;
+    value read_int32 : I.iteratee char int32;
+    value read_int32_nz : I.iteratee char int32;
+
+    value read_uint64 : I.iteratee char int64;
+    value read_uint64_nz : I.iteratee char int64;
+    value read_int64 : I.iteratee char int64;
+    value read_int64_nz : I.iteratee char int64;
+    (* . *)
 
     value read_lengths : int -> I.iteratee char (list int)
     ;
     value ie_cont k = I.IE_cont None k
     ;
 
-    (* to iteratees: *)
-    value junk = I.drop 1
-    ;
-
-
     (* todo: move to ocaml-iteratees: *)
     module It_add
      :
          : list (I.iteratee 'el 'a) -> I.iteratee 'el 'a
         ;
 
-        (* leading zeroes accepted *)
-        value read_uint : I.iteratee char int
-        ;
+        value read_uint : I.iteratee char int;
+        value read_uint_nz : I.iteratee char int;
+        value read_int : I.iteratee char int;
+        value read_int_nz : I.iteratee char int;
 
-        (* leading zeroes = error *)
-        value read_uint_nz : I.iteratee char int
-        ;
+        value read_uint32 : I.iteratee char int32;
+        value read_uint32_nz : I.iteratee char int32;
+        value read_int32 : I.iteratee char int32;
+        value read_int32_nz : I.iteratee char int32;
 
-        (* leading zeroes accepted *)
-        value read_uint64 : I.iteratee char int64
-        ;
-
-        (* leading zeroes = error *)
-        value read_uint64_nz : I.iteratee char int64
-        ;
+        value read_uint64 : I.iteratee char int64;
+        value read_uint64_nz : I.iteratee char int64;
+        value read_int64 : I.iteratee char int64;
+        value read_int64_nz : I.iteratee char int64;
 
       end
      =
           end
         ;
 
+        module SInt32_T : SIGNED_INT with type t = int32
+         =
+          struct
+            type t = int32;
+            value max_int = Int32.max_int;
+            value of_int = Int32.of_int;
+            value to_int = Int32.to_int;
+            value ( + ) = Int32.add;
+            value ( - ) = Int32.sub;
+            value ( * ) = Int32.mul;
+            value ( / ) = Int32.div;
+            value ( <? ) a b = (Int32.compare a b) < 0;
+            value ( =? ) a b = (Int32.compare a b) = 0;
+          end
+        ;
+
         module SInt64_T : SIGNED_INT with type t = int64
          =
           struct
             (* value digits : S.t -> int; *)
 
             value read_unsigned_gen : ~allow0:bool -> iteratee char S.t;
+            value read_signed_gen : ~allow0:bool -> iteratee char S.t;
           end
          =
           struct
               and ( <>? ) a b = not (a =? b)
             ;
 
+            value one = of_int 1
+            ;
+
+            value minus_one = (- one)
+            ;
+
+            value min_int = (- max_int) - one
+            ;
+
             value ten = of_int 10
             ;
 
-            value rec digits n =
+            value rec digits_count n =
               Pervasives.( + )
                 1
                 (let n' = n / ten in
                  if n' =? zero
                  then 0
-                 else digits n'
+                 else digits_count n'
                 )
             ;
 
 
             module P = Pervasives;
 
-            value string_reverse_inplace str =
+            value string_reverse_inplace str = P.(
               let len = String.length str in
-              let len1 = P.( - ) len 1 in
-              let len2 = P.( / ) len 2 in
+              let len1 = len - 1 in
+              let len2 = len / 2 - 1 in
               ( for i = 0 to len2
                 do
                   let j = P.( - ) len1 i in
                 done
               ; str
               )
-            ;
+            );
 
-            (* value min_int_digits = digits min_int; *)
-            value max_int_digits = digits max_int;
+            value min_int_digits = digits_count min_int;
+            value max_int_digits = digits_count max_int;
 
-            value to_base b n =
+            value to_base_abs b n =
               let buf = Buffer.create max_int_digits in
               let intb = to_int b in
               let digit n =
-                let n = to_int n in
-                ( assert (n >= 0 && n < intb)
+                let n = abs (to_int n) in
+                ( assert (n < intb)
                 ; assert (n < 10)
                 ; Char.chr (P.( + ) n (Char.code '0'))
                 ) in
               let rec loop n =
                 let d = rem n b in
-                let () = Buffer.add_char buf (digit d) in
+                let c = digit d in
+                let () = Buffer.add_char buf c in
                 let n' = n / b in
                 if n' =? zero
                 then string_reverse_inplace (Buffer.contents buf)
                 loop n
             ;
 
-            value to_dec = to_base ten
+            value to_dec_abs = to_base_abs ten
             ;
 
-            value max_int_dec = to_dec max_int;
+            value max_int_dec_abs = to_dec_abs max_int;
 
-            value from_base_neg b maxstr str =
+            value min_int_dec_abs = to_dec_abs min_int;
+
+
+            value from_base_neg b ~maxstr str =
               let len = String.length str in
               let rec loop acc i =
                 if i = len
                 let maxlen = String.length maxstr in
                 if len > maxlen
                 then
-                  let () = dbg "(from_base: len>maxlen) %!" in
+                  let () = dbgn "(from_base: len>maxlen) %!" in
                   `Overflow
                 else if len = maxlen && str > maxstr
                 then
-                  let () = dbg "(from_base: str>maxstr) %!" in
+                  let () = dbgn "(from_base: str>maxstr: %S > %S) %!"
+                    str maxstr
+                  in
                   `Overflow
                 else
                   try
                   [ SInt_not_a_number _ -> `Not_a_number ]
             ;
 
-            value from_dec_neg = from_base_neg ten max_int_dec
+            value from_dec_neg ~maxstr = from_base_neg ~maxstr ten
             ;
 
             value is_digit c = (c <= '9' && c >= '0')
               )
             ;
 
-            value read_unsigned_gen
+            value read_gen
               ~allow0
+              ~max_num_digits
+              ~maxstr
+              ~sign
              :
               iteratee char S.t
              =
                     match (d, read0, allow0) with
                     [ ('0', _, True)
                     | ('0', False, False) ->
-                      junk >>= fun () ->
+                      I.junk >>= fun () ->
                       read_beginning ~read0:True
                     | (_, True, False) -> inan "leading zeroes"
                     | (_, False, _) -> I.return None
               read_beginning ~read0:False >>= fun
               [ Some r -> I.return r
               | None ->
-                   (I.limit max_int_digits &
+                   (I.limit max_num_digits &
                     I.break_chars is_not_digit
                    ) >>= fun it ->
                    I.joinI (I.return it) >>= fun res ->
                    match (it, res, optd) with
                    [ (I.IE_done _, _, Some _) ->
                        assert False
-                       (* так как limit должен был выдать IE_cont *)
+                       (* limit should return IE_cont *)
                    | (I.IE_cont (Some _) _, _, _) ->
                        assert False
-                       (* так как joinI кинет эту ошибку сам *)
+                       (* joinI should raise this error *)
                    | (I.IE_done str, _, None)
                    | (I.IE_cont None _, str, None) ->
                        let () = assert
-                         (String.length str <= max_int_digits) in
-                       match from_dec_neg str with
+                         (String.length str <= max_num_digits) in
+                       match from_dec_neg ~maxstr str with
                        [ `Not_a_number -> assert False
                        | `Empty -> assert False
-                       | `Ok r -> I.return (-r)
+                       | `Ok r -> I.return (r * (-sign))
                        | `Overflow -> I.throw_err SInt_overflow
                        ]
 
                    | (IE_cont _ _, _, Some _) ->
-                       let () = dbg "(read_gen: cont/digit) %!" in
+                       let () = dbgn "(read_gen: cont/digit) %!" in
                        I.throw_err SInt_overflow
                    ]
               ]
             ;
 
+            value read_unsigned_gen ~allow0 =
+              read_gen
+                ~allow0
+                ~max_num_digits:max_int_digits
+                ~sign:one
+                ~maxstr:max_int_dec_abs
+            ;
+
+            value read_negative_gen ~allow0 =
+              read_gen
+                ~allow0
+                ~max_num_digits:min_int_digits
+                ~sign:minus_one
+                ~maxstr:min_int_dec_abs
+            ;
+
+            value read_signed_gen
+              ~allow0
+             :
+              iteratee char S.t
+             =
+              peek >>= fun
+              [ Some '-' -> junk >>= fun () -> read_negative_gen ~allow0
+              | Some '+' -> junk >>= fun () -> read_unsigned_gen ~allow0
+              | _ -> read_unsigned_gen ~allow0
+              ]
+            ;
+
           end
         ;
 
         module SInt = SInt_F(SInt_T)
         ;
 
+        module SInt32 = SInt_F(SInt32_T)
+        ;
+
         module SInt64 = SInt_F(SInt64_T)
         ;
 
-        (* leading zeroes = error *)
-        value read_uint_nz
-         : I.iteratee char int
-         =
-          SInt.read_unsigned_gen ~allow0:False
-        ;
+        value read_uint_nz = SInt.read_unsigned_gen ~allow0:False;
+        value read_uint = SInt.read_unsigned_gen ~allow0:True;
+        value read_int_nz = SInt.read_signed_gen ~allow0:False;
+        value read_int = SInt.read_signed_gen ~allow0:True;
 
-        value read_uint =
-          SInt.read_unsigned_gen ~allow0:True
-        ;
+        value read_uint32_nz = SInt32.read_unsigned_gen ~allow0:False;
+        value read_uint32 = SInt32.read_unsigned_gen ~allow0:True;
+        value read_int32_nz = SInt32.read_signed_gen ~allow0:False;
+        value read_int32 = SInt32.read_signed_gen ~allow0:True;
 
-        (* leading zeroes = error *)
-        value read_uint64_nz
-         : I.iteratee char int64
-         =
-          SInt64.read_unsigned_gen ~allow0:False
-        ;
-
-        value read_uint64 =
-          SInt64.read_unsigned_gen ~allow0:True
-        ;
+        value read_uint64_nz = SInt64.read_unsigned_gen ~allow0:False;
+        value read_uint64 = SInt64.read_unsigned_gen ~allow0:True;
+        value read_int64_nz = SInt64.read_signed_gen ~allow0:False;
+        value read_int64 = SInt64.read_signed_gen ~allow0:True;
 
       end
     ;
+    (* / todo: move to ocaml-iteratees *)
 
     open It_add
     ;
     open I.Ops;
 
 
-    value read_uint = read_uint;
-    value read_uint_nz = read_uint_nz;
-    value read_uint64 = read_uint64;
-    value read_uint64_nz = read_uint64_nz;
+    value read_uint = It_add.read_uint;
+    value read_uint_nz = It_add.read_uint_nz;
+    value read_int = It_add.read_int;
+    value read_int_nz = It_add.read_int_nz;
+
+    value read_uint32 = It_add.read_uint32;
+    value read_uint32_nz = It_add.read_uint32_nz;
+    value read_int32 = It_add.read_int32;
+    value read_int32_nz = It_add.read_int32_nz;
+
+    value read_uint64 = It_add.read_uint64;
+    value read_uint64_nz = It_add.read_uint64_nz;
+    value read_int64 = It_add.read_int64;
+    value read_int64_nz = It_add.read_int64_nz;
 
 
     value itpair_anyresult_lasterror it1 it2 =
 
       in
       I.peek >>= fun
-      [ Some '\x20' -> junk >>= read_ver2
-      | Some '\x0A' -> junk >>= read_ver1
+      [ Some '\x20' -> I.junk >>= read_ver2
+      | Some '\x0A' -> I.junk >>= read_ver1
       | Some _ | None -> ds_error
           "space or \\x0A expected after packet length"
       ]

File dumbstreaming_it.mli

 
     (* for tests: *)
     value read_uint : I.iteratee char int;
+    value read_uint_nz : I.iteratee char int;
+    value read_int : I.iteratee char int;
+    value read_int_nz : I.iteratee char int;
 
-    (* for tests: *)
-    value read_uint_nz : I.iteratee char int;
+    value read_uint32 : I.iteratee char int32;
+    value read_uint32_nz : I.iteratee char int32;
+    value read_int32 : I.iteratee char int32;
+    value read_int32_nz : I.iteratee char int32;
+
+    value read_uint64 : I.iteratee char int64;
+    value read_uint64_nz : I.iteratee char int64;
+    value read_int64 : I.iteratee char int64;
+    value read_int64_nz : I.iteratee char int64;
+    (* . *)
+
 
     (* for tests: *)
     value read_lengths : int -> I.iteratee char (list int)
   ]
 ;
 
-value test_uint reader string =
+value test_int (reader : I.iteratee char int32) string =
   let stream = I.Chunk (I.Subarray.of_string string) in
   let () = Printf.printf "%S -> %!" string in
   match IO.runIO ((enum1 stream reader) >>% I.run) with
-  [ `Ok r -> Printf.printf "ok %i\n%!" r
+  [ `Ok r -> Printf.printf "ok %li\n%!" r
   | `Error e -> Printf.printf "error \"%s\"\n%!"
       (printexc e)
   ]
 open Printf
 ;
 
+
 value () =
-  let maxint = Int64.of_int max_int in
+  let max_int = Int64.of_int32 Int32.max_int in
   let pr = Printf.sprintf "%Li" in
-  let samples =
+  let samples_u =
     [ "0"
     ; "00"
     ; "123"
+    ; "+123"
     ; "0123"
     ; "-123"
-    ; pr maxint
-    ; "000000" ^ pr maxint
-    ; pr (Int64.add 1L maxint)
+    ; pr max_int
+    ; "000000" ^ pr max_int
+    ; pr (Int64.add 1L max_int)
+    ; pr (Int64.add 2L max_int)
     ; "19223372036854775806"
     ]
   in
-    ( printf "reading unsigned ints with leading zeroes allowed:\n"
-    ; List.iter (test_uint D.read_uint) samples
+  let samples = List.concat
+    [ samples_u
+    ; List.map (fun s -> "-" ^ s) samples_u
+    ; List.map (fun s -> "+" ^ s) samples_u
+    ]
+  in
+    ( printf "reading unsigned int32 with leading zeroes allowed:\n"
+    ; List.iter (test_int D.read_uint32) samples
     ; print_newline ()
-    ; printf "reading unsigned ints with leading zeroes forbidden:\n"
-    ; List.iter (test_uint D.read_uint_nz) samples
+    ; printf "reading unsigned int32 with leading zeroes forbidden:\n"
+    ; List.iter (test_int D.read_uint32_nz) samples
+    ; print_newline ()
+
+    ; printf "reading signed int32 with leading zeroes allowed:\n"
+    ; List.iter (test_int D.read_int32) samples
+    ; print_newline ()
+    ; printf "reading signed int32 with leading zeroes forbidden:\n"
+    ; List.iter (test_int D.read_int32_nz) samples
     ; print_newline ()
     )
 ;