Commits

Anonymous committed 8fc04e0

bert almost written ... ..

  • Participants
  • Parent commits fbf7740

Comments (0)

Files changed (3)

 PROGRAM = tcp_server
 OCAML_LIBS +=
 OCAML_CLIBS +=
-OCAML_OTHER_LIBS += unix
+OCAML_OTHER_LIBS += unix str
 OCAML_LIB_FLAGS +=
 
 .DEFAULT: $(OCamlProgram $(PROGRAM), $(FILES))
 * types matter
 
 erlang terms - support in ocaml
-  integer  - ok in ocaml
-  float    - ok in ocaml
-  atom     - static, or polymorphic variant?
-  list     - list with polymorphic variant ... 
-  tuple    - tuple.
-  pid      - not supported or libei supported?!
-  ref      - not supported or translated to some binary
-  fun      - not supported 
-  binary   - just an string, maybe
-  port     - not supported
+  integer  o- ok in ocaml
+  float    o- ok in ocaml
+  atom     x- static, or polymorphic variant?
+  list     o- list with polymorphic variant ... maybe supported.
+  tuple    o- tuple. maybe supported. difficult problem of types.
+  pid      x- not supported or libei supported?!
+  ref      x- not supported or translated to some binary
+  fun      x- not supported 
+  binary   o- just an string, maybe
+  port     x- not supported
 
 
 * interface
   bignum  <-> integer
   float   <-> flost
   string  <-> atom
+  ..... 
+  ...
 
 see http://www.erlang.org/doc/apps/erts/erl_ext_dist.html
 for erlang binary term format.
+open Str;;
+
 type term =
     Int of int
   | Float of float
-(*  | Atom of string
-  | `Tuple of term list 
-  | List of 'term list  *)
+(*  | Atom of string *) 
+  | Tuple of term list (* type of tuple is different btw Erlang and OCaml *)
+  | List of term list 
   | String of string
   | Binary of string
   | None;;
   | More of int
   | None;;
 
-let bert_version_number = 131;;
-
 (*
 class pid = let a in 1;;
 class ref = let a in 1;;
 exception Not_supported;;
 exception Unknown_type;;
 
+let make_small_bigint bin len =
+  let rec make_small_bigint_ i prod v = 
+    if i < len then
+      let p = prod lsl 8 in
+      let n = int_of_char (String.get bin i) in
+	make_small_bigint_ (i+1) p (v  + p * n)
+    else v in
+    make_small_bigint_ 0 1 0;;
+    
 
 let make_int32 bin = 
   let rec make_int32_ bin v i =
     if i < 4 then 
-      make_int32_ bin ((v*16) + (int_of_char (String.get bin i))) (i+1)
+      make_int32_ bin ((v*256) + (int_of_char (String.get bin i))) (i+1)
     else v
   in make_int32_ bin 0 0;;
 
-let make_int8 r1 r2 = 
-  (int_of_char r1) * 16 + (int_of_char r2);;
+(*  8 bit is: 0 - 255 *)
+let make_int8 r = (int_of_char r);;
 
 (* binary -> (decoded tuple, remain), (more, Length), (error, Reason)
    throws exceptions: Not_supported | Unknown_type
    when more binaries  *)
 let decode_binary bin = 
-  let local_decode local_bin = 
-    let length = String.length local_bin in 
+  let rec decode_list len binary list = 
+    if len = 0 then
+      Ok(List(list), binary)
+    else 
+      begin match local_decode binary with
+	| Ok(t, remain) ->  decode_list (len-1) remain (t::list);
+	| other -> other;
+      end
+  and local_decode local_bin = 
       (* see http://www.erlang.org/doc/apps/erts/erl_ext_dist.html for details*)
-      begin match (String.get local_bin 0) with
-	| 'a' ->  (* SMALL_INTEGER_EXT *)
-	    Ok( Int(int_of_char (String.get local_bin 1)), 
-		String.sub local_bin 2 (length-2) );
-	| 'b' ->  (* INTEGER_EXT *)
-	    Ok( Int( make_int32 (String.sub local_bin 1 5)),
-		String.sub local_bin 5 (length-5) );
-	| 'c' -> (* FLOAT_EXT *)
-	    let v = Scanf.sscanf (String.sub local_bin 1 32) "%f" (fun x->x) in
-	    Ok( Float( v ), String.sub local_bin 32 (length-32) );
-	| 'd' -> (* ATOM_EXT *)
-	    raise Not_supported;
-	| 'e' -> (* REFERENCE_EXT *)
-	    raise Not_supported;
-	| 'f' -> (* PORT_EXT *)
-	    raise Not_supported;
-	| 'g' -> (* PID_EXT *)
-	    raise Not_supported;
-	| 'h' -> (* SMALL_TUPLE_EXT *)
-	    raise Not_supported;
-	| 'i' -> (* LARGE_TUPLE_EXT *)
-	    raise Not_supported;
-	| 'j' -> (* NIL_EXT *)
-	    None;
-	| 'k' -> (* STRING_EXT *)
-	    let len = make_int8 (String.get local_bin 1) (String.get local_bin 2) in
-	    Ok( String( String.sub local_bin 3 (len+3) ),
-		String.sub local_bin (len+3) (length-len-3) );
-	| 'l' -> (* LIST_EXT *)
-	    raise Not_supported;
-	| 'm' -> (* BINARY_EXT *)
-	    let len = make_int32 (String.sub local_bin 1 5) in
-	    let data = String.sub local_bin 5 (len+5) in (* TODO: you'd better use Str.split *)
-	      Ok( Binary(data), 
-		  String.sub local_bin (len+5) (length-len-5));
-	| 'n' -> (* SMALL_BIG_EXT *)
-	    raise Unknown_type;
-	| 'o' -> (* LARGE_BIG_EXT *)
-	    raise Unknown_type;
-	| 'p' -> (* NEW_REFERENCE_EXT *)
-	    raise Unknown_type;	    
-	| 'q' -> (* SMALL_ATOM_EXT *)
-	    raise Unknown_type;	    
-	| 'r' -> (* FUN_EXT *)
-	    raise Unknown_type;	    
-	| 's' -> (* NEW_FUN_EXT *)
-	    raise Unknown_type;	    
-	| 't' -> (* EXPORT_EXT *)
-	    raise Unknown_type;	    
-	| 'M' -> (* BIT_BINARY_EXT *)
-	    raise Unknown_type;	    
-	| 'F' -> (* NEW_FLOAT_EXT *)
-	    raise Unknown_type;	    
-	| _-> raise Unknown_type;
-      end in
+    begin match (String.get local_bin 0) with
+      | 'a' ->  (* SMALL_INTEGER_EXT *)
+	  Ok( Int(int_of_char (String.get local_bin 1)), Str.string_after local_bin 1)
+      | 'b' ->  (* INTEGER_EXT *)
+	  Ok( Int( make_int32 (String.sub local_bin 1 5)), Str.string_after local_bin 5);
+      | 'c' -> (* FLOAT_EXT *)
+	  let v = Scanf.sscanf (String.sub local_bin 1 32) "%f" (fun x->x) in
+	    Ok( Float( v ), Str.string_after local_bin 32); 
+      | 'd' -> (* ATOM_EXT *)
+	  raise Not_supported;
+      | 'e' -> (* REFERENCE_EXT *)
+	  raise Not_supported;
+      | 'f' -> (* PORT_EXT *)
+	  raise Not_supported;
+      | 'g' -> (* PID_EXT *)
+	  raise Not_supported;
+      | 'h' -> (* SMALL_TUPLE_EXT *)
+	  let len = int_of_char (String.get local_bin 1) in
+	    decode_list len (Str.string_after local_bin 2) []; (* is it OK to use list? *)
+      | 'i' -> (* LARGE_TUPLE_EXT *)
+	  let len = make_int32 (String.sub local_bin 1 5) in
+	    decode_list len (Str.string_after local_bin 5) []; (* is it OK to use list? *)
+      | 'j' -> (* NIL_EXT *)
+	  None;
+      | 'k' -> (* STRING_EXT *)
+	  let len = (int_of_char (String.get local_bin 1))*256 + (int_of_char (String.get local_bin 2)) in
+	    Ok( String( String.sub local_bin 3 (len+3) ), Str.string_after local_bin (len+3) );
+      | 'l' -> (* LIST_EXT *)
+	  let len = make_int32 (String.sub local_bin 1 5) in
+	    decode_list len (Str.string_after local_bin 5) [];
+	  (*raise Not_supported; *)
+      | 'm' -> (* BINARY_EXT *)
+	  let len = make_int32 (String.sub local_bin 1 5) in
+	  let remain = Str.string_after local_bin 5 in (* TODO: you'd better use Str.split *)
+	    Ok( Binary( Str.string_before remain len ),  Str.string_after remain len );
+      | 'n' -> (* SMALL_BIG_EXT *)
+	  let n = int_of_char (String.get local_bin 1) in
+	  let sign = int_of_char  (String.get local_bin 2) in
+	  let result = make_small_bigint (String.sub local_bin 3 (n+3)) n in
+	    if sign=0 then 
+	      Ok( Int(result), Str.string_after local_bin (n+3) )
+	    else if sign=1 then
+	      Ok( Int(-result), Str.string_after local_bin (n+3) )
+	    else 
+	      raise Unknown_type;
+      | 'o' -> (* LARGE_BIG_EXT *)
+	  let n = make_int32 local_bin in
+	  let sign = int_of_char  (String.get local_bin 5) in
+	  let result = make_small_bigint (String.sub local_bin 6 (n+6)) n in
+	    if sign=0 then 
+	      Ok( Int(result), Str.string_after local_bin (n+6) )
+	    else if sign=1 then
+	      Ok( Int(-result), Str.string_after local_bin (n+6) )
+	    else 
+	      raise Unknown_type;
+      | 'p' -> (* NEW_REFERENCE_EXT *)
+	  raise Not_supported;
+      | 'q' -> (* SMALL_ATOM_EXT *)
+	  raise Not_supported;	    
+      | 'r' -> (* FUN_EXT *)
+	  raise Not_supported;	    
+      | 's' -> (* NEW_FUN_EXT *)
+	  raise Not_supported;	    
+      | 't' -> (* EXPORT_EXT *)
+	  raise Not_supported;	    
+      | 'M' -> (* BIT_BINARY_EXT *)
+	  raise Not_supported;
+      | 'F' -> (* NEW_FLOAT_EXT *)
+	  raise Not_supported;
+      | _-> raise Unknown_type;
+    end in
     begin match int_of_char (String.get bin 0) with
-      | 131 -> local_decode (String.sub bin 1 ((String.length bin)-1)); (* magic number for BERT term; *)
+      | 131 -> (* magic number for BERT term; *)
+	  local_decode (String.sub bin 1 ((String.length bin)-1)); 
       | _ -> raise Unknown_type;
     end;;