-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathescape.lisp
70 lines (62 loc) · 2.72 KB
/
escape.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
(in-package #:hextml)
;;;; Code stolen from CL-WHO!
(defparameter *escape-char-p*
#'(lambda (char)
(or (find char "<>&'\"")
(> (char-code char) 127)))
"Used by ESCAPE-STRING to test whether a character should be escaped.")
(defun escape-string (string &key (test *escape-char-p*))
(declare (optimize speed))
"Escape all characters in STRING which pass TEST. This function is
not guaranteed to return a fresh string. Note that you can pass NIL
for STRING which'll just be returned."
(let ((first-pos (position-if test string))
;(format-string (if (eq *html-mode* :xml) "&#x~x;" "&#~d;"))
(format-string "&#~d;"))
(if (not first-pos)
;; nothing to do, just return STRING
string
(with-output-to-string (s)
(loop with len = (length string)
for old-pos = 0 then (1+ pos)
for pos = first-pos
then (position-if test string :start old-pos)
;; now the characters from OLD-POS to (excluding) POS
;; don't have to be escaped while the next character has to
for char = (and pos (char string pos))
while pos
do (write-sequence string s :start old-pos :end pos)
(case char
((#\<)
(write-sequence "<" s))
((#\>)
(write-sequence ">" s))
((#\&)
(write-sequence "&" s))
((#\')
(write-sequence "'" s))
((#\")
(write-sequence """ s))
(otherwise
(format s format-string (char-code char))))
while (< (1+ pos) len)
finally (unless pos
(write-sequence string s :start old-pos)))))))
(defun escape-string-minimal (string)
"Escape only #\<, #\>, and #\& in STRING."
(escape-string string :test #'(lambda (char) (find char "<>&"))))
(defun escape-string-minimal-plus-quotes (string)
"Like ESCAPE-STRING-MINIMAL but also escapes quotes."
(escape-string string :test #'(lambda (char) (find char "<>&'\""))))
(defun escape-string-iso-8859-1 (string)
"Escapes all characters in STRING which aren't defined in
ISO-8859-1."
(escape-string string :test #'(lambda (char)
(or (find char "<>&'\"")
(> (char-code char) 255)))))
(defun escape-string-all (string)
"Escapes all characters in STRING which aren't in the 7-bit ASCII
character set."
(escape-string string :test #'(lambda (char)
(or (find char "<>&'\"")
(> (char-code char) 127)))))