git.fiddlerwoaroof.com
Browse code

2008-11-19 Ahmon Dancy <dancy@dancy>

layer authored on 20/11/2008 21:23:14
Showing 2 changed files
... ...
@@ -1,3 +1,9 @@
1
+2008-11-19  Ahmon Dancy  <dancy@dancy>
2
+
3
+	* rfe8406: mime-api.cl: Improved performance of
4
+	charset-to-external-format by using a hash table for caching.
5
+	Also added ansi_x3.4-1968 as an alias for :latin1.
6
+
1 7
 2008-09-16  Mikel Bancroft  <mikel@gemini>
2 8
 
3 9
 	* rfe8214 - smtp.cl: Add support for SSL connections to secure
... ...
@@ -1,7 +1,8 @@
1 1
 #+(version= 8 1)
2
-(sys:defpatch "mime" 2
2
+(sys:defpatch "mime" 3
3 3
   "v1: changes to internal/undocumented portions of module;
4
-v2: better parse-mime-structure behavior in the face of malformatted headers."
4
+v2: better parse-mime-structure behavior in the face of malformatted headers;
5
+v3: Improved performance when converting charset to external-format."
5 6
   :type :system
6 7
   :post-loadable t)
7 8
 
... ...
@@ -40,7 +41,7 @@ v2: make-mime-part: Default external-format is :utf8."
40 41
 ;; merchantability or fitness for a particular purpose.  See the GNU
41 42
 ;; Lesser General Public License for more details.
42 43
 ;;
43
-;; $Id: mime-api.cl,v 1.9 2008/05/21 21:01:56 layer Exp $
44
+;; $Id: mime-api.cl,v 1.10 2008/11/20 21:23:14 layer Exp $
44 45
 
45 46
 (defpackage :net.post-office
46 47
   (:use #:lisp #:excl)
... ...
@@ -369,33 +370,63 @@ This is a multi-part message in MIME format.~%"))
369 370
    elseif (message-rfc822-p (mime-part-type part) (mime-part-subtype part))
370 371
      then (map-over-parts (mime-part-message part) function)))
371 372
 
372
-(defparameter *charset-to-ef*
373
-    '(("shift-jis" . :shiftjis)
374
-      ("us-ascii" . :latin1)
373
+;;
374
+
375
+(defparameter *default-charset-to-ef* 
376
+    '(("us-ascii" . :latin1)
377
+      ("ansi_x3.4-1968" . :latin1)
378
+      ("shift-jis" . :shiftjis)
375 379
       ("gbk" . :936)
376
-      #+ignore("euc-kr" :iso-2022-kr)
377
-      ))
380
+      #+ignore("euc-kr" :iso-2022-kr)))
381
+
382
+(defparameter *charset-to-ef* nil)
383
+
384
+(defparameter *charset-to-ef-lock* (mp:make-process-lock))
385
+
386
+(defparameter *debug-charset-to-ef* nil)
387
+
388
+(defun init-charset-to-ef ()
389
+  (let ((ht (make-hash-table :test #'equal)))
390
+    (dolist (pair *default-charset-to-ef*)
391
+      (setf (gethash (car pair) ht) (find-external-format (cdr pair) :errorp nil)))
392
+    (setf *charset-to-ef* ht)))
378 393
 
379 394
 (defun charset-to-external-format (charset)
380 395
   (setf charset (string-downcase charset))
381
-  (block nil
382
-    (let ((ef (find-external-format charset :errorp nil)))
383
-      (if ef
384
-	  (return ef))
385
-      (if (setf ef (cdr (assoc charset *charset-to-ef* :test #'string=)))
386
-	  (return (find-external-format ef)))
387
-      (multiple-value-bind (matched x inner)
388
-	  (match-re "^windows-(\\d+)$" charset)
389
-	(declare (ignore x))
390
-	(if (and matched (setf ef (find-external-format inner :errorp nil)))
391
-	    (return ef)))
392
-      (multiple-value-bind (matched x dig)
393
-	  (match-re "^iso-8859-(\\d+)(?:-[ie])?$" charset)
394
-	(declare (ignore x))
395
-	(if (and matched (setf ef (find-external-format (format nil "iso8859-~a" dig) :errorp nil)))
396
-	    (return ef)))
397
-
398
-      nil)))
396
+  (mp:with-process-lock (*charset-to-ef-lock*)
397
+    (if (null *charset-to-ef*)
398
+	(init-charset-to-ef))
399
+
400
+    (macrolet ((save-and-return (ef)
401
+		 (let ((ef-x (gensym)))
402
+		   `(let ((,ef-x ,ef))
403
+		      (progn (setf (gethash charset *charset-to-ef*) ,ef-x)
404
+			     (return-from charset-to-external-format ,ef-x))))))
405
+      
406
+      (let ((ef (gethash charset *charset-to-ef*)))
407
+	(if ef 
408
+	    (return-from charset-to-external-format ef)) ;; Use cached result
409
+	
410
+	(if (setf ef (find-external-format charset :errorp nil))
411
+	    (save-and-return ef))
412
+	
413
+	(multiple-value-bind (matched x inner)
414
+	    (match-re "^windows-(\\d+)$" charset)
415
+	  (declare (ignore x))
416
+	  (if (and matched (setf ef (find-external-format inner :errorp nil)))
417
+	      (save-and-return ef)))
418
+
419
+	(multiple-value-bind (matched x dig)
420
+	    (match-re "^iso-8859-(\\d+)(?:-[ie])?$" charset)
421
+	  (declare (ignore x))
422
+	  (if (and matched (setf ef (find-external-format (format nil "iso8859-~a" dig) :errorp nil)))
423
+	      (save-and-return ef)))
424
+
425
+	(if *debug-charset-to-ef*
426
+	    (format t "no external found for ~a~%" charset))
427
+	
428
+	;; No luck
429
+	nil))))
399 430
 
400 431
 (defun decode-header-text (text)
401 432
   (declare (optimize (speed 3))