[Mew-dist 10934] mew-header-decode-base64

Masaki KONUMA konuma at example.com
1999年 10月 15日 (金) 19:13:08 JST


mew-header-decode-base64 が、

o 遅いように見える

o mew-header-sanity-check-string しているので実質的な問題はないが、
  (mew-header-decode-base64 (mew-header-encode-base64 "abcd"))
    ==> "abcd^@^@"
  となって気持ち悪い

のでパッチです。mew-header-encode-base64 も少し速くなります。

-- 小沼雅樹
-------------- next part --------------
--- mew-bq.el.orig	Mon Aug 30 12:43:14 1999
+++ mew-bq.el	Wed Sep 29 14:26:24 1999
@@ -18,10 +18,15 @@
   (list (cons "B" 'mew-header-decode-base64)
 	(cons "Q" 'mew-header-decode-qp)))
 
-(defconst mew-base64-boundary1 26)
-(defconst mew-base64-boundary2 52)
-(defconst mew-base64-boundary3 62)
-(defconst mew-base64-boundary4 63)
+(defconst mew-base64-char64
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
+
+(defconst mew-base64-char256
+  (let ((i 0) (len (length mew-base64-char64)) (s (make-string 256 0)))
+    (while (< i len)
+      (aset s (aref mew-base64-char64 i) i)
+      (setq i (1+ i)))
+    s))
 
 (defconst mew-header-decode-regex 
   "=\\?\\([^? \t]+\\)\\?\\(.\\)\\?\\([^? \t]+\\)\\?=")
@@ -73,100 +78,79 @@
 ;;; Base64 encoding
 ;;;
 
-(defun mew-base64-char256 (ch64)
-  (cond
-   ((null ch64) 0)
-   ((and (<= ?A ch64) (<= ch64 ?Z)) (- ch64 ?A))
-   ((and (<= ?a ch64) (<= ch64 ?z)) (+ (- ch64 ?a) mew-base64-boundary1))
-   ((and (<= ?0 ch64) (<= ch64 ?9)) (+ (- ch64 ?0) mew-base64-boundary2))
-   ((char-equal ch64 ?+) mew-base64-boundary3)
-   ((char-equal ch64 ?/) mew-base64-boundary4)
-   ((char-equal ch64 ?=) 0)))
-
 (defun mew-header-encode-base64 (str256)
   (let* ((len (length str256))
 	 (ret (make-string (* (/ (+ len 2) 3) 4) ?=))
-	 (lim (* (/ len 3) 3))
 	 (pad (% len 3))
-	 (i 0) (j 0) char0 char1 char2)
-    (while (< i lim)
-      (setq char0 (aref str256 i))
-      (setq i (1+ i))
-      (setq char1 (aref str256 i))
-      (setq i (1+ i))
-      (setq char2 (aref str256 i))
-      (setq i (1+ i))
-      (aset ret j (mew-base64-char64 (lsh char0 -2)))
-      (setq j (1+ j))
-      (aset ret j (mew-base64-char64 (logior (lsh (logand char0 3) 4)
-					     (lsh char1 -4))))
-      (setq j (1+ j))
-      (aset ret j (mew-base64-char64 (logior (lsh (logand char1 15) 2)
-					     (lsh char2 -6))))
-      (setq j (1+ j))
-      (aset ret j (mew-base64-char64 (logand char2 63)))
-      (setq j (1+ j)))
+	 (lim (- len pad))
+	 (i -1) (j -1) c)
+    (while (< (setq i (1+ i)) lim)
+      (setq c (logior (lsh (aref str256 i) 16)
+		      (lsh (aref str256 (setq i (1+ i))) 8)
+		      (aref str256 (setq i (1+ i)))))
+      (aset ret (setq j (1+ j))
+	    (aref mew-base64-char64 (lsh c -18)))
+      (aset ret (setq j (1+ j))
+	    (aref mew-base64-char64 (logand (lsh c -12) 63)))
+      (aset ret (setq j (1+ j))
+	    (aref mew-base64-char64 (logand (lsh c -6) 63)))
+      (aset ret (setq j (1+ j))
+	    (aref mew-base64-char64 (logand c 63))))
     (cond
-     ((equal pad 1)
-      (setq char0 (aref str256 i))
-      (setq char1 0)
-      (aset ret j (mew-base64-char64 (lsh char0 -2)))
-      (setq j (1+ j))
-      (aset ret j (mew-base64-char64 (logior (lsh (logand char0 3) 4)
-					     (lsh char1 -4))))
-      (setq j (1+ j)))
-     ((equal pad 2)
-      (setq char0 (aref str256 i))
-      (setq i (1+ i))
-      (setq char1 (aref str256 i))
-      (setq char2 0)
-      (aset ret j (mew-base64-char64 (lsh char0 -2)))
-      (setq j (1+ j))
-      (aset ret j (mew-base64-char64 (logior (lsh (logand char0 3) 4)
-					     (lsh char1 -4))))
-      (setq j (1+ j))
-      (aset ret j (mew-base64-char64 (logior (lsh (logand char1 15) 2)
-					     (lsh char2 -6))))
-      (setq j (1+ j))))
+     ((= pad 1)
+      (setq c (aref str256 i))
+      (aset ret (setq j (1+ j))
+	    (aref mew-base64-char64 (lsh c -2)))
+      (aset ret (1+ j)
+	    (aref mew-base64-char64 (lsh (logand c 3) 4))))
+     ((= pad 2)
+      (setq c (logior (lsh (aref str256 i) 8)
+		      (aref str256 (1+ i))))
+      (aset ret (setq j (1+ j))
+	    (aref mew-base64-char64 (lsh c -10)))
+      (aset ret (setq j (1+ j))
+	    (aref mew-base64-char64 (logand (lsh c -4) 63)))
+      (aset ret (1+ j)
+	    (aref mew-base64-char64 (logand (lsh c 2) 63)))))
     ret))
-	      
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;;
 ;;; Base64 decoding
 ;;;
 
-(defun mew-base64-char64 (ch256)
-  (aref "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" 
-	ch256))
-
 (defun mew-header-decode-base64 (str64)
   (let* ((len (length str64))
-	 (ret (make-string len ?a))
-	 (i 0) (j 0) (padlen 0) char0 char1 char2 char3)
+	 ret
+	 (i 0) (j -1) (padlen 0) c)
     (if (string-match "=+$" str64)
 	(setq padlen (- (match-end 0) (match-beginning 0))))
-    (if (or (string-match "[^a-zA-Z0-9+/=]" str64)
-	    (not (equal (* (/ len 4) 4) len))
-	    (< padlen 0)
-	    (> padlen 3))
-	mew-error-illegal-base64 ;; return value
-      (setq len (- len padlen))
-      (while (< i len)
-	(setq char0 (mew-base64-char256 (aref str64 i)))
-	(setq i (1+ i))
-	(setq char1 (mew-base64-char256 (aref str64 i)))
-	(setq i (1+ i))
-	(setq char2 (mew-base64-char256 (aref str64 i)))
-	(setq i (1+ i))
-	(setq char3 (mew-base64-char256 (aref str64 i)))
-	(setq i (1+ i))
-	(aset ret j (logand (logior (lsh char0 2) (lsh char1 -4)) 255))
-	(setq j (1+ j))
-	(aset ret j (logand (logior (lsh char1 4) (lsh char2 -2)) 255))
-	(setq j (1+ j))
-	(aset ret j (logand (logior (lsh char2 6) char3) 255))
-	(setq j (1+ j)))
-      (substring ret 0 j))))
+    (cond
+     ((or (string-match "[^a-zA-Z0-9+/=]" str64)
+	  (not (zerop (logand len 3)))
+	  (< padlen 0)
+	  (> padlen 2))
+      mew-error-illegal-base64)  ;; return value
+     ((zerop (setq len (- len padlen))) "")
+     (t
+      (setq ret (make-string (/ (* len 3) 4) ?a))
+      (while 
+	  (progn 
+	    (setq
+	     c (logior
+		(lsh (aref mew-base64-char256 (aref str64 i)) 18)
+		(lsh (aref mew-base64-char256 (aref str64 (setq i (1+ i)))) 12)
+		(lsh (aref mew-base64-char256 (aref str64 (setq i (1+ i)))) 6)
+		(aref mew-base64-char256 (aref str64 (setq i (1+ i))))))
+	    (aset ret (setq j (1+ j)) (lsh c -16))
+	    (< (setq i (1+ i)) len))
+	(aset ret (setq j (1+ j)) (logand (lsh c -8) 255))
+	(aset ret (setq j (1+ j)) (logand c 255)))
+      (if (< padlen 2)
+	  (aset ret (1+ j) (logand (lsh c -8) 255)))
+      (if (zerop padlen)
+	  (aset ret (1+ (1+ j)) (logand c 255)))
+      ret))))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;;


Mew-dist メーリングリストの案内