[Gd-chatter] r11685 - trunk/libraries/strings
cgay at gwydiondylan.org
cgay at gwydiondylan.org
Tue Feb 19 00:30:59 CET 2008
Author: cgay
Date: Tue Feb 19 00:30:59 2008
New Revision: 11685
Modified:
trunk/libraries/strings/library.dylan
trunk/libraries/strings/strings.dylan
Log:
job: 7372
Use new common-dylan split implementation.
Modified: trunk/libraries/strings/library.dylan
==============================================================================
--- trunk/libraries/strings/library.dylan (original)
+++ trunk/libraries/strings/library.dylan Tue Feb 19 00:30:59 2008
@@ -58,8 +58,6 @@
// Creation/modification/conversion
create
substring,
- join,
- split,
trim,
replace,
replace!,
@@ -86,8 +84,7 @@
//
define module strings-implementation
use strings; // Use API module
- use common-dylan,
- exclude: { split };
+ use common-dylan;
use streams,
import: { \with-output-to-string,
write,
@@ -100,10 +97,4 @@
<case-sensitive-character-set>,
<case-insensitive-character-set>,
<byte-character-table> };
- use regular-expressions,
- import: { <regex>,
- regex-search,
- match-group,
- group-start,
- group-end };
end module strings-implementation;
Modified: trunk/libraries/strings/strings.dylan
==============================================================================
--- trunk/libraries/strings/strings.dylan (original)
+++ trunk/libraries/strings/strings.dylan Tue Feb 19 00:30:59 2008
@@ -779,220 +779,6 @@
int
end method digit-to-integer;
-// ----------------------------------------------------------------------
-define open generic join
- (items :: <sequence>, separator :: <sequence>, #key key, conjunction)
- => (joined :: <sequence>);
-
-// join(range(from: 1, to: 3), ", ",
-// key: integer-to-string,
-// conjunction: " and ");
-// => "1, 2 and 3"
-
-define method join
- (sequences :: <sequence>, separator :: <sequence>,
- #key key :: <function> = identity,
- conjunction :: false-or(<sequence>))
- => (joined :: <sequence>)
- let length :: <integer> = sequences.size;
- if (length == 0)
- error("Attempt to join an empty sequence.")
- elseif (length == 1)
- key(sequences[0])
- else
- let result-size :: <integer>
- = (reduce(method (len, seq)
- len + seq.size
- end,
- 0,
- sequences)
- + (separator.size * (length - 1))
- + if (conjunction)
- // the last separator is replaced by the conjunction
- conjunction.size - separator.size
- else
- 0
- end);
- let first = key(sequences[0]); // don't call key > once on sequences[0]
- let result = make(object-class(first), size: result-size);
- let result-index :: <integer> = 0;
- local method copy-to-result (seq :: <sequence>)
- result := replace-subsequence!(result, seq, start: result-index);
- result-index := result-index + seq.size;
- end;
- copy-to-result(first);
- let max-index :: <integer> = length - 1;
- for (i :: <integer> from 1 to max-index)
- let seq :: <sequence> = sequences[i];
- copy-to-result(if(conjunction & i == max-index)
- conjunction
- else
- separator
- end);
- copy-to-result(key(seq));
- end;
- result
- end if
-end method join;
-
-
-
-// In common-dylan library...
-// Split a sequence into parts at each occurrance of the 'separator'
-// and return a sequence containing the parts. The sequence is
-// searched from beginning to end for the given 'separator' and stops
-// when it reaches the end of 'sequence' or when the size of the
-// result reaches 'count' elements. The meaning of the 'start' and
-// 'end' parameters may differ for different methods, but the intent
-// is that it be the same as if you passed in the subsequence delimited
-// by 'start' and 'end'. See the individual methods for details.
-//
-define generic split
- (sequence :: <sequence>, separator :: <object>,
- #key start :: <integer> = 0,
- end: _end :: false-or(<integer>),
- count :: false-or(<integer>))
- => (parts :: <sequence>);
-
-// In common-dylan library
-
-// This is in some sense the most basic method, since others can be
-// implemented in terms of it. The 'separator' function must accept
-// three arguments: (1) the sequence in which to search for a
-// separator, (2) the start index in that sequence at which to begin
-// searching, and (3) the index at which to stop searching, or #f to
-// search the entire sequence. The 'separator' function must return
-// #f to indicate that no separator was found, or two values: the
-// start and end indices of the separator in the given sequence. The
-// initial start and end indices passed to the 'separator' function
-// are the same as the 'start' and 'end' arguments passed to this
-// method. The 'separator' function should stay within the given
-// bounds whenever possible. (In particular it may not always be
-// possible when the separator is a regex.)
-define method split
- (seq :: <sequence>, find-separator :: <function>,
- #key start :: <integer> = 0,
- end: _end :: false-or(<integer>),
- count :: false-or(<integer>))
- => (parts :: <sequence>)
- let bpos = start;
- let epos :: <integer> = _end | seq.size;
- let parts = list(); // likely to be short
- // The use of epos below is an efficiency hack, but having more than
- // epos splits is impossible so it works.
- let max-parts :: <integer> = count | epos;
- let num-parts :: <integer> = 0;
- let separator-end = #f;
- while (bpos & bpos < epos & num-parts < max-parts)
- let (sep-start, sep-end) = find-separator(seq, bpos, epos);
- if (sep-start)
- parts := add!(parts, copy-sequence(seq, start: bpos, end: sep-start));
- separator-end := sep-end;
- num-parts := num-parts + 1;
- end;
- bpos := sep-end; // may be #f and terminate loop
- end while;
- parts := add!(parts, if (separator-end)
- copy-sequence(seq, start: separator-end, end: epos)
- else
- seq
- end);
- reverse!(parts)
-end method split;
-
-// In common-dylan library
-// Splits seq around occurrances of the separator subsequence.
-// Works for the relatively common case where seq and separator
-// are both <string>s.
-define method split
- (seq :: <sequence>, separator :: <sequence>,
- #key start :: <integer> = 0,
- end: _end :: false-or(<integer>),
- count :: false-or(<integer>))
- => (parts :: <sequence>)
- local method find-string (seq :: <sequence>,
- bpos :: <integer>,
- epos :: false-or(<integer>))
- // Note that this only splits on the separator sequence if it is
- // entirely contained between the start and end positions.
- let epos :: <integer> = epos | seq.size;
- let max-separator-start :: <integer> = epos - separator.size;
- block (exit-loop)
- for (seq-index from bpos to max-separator-start)
- if (looking-at?(separator, seq, seq-index))
- exit-loop(seq-index, seq-index + separator.size);
- end;
- end;
- #f // separator not found
- end
- end;
- split(seq, find-string, start: start, end: _end, count: count);
-end method split;
-
-// In common-dylan library
-// Split on a given object.
-// Covers the (<string>, <character>) case, for example.
-define method split
- (seq :: <sequence>, separator :: <object>,
- #key start :: <integer> = 0,
- end: _end :: false-or(<integer>),
- count :: false-or(<integer>))
- => (parts :: <sequence>)
- local method find-pos (seq :: <sequence>,
- bpos :: <integer>,
- epos :: false-or(<integer>))
- // Unfortunately common-dylan's position function doesn't accept
- // start and end parameters so we have to write our own.
- block (exit-loop)
- for (i from bpos below epos)
- // Should this use = or ==?
- // How should we provide case-insensitive comparisons?
- if (seq[i] = separator)
- exit-loop(i, i + 1)
- end;
- end;
- #f
- end block
- end method;
- split(seq, find-pos, start: start, end: _end, count: count);
-end method split;
-
-// In regular-expressions library
-define method split
- (seq :: <string>, separator :: <regex>,
- #key start :: <integer> = 0,
- end: _end :: false-or(<integer>),
- count :: false-or(<integer>))
- => (parts :: <sequence>)
- local method find-regex (seq :: <string>,
- bpos :: <integer>,
- epos :: false-or(<integer>))
- let match = regex-search(separator, seq, start: bpos, end: epos);
- if (match)
- let (ignore, match-start, match-end) = match-group(match, 0);
- values(match-start, match-end)
- else
- #f
- end
- end method find-regex;
- split(seq, find-regex, start: start, end: _end, count: count)
-end method split;
-
-// todo -- should this be exported?
-define method looking-at?
- (pattern :: <byte-string>, big :: <byte-string>, bpos :: <integer>)
- => (result :: <boolean>)
- block (return)
- let len :: <integer> = big.size;
- for (char in pattern, pos from bpos)
- if (pos >= len | char ~== big[pos])
- return(#f)
- end if;
- end for;
- #t
- end
-end method looking-at?;
-
define sealed method count-matches
(source :: <byte-string>, pattern :: <byte-string>,
#key test :: <function> = \==,
More information about the chatter
mailing list