bug#54143: [PATCH] Add string-split-substring to ice-9 string-fun

Vijay Marupudi <[email protected]>
Newsgroups gmane.lisp.guile.bugs
Message-ID <[email protected]>
Hello,

I've attached a patch adding a new function, (string-split-substring str
substr), that splits a string into a list of multiple strings delimited
by a substring. The behavior matches (string-split str char/pred)
exactly.

~ Vijay
0001-Add-string-split-substring.patch (text/x-patch, 3.6 KB)
From 3c0940082ff49695ac9c2147c900b959be5f8e70 Mon Sep 17 00:00:00 2001
From: Vijay Marupudi <[email protected]>
Date: Sat, 12 Feb 2022 22:00:57 -0500
Subject: [PATCH] Add string-split-substring

* /ref/api-data.texi: Added documentation
* module/ice-9/string-fun.scm: Added implementation
* test-suite/tests/strings.test: Added tests
---
 doc/ref/api-data.texi         | 10 ++++++++++
 module/ice-9/string-fun.scm   | 23 ++++++++++++++++++++++-
 test-suite/tests/strings.test | 22 +++++++++++++++++++++-
 3 files changed, 53 insertions(+), 2 deletions(-)

diff --git a/doc/ref/api-data.texi b/doc/ref/api-data.texi
index 8658b9785..a5fcc47b1 100644
--- a/doc/ref/api-data.texi
+++ b/doc/ref/api-data.texi
@@ -4245,6 +4245,16 @@ Return a new string where every instance of @var{substring} in string
 @end lisp
 @end deffn
 
+@deffn {Scheme Procedure} string-split-substring str substring
+Split the string @var{str} into a list of substrings delimited by the
+appearance of substring @var{substring}. For example:
+
+@lisp
+(string-replace-substring "item-1::item-2::item-3::item-4" "::")
+@result{} ("item-1" "item-2" "item-3" "item-4")
+@end lisp
+@end deffn
+
 @node Representing Strings as Bytes
 @subsubsection Representing Strings as Bytes
 
diff --git a/module/ice-9/string-fun.scm b/module/ice-9/string-fun.scm
index 03e0238fa..a1d4c0366 100644
--- a/module/ice-9/string-fun.scm
+++ b/module/ice-9/string-fun.scm
@@ -26,7 +26,7 @@
 	   separate-fields-before-char string-prefix-predicate string-prefix=?
 	   sans-surrounding-whitespace sans-trailing-whitespace
 	   sans-leading-whitespace sans-final-newline has-trailing-newline?
-           string-replace-substring))
+           string-replace-substring string-split-substring))
 
 ;;;;
 ;;;
@@ -313,3 +313,24 @@
            (else
             (display (substring/shared str start)))))))))
 
+(define (string-split-substring str substr)
+  "Split the string @var{str} into a list of substrings delimited by the
+substring @var{substr}."
+
+  (define substrlen (string-length substr))
+  (define strlen (string-length str))
+
+  (define (loop index start)
+    (cond
+     ((>= start strlen) (list ""))
+     ((not index) (list (substring str start)))
+     (else
+      (cons (substring str start index)
+            (let ((new-start (+ index substrlen)))
+              (loop (string-contains str substr new-start)
+                    new-start))))))
+
+  (cond
+   ((string-contains str substr) => (lambda (idx) (loop idx 0)))
+   (else (list str))))
+
diff --git a/test-suite/tests/strings.test b/test-suite/tests/strings.test
index 7393bc8ec..8bc26e3e3 100644
--- a/test-suite/tests/strings.test
+++ b/test-suite/tests/strings.test
@@ -699,4 +699,24 @@
 
   (pass-if "string-replace-substring"
     (string=? (string-replace-substring "a ring of strings" "ring" "rut")
-              "a rut of struts")))
+              "a rut of struts"))
+
+  (pass-if "string-split-substring - empty string"
+    (equal? (string-split-substring "" "foo")
+            '("")))
+
+  (pass-if "string-split-substring - non-empty, no delimiters"
+    (equal? (string-split-substring "testing" "foo")
+            '("testing")))
+
+  (pass-if "string-split-substring - non-empty, delimiters"
+    (equal? (string-split-substring "testingfoobar" "foo")
+            '("testing" "bar")))
+
+  (pass-if "string-split-substring - non-empty, leading delimiters"
+    (equal? (string-split-substring "foobar" "foo")
+            '("" "bar")))
+
+  (pass-if "string-split-substring - non-empty, trailing delimiters"
+    (equal? (string-split-substring "barfoo" "foo")
+            (list "bar" ""))))
-- 
2.35.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.