1 ;;; -*- Mode: Lisp; Syntax: Common-Lisp; Package: RUNES; -*-
2 ;;; ---------------------------------------------------------------------------
3 ;;; Title: Unicode strings (called RODs)
4 ;;; Created: 1999-05-25 22:29
5 ;;; Author: Gilbert Baumann <unk6@rz.uni-karlsruhe.de>
6 ;;; License: Lisp-LGPL (See file COPYING for details).
7 ;;; ---------------------------------------------------------------------------
8 ;;; (c) copyright 1998,1999 by Gilbert Baumann
10 ;;; This code is free software; you can redistribute it and/or modify it
11 ;;; under the terms of the version 2.1 of the GNU Lesser General Public
12 ;;; License as published by the Free Software Foundation, as clarified
13 ;;; by the "Preamble to the Gnu Lesser General Public License" found in
16 ;;; This code is distributed in the hope that it will be useful,
17 ;;; but without any warranty; without even the implied warranty of
18 ;;; merchantability or fitness for a particular purpose. See the GNU
19 ;;; Lesser General Public License for more details.
21 ;;; Version 2.1 of the GNU Lesser General Public License is in the file
22 ;;; COPYING that was distributed with this file. If it is not present,
23 ;;; you can access it from http://www.gnu.org/copyleft/lesser.txt (until
24 ;;; superseded by a newer version) or write to the Free Software
25 ;;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 ;; ----------------------------------------------------------------------------
31 ;; 1999-08-15 GB - ROD=, ROD-EQUAL
33 ;; MAKE-ROD, ROD-SUBSEQ
34 ;; CHAR-RUNE, RUNE-CHAR, ROD-STRING, STRING-ROD
36 ;; - Added rune reader
41 (deftype rune
() '(unsigned-byte 16))
42 (deftype rod
() '(array rune
(*)))
43 (deftype simple-rod
() '(simple-array rune
(*)))
45 (definline rune
(rod index
)
48 (defun (setf rune
) (new rod index
)
49 (setf (aref rod index
) new
))
51 (definline %rune
(rod index
)
52 (aref (the (simple-array (unsigned-byte 16) (*)) rod
) (the fixnum index
)))
54 (definline (setf %rune
) (new rod index
)
55 (setf (aref (the (simple-array (unsigned-byte 16) (*)) rod
) (the fixnum index
)) new
))
57 (defun rod-capitalize (rod)
58 (warn "~S is not implemented." 'rod-capitalize
)
61 (definline code-rune
(x) x
)
62 (definline rune-code
(x) x
)
64 (definline rune
= (x y
)
67 (defun rune-downcase (rune)
68 (cond ((<= #x0041 rune
#x005a
) (+ rune
#x20
))
69 ((= rune
#x00d7
) rune
)
70 ((<= #x00c0 rune
#x00de
) (+ rune
#x20
))
73 (definline rune-upcase
(rune)
74 (cond ((<= #x0061 rune
#x007a
) (- rune
#x20
))
75 ((= rune
#x00f7
) rune
)
76 ((<= #x00e0 rune
#x00fe
) (- rune
#x20
))
79 (defun rune-upper-case-letter-p (rune)
80 (or (<= #x0041 rune
#x005a
) (<= #x00c0 rune
#x00de
)))
82 (defun rune-lower-case-letter-p (rune)
83 (or (<= #x0061 rune
#x007a
) (<= #x00e0 rune
#x00fe
)
87 (defun rune-equal (x y
)
88 (rune= (rune-upcase x
) (rune-upcase y
)))
90 (defun rod-downcase (rod)
92 (map '(simple-array (unsigned-byte 16) (*)) #'rune-downcase rod
))
94 (defun rod-upcase (rod)
96 (map '(simple-array (unsigned-byte 16) (*)) #'rune-upcase rod
))
98 (definline white-space-rune-p
(char)
100 (= char
10) ;Linefeed
101 (= char
13) ;Carriage Return
104 (definline digit-rune-p
(char &optional
(radix 10))
105 (cond ((<= #.
(char-code #\
0) char
#.
(char-code #\
9))
106 (and (< (- char
#.
(char-code #\
0)) radix
)
107 (- char
#.
(char-code #\
0))))
108 ((<= #.
(char-code #\A
) char
#.
(char-code #\Z
))
109 (and (< (- char
#.
(char-code #\A
) -
10) radix
)
110 (- char
#.
(char-code #\A
) -
10)))
111 ((<= #.
(char-code #\a) char
#.
(char-code #\z
))
112 (and (< (- char
#.
(char-code #\a) -
10) radix
)
113 (- char
#.
(char-code #\a) -
10))) ))
116 (cond ((stringp x
) (map 'rod
#'char-code x
))
117 ((symbolp x
) (rod (string x
)))
118 ((characterp x
) (rod (string x
)))
119 ((vectorp x
) (coerce x
'rod
))
120 ((integerp x
) (map 'rod
#'identity
(list x
)))
121 (t (error "Cannot convert ~S to a ~S" x
'rod
))))
127 (defun sloopy-rod-p (x)
128 (and (not (stringp x
))
133 (and (= (length x
) (length y
))
134 (dotimes (i (length x
) t
)
135 (unless (rune= (rune x i
) (rune y i
))
138 (defun rod-equal (x y
)
139 (and (= (length x
) (length y
))
140 (dotimes (i (length x
) t
)
141 (unless (rune-equal (rune x i
) (rune y i
))
144 (definline make-rod
(size)
145 (make-array size
:element-type
'rune
))
147 (defun char-rune (char)
148 (code-rune (char-code char
)))
150 (defparameter *invalid-rune
* nil
;;#\?
151 "Rune to use as a replacement in RUNE-CHAR and ROD-STRING for runes not
152 representable as characters. If NIL, an error is signalled instead.")
154 (defun rune-char (rune &optional
(default *invalid-rune
*))
155 (or (if (>= rune char-code-limit
)
157 (or (code-char rune
) default
))
158 (error "rune cannot be represented as a character: ~A" rune
)))
160 (defun rod-string (rod &optional
(default-char *invalid-rune
*))
161 (map 'string
(lambda (x) (rune-char x default-char
)) rod
))
163 (defun string-rod (string)
164 (let* ((n (length string
))
167 (setf (%rune res i
) (char-rune (char string i
))))
172 (defun rune<= (rune &rest more-runes
)
173 (apply #'<= rune more-runes
))
175 (defun rune>= (rune &rest more-runes
)
176 (apply #'>= rune more-runes
))
181 (defun rod-subseq (source start
&optional
(end (length source
)))
182 (unless (rodp source
)
183 (error "~S is not of type ~S." source
'rod
))
184 (unless (and (typep start
'fixnum
) (>= start
0))
185 (error "~S is not a non-negative fixnum." start
))
186 (unless (and (typep end
'fixnum
) (>= end start
))
187 (error "END argument, ~S, is not a fixnum no less than START, ~S." end start
))
188 (when (> start
(length source
))
189 (error "START argument, ~S, should be no greater than length of rod." start
))
190 (when (> end
(length source
))
191 (error "END argument, ~S, should be no greater than length of rod." end
))
193 (declare (type rod source
)
194 (type fixnum start end
))
195 (let ((res (make-rod (- end start
))))
196 (declare (type rod res
))
197 (do ((i (- (- end start
) 1) (the fixnum
(- i
1))))
199 (declare (type fixnum i
))
200 (setf (%rune res i
) (%rune source
(the fixnum
(+ i start
))))))))
202 (defun rod-subseq* (source start
&optional
(end (length source
)))
203 (unless (and (typep start
'fixnum
) (>= start
0))
204 (error "~S is not a non-negative fixnum." start
))
205 (unless (and (typep end
'fixnum
) (>= end start
))
206 (error "END argument, ~S, is not a fixnum no less than START, ~S." end start
))
207 (when (> start
(length source
))
208 (error "START argument, ~S, should be no greater than length of rod." start
))
209 (when (> end
(length source
))
210 (error "END argument, ~S, should be no greater than length of rod." end
))
212 (declare (type fixnum start end
))
213 (let ((res (make-rod (- end start
))))
214 (declare (type rod res
))
215 (do ((i (- (- end start
) 1) (the fixnum
(- i
1))))
217 (declare (type fixnum i
))
218 (setf (%rune res i
) (aref source
(the fixnum
(+ i start
))))))))
220 (defun rod< (rod1 rod2
)
223 (cond ((= i
(length rod1
))
227 ((< (aref rod1 i
) (aref rod2 i
))
229 ((> (aref rod1 i
) (aref rod2 i
))