Browse code
Bugfix for string splitting
Ed Langley authored on 06/05/2019 05:45:24
Showing 2 changed files
Showing 2 changed files
... | ... |
@@ -35,7 +35,8 @@ |
35 | 35 |
(simple-string (char= (aref string end-idx) char)) |
36 | 36 |
(string (char= (aref string end-idx) char))) |
37 | 37 |
(setf (aref parts target-spot) |
38 |
- (make-array (- end-idx start-idx) :displaced-to string :displaced-index-offset start-idx |
|
38 |
+ (make-array (- end-idx start-idx) |
|
39 |
+ :displaced-to string :displaced-index-offset start-idx |
|
39 | 40 |
:element-type 'character)) |
40 | 41 |
(incf target-spot) |
41 | 42 |
(setf start-idx (1+ end-idx)) |
... | ... |
@@ -79,7 +80,7 @@ |
79 | 80 |
0)) |
80 | 81 |
(find-pos (start-pos) |
81 | 82 |
(declare (optimize #+dev (debug 3) #+dev (speed 0) #+dev (space 0) |
82 |
- #-dev (speed 3) #-dev(space 2)) |
|
83 |
+ #-dev (speed 3) #-dev(space 2)) |
|
83 | 84 |
(type array-index start-pos)) |
84 | 85 |
(etypecase test |
85 | 86 |
(function (position divider string :start start-pos :test test)) |
... | ... |
@@ -90,18 +91,18 @@ |
90 | 91 |
(setf count (count-splits string))) |
91 | 92 |
|
92 | 93 |
(check-type count array-length) |
93 |
- (let ((parts (make-array (max count 1) :fill-pointer 0)) |
|
94 |
+ (let ((parts (make-array (max (1+ count) 1) :fill-pointer 0)) |
|
94 | 95 |
(start-pos (the fixnum 0))) |
95 | 96 |
(declare (dynamic-extent start-pos)) |
96 | 97 |
(prog1 parts |
97 | 98 |
(loop |
98 |
- for end-pos = (find-pos start-pos) |
|
99 |
- while end-pos |
|
100 |
- do |
|
99 |
+ for end-pos = (find-pos start-pos) |
|
100 |
+ while end-pos |
|
101 |
+ do |
|
101 | 102 |
(vector-push (subseq string start-pos end-pos) parts) |
102 | 103 |
(setf start-pos (1+ end-pos)) |
103 |
- while (< (length parts) (1- count)) |
|
104 |
- finally |
|
104 |
+ while (< (length parts) count) |
|
105 |
+ finally |
|
105 | 106 |
(cond ((or (and end-pos count) |
106 | 107 |
(< start-pos (length string))) |
107 | 108 |
(vector-push (subseq string start-pos) |
... | ... |
@@ -146,16 +147,16 @@ |
146 | 147 |
:fill-pointer 0)) |
147 | 148 |
(start-pos 0)) |
148 | 149 |
(loop |
149 |
- for end-pos = (typecase search-test |
|
150 |
- (function (%search-with-test start-pos search-test)) |
|
151 |
- (null (%search start-pos))) |
|
152 |
- do |
|
150 |
+ for end-pos = (typecase search-test |
|
151 |
+ (function (%search-with-test start-pos search-test)) |
|
152 |
+ (null (%search start-pos))) |
|
153 |
+ do |
|
153 | 154 |
(vector-push-extend (subseq string start-pos end-pos) parts) |
154 | 155 |
(incf (the array-length num-parts)) |
155 |
- while end-pos |
|
156 |
- do (setf start-pos (the array-length (+ pattern-length end-pos))) |
|
157 |
- until (and count (>= (1+ num-parts) count)) |
|
158 |
- finally |
|
156 |
+ while end-pos |
|
157 |
+ do (setf start-pos (the array-length (+ pattern-length end-pos))) |
|
158 |
+ until (and count (>= num-parts count)) |
|
159 |
+ finally |
|
159 | 160 |
(when (and count end-pos) |
160 | 161 |
(vector-push-extend (subseq string (+ pattern-length end-pos)) parts)) |
161 | 162 |
(return parts))))) |
... | ... |
@@ -10,10 +10,18 @@ |
10 | 10 |
(st:should be vos-equal |
11 | 11 |
#("a" "a" "a" "a") |
12 | 12 |
(%split-on-string "b" "abababa" :test #'string-equal))) |
13 |
- (st:deftest string-split-as-expected-with-count () |
|
13 |
+ (st:deftest string-split-as-expected-with-count-1 () |
|
14 | 14 |
(st:should be vos-equal |
15 | 15 |
#("a" "b c d") |
16 |
+ (%split-on-string " " "a b c d" :count 1))) |
|
17 |
+ (st:deftest string-split-as-expected-with-count-2 () |
|
18 |
+ (st:should be vos-equal |
|
19 |
+ #("a" "b" "c d") |
|
16 | 20 |
(%split-on-string " " "a b c d" :count 2))) |
21 |
+ (st:deftest string-split-as-expected-with-count-3 () |
|
22 |
+ (st:should be vos-equal |
|
23 |
+ #("a" "b" "c" "d") |
|
24 |
+ (%split-on-string " " "a b c d" :count 3))) |
|
17 | 25 |
(st:deftest string-split-as-expected-with-consecutive-sep () |
18 | 26 |
(st:should be vos-equal |
19 | 27 |
#("a" "b" "" "c" "d") |
... | ... |
@@ -47,10 +55,18 @@ |
47 | 55 |
(st:should be vos-equal |
48 | 56 |
#("a" "a" "a" "a") |
49 | 57 |
(%split-on-char #\b "abababa" :test #'char-equal))) |
50 |
- (st:deftest char-split-as-expected-with-count () |
|
58 |
+ (st:deftest char-split-as-expected-with-count-1 () |
|
51 | 59 |
(st:should be vos-equal |
52 | 60 |
#("a" "b c d") |
61 |
+ (%split-on-char #\space "a b c d" :count 1))) |
|
62 |
+ (st:deftest char-split-as-expected-with-count-2 () |
|
63 |
+ (st:should be vos-equal |
|
64 |
+ #("a" "b" "c d") |
|
53 | 65 |
(%split-on-char #\space "a b c d" :count 2))) |
66 |
+ (st:deftest char-split-as-expected-with-count-3 () |
|
67 |
+ (st:should be vos-equal |
|
68 |
+ #("a" "b" "c" "d") |
|
69 |
+ (%split-on-char #\space "a b c d" :count 3))) |
|
54 | 70 |
(st:deftest char-split-as-expected-with-consecutive-sep () |
55 | 71 |
(st:should be vos-equal |
56 | 72 |
#("a" "b" "" "c" "d") |
... | ... |
@@ -82,3 +98,30 @@ |
82 | 98 |
#("Bacon") |
83 | 99 |
(%split-on-char #\. "Bacon"))) |
84 | 100 |
) |
101 |
+ |
|
102 |
+(progn |
|
103 |
+ (unintern 'char-split-as-expected) |
|
104 |
+ (unintern 'char-split-as-expected-with-consecutive-sep) |
|
105 |
+ (unintern 'char-split-as-expected-with-test) |
|
106 |
+ (unintern 'char-split-as-expected-with-count) |
|
107 |
+ (unintern 'char-split-as-expected-with-count-1) |
|
108 |
+ (unintern 'char-split-as-expected-with-count-2) |
|
109 |
+ (unintern 'char-split-as-expected-with-count-3) |
|
110 |
+ (unintern 'char-split-as-expected-with-leading-and-trailing-sep) |
|
111 |
+ (unintern 'char-split-as-expected-with-leading-sep) |
|
112 |
+ (unintern 'char-split-as-expected-with-trailing-sep) |
|
113 |
+ (unintern 'string-split-as-expected) |
|
114 |
+ (unintern 'string-split-as-expected-with-consecutive-sep) |
|
115 |
+ (unintern 'string-split-as-expected-with-test) |
|
116 |
+ (unintern 'string-split-as-expected-with-count) |
|
117 |
+ (unintern 'string-split-as-expected-with-count-1) |
|
118 |
+ (unintern 'string-split-as-expected-with-count-2) |
|
119 |
+ (unintern 'string-split-as-expected-with-count-3) |
|
120 |
+ (unintern 'string-split-as-expected-with-leading-and-trailing-sep) |
|
121 |
+ (unintern 'string-split-as-expected-with-leading-sep) |
|
122 |
+ (unintern 'string-split-as-expected-with-test) |
|
123 |
+ (unintern 'string-split-as-expected-with-trailing-sep) |
|
124 |
+ (unintern 'string-split-empty-string-as-expected) |
|
125 |
+ (unintern 'string-split-multichar-as-expected) |
|
126 |
+ (unintern 'CHAR-SPLIT-NO-SEP-RETURNS-VEC-WITH-CONTENTS) |
|
127 |
+ (unintern 'CHAR-SPLIT-EMPTY-STRING-AS-EXPECTED)) |