str.sa
Generated by gen_html_sa_files from ICSI. Contact gomes@icsi.berkeley.edu for details
---------------------------> Sather 1.1 source file <--------------------------
-- Copyright (C) International Computer Science Institute, 1994. COPYRIGHT --
-- NOTICE: This code is provided "AS IS" WITHOUT ANY WARRANTY and is subject --
-- to the terms of the SATHER LIBRARY GENERAL PUBLIC LICENSE contained in --
-- the file "Doc/License" of the Sather distribution. The license is also --
-- available from ICSI, 1947 Center St., Suite 600, Berkeley CA 94704, USA. --
--------> Please email comments to sather-bugs@icsi.berkeley.edu. <----------
-- str.sa: Strings.
-- Integrated Rob's changes (escape, minus)
class STR < $IS_LT{STR},$HASH,$STR,$ELT{CHAR},$FMT
class STR < $IS_LT{STR},$HASH,$STR,$ELT{CHAR},$FMT is
-- Strings are represented as arrays of characters. Every
-- character is significant.
--
-- References: Gonnet and Baeza-Yates, "Handbook of Algorithms and
-- Data Structures", Addison Wesley, 1991.
include COMPARABLE;
private include AREF{CHAR} aget -> aget;
-- Make modification routines private.
private shared buf:FSTR; -- Character buffer.
create:SAME is
-- An empty string. (Occasionally useful in constructs like
-- `#STR + foo').
return "" end;
create(c:CHAR):SAME is
-- String containing the single character 'c'.
r::=new(1);
r[0]:=c;
return r;
end;
create_from_file(nm:STR):SAME is
-- Open the file named `nm' in the current directory, create a
-- string containing its contents and then close the file. Return
-- void if there is no such file.
fd::=RUNTIME::rt_file_open(nm);
if fd<0 then return void end;
sz::=RUNTIME::rt_file_size(fd);
r::=new(sz);
RUNTIME::rt_file_in_str(fd,r,0,sz);
RUNTIME::rt_file_close(fd);
return r
end;
create_from_file_range(nm:STR,st,sz:INT):SAME is
-- Open the file named `nm' in the current directory, create a
-- string containing `sz' characters starting at `st'. Fill in
-- the remainder with '\0' if the file is too small. Return
-- void if there is no such file.
fd::=RUNTIME::rt_file_open(nm);
if fd<0 then return void end;
fsz::=RUNTIME::rt_file_size(fd);
r::=new(sz);
if st+sz<fsz then RUNTIME::rt_file_in_str(fd,r,st,sz);
else RUNTIME::rt_file_in_str(fd,r,st,fsz-st) end;
RUNTIME::rt_file_close(fd);
return r
end;
create_from_c_string(s:EXT_OB):SAME is
-- Create a Sather string from a C pointer. Needless to say,
-- use this with caution.
if void(s) then return void end;
len::=RUNTIME::strlen(s);
r::=new(len);
ext::=RUNTIME::memcpy(r,s,len);
return r;
end;
create_from_memory_area(s:EXT_OB,len:INT):SAME is
-- Create a Sather string from a memory area of size
-- 'len' bytes starting at 's'. Needless to say,
-- use this with caution.
if void(s) or len<=0 then return void end;
r::=new(len);
ext::=RUNTIME::memcpy(r,s,len);
return r;
end;
size:INT is
-- The number of characters in self. 0 if self is void.
if void(self) then return 0 else return asize end
end;
cursor: STR_CURSOR is return #STR_CURSOR(self) end;
length:INT is
-- The number of characters in self. 0 if self is void.
-- Another name for `size'.
if void(self) then return 0 else return asize end
end;
char(i:INT):CHAR
-- The character at index `i' of self.
pre i.is_bet(0,asize-1) is
return [i]
end;
acopyn(s:FSTR,n:INT) pre n <= s.length is
-- copy "n" chars from "s" into "self". Built-in.
builtin STR_ACOPY_FSTR_INT;
end;
acopyn(s:STR,n:INT) pre n <= s.length is
-- copy "n" chars from "s" into "self". Built-in.
builtin STR_ACOPY_STR_INT;
end;
from_fstr(s:FSTR):SAME is
-- A new string with the characters currently held in `s'.
-- Returns empty string if emtpy. Modified MBK.
sz ::= s.size; -- save it.
if sz=0 then return "" end;
r::=new(sz);
r.acopyn(s,sz);
-- loop r.aset!(s.elt!) end;
return r
end;
fstr:FSTR is
-- An FSTR with the same characters as self.
-- if size=0 then return void; end;
-- r::=#FSTR(size);
-- loop r:=r.push(elt!); end;
-- return r;
-- end;
return #FSTR(self);
end;
plus(sarg:$STR):SAME is
-- A new string obtained by appending `sarg' to self.
-- Either self or `s' may be void. Sped up, MBK et al.
-- This is the most general version. Specialized versions
-- exploiting Sather 1.1 overloading rules follow
can_delete:BOOL:=false;
s:STR;
-- This is a hack. Om's STR representation allows 'void'
-- for "", but that breaks $STR dispatching. For the
-- moment assume that any void arg must represent something
-- that translates to "" and so there's no append. The
-- correct thing to do, however, is to get rid of the
-- bad representation elsewhere in the libraries.
if void(sarg) then return self end;
s:=sarg.str;
return append_destroy(s, false);
end;
-- Specialized versions of plus
plus(sarg:STR):SAME is
return append(sarg);
end;
-- the following ones could be optimized if one gets excited about
-- it
plus(sarg:FSTR):SAME is
s::=sarg.str;
return append_destroy(s, true);
end;
plus(arg:INT):SAME is
s::=arg.str;
return append_destroy(s, true);
end;
plus(arg:CHAR):SAME is
s::=arg.str;
return append_destroy(s, true);
end;
append_destroy(s:SAME, destroy:BOOL):SAME is
-- appends s to self and destroys s if possible
r:STR;
if size=0 then return s
else
sz ::= s.size;
if sz=0 then return self
else
r:=new(asize+sz);
r.acopyn(self,asize);
r.acopy(asize,s);
end;
end;
if destroy and ~void(s) then
-- 's' was just a temporary
SYS::destroy(s);
end;
return r;
end;
append(s:SAME):SAME is
-- A new string obtained by appending `s' to self.
-- Either self or `s' may be void.
if void(self) then return s; end;
if void(s) then return self; end;
selfsize::=asize;
ssize::=s.asize;
r::=new(selfsize+ssize);
r.acopy(self);
r.acopy(selfsize,s);
return r;
end;
append(s1,s2:SAME):SAME is
-- A new string obtained by appending args to self.
-- Any of the strings may be void.
if void(self) then return s1.append(s2); end;
if void(s1) then return self.append(s2); end;
if void(s2) then return self.append(s1); end;
p1::=asize;
p2::=p1+s1.asize;
p3::=p2+s2.asize;
r::=new(p3);
r.acopy(self);
r.acopy(p1,s1);
r.acopy(p2,s2);
return r;
end;
append(s1,s2,s3:SAME):SAME is
-- A new string obtained by appending args to self.
-- Any of the strings may be void.
if void(self) then return s1.append(s2,s3); end;
if void(s1) then return self.append(s2,s3); end;
if void(s2) then return self.append(s1,s3); end;
if void(s3) then return self.append(s1,s2); end;
p1::=asize;
p2::=p1+s1.asize;
p3::=p2+s2.asize;
p4::=p3+s3.asize;
r::=new(p4);
r.acopy(self);
r.acopy(p1,s1);
r.acopy(p2,s2);
r.acopy(p3,s3);
return r;
end;
append(s1,s2,s3,s4:SAME):SAME is
-- A new string obtained by appending args to self.
-- Any of the strings may be void.
if void(self) then return s1.append(s2,s3,s4); end;
if void(s1) then return self.append(s2,s3,s4); end;
if void(s2) then return self.append(s1,s3,s4); end;
if void(s3) then return self.append(s1,s2,s4); end;
if void(s3) then return self.append(s1,s2,s3); end;
p1::=asize;
p2::=p1+s1.asize;
p3::=p2+s2.asize;
p4::=p3+s3.asize;
p5::=p4+s4.asize;
r::=new(p5);
r.acopy(self);
r.acopy(p1,s1);
r.acopy(p2,s2);
r.acopy(p3,s3);
r.acopy(p4,s4);
return r;
end;
append(s1,s2,s3,s4,s5:SAME):SAME is
-- A new string obtained by appending args to self.
-- Any of the strings may be void.
if void(self) then return s1.append(s2,s3,s4,s5); end;
if void(s1) then return self.append(s2,s3,s4,s5); end;
if void(s2) then return self.append(s1,s3,s4,s5); end;
if void(s3) then return self.append(s1,s2,s4,s5); end;
if void(s3) then return self.append(s1,s2,s3,s5); end;
if void(s3) then return self.append(s1,s2,s3,s4); end;
p1::=asize;
p2::=p1+s1.asize;
p3::=p2+s2.asize;
p4::=p3+s3.asize;
p5::=p4+s4.asize;
p6::=p5+s5.asize;
r::=new(p6);
r.acopy(self);
r.acopy(p1,s1);
r.acopy(p2,s2);
r.acopy(p3,s3);
r.acopy(p4,s4);
r.acopy(p5,s5);
return r;
end;
append(s1,s2,s3,s4,s5,s6:SAME):SAME is
-- A new string obtained by appending args to self.
-- Any of the strings may be void.
if void(self) then return s1.append(s2,s3,s4,s5,s6); end;
if void(s1) then return self.append(s2,s3,s4,s5,s6); end;
if void(s2) then return self.append(s1,s3,s4,s5,s6); end;
if void(s3) then return self.append(s1,s2,s4,s5,s6); end;
if void(s3) then return self.append(s1,s2,s3,s5,s6); end;
if void(s3) then return self.append(s1,s2,s3,s4,s6); end;
if void(s3) then return self.append(s1,s2,s3,s4,s5); end;
p1::=asize;
p2::=p1+s1.asize;
p3::=p2+s2.asize;
p4::=p3+s3.asize;
p5::=p4+s4.asize;
p6::=p5+s5.asize;
p7::=p6+s6.asize;
r::=new(p7);
r.acopy(self);
r.acopy(p1,s1);
r.acopy(p2,s2);
r.acopy(p3,s3);
r.acopy(p4,s4);
r.acopy(p5,s5);
r.acopy(p6,s6);
return r;
end;
str:STR is
return self; end;
fmt( f: STR ): STR is
return BASE_FORMAT::fmt_str( self, f )
end;
pretty:STR is
-- Pretty print self. This surrounds the string with
-- a pair of double quotes. Any non-printing characters or double
-- quotes are replaced by their special codes or the octal
-- representation.
buf.clear; buf:=buf+'\"';
loop c::=elt!;
if c.is_print and c/='\"' and c/='\\' then buf:=buf+c
else buf:=buf + '\\';
case c
when '\a' then buf:=buf+'a' when '\b' then buf:=buf+'b'
when '\f' then buf:=buf+'f' when '\n' then buf:=buf+'n'
when '\r' then buf:=buf+'r' when '\t' then buf:=buf+'t'
when '\v' then buf:=buf+'v' when '\\' then buf:=buf+'\\'
when '\"' then buf:=buf+'\"'
else s::=c.int.octal_str;
buf:=buf+s.tail(s.size-2) end end end;
buf:=buf+'\"'; return buf.str end;
as_literal:STR is
-- Returns the string described by self assuming it is in "string
-- literal" form. This means it must begin and end with double
-- quotes and must not contain any non-printing characters.
-- The returned string eliminates the initial and final double
-- quotes and converts any escape codes to the corresponding
-- characters. self may consist of several double-quote enclosed
-- strings separated by whitespace. In this case the strings are
-- concatenated together. If self is not in correct string literal
-- format, returns void.
if void(self) or size<2 or [0]/='\"' or [size-1]/='\"' then
return void
end;
buf.clear; esc,oct,qt:BOOL; oval:INT;
loop c::=aelt!(1,size-2);
if qt then -- We're between concatted strings.
if c='\"' then qt:=false
elsif ~c.is_space then return void end;
else
if oct then -- we're in an octal escape code
if c.is_octal_digit then oval:=oval*8+c.octal_digit_value
else buf:=buf+oval.char; oct:=false; esc:=false end end;
if ~oct then
if esc then -- we've seen only a '\'
case c
when 'a' then buf:=buf+'\a'; esc:=false
when 'b' then buf:=buf+'\b'; esc:=false
when 'f' then buf:=buf+'\f'; esc:=false
when 'n' then buf:=buf+'\n'; esc:=false
when 'r' then buf:=buf+'\r'; esc:=false
when 't' then buf:=buf+'\t'; esc:=false
when 'v' then buf:=buf+'\v'; esc:=false
when '\\' then buf:=buf+'\\'; esc:=false
when '\"' then buf:=buf+'\"'; esc:=false
when '\'' then buf:=buf+'\''; esc:=false
when 0,1,2,3,4,5,6,7 then
oct:=true; oval:=c.octal_digit_value
else return void end; -- illegal escape code
elsif c='\\' then esc:=true
elsif c='\"' then qt:=true
elsif c.is_print then buf:=buf+c
else return void end; -- Illegal character
end end end;
if qt then return void -- Must close internal quotes.
elsif oct then buf:=buf+oval.char -- Ended with octal code.
elsif esc then return void end; -- Ended with '\'
return buf.str end;
is_empty:BOOL is
-- True if self has no characters.
-- Self may be void.
return (void(self)) or (asize=0) end;
private is_eq_helper(s:SAME,i:INT):BOOL is
-- Matt Kennel, INLS. The reason for this
-- function's existence is that it will be overridden
-- by "memcmp" in MACROS.
loop if aelt!/=s.aelt! then return false end; end;
return true;
end;
is_eq(s:SAME):BOOL is
-- True if `s' equals self. Either may be void.
if void(self) then
if void(s) then return true
elsif s.asize=0 then return true
else return false end;
elsif void(s) then
if asize=0 then return true else return false end
elsif asize/=s.asize then return false
else
return is_eq_helper(s,asize);
end;
end;
is_lt(s:SAME):BOOL is
-- True if self is lexicographically before `s'.
-- Void is taken to be before everything else.
if size=0 then
if s.size/=0 then return true else return false end
elsif s.size=0 then return false
else
loop c::=aelt!; sc::=s.aelt!;
if c>sc then return false
elsif c<sc then return true end end;
if size<s.size then return true
else return false end
end
end;
is_leq(s:SAME):BOOL is
-- True if self is lexicographically before `s' or equal to it.
-- Either may be void.
if size=0 then return true
elsif s.size=0 then return false
else
loop c::=aelt!; sc::=s.aelt!;
if c>sc then return false
elsif c<sc then return true end end;
if size<=s.size then return true
else return false end
end
end;
is_upper:BOOL is
-- True if each alphabetic character of self is upper case.
-- Self may be void.
loop if ~elt!.is_upper then return false end end;
return true
end;
is_lower:BOOL is
-- True if each alphabetic character of self is lower case.
-- Self may be void.
loop if ~elt!.is_lower then return false end end;
return true
end;
upper:SAME is
-- A copy of self with each character in upper case.
-- Self may be void.
if void(self) then return void end;
r::=new(asize);
loop r.aset!(aelt!.upper) end;
return r
end;
lower:SAME is
-- A copy of self with each character in lower case.
-- Self may be void.
if void(self) then return void end;
r::=new(asize);
loop r.aset!(aelt!.lower) end;
return r
end;
capitalize:SAME is
-- A copy of self with each word capitalized.
-- Self may be void.
if void(self) then return void end;
r::=new(asize);
sp::=true; -- True if previous char was punct.
loop c::=aelt!;
if sp then c:=c.upper end;
if c.is_punct or c.is_space then sp:=true else sp:=false end;
r.aset!(c)
end;
return r
end;
head(i:INT):SAME
-- The first `i' characters of self.
-- Self may be void if i=0.
pre i.is_bet(0,size) is
if void(self) then return void end;
r::=new(i); r.acopy(self);
return r
end;
tail(i:INT):SAME
-- The last `i' characters of self.
-- Self may be void if i=0.
pre i.is_bet(0,size) is
if void(self) then return self end;
r::=new(i); r.acopy(0,i,asize-i,self);
return r
end;
replace_suffix(old,rpl:SAME):SAME
pre length>=old.length and tail(old.length)=old is
-- New string which replaces old suffix with new one.
return head(length-old.size)+rpl;
end;
substring(beg,num:INT):SAME
-- The substring with `num' charcters whose first character has
-- index `beg'. Self may be void if beg=0 and num=0.
pre num>=0 and beg.is_bet(0,size-num) is
if void(self) then return void end;
r::=new(num); r.acopy(0,num,beg,self);
return r
end;
substring(beg:INT): SAME
pre beg.is_bet(0,size)
is
if beg=0 then return void end;
r::=new(size-beg); r.acopy(0,size-beg,beg,self); return r;
end;
reverse:SAME is
-- A string whose characters are the reverse of those in self.
-- Self may be void.
if void(self) then return void end;
r::=new(asize);
loop r.aset!(aelt!(asize-1,asize,-1)) end;
return r
end;
repeat(i:INT):SAME
-- Self repeated `i' times. Self may be void.
pre i>=0 is
if void(self) then return void end;
r::=new(asize*i);
loop r.acopy(0.step!(i,asize),self) end;
return r
end;
contains(c:CHAR):BOOL is
-- True if `c' appears in self. Self may be void.
loop if elt!=c then return true end end;
return false
end;
count(c:CHAR):INT is
-- The number of times `c' appears in self.
-- Self may be void.
r::=0; loop if elt!=c then r:=r+1 end end;
return r
end;
count(s:STR):INT is
-- The number of times a character in `s' appears in self.
-- Self may be void.
if void(self) or void(s) then return 0 end;
r::=0; loop if s.contains(elt!) then r:=r+1 end end;
return r
end;
search(c:CHAR):INT is
-- The index of the first appearance of `c' in self or -1 if absent.
-- Self may be void.
loop r::=ind!; if [r]=c then return r end end;
return -1
end;
search_backwards(c:CHAR):INT is
-- The index of the last appearance of `c' in self or -1 if absent.
-- Self may be void.
if void(c) then return -1; end;
loop r::=(size-1).downto!(0); if [r]=c then return r end end;
return -1
end;
search(c:CHAR,st:INT):INT is
-- The index of the first appearance of `c' at location `st' or
-- greater in self or -1 if absent.
-- Self may be void.
loop r::=st.upto!(size-1); if [r]=c then return r end end;
return -1
end;
search_backwards(c:CHAR,st:INT):INT is
-- The index of the last appearance of `c' in self
-- before st,or -1 if absent. Self may be void.
if void(c) then return -1; end;
loop r::=st.downto!(0); if [r]=c then return r end end;
return -1
end;
replace(o,n:CHAR):SAME is
-- A new string with each occurance of `o' replaced by `n'.
-- Self may be void.
if void(self) then return void end;
r::=new(asize);
loop c::=aelt!; if c=o then c:=n end;
r.aset!(c) end;
return r
end;
remove(c:CHAR):SAME is
-- Self with all occurances of `c' removed.
-- Self may be void.
if void(self) then return void end;
ns::=asize-count(c);
if ns=0 then return void end;
r::=new(ns);
loop sc::=aelt!;
if ~(sc=c) then r.aset!(sc) end end;
return r
end;
escape(esc:CHAR, elist:SAME):SAME is
-- return self w/ each occurance of esc & of all chars in elist
-- preceded by esc (Rob)
if void(self) or void(esc) then return self end;
buf::=#FSTR(self.length); -- expand buf early? any stats?
loop c::=self.elt!;
if elist.contains(c) or c = esc then buf:=buf.push(esc); end;
buf:=buf.push(c);
end;
ret::=self.from_fstr(buf);
return ret;
end;
minus(s:SAME):SAME is
-- return self with the first instance of s deleted if any
-- (Rob)
return minus(s,0)
end;
minus(s:SAME,start:INT):SAME is
-- return self with the first instance of s after start deleted if any
if void(s) or void(self) then return self end;
loc::=search(s,start); if loc = -1 then return self end;
front::=#FSTR( self.head(loc));
back::=#FSTR(self.tail( self.length - (loc + s.length)));
ret::=#STR; ret:=from_fstr( front.append(back));
return ret;
end;
contains_chars_from(s:STR):BOOL is
-- True if any of the characters in self are contained in `s'.
-- Either may be void.
loop if s.contains(elt!) then return true end end;
return false
end;
count_chars_from(s:SAME):INT is
-- The number of characters in self which are contained in `s'.
-- Either may be void.
r::=0; loop if s.contains(elt!) then r:=r+1 end end;
return r
end;
search_chars_from(s:SAME):INT is
-- The index of the first appearance in self of a character
-- contained in `s' or -1 if none.
-- Self or `s' may be void.
loop r::=ind!; if s.contains([r]) then return r end end;
return -1
end;
replace_chars_from(set:SAME,n:CHAR):SAME is
-- A new string with character contained in `set' replaced by
-- `n'. Self may be void.
if void(self) then return void end;
r::=new(asize);
loop c::=aelt!; if set.contains(c) then c:=n end;
r.aset!(c) end;
return r
end;
remove_chars_from(s:SAME):SAME is
-- Self with all characters which are contained in `s' removed.
-- Either may be void.
if void(self) then return void end;
if void(s) then return self end;
ns::=asize-count(s); if ns=0 then return self end;
r::=new(ns);
loop c::=aelt!;
if ~s.contains(c) then r.aset!(c) end end;
return r
end;
is_prefix(s:SAME):BOOL is
-- true is s is a prefix of self.
if length<s.length then return false; end;
loop if (elt!/=s.elt!) then return false; end; end;
return true;
end;
mismatch(s:SAME):INT is
-- The index of the first character of self which differs from `s'.
-- -1 if self is a prefix of `s'. Either may be void.
if void(self) then return -1 end;
if void(s) then return 0 end;
r:INT;
loop r:=ind!; if [r]/=s.aelt! then return r end end;
if r=asize-1 then return -1 end;
return r
end;
search(s:SAME, st:INT):INT is
-- the index of the first appearance of `s' at location `st' or
-- greater in self or -1 if not found. Self may be void.
if void(s) then return st end;
if void(self) then return -1 end;
loop r::=st.upto!(asize-s.asize);
match ::= true;
loop
if aelt!(r) /= s.aelt! then match := false; break! end;
end;
if match=true then return r end
end;
return -1
end;
search(s:SAME):INT is
-- The index of the leftmost substring of self which matches `s'.
-- -1 if none. Uses simple algorithm which has good performance
-- unless the strings are special (eg. many repeated values).
-- Either string may be void. (Void matches void at 0).
if void(s) then return 0 end;
if void(self) then return -1 end;
loop r::=0.upto!(asize-s.asize); match::=true;
loop if aelt!(r)/=s.aelt! then
match:=false; break! end end;
if match=true then return r end
end;
return -1
end;
hash:INT is
if void(self) or asize=0 then return 0 end;
r::=0;
i::=0;
loop
r:=r.mplus([i].int).mplus(i).mtimes(19); -- A nice prime
i:=i+1;
until!(i>=asize);
end;
return r;
end;
left(i:INT): SAME is return left(i,' ') end;
left(i:INT,fill:CHAR):SAME is
-- A string of at least `i' characters in which self
-- is left-justified and padded with spaces on the right.
-- Returns self if i<=size.
if i<=size then return self end;
if void(self) then return fill.str.repeat(i) end;
r::=new(i); r.acopy(self);
loop r.aset!(asize, fill) end;
return r
end;
right(i:INT): SAME is return right(i,' ') end;
right(i:INT,fill:CHAR):SAME is
-- A string of at least `i' characters in which self
-- is right-justified and padded with spaces on the left.
-- Returns self if i<=size.
if i<=size then return self end;
if void(self) then return fill.str.repeat(i) end;
r::=new(i); r.acopy(i-asize,self);
loop r.aset!(0, i-asize, fill) end;
return r
end;
center(i:INT): SAME is return center(i,' ') end;
center(i:INT,fill:CHAR):SAME is
-- A string of at least `i' characters in which self
-- is centered and padded with spaces on the left and right.
-- Returns self if i<=size.
if i<=size then return self end;
if void(self) then return fill.str.repeat(i) end;
r::=new(i);
lp::=(i-asize)/2; -- Size of left padding.
r.acopy(lp,self);
loop r.aset!(0, lp, fill) end;
loop r.aset!(lp+asize, fill) end;
return r
end;
concat_all(a: ARRAY{SAME}): SAME is
-- Concatinate all array of STRING. Separator is '\0'.
r: SAME;
l: INT := a.size;
loop i ::= 0.upto!(l - 2);
r := r + a[i] + '\0';
end; -- loop
return r + a[l - 1];
end;
chunk!(chunk_size: INT): STR pre chunk_size >= 0 is
-- Yield successive chunks of self, defined by the chunk size "size"
-- s ::= "122333444455555";
-- loop #OUT+s.chunk!(1)+","; end;
-- "1,2,2,3,3,3,4,4,4,4,5,5,5,5,5"
-- loop #OUT+s.chunk!(5.times!)+","; end;
-- will print out ",1,22,333,4444,55555"
cur_loc: INT := 0;
str_sz: INT := size;
loop until!(cur_loc >= str_sz);
res: STR := substring(cur_loc,chunk_size);
yield res;
cur_loc := cur_loc+chunk_size;
end;
end;
split!(once c: CHAR): STR is
-- Yield successive substrings that are separated by the character "c"
-- s ::= "This is \n a test \n of split";
-- loop #OUT+"Next line:"+s.split!('\n'); end;
-- The "c" characters will occur at the end of each string
if void(self) then quit end;
cur_loc: INT := 0; -- Start of next string
loop until!(cur_loc >= size-1);
next_loc: INT := search(c,cur_loc);
if next_loc >= 0 then -- The character was found
yield substring(cur_loc,next_loc-cur_loc+1);
cur_loc := next_loc+1;
else -- The character was not found
-- Use the rest of the string
yield substring(cur_loc,size-cur_loc);
cur_loc := size; -- Terminate the loop at the next until
end;
end;
end;
separate!(s:$STR):STR is
-- On the first iteration just outputs `s', on successive
-- iterations it outputs self followed by `s'. Useful for
-- forming lists,
-- loop #OUT + ", ".separate!(a.elt!) end;
yield s.str; loop yield self + s.str end
end;
elt!:CHAR is
-- Yield the characters of self in order.
-- Self may be void.
-- Modified (ben)
if ~void(self) then
i ::= 0; sz ::= size;
loop until!(i = sz); yield [i]; i := i + 1; end;
end;
end;
-- if ~void(self) then loop yield aelt! end end end;
elt!(once beg:INT):CHAR is
-- Yield the characters of self in order starting at `beg'.
-- Self may be void.
-- Modified (ben)
if ~void(self) then
i ::= beg; sz ::= size;
loop until!(i = sz); yield [i]; i := i + 1; end;
end;
end;
-- if ~void(self) then loop yield aelt!(beg) end end end;
elt!(once beg,once num:INT):CHAR is
-- Yield 'num' characters of self in order starting at `beg'.
-- Self may be void.
-- Modified (ben)
if ~void(self) then
i ::= beg; sz ::= size.min(beg+num);
loop until!(i = sz); yield [i]; i := i + 1; end;
end;
end;
-- if ~void(self) then loop yield aelt!(beg,num) end end end;
ind!:INT is
-- Yield the indices of the characters of self in order.
-- Self may be void.
-- Modified (ben)
if ~void(self) then
i ::= 0; sz ::= size;
loop until!(i = sz);
yield i;
i := i + 1;
end;
end;
end;
-- if ~void(self) then loop yield aind! end end end;
end; -- class STR