#| -*-Scheme-*-
-$Id: string.scm,v 14.12 1995/07/27 21:33:44 adams Exp $
+$Id: string.scm,v 14.13 1997/06/26 22:55:46 adams Exp $
Copyright (c) 1988-1995 Massachusetts Institute of Technology
;;;; Character String Operations
;;; package: ()
+;; NOTE
+;;
+;; This file is designed to be compiled with type and range checking
+;; turned off. The advertised user-visible procedures all explicitly
+;; check their arguments.
+;;
+;; Many of the procedures are split into several user versions that just
+;; validate their arguments and pass them on to an internal version
+;; (prefixed with `%') that assumes all arguments have been checked.
+;; This avoids repeated argument checks.
+
(declare (usual-integrations))
\f
;;;; Primitives
;;; Substring Covers
(define (string=? string1 string2)
- (guarantee-2-strings string1 string2 'string=?)
+ (guarantee-2-strings string1 string2 'STRING=?)
(substring=? string1 0 (string-length string1)
string2 0 (string-length string2)))
(define (string-ci=? string1 string2)
- (guarantee-2-strings string1 string2 'string-ci=?)
+ (guarantee-2-strings string1 string2 'STRING-CI=?)
(substring-ci=? string1 0 (string-length string1)
string2 0 (string-length string2)))
(define (string<? string1 string2)
- (guarantee-2-strings string1 string2 'string<?)
+ (guarantee-2-strings string1 string2 'STRING<?)
(substring<? string1 0 (string-length string1)
string2 0 (string-length string2)))
(define (string-ci<? string1 string2)
- (guarantee-2-strings string1 string2 'string-ci<?)
+ (guarantee-2-strings string1 string2 'STRING-ci<?)
(substring-ci<? string1 0 (string-length string1)
string2 0 (string-length string2)))
(define (string>? string1 string2)
- (guarantee-2-strings string1 string2 'string>?)
+ (guarantee-2-strings string1 string2 'STRING>?)
(substring<? string2 0 (string-length string2)
string1 0 (string-length string1)))
(define (string-ci>? string1 string2)
- (guarantee-2-strings string1 string2 'string-ci>?)
+ (guarantee-2-strings string1 string2 'STRING-CI>?)
(substring-ci<? string2 0 (string-length string2)
string1 0 (string-length string1)))
(define (string>=? string1 string2)
- (guarantee-2-strings string1 string2 'string-ci>=?)
+ (guarantee-2-strings string1 string2 'STRING-CI>=?)
(not (substring<? string1 0 (string-length string1)
string2 0 (string-length string2))))
(define (string-ci>=? string1 string2)
- (guarantee-2-strings string1 string2 'string-ci>=?)
+ (guarantee-2-strings string1 string2 'STRING-CI>=?)
(not (substring-ci<? string1 0 (string-length string1)
string2 0 (string-length string2))))
(define (string<=? string1 string2)
- (guarantee-2-strings string1 string2 'string<=?)
+ (guarantee-2-strings string1 string2 'STRING<=?)
(not (substring<? string2 0 (string-length string2)
string1 0 (string-length string1))))
(define (string-ci<=? string1 string2)
- (guarantee-2-strings string1 string2 'string-ci<=?)
+ (guarantee-2-strings string1 string2 'STRING-ci<=?)
(not (substring-ci<? string2 0 (string-length string2)
string1 0 (string-length string1))))
(define (string-fill! string char)
- (guarantee-string string 'string-fill!)
+ (guarantee-string string 'STRING-FILL!)
(substring-fill! string 0 (string-length string) char))
-
+\f
(define (string-find-next-char string char)
- (guarantee-string string 'string-find-next-char)
+ (guarantee-string string 'STRING-FIND-NEXT-CHAR)
(substring-find-next-char string 0 (string-length string) char))
(define (string-find-previous-char string char)
- (guarantee-string string 'string-find-previous-char)
+ (guarantee-string string 'STRING-FIND-PREVIOUS-CHAR)
(substring-find-previous-char string 0 (string-length string) char))
(define (string-find-next-char-ci string char)
- (guarantee-string string 'string-find-next-char-ci)
+ (guarantee-string string 'STRING-FIND-NEXT-CHAR-CI)
(substring-find-next-char-ci string 0 (string-length string) char))
(define (string-find-previous-char-ci string char)
- (guarantee-string string 'string-find-previous-char-ci)
+ (guarantee-string string 'STRING-FIND-PREVIOUS-CHAR-CI)
(substring-find-previous-char-ci string 0 (string-length string) char))
(define (string-find-next-char-in-set string char-set)
- (guarantee-string string 'string-find-next-char-in-set)
+ (guarantee-string string 'STRING-FIND-NEXT-CHAR-IN-SET)
(substring-find-next-char-in-set string 0 (string-length string) char-set))
(define (string-find-previous-char-in-set string char-set)
- (guarantee-string string 'string-find-previous-char-in-set)
+ (guarantee-string string 'STRING-FIND-PREVIOUS-CHAR-IN-SET)
(substring-find-previous-char-in-set string 0 (string-length string)
char-set))
(define (string-match-forward string1 string2)
- (guarantee-2-strings string1 string2 'string-match-forward)
+ (guarantee-2-strings string1 string2 'STRING-MATCH-FORWARD)
(substring-match-forward string1 0 (string-length string1)
string2 0 (string-length string2)))
(define (string-match-backward string1 string2)
- (guarantee-2-strings string1 string2 'string-match-backward)
+ (guarantee-2-strings string1 string2 'STRING-MATCH-BACKWARD)
(substring-match-backward string1 0 (string-length string1)
string2 0 (string-length string2)))
(define (string-match-forward-ci string1 string2)
- (guarantee-2-strings string1 string2 'string-match-forward-ci)
+ (guarantee-2-strings string1 string2 'STRING-MATCH-FORWARD-CI)
(substring-match-forward-ci string1 0 (string-length string1)
string2 0 (string-length string2)))
(define (string-match-backward-ci string1 string2)
- (guarantee-2-strings string1 string2 'string-match-backward-ci)
+ (guarantee-2-strings string1 string2 'STRING-MATCH-BACKWARD-CI)
(substring-match-backward-ci string1 0 (string-length string1)
string2 0 (string-length string2)))
\f
;;;; Basic Operations
(define (make-string length #!optional char)
- (guarantee-index/string length 'make-string)
+ (guarantee-index/string length 'MAKE-STRING)
(if (default-object? char)
(string-allocate length)
(let ((result (string-allocate length)))
result)))
(define (string-null? string)
- (guarantee-string string 'string-null?)
+ (guarantee-string string 'STRING-NULL?)
(%string-null? string))
(define-integrable (%string-null? string)
result)))
(define (substring string start end)
- (guarantee-string string 'substring)
- (guarantee-index/string start 'substring)
- (guarantee-index/string end 'substring)
+ (guarantee-substring string start end 'SUBSTRING)
(%substring string start end))
(define (string-head string end)
- (guarantee-string string 'string-head)
- (guarantee-index/string end 'string-head)
+ (guarantee-string string 'STRING-HEAD)
+ (guarantee-index/string end 'STRING-HEAD)
(%substring string 0 end))
(define (string-tail string start)
- (guarantee-string string 'string-tail)
- (guarantee-index/string start 'string-tail)
+ (guarantee-string string 'STRING-TAIL)
+ (guarantee-index/string start 'STRING-TAIL)
(%substring string start (string-length string)))
(define (list->string chars)
(define char->string string)
(define (string->list string)
- (guarantee-string string 'string->list)
+ (guarantee-string string 'STRING->LIST)
(%substring->list string 0 (string-length string)))
-;; This version is unnecessarily recursive:
-;;
-;;(define (%substring->list string start end)
-;; (let loop ((index start))
-;; (if (fix:< index end)
-;; (cons (string-ref string index)
-;; (loop (fix:+ index 1)))
-;; '())))
-
(define (%substring->list string start end)
(let loop ((index (fix:- end 1)) (list '()))
(if (fix:>= index start)
list)))
(define (substring->list string start end)
- (guarantee-string string 'substring->list)
- (guarantee-index/string start 'substring->list)
- (guarantee-string-bound end string 'substring->list)
+ (guarantee-substring string start end 'SUBSTRING->LIST)
(%substring->list string start end))
(define (string-copy string)
- (guarantee-string string 'string-copy)
+ (guarantee-string string 'STRING-COPY)
(let ((size (string-length string)))
(let ((result (string-allocate size)))
(substring-move-right! string 0 size result 0)
(if (null? strings)
length
(begin
- (guarantee-string (car strings) 'string-append)
+ (guarantee-string (car strings) 'STRING-APPEND)
(loop (cdr strings)
(fix:+ (string-length (car strings)) length))))))))
;;;; Case
(define (string-upper-case? string)
- (guarantee-string string 'string-upper-case?)
+ (guarantee-string string 'STRING-UPPER-CASE?)
(%substring-upper-case? string 0 (string-length string)))
(define (substring-upper-case? string start end)
- (guarantee-string string 'substring-upper-case?)
- (guarantee-index/string start 'substring-upper-case?)
- (guarantee-string-bound end string 'substring-upper-case?)
+ (guarantee-substring string start end 'SUBSTRING-UPPER-CASE?)
(%substring-upper-case? string start end))
(define (%substring-upper-case? string start end)
string))
(define (string-upcase! string)
- (guarantee-string string 'string-upcase!)
+ (guarantee-string string 'STRING-UPCASE!)
(substring-upcase! string 0 (string-length string)))
-;;
(define (string-lower-case? string)
- (guarantee-string string 'string-lower-case?)
+ (guarantee-string string 'STRING-LOWER-CASE?)
(%substring-lower-case? string 0 (string-length string)))
(define (substring-lower-case? string start end)
- (guarantee-string string 'substring-lower-case?)
- (guarantee-index/string start 'substring-lower-case?)
- (guarantee-string-bound end string 'substring-lower-case?)
+ (guarantee-substring string start end 'SUBSTRING-LOWER-CASE?)
(%substring-lower-case? string start end))
(define (%substring-lower-case? string start end)
string))
(define (string-downcase! string)
- (guarantee-string string 'string-downcase!)
+ (guarantee-string string 'STRING-DOWNCASE!)
(substring-downcase! string 0 (string-length string)))
\f
(define (string-capitalized? string)
- (guarantee-string string 'string-capitalized?)
+ (guarantee-string string 'STRING-CAPITALIZED?)
(substring-capitalized? string 0 (string-length string)))
(define (substring-capitalized? string start end)
- (guarantee-string string 'substring-capitalized?)
- (guarantee-index/string start 'substring-capitalized?)
- (guarantee-string-bound end string 'substring-capitalized?)
+ (guarantee-substring string start end 'SUBSTRING-CAPITALIZED?)
(%substring-capitalized? string start end))
(define (%substring-capitalized? string start end)
string))
(define (string-capitalize! string)
- (guarantee-string string 'string-capitalize!)
+ (guarantee-string string 'STRING-CAPITALIZE!)
(substring-capitalize! string 0 (string-length string)))
(define (substring-capitalize! string start end)
string))
(define (string-replace! string char1 char2)
- (guarantee-string string 'string-replace!)
+ (guarantee-string string 'STRING-REPLACE!)
(substring-replace! string 0 (string-length string) char1 char2))
(define (substring-replace! string start end char1 char2)
;;;; Compare
(define (string-compare string1 string2 if= if< if>)
- (guarantee-2-strings string1 string2 'string-compare)
+ (guarantee-2-strings string1 string2 'STRING-COMPARE)
(let ((size1 (string-length string1))
(size2 (string-length string2)))
(let ((match (substring-match-forward string1 0 size1 string2 0 size2)))
if< if>)))))))
(define (string-prefix? string1 string2)
- (guarantee-2-strings string1 string2 'string-prefix?)
+ (guarantee-2-strings string1 string2 'STRING-PREFIX?)
(substring-prefix? string1 0 (string-length string1)
string2 0 (string-length string2)))
length))))
(define (string-suffix? string1 string2)
- (guarantee-2-strings string1 string2 'string-suffix?)
+ (guarantee-2-strings string1 string2 'STRING-SUFFIX?)
(substring-suffix? string1 0 (string-length string1)
string2 0 (string-length string2)))
length))))
(define (string-compare-ci string1 string2 if= if< if>)
- (guarantee-2-strings string1 string2 'string-compare-ci)
+ (guarantee-2-strings string1 string2 'STRING-COMPARE-CI)
(let ((size1 (string-length string1))
(size2 (string-length string2)))
(let ((match (substring-match-forward-ci string1 0 size1 string2 0 size2)))
if< if>)))))))
(define (string-prefix-ci? string1 string2)
- (guarantee-2-strings string1 string2 'string-prefix-ci?)
+ (guarantee-2-strings string1 string2 'STRING-PREFIX-CI?)
(substring-prefix-ci? string1 0 (string-length string1)
string2 0 (string-length string2)))
length))))
(define (string-suffix-ci? string1 string2)
- (guarantee-2-strings string1 string2 'string-suffix-ci?)
+ (guarantee-2-strings string1 string2 'STRING-SUFFIX-CI?)
(substring-suffix-ci? string1 0 (string-length string1)
string2 0 (string-length string2)))
(length (string-length string)))
(if (not index)
""
- (substring string index length))))
+ (%substring string index length))))
(define (string-trim-right string #!optional char-set)
(let ((index
char-set))))
(if (not index)
""
- (substring string 0 (fix:+ index 1)))))
+ (%substring string 0 (fix:+ index 1)))))
(define (string-trim string #!optional char-set)
(let ((char-set
(let ((index (string-find-next-char-in-set string char-set)))
(if (not index)
""
- (substring string
- index
- (fix:+ (string-find-previous-char-in-set string char-set)
- 1))))))
+ (%substring string
+ index
+ (fix:+ (string-find-previous-char-in-set string char-set)
+ 1))))))
(define (string-pad-right string n #!optional char)
- (guarantee-string string 'string-pad-right)
- (guarantee-index/string n 'string-pad-right)
+ (guarantee-string string 'STRING-PAD-RIGHT)
+ (guarantee-index/string n 'STRING-PAD-RIGHT)
(let ((length (string-length string)))
(if (fix:= length n)
string
result))))
(define (string-pad-left string n #!optional char)
- (guarantee-string string 'string-pad-left)
- (guarantee-index/string n 'string-pad-left)
+ (guarantee-string string 'STRING-PAD-LEFT)
+ (guarantee-index/string n 'STRING-PAD-LEFT)
(let ((length (string-length string)))
(if (fix:= length n)
string
(define (substring? substring string)
;; Returns starting-position or #f if not true.
- (guarantee-string substring 'substring?)
- (guarantee-string string 'substring?)
+ (guarantee-string substring 'SUBSTRING?)
+ (guarantee-string string 'SUBSTRING?)
(if (%string-null? substring)
0
(let ((len (string-length substring))
posn*
(loop posn*))))))))))
\f
+;;;; Guarantors
+;;
+;; The guarantors are integrated. Most are structured as combination of
+;; simple tests which the compiler can open-code, followed by a call to a
+;; GUARANTEE-.../FAIL version which does the tests again to signal a
+;; menaingful message. Structuring the code this way significantly
+;; reduces code bloat from large integrated procedures.
+
+
(define-integrable (guarantee-string object procedure)
(if (not (string? object))
(error:wrong-type-argument object "string" procedure)))
(define (guarantee-index/string/fail object procedure)
(error:wrong-type-argument object "valid string index"
procedure))
-;; Not used:
-;;(define-integrable (guarantee-string-index object string procedure)
-;; (guarantee-index/string object procedure)
-;; (if (not (fix:< object (string-length string)))
-;; (error:bad-range-argument object procedure)))
-(define-integrable (guarantee-string-bound object string procedure)
- (guarantee-index/string object procedure)
- (if (not (fix:<= object (string-length string)))
- (error:bad-range-argument object procedure)))
+(define-integrable (guarantee-substring string start end procedure)
+ (if (or (not (string? string))
+ (not (index-fixnum? start))
+ (not (index-fixnum? end))
+ (not (fix:<= start end))
+ (not (fix:<= end (string-length string))))
+ (guarantee-substring/fail string start end procedure)))
+
+(define (guarantee-substring/fail string start end procedure)
+ (guarantee-string string procedure)
+ (guarantee-index/string start procedure)
+ (guarantee-index/string end procedure)
+ (if (not (fix:<= end (string-length string)))
+ (error:bad-range-argument end procedure))
+ (if (not (fix:<= start end))
+ (error:bad-range-argument start procedure)))