git.fiddlerwoaroof.com
Browse code

Bugfix for string splitting

Ed Langley authored on 06/05/2019 05:45:24
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))