2
;;;; Author: Paul Dietz
3
;;;; Created: Fri Oct 4 06:51:32 2002
4
;;;; Contains: Auxiliary functions for string testing
8
(defun my-string-compare (string1 string2 comparison
9
&key (start1 0) end1 (start2 0) end2 case
11
(len1 (progn (assert (stringp string1))
13
(len2 (progn (assert (stringp string2))
17
(< (if case #'char-lessp #'char<))
18
(<= (if case #'char-not-greaterp
20
(= (if case #'char-equal #'char=))
21
(/= (if case #'char-not-equal #'char/=))
22
(> (if case #'char-greaterp #'char>))
23
(>= (if case #'char-not-lessp #'char>=))
24
(t (error "Bad comparison arg: ~A~%"
26
(equal-fn (if case #'char-equal #'char=)))
28
(assert (integerp start1))
29
(assert (integerp start2))
30
(unless end1 (setq end1 len1))
31
(unless end2 (setq end2 len2))
32
(assert (<= 0 start1 end1))
33
(assert (<= 0 start2 end2))
43
;; Both ended -- equality case
44
(if (member comparison '(= <= >=))
47
(t ;; string2 still extending
48
(if (member comparison '(/= < <=))
52
;; string1 still extending
54
(if (member comparison '(/= > >=))
58
(let ((c1 (my-aref string1 i1))
59
(c2 (my-aref string2 i2)))
61
((funcall equal-fn c1 c2))
62
(t ;; mismatch found -- what kind?
64
(if (funcall compare-fn c1 c2)
68
(defun make-random-string-compare-test (n)
69
(let* ((len (random n))
70
;; Lengths of the two strings
71
(len1 (if (or (coin) (= len 0)) len (+ len (random len))))
72
(len2 (if (or (coin) (= len 0)) len (+ len (random len))))
73
;; Lengths of the parts of the strings to be matched
74
(sublen1 (if (or (coin) (= len1 0)) (min len1 len2) (random len1)))
75
(sublen2 (if (or (coin) (= len2 0)) (min len2 sublen1) (random len2)))
76
;; Start and end of the substring of the first string
77
(start1 (if (coin 3) 0
78
(max 0 (min (1- len1) (random (- len1 sublen1 -1))))))
79
(end1 (+ start1 sublen1))
80
;; Start and end of the substring of the second string
81
(start2 (if (coin 3) 0
82
(max 0 (min (1- len2) (random (- len2 sublen2 -1))))))
83
(end2 (+ start2 sublen2))
84
;; generate the strings
85
(s1 (make-random-string len1))
86
(s2 (make-random-string len2)))
88
(format t "len = ~A, len1 = ~A, len2 = ~A, sublen1 = ~A, sublen2 = ~A~%"
89
len len1 len2 sublen1 sublen2)
90
(format t "start1 = ~A, end1 = ~A, start2 = ~A, end2 = ~A~%"
91
start1 end1 start2 end2)
92
(format t "s1 = ~S, s2 = ~S~%" s1 s2)
94
;; Sometimes we want them to have a common prefix
96
(if (<= sublen1 sublen2)
97
(setf (subseq s2 start2 (+ start2 sublen1))
98
(subseq s1 start1 (+ start1 sublen1)))
99
(setf (subseq s1 start1 (+ start1 sublen2))
100
(subseq s2 start2 (+ start2 sublen2)))))
107
(if (and (= start1 0) (coin))
109
(list :start1 start1))
110
(if (and (= end1 len1) (coin))
113
(if (and (= start2 0) (coin))
115
(list :start2 start2))
116
(if (and (= end2 len2) (coin))
118
(list :end2 end2))))))))
120
(defun random-string-compare-test (n comparison case &optional (iterations 1))
121
(loop for i from 1 to iterations
123
(multiple-value-bind (s1 s2 args)
124
(make-random-string-compare-test n)
125
;; (format t "Args = ~S~%" args)
126
(let ((x (apply (case comparison
127
(< (if case #'string-lessp #'string<))
128
(<= (if case #'string-not-greaterp
130
(= (if case #'string-equal #'string=))
131
(/= (if case #'string-not-equal #'string/=))
132
(> (if case #'string-greaterp #'string>))
133
(>= (if case #'string-not-lessp #'string>=))
134
(t (error "Bad comparison arg: ~A~%" comparison)))
136
(y (apply #'my-string-compare s1 s2 comparison :case case args)))
139
(and x y (eqt comparison '=))))))))
141
(defparameter *use-random-byte* t)
143
(defun make-random-string (n)
144
(let ((s (random-case
146
(make-array n :element-type 'character
147
:initial-element #\a)
148
(make-array n :element-type 'standard-char
149
:initial-element #\a)
150
(make-array n :element-type 'base-char
151
:initial-element #\a))))
154
(setf (char s i) (elt #(#\a #\b #\A #\B) (random 4))))
158
(or (and *use-random-byte* (code-char (random 256)))
159
(elt "abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
163
(defun string-all-the-same (s)
164
(let ((len (length s)))
166
(let ((c (my-aref s 0)))
167
(loop for i below len
168
for d = (my-aref s i)
169
always (eql c d))))))