Miki Tebeka committed 173d072

Right handling of files etc

Comments (0)

Files changed (3)

   #^{ :author "Miki Tebeka <>"
       :doc "Message digest algorithms for Clojure"}
   (:use [clojure.string :only (split lower-case)])
-  (:import ( MessageDigest Security)))
+  (:import ( MessageDigest Security)
+           ( FileInputStream File InputStream)))
+; Default buffer size for reading
+(def *buffer-size* 1024)
+(def ByteArray (type (make-array Byte/TYPE 0)))
+(defn- read-some 
+  "Read some data from reader. Return [data size] if there's more to read,
+  otherwise nil."
+  [reader]
+  (let [buffer (make-array Byte/TYPE *buffer-size*)
+        size (.read reader buffer)]
+    (when (> size 0) [buffer size])))
+(defn- byte-seq
+  "Return a sequence of [data size] from reader."
+  [reader]
+  (take-while (complement nil?) (repeatedly (partial read-some reader))))
 (defmulti digest
-  "Returns digest for message with given algorithm."
+  "Returns digest for input with given algorithm."
   (fn [algorithm message] (class message)))
 (defmethod digest String [algorithm message]
-  (digest algorithm [message]))
+  (digest algorithm (.getBytes message)))
-; Code "borrowed" from
-(defmethod digest :default
-  [algorithm messages]
+(defmethod digest ByteArray [algorithm message]
+  (digest algorithm [[message (count message)]]))
+(defmethod digest File [algorithm file]
+  (digest algorithm (FileInputStream. file)))
+(defmethod digest InputStream [algorithm reader]
+  (digest algorithm (byte-seq reader)))
+; Code "borrowed" from 
+; *
+; * 
+(defmethod digest :default [algorithm chunks]
   (let [algo (MessageDigest/getInstance algorithm)]
     (.reset algo)
-    (dorun (map #(.update algo (.getBytes %)) messages))
+    (dorun (map (fn [[message size]] (.update algo message 0 size)) chunks))
     (.toString (BigInteger. 1 (.digest algo)) 16)))
 (defn algorithms []


New image


 (ns digest-test
   (:use [digest] :reload-all)
   (:use [clojure.string :only (lower-case)])
-  (:use [clojure.test]))
+  (:use [clojure.test])
+  (:import
 (deftest md5-test
   (is (= (digest "md5" "foo") "acbd18db4cc2f85cedef654fccc4a4d8")))
 (deftest utils-test
   (for [name (algorithms)]
     (dorun (is (ns-resolve *ns* (symbol (lower-case name)))))))
+(def *logo-md5* "38cf20fa3c9dc72be56965eb1c311dfa")
+(def *logo-sha256* 
+  "42c2af2a0509832f39d0cef3ecd1612b7857c55abbe2170470eabb2a0318701c")
+(deftest file-test
+  (let [f (File. "test/clojure.png")]
+    (is (= (md5 f) *logo-md5*))
+    (is (= (sha-256 f) *logo-sha256*))))