📄 splash.cpp
字号:
rg= re.getgroup(0);
if(rg.end()+1 < length()){
SPString st(substr(rg.end()+1));
// cout << "Substring: " << st << endl;
cnt += st.s(exp, repl, opts);
substr(rg.end()+1)= st;
// cout << "NewString: " << *this << endl;
}
}
if(!strchr(repl, '$')){ // straight, simple substitution
rg= re.getgroup(0);
substr(rg.start(), rg.length())= repl;
cnt++;
}else{ // need to do subexpression substitution
char c;
const char *src= repl;
SPString dst;
int no;
while ((c = *src++) != '\0') {
if(c == '$' && *src == '&'){
no = 0; src++;
}else if(c == '$' && '0' <= *src && *src <= '9')
no = *src++ - '0';
else no = -1;
if(no < 0){ /* Ordinary character. */
if(c == '\\' && (*src == '\\' || *src == '$'))
c = *src++;
dst += c;
}else{
rg= re.getgroup(no);
dst += substr(rg.start(), rg.length());
}
}
rg= re.getgroup(0);
substr(rg.start(), rg.length())= dst;
cnt++;
}
return cnt;
}
return cnt;
}
SPStringList SPString::split(const char *pat, int limit)
{
SPStringList l;
l.split(*this, pat, limit);
return l;
}
//************************************************************
// SPStringList stuff
//************************************************************
int SPStringList::split(const char *str, const char *pat, int limit)
{
Regexp re(pat);
Range rng;
SPString s(str);
int cnt= 1;
if(*pat == '\0'){ // special empty string case splits entire thing
while(*str){
s= *str++;
push(s);
}
return count();
}
if(strcmp(pat, "' '") == 0){ // special awk case
char *p, *ws= " \t\n";
TempString t(str); // can't hack users data
p= strtok(t, ws);
while(p){
push(p);
p= strtok(NULL, ws);
}
return count();
}
while(re.match(s) && (limit < 0 || cnt < limit)){ // find separator
rng= re.getgroup(0); // full matched string (entire separator)
push(s.substr(0, rng.start()));
for(int i=1;i<re.groups();i++){
push(s.substr(re.getgroup(i))); // add subexpression matches
}
s= s.substr(rng.end()+1);
cnt++;
}
if(s.length()) push(s);
if(limit < 0){ // strip trailing null entries
int off= count()-1;
while(off >= 0 && (*this)[off].length() == 0){
off--;
}
splice(off+1);
}
return count();
}
SPString SPStringList::join(const char *pat)
{
SPString ts;
for(int i=0;i<count();i++){
ts += (*this)[i];
if(i<count()-1) ts += pat;
}
return ts;
}
SPStringList::SPStringList(const SPStringList& n)
{
for(int i=0;i<n.count();i++){
push(n[i]);
}
}
SPStringList& SPStringList::operator=(const SPList<SPString>& n)
{
if(this == &n) return *this;
// erase old one
reset();
for(int i=0;i<n.count();i++){
push(n[i]);
}
return *this;
}
int SPStringList::m(const char *rege, const char *targ, const char *opts)
{
int iflg= strchr(opts, 'i') != NULL;
Regexp r(rege, iflg?Regexp::nocase:0);
if(!r.match(targ)) return 0;
Range rng;
for (int i=0; i<r.groups(); i++){
rng= r.getgroup(i);
push(SPString(targ).substr(rng.start(), rng.length()));
}
return r.groups();
}
SPStringList SPStringList::grep(const char *rege, const char *opts)
{
SPStringList rt;
int iflg= strchr(opts, 'i') != NULL;
Regexp rexp(rege, iflg?Regexp::nocase:0); // compile once
for(int i=0;i<count();i++){
if(rexp.match((*this)[i])){
rt.push((*this)[i]);
}
}
return rt;
}
#if 1
SPStringList m(const char *pat, const char *str, const char *opts)
{
SPStringList l;
l.m(pat, str, opts);
l.shift(); // remove the first element which would be $&
return l;
}
#endif
//************************************************************
// streams stuff
//************************************************************
istream& operator>>(istream& ifs, SPString& s)
{
char c;
#if 0
char buf[40];
#else
char buf[132];
#endif
s= ""; // empty string
ifs.get(buf, sizeof buf);
// This is tricky because a line teminated by end of file that is not terminated
// with a '\n' first is considered an OK line, but ifs.good() will fail.
// This will correctly return the last line if it is terminated by eof with the
// stream still in a non-fail condition, but at eof, so next call will fail as
// expected
if(ifs){ // previous operation was ok
s += buf; // append buffer to string
// cout << "<" << buf << ">" << endl;
// if its a long line continue appending to string
while(ifs.good() && (c=ifs.get()) != '\n'){
// cout << "eof1= " << ifs.eof() << endl;
ifs.putback(c);
// cout << "eof2= " << ifs.eof() << endl;
if(ifs.get(buf, sizeof buf)) s += buf; // append to line
}
}
return ifs;
}
istream& operator>>(istream& ifs, SPStringList& sl)
{
SPString s;
// Should I reset sl first?
sl.reset(); // I think so, to be consistent
while(ifs >> s){
sl.push(s);
// cout << "<" << s << ">" << endl;
};
return ifs;
}
ostream& operator<<(ostream& os, const SPString& arr)
{
#ifdef TEST
os << "(" << arr.length() << ")" << "\"";
os << (const char *)arr;
os << "\"";
#else
os << (const char *)arr;
#endif
return os;
}
ostream& operator<<(ostream& os, const SPStringList& arr)
{
for(int i=0;i<arr.count();i++)
#ifdef TEST
os << "[" << i << "]" << arr[i] << endl;
#else
os << arr[i] << endl;
#endif
return os;
}
//************************************************************
// Slice stuff
//************************************************************
// a..b is range a thru b
// a-b is also range a thru b
// a,b,c is a and b and c
Slice::Slice(const char *s)
{
SPStringList sl;
SPString sep;
int i1, i2;
rl= new SPList<Range>;
sl.split(s, "([-,]|\\.\\.)"); // split on separators and save them
// cout << sl << endl;
while(sl){
i1= atoi(sl.shift()); // +++ should check it is a valid number
if(sl){
sep= sl.shift(); // get separator
if(sep == "-" || sep == ".."){ // its a range
if(sl.isempty()){ // check there is more
cerr << "\nError in Slice, bad range in string: " << s << endl;
return;
}
i2= atoi(sl.shift()); // +++ get end of range
rl->push(Range(i1, i2)); // +++ Should see if range is reversed, or contiguous
if(sl && (sep=sl.shift()) != ","){
cerr << "\nError in Slice, Range not terminated correctly in string: "
<< s << " by: " << sep << endl;
}
}else if(sep == ","){ // its a single
add(i1);
}else{ // oops
cerr << "\nError in Slice, bad separator in string: " << s
<< "at: " << sep << endl;
return;
}
}else add(i1); // last one must be a single
}
cout << *this << endl;
}
void Slice::add(int i)
{
int n= rl->count()-1;
// if and only if this index is one greater than the previous on
if(n >= 0 && (*rl)[n].end() == i-1){ // extend end of range by 1
((*rl)[n])++;
}else rl->push(Range(i, i));
}
// a list of at least one indices, terminated by -1
Slice::Slice(int n, ...)
{
va_list ap;
int arg;
va_start(ap, n);
rl= new SPList<Range>;
add(n);
while((arg=va_arg(ap, int)) >= 0){
add(arg);
}
va_end(ap);
}
ostream& operator<<(ostream& os, const Slice& sl)
{
for(int i=0;i<sl.rl->count();i++){
os << (*sl.rl)[i] << endl;
}
return os;
}
#ifdef __TURBOC__
int Regexp::groups(void) const
{
int res= 0;
for (int i=0; i<NSUBEXP; i++) {
if(repat->startp[i] == NULL) break;
res++;
}
return res;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -