Browse code
2008-11-19 Ahmon Dancy <dancy@dancy>
layer authored on 20/11/2008 21:23:14
Showing 2 changed files
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)) |