src/Pure/General/sha1_polyml.ML
author wenzelm
Thu, 20 Aug 2015 19:19:19 +0200
changeset 60989 c967d423953a
parent 60970 e08d868ceca9
permissions -rw-r--r--
obsolete;

(*  Title:      Pure/General/sha1_polyml.ML
    Author:     Sascha Boehme, TU Muenchen

Digesting strings according to SHA-1 (see RFC 3174) -- based on an
external implementation in C with a fallback to an internal
implementation.
*)

structure SHA1: SHA1 =
struct

(* digesting *)

fun hex_digit i = if i < 10 then chr (ord "0" + i) else chr (ord "a" + i - 10);

fun hex_string arr i =
  let val c = CInterface.fromCchar (CInterface.offset i CInterface.Cchar arr)
  in (op ^) (apply2 hex_digit (Integer.div_mod (Char.ord c) 16)) end

val lib_path =
  ("$ML_HOME/" ^ (if ML_System.platform_is_windows then "sha1.dll" else "libsha1.so"))
  |> Path.explode;

val STRING_INPUT_BYTES =
  CInterface.mkConversion undefined (CInterface.toCbytes o Byte.stringToBytes)
    (CInterface.Cpointer CInterface.Cchar);

fun digest_external str =
  let
    val digest = CInterface.alloc 20 CInterface.Cchar;
    val _ =
      CInterface.call3
        (CInterface.get_sym (File.platform_path lib_path) "sha1_buffer")
        (STRING_INPUT_BYTES, CInterface.LONG, CInterface.POINTER)
        CInterface.POINTER (str, size str, CInterface.address digest);
  in fold (suffix o hex_string digest) (0 upto 19) "" end;

fun digest_string str = digest_external str
  handle CInterface.Foreign msg =>
    (warning (msg ^ "\nUsing slow ML implementation of SHA1.digest"); SHA1.rep (SHA1.digest str));


(* type digest *)

datatype digest = Digest of string;

val digest = Digest o digest_string;
fun rep (Digest s) = s;

val fake = Digest;

end;