| 1 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|---|
| 2 |
;;;; utilities.lisp: General non-mime specific utilities |
|---|
| 3 |
;;;; Copyright (C) 2004 Robert Marlow <bobstopper@bobturf.org> |
|---|
| 4 |
;;;; |
|---|
| 5 |
;;;; This library is free software; you can redistribute it and/or |
|---|
| 6 |
;;;; modify it under the terms of the GNU Library General Public |
|---|
| 7 |
;;;; License as published by the Free Software Foundation; either |
|---|
| 8 |
;;;; version 2 of the License, or (at your option) any later version. |
|---|
| 9 |
;;;; |
|---|
| 10 |
;;;; This library is distributed in the hope that it will be useful, |
|---|
| 11 |
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 12 |
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|---|
| 13 |
;;;; Library General Public License for more details. |
|---|
| 14 |
;;;; |
|---|
| 15 |
;;;; You should have received a copy of the GNU Library General Public |
|---|
| 16 |
;;;; License along with this library; if not, write to the |
|---|
| 17 |
;;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
|---|
| 18 |
;;;; Boston, MA 02111-1307, USA. |
|---|
| 19 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|---|
| 20 |
|
|---|
| 21 |
|
|---|
| 22 |
|
|---|
| 23 |
(in-package :mime) |
|---|
| 24 |
|
|---|
| 25 |
;;; This function reads a line from the given input stream that |
|---|
| 26 |
;;; is either terminated by LF or by CRLF. |
|---|
| 27 |
(defun read-line/strip-cr (&rest args) |
|---|
| 28 |
(multiple-value-bind (line missing-newline-p) |
|---|
| 29 |
(apply #'read-line args) |
|---|
| 30 |
(if (not missing-newline-p) |
|---|
| 31 |
(let ((l (length line))) |
|---|
| 32 |
(if (and (>= l 1) (char= (char line (1- l)) #\Return)) |
|---|
| 33 |
(values (subseq line 0 (1- l)) missing-newline-p) |
|---|
| 34 |
(values line missing-newline-p))) |
|---|
| 35 |
(values line missing-newline-p)))) |
|---|
| 36 |
|
|---|
| 37 |
;;; This macro does very little other than tidy up the do-loops I tend to do |
|---|
| 38 |
;;; when reading files line-by-line. |
|---|
| 39 |
(defmacro read-lines ((line-var stream) (exit-clause &body exit-body) &body body) |
|---|
| 40 |
"Reads lines into LINE-VAR from STREAM until either EOF is |
|---|
| 41 |
reached or EXIT-CLAUSE is true where upon EXIT-BODY is executed. |
|---|
| 42 |
Executes BODY for every line in the file" |
|---|
| 43 |
`(do ((,line-var (read-line/strip-cr ,stream nil 'eof) |
|---|
| 44 |
(read-line/strip-cr ,stream nil 'eof))) |
|---|
| 45 |
((or (eql ,line-var 'eof) |
|---|
| 46 |
,exit-clause) |
|---|
| 47 |
,@exit-body) |
|---|
| 48 |
,@body)) |
|---|
| 49 |
|
|---|
| 50 |
|
|---|
| 51 |
;;; This makes it simple to convert the contents of a stream to a string |
|---|
| 52 |
(defmacro read-stream-to-string (stream line-var &optional exit-clause) |
|---|
| 53 |
"Reads STREAM until EOF and returns a string containing the contents" |
|---|
| 54 |
(let ((string-stream (gensym))) |
|---|
| 55 |
`(with-output-to-string |
|---|
| 56 |
(,string-stream) |
|---|
| 57 |
(read-lines (,line-var ,stream) |
|---|
| 58 |
(,exit-clause t) |
|---|
| 59 |
(princ ,line-var ,string-stream) |
|---|
| 60 |
(terpri ,string-stream))))) |
|---|
| 61 |
|
|---|
| 62 |
|
|---|
| 63 |
;;; These macros stolen from KMRCL |
|---|
| 64 |
(defmacro aif (test then &optional else) |
|---|
| 65 |
`(let ((it ,test)) |
|---|
| 66 |
(if it ,then ,else))) |
|---|
| 67 |
|
|---|
| 68 |
|
|---|
| 69 |
(defun ensure-keyword (name) |
|---|
| 70 |
"Returns keyword for a name" |
|---|
| 71 |
(etypecase name |
|---|
| 72 |
(keyword name) |
|---|
| 73 |
(string (nth-value 0 (intern (string-upcase name) :keyword))) |
|---|
| 74 |
(symbol (nth-value 0 (intern (symbol-name name) :keyword))))) |
|---|
| 75 |
|
|---|