Mercurial > lasercutter
diff src/clojure/contrib/base64.clj @ 10:ef7dbbd6452c
added clojure source goodness
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 21 Aug 2010 06:25:44 -0400 |
parents | |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/clojure/contrib/base64.clj Sat Aug 21 06:25:44 2010 -0400 1.3 @@ -0,0 +1,99 @@ 1.4 +;;; base64.clj: Experimental Base-64 encoding and (later) decoding 1.5 + 1.6 +;; by Stuart Sierra, http://stuartsierra.com/ 1.7 +;; August 19, 2009 1.8 + 1.9 +;; Copyright (c) Stuart Sierra, 2009. All rights reserved. The use 1.10 +;; and distribution terms for this software are covered by the Eclipse 1.11 +;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 1.12 +;; which can be found in the file epl-v10.html at the root of this 1.13 +;; distribution. By using this software in any fashion, you are 1.14 +;; agreeing to be bound by the terms of this license. You must not 1.15 +;; remove this notice, or any other, from this software. 1.16 + 1.17 + 1.18 +(ns ^{:doc "Base-64 encoding and (maybe later) decoding. 1.19 + 1.20 + This is mainly here as an example. It is much slower than the 1.21 + Apache Commons Codec implementation or sun.misc.BASE64Encoder." 1.22 + :author "Stuart Sierra"} 1.23 + clojure.contrib.base64 1.24 + (:import (java.io InputStream Writer ByteArrayInputStream 1.25 + StringWriter))) 1.26 + 1.27 +(def *base64-alphabet* 1.28 + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=") 1.29 + 1.30 +(defn encode 1.31 + "Encodes bytes of input, writing Base 64 text on output. alphabet 1.32 + is a 65-character String containing the 64 characters to use in the 1.33 + encoding; the 65th character is the pad character. line-length is 1.34 + the maximum number of characters per line, nil for no line breaks." 1.35 + [^InputStream input ^Writer output ^String alphabet line-length] 1.36 + (let [buffer (make-array Byte/TYPE 3)] 1.37 + (loop [line 0] 1.38 + (let [len (.read input buffer)] 1.39 + (when (pos? len) 1.40 + ;; Pre-boxing the bytes as Integers is more efficient for 1.41 + ;; Clojure's bit operations. 1.42 + (let [b0 (Integer/valueOf (int (aget buffer 0))) 1.43 + b1 (Integer/valueOf (int (aget buffer 1))) 1.44 + b2 (Integer/valueOf (int (aget buffer 2)))] 1.45 + (cond (= len 3) 1.46 + (let [s0 (bit-and 0x3F (bit-shift-right b0 2)) 1.47 + s1 (bit-and 0x3F 1.48 + (bit-or (bit-shift-left b0 4) 1.49 + (bit-shift-right b1 4))) 1.50 + s2 (bit-and 0x3F 1.51 + (bit-or (bit-shift-left b1 2) 1.52 + (bit-shift-right b2 6))) 1.53 + s3 (bit-and 0x3F b2)] 1.54 + (.append output (.charAt alphabet s0)) 1.55 + (.append output (.charAt alphabet s1)) 1.56 + (.append output (.charAt alphabet s2)) 1.57 + (.append output (.charAt alphabet s3))) 1.58 + 1.59 + (= len 2) 1.60 + (let [s0 (bit-and 0x3F (bit-shift-right b0 2)) 1.61 + s1 (bit-and 0x3F 1.62 + (bit-or (bit-shift-left b0 4) 1.63 + (bit-shift-right b1 4))) 1.64 + s2 (bit-and 0x3F (bit-shift-left b1 2))] 1.65 + (.append output (.charAt alphabet s0)) 1.66 + (.append output (.charAt alphabet s1)) 1.67 + (.append output (.charAt alphabet s2)) 1.68 + (.append output (.charAt alphabet 64))) 1.69 + 1.70 + (= len 1) 1.71 + (let [s0 (bit-and 0x3F (bit-shift-right b0 2)) 1.72 + s1 (bit-and 0x3F (bit-shift-left b0 4))] 1.73 + (.append output (.charAt alphabet s0)) 1.74 + (.append output (.charAt alphabet s1)) 1.75 + (.append output (.charAt alphabet 64)) 1.76 + (.append output (.charAt alphabet 64))))) 1.77 + (if (and line-length (> (+ line 4) line-length)) 1.78 + (do (.append output \newline) 1.79 + (recur 0)) 1.80 + (recur (+ line 4)))))))) 1.81 + 1.82 +(defn encode-str 1.83 + "Encodes String in base 64; returns a String. If not specified, 1.84 + encoding is UTF-8 and line-length is nil." 1.85 + ([s] (encode-str s "UTF-8" nil)) 1.86 + ([^String s ^String encoding line-length] 1.87 + (let [output (StringWriter.)] 1.88 + (encode (ByteArrayInputStream. (.getBytes s encoding)) 1.89 + output *base64-alphabet* line-length) 1.90 + (.toString output)))) 1.91 + 1.92 + 1.93 +;;; tests 1.94 + 1.95 +;; (deftest t-encode-str 1.96 +;; (is (= (encode-str "") "")) 1.97 +;; (is (= (encode-str "f") "Zg==")) 1.98 +;; (is (= (encode-str "fo") "Zm8=")) 1.99 +;; (is (= (encode-str "foo") "Zm9v")) 1.100 +;; (is (= (encode-str "foob") "Zm9vYg==")) 1.101 +;; (is (= (encode-str "fooba") "Zm9vYmE=")) 1.102 +;; (is (= (encode-str "foobar") "Zm9vYmFy")))