;;;; string-fun.scm --- string manipulation functions ;;;; ;;;; Copyright (C) 1995, 1996, 1997, 1999, 2001, 2006 Free Software Foundation, Inc. ;;;; ;;;; This library is free software; you can redistribute it and/or ;;;; modify it under the terms of the GNU Lesser General Public ;;;; License as published by the Free Software Foundation; either ;;;; version 3 of the License, or (at your option) any later version. ;;;; ;;;; This library is distributed in the hope that it will be useful, ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;;; Lesser General Public License for more details. ;;;; ;;;; You should have received a copy of the GNU Lesser General Public ;;;; License along with this library; if not, write to the Free Software ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ;;;; (define-module (ice-9 string-fun) :export (split-after-char split-before-char split-discarding-char split-after-char-last split-before-char-last split-discarding-char-last split-before-predicate split-after-predicate split-discarding-predicate separate-fields-discarding-char separate-fields-after-char separate-fields-before-char string-prefix-predicate string-prefix=? sans-surrounding-whitespace sans-trailing-whitespace sans-leading-whitespace sans-final-newline has-trailing-newline?)) ;;;; ;;; ;;; Various string funcitons, particularly those that take ;;; advantage of the "shared substring" capability. ;;; ;;; {String Fun: Dividing Strings Into Fields} ;;; ;;; The names of these functions are very regular. ;;; Here is a grammar of a call to one of these: ;;; ;;; <string-function-invocation> ;;; := (<action>-<seperator-disposition>-<seperator-determination> <seperator-param> <str> <ret>) ;;; ;;; <str> = the string ;;; ;;; <ret> = The continuation. String functions generally return ;;; multiple values by passing them to this procedure. ;;; ;;; <action> = split ;;; | separate-fields ;;; ;;; "split" means to divide a string into two parts. ;;; <ret> will be called with two arguments. ;;; ;;; "separate-fields" means to divide a string into as many ;;; parts as possible. <ret> will be called with ;;; however many fields are found. ;;; ;;; <seperator-disposition> = before ;;; | after ;;; | discarding ;;; ;;; "before" means to leave the seperator attached to ;;; the beginning of the field to its right. ;;; "after" means to leave the seperator attached to ;;; the end of the field to its left. ;;; "discarding" means to discard seperators. ;;; ;;; Other dispositions might be handy. For example, "isolate" ;;; could mean to treat the separator as a field unto itself. ;;; ;;; <seperator-determination> = char ;;; | predicate ;;; ;;; "char" means to use a particular character as field seperator. ;;; "predicate" means to check each character using a particular predicate. ;;; ;;; Other determinations might be handy. For example, "character-set-member". ;;; ;;; <seperator-param> = A parameter that completes the meaning of the determinations. ;;; For example, if the determination is "char", then this parameter ;;; says which character. If it is "predicate", the parameter is the ;;; predicate. ;;; ;;; ;;; For example: ;;; ;;; (separate-fields-discarding-char #\, "foo, bar, baz, , bat" list) ;;; => ("foo" " bar" " baz" " " " bat") ;;; ;;; (split-after-char #\- 'an-example-of-split list) ;;; => ("an-" "example-of-split") ;;; ;;; As an alternative to using a determination "predicate", or to trying to do anything ;;; complicated with these functions, consider using regular expressions. ;;; (define (split-after-char char str ret) (let ((end (cond ((string-index str char) => 1+) (else (string-length str))))) (ret (substring str 0 end) (substring str end)))) (define (split-before-char char str ret) (let ((end (or (string-index str char) (string-length str)))) (ret (substring str 0 end) (substring str end)))) (define (split-discarding-char char str ret) (let ((end (string-index str char))) (if (not end) (ret str "") (ret (substring str 0 end) (substring str (1+ end)))))) (define (split-after-char-last char str ret) (let ((end (cond ((string-rindex str char) => 1+) (else 0)))) (ret (substring str 0 end) (substring str end)))) (define (split-before-char-last char str ret) (let ((end (or (string-rindex str char) 0))) (ret (substring str 0 end) (substring str end)))) (define (split-discarding-char-last char str ret) (let ((end (string-rindex str char))) (if (not end) (ret str "") (ret (substring str 0 end) (substring str (1+ end)))))) (define (split-before-predicate pred str ret) (let loop ((n 0)) (cond ((= n (string-length str)) (ret str "")) ((not (pred (string-ref str n))) (loop (1+ n))) (else (ret (substring str 0 n) (substring str n)))))) (define (split-after-predicate pred str ret) (let loop ((n 0)) (cond ((= n (string-length str)) (ret str "")) ((not (pred (string-ref str n))) (loop (1+ n))) (else (ret (substring str 0 (1+ n)) (substring str (1+ n))))))) (define (split-discarding-predicate pred str ret) (let loop ((n 0)) (cond ((= n (string-length str)) (ret str "")) ((not (pred (string-ref str n))) (loop (1+ n))) (else (ret (substring str 0 n) (substring str (1+ n))))))) (define (separate-fields-discarding-char ch str ret) (let loop ((fields '()) (str str)) (cond ((string-rindex str ch) => (lambda (w) (loop (cons (substring str (+ 1 w)) fields) (substring str 0 w)))) (else (apply ret str fields))))) (define (separate-fields-after-char ch str ret) (reverse (let loop ((fields '()) (str str)) (cond ((string-index str ch) => (lambda (w) (loop (cons (substring str 0 (+ 1 w)) fields) (substring str (+ 1 w))))) (else (apply ret str fields)))))) (define (separate-fields-before-char ch str ret) (let loop ((fields '()) (str str)) (cond ((string-rindex str ch) => (lambda (w) (loop (cons (substring str w) fields) (substring str 0 w)))) (else (apply ret str fields))))) ;;; {String Fun: String Prefix Predicates} ;;; ;;; Very simple: ;;; ;;; (define-public ((string-prefix-predicate pred?) prefix str) ;;; (and (<= (string-length prefix) (string-length str)) ;;; (pred? prefix (substring str 0 (string-length prefix))))) ;;; ;;; (define-public string-prefix=? (string-prefix-predicate string=?)) ;;; (define (string-prefix-predicate pred?) (lambda (prefix str) (and (<= (string-length prefix) (string-length str)) (pred? prefix (substring str 0 (string-length prefix)))))) (define string-prefix=? (string-prefix-predicate string=?)) ;;; {String Fun: Strippers} ;;; ;;; <stripper> = sans-<removable-part> ;;; ;;; <removable-part> = surrounding-whitespace ;;; | trailing-whitespace ;;; | leading-whitespace ;;; | final-newline ;;; (define (sans-surrounding-whitespace s) (let ((st 0) (end (string-length s))) (while (and (< st (string-length s)) (char-whitespace? (string-ref s st))) (set! st (1+ st))) (while (and (< 0 end) (char-whitespace? (string-ref s (1- end)))) (set! end (1- end))) (if (< end st) "" (substring s st end)))) (define (sans-trailing-whitespace s) (let ((st 0) (end (string-length s))) (while (and (< 0 end) (char-whitespace? (string-ref s (1- end)))) (set! end (1- end))) (if (< end st) "" (substring s st end)))) (define (sans-leading-whitespace s) (let ((st 0) (end (string-length s))) (while (and (< st (string-length s)) (char-whitespace? (string-ref s st))) (set! st (1+ st))) (if (< end st) "" (substring s st end)))) (define (sans-final-newline str) (cond ((= 0 (string-length str)) str) ((char=? #\nl (string-ref str (1- (string-length str)))) (substring str 0 (1- (string-length str)))) (else str))) ;;; {String Fun: has-trailing-newline?} ;;; (define (has-trailing-newline? str) (and (< 0 (string-length str)) (char=? #\nl (string-ref str (1- (string-length str)))))) ;;; {String Fun: with-regexp-parts} ;;; This relies on the older, hairier regexp interface, which we don't ;;; particularly want to implement, and it's not used anywhere, so ;;; we're just going to drop it for now. ;;; (define-public (with-regexp-parts regexp fields str return fail) ;;; (let ((parts (regexec regexp str fields))) ;;; (if (number? parts) ;;; (fail parts) ;;; (apply return parts))))
Name | Type | Size | Permission | Actions |
---|---|---|---|---|
peg | Folder | 0755 |
|
|
and-let-star.scm | File | 2.53 KB | 0644 |
|
arrays.scm | File | 2.63 KB | 0644 |
|
atomic.scm | File | 1.55 KB | 0644 |
|
binary-ports.scm | File | 1.99 KB | 0644 |
|
boot-9.scm | File | 143.94 KB | 0644 |
|
buffered-input.scm | File | 4.82 KB | 0644 |
|
calling.scm | File | 10.54 KB | 0644 |
|
channel.scm | File | 5.19 KB | 0644 |
|
command-line.scm | File | 18.2 KB | 0644 |
|
common-list.scm | File | 8.95 KB | 0644 |
|
control.scm | File | 4.08 KB | 0644 |
|
curried-definitions.scm | File | 1.79 KB | 0644 |
|
debug.scm | File | 1.09 KB | 0644 |
|
deprecated.scm | File | 2.95 KB | 0644 |
|
documentation.scm | File | 7.41 KB | 0644 |
|
eval-string.scm | File | 2.99 KB | 0644 |
|
eval.scm | File | 25.12 KB | 0644 |
|
expect.scm | File | 5.5 KB | 0644 |
|
fdes-finalizers.scm | File | 1.06 KB | 0644 |
|
format.scm | File | 74.37 KB | 0644 |
|
ftw.scm | File | 24.17 KB | 0644 |
|
futures.scm | File | 10.49 KB | 0644 |
|
gap-buffer.scm | File | 10.14 KB | 0644 |
|
getopt-long.scm | File | 16.49 KB | 0644 |
|
hash-table.scm | File | 1.77 KB | 0644 |
|
hcons.scm | File | 2.55 KB | 0644 |
|
history.scm | File | 2.29 KB | 0644 |
|
i18n.scm | File | 20.51 KB | 0644 |
|
iconv.scm | File | 3.65 KB | 0644 |
|
lineio.scm | File | 3.85 KB | 0644 |
|
list.scm | File | 1.29 KB | 0644 |
|
local-eval.scm | File | 9.96 KB | 0644 |
|
ls.scm | File | 3.2 KB | 0644 |
|
mapping.scm | File | 4.84 KB | 0644 |
|
match.scm | File | 2 KB | 0644 |
|
match.upstream.scm | File | 35.92 KB | 0644 |
|
networking.scm | File | 3.33 KB | 0644 |
|
null.scm | File | 1.13 KB | 0644 |
|
occam-channel.scm | File | 7.26 KB | 0644 |
|
optargs.scm | File | 15.75 KB | 0644 |
|
peg.scm | File | 1.64 KB | 0644 |
|
poe.scm | File | 3.3 KB | 0644 |
|
poll.scm | File | 5.79 KB | 0644 |
|
popen.scm | File | 6.82 KB | 0644 |
|
ports.scm | File | 18.89 KB | 0644 |
|
posix.scm | File | 2.73 KB | 0644 |
|
pretty-print.scm | File | 16.88 KB | 0644 |
|
psyntax-pp.scm | File | 180.55 KB | 0644 |
|
psyntax.scm | File | 148.7 KB | 0644 |
|
q.scm | File | 4.2 KB | 0644 |
|
quasisyntax.scm | File | 5.22 KB | 0644 |
|
r5rs.scm | File | 1.56 KB | 0644 |
|
r6rs-libraries.scm | File | 9.43 KB | 0644 |
|
rdelim.scm | File | 7.72 KB | 0644 |
|
readline.scm | File | 9.56 KB | 0644 |
|
receive.scm | File | 1.06 KB | 0644 |
|
regex.scm | File | 8.87 KB | 0644 |
|
runq.scm | File | 8.18 KB | 0644 |
|
rw.scm | File | 1.02 KB | 0644 |
|
safe-r5rs.scm | File | 3.72 KB | 0644 |
|
safe.scm | File | 1.25 KB | 0644 |
|
sandbox.scm | File | 34.23 KB | 0644 |
|
save-stack.scm | File | 2.15 KB | 0644 |
|
scm-style-repl.scm | File | 11.62 KB | 0644 |
|
serialize.scm | File | 3.78 KB | 0644 |
|
session.scm | File | 17.72 KB | 0644 |
|
slib.scm | File | 1.55 KB | 0644 |
|
stack-catch.scm | File | 1.94 KB | 0644 |
|
streams.scm | File | 5.86 KB | 0644 |
|
string-fun.scm | File | 8.59 KB | 0644 |
|
suspendable-ports.scm | File | 29.87 KB | 0644 |
|
syncase.scm | File | 1.52 KB | 0644 |
|
textual-ports.scm | File | 2.29 KB | 0644 |
|
threads.scm | File | 12.54 KB | 0644 |
|
time.scm | File | 2.07 KB | 0644 |
|
top-repl.scm | File | 2.75 KB | 0644 |
|
unicode.scm | File | 1005 B | 0644 |
|
vlist.scm | File | 21.56 KB | 0644 |
|
weak-vector.scm | File | 1.2 KB | 0644 |
|