optimizations to input class for reading very long lines
This commit is contained in:
144
src/input.cpp
144
src/input.cpp
@ -188,17 +188,20 @@ of the file is reached. The *infile* pointer will usually point to
|
|||||||
|
|
||||||
void Input::file()
|
void Input::file()
|
||||||
{
|
{
|
||||||
int m,n;
|
int m,n,mstart,ntriple,endfile;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
||||||
// read a line from input script
|
// read a line from input script
|
||||||
// n = length of line including str terminator, 0 if end of file
|
// when done, n = length of line including str terminator, 0 if end of file
|
||||||
// if line ends in continuation char '&', concatenate next line
|
// if line ends in continuation char '&', concatenate next line
|
||||||
|
// if triple quotes are used, read until closing triple quotes
|
||||||
|
|
||||||
if (me == 0) {
|
if (me == 0) {
|
||||||
|
ntriple = 0;
|
||||||
|
endfile = 0;
|
||||||
m = 0;
|
m = 0;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
||||||
if (infile == nullptr) {
|
if (infile == nullptr) {
|
||||||
@ -206,40 +209,60 @@ void Input::file()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mstart = m;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
if (maxline-m < 2) reallocate(line,maxline,0);
|
if (maxline-m < 2) reallocate(line,maxline,0);
|
||||||
|
|
||||||
// end of file reached, so break
|
// end of file reached, so break
|
||||||
// n == 0 if nothing read, else n = line with str terminator
|
// n == 0 if nothing read, else n = line with str terminator
|
||||||
|
|
||||||
if (fgets(&line[m],maxline-m,infile) == nullptr) {
|
if (fgets(&line[m],maxline-m,infile) == nullptr) {
|
||||||
|
endfile = 1;
|
||||||
if (m) n = strlen(line) + 1;
|
if (m) n = strlen(line) + 1;
|
||||||
else n = 0;
|
else n = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// continue if last char read was not a newline
|
// continue if last char read was not a newline
|
||||||
// could happen if line is very long
|
// can happen if line is very long
|
||||||
|
|
||||||
m = strlen(line);
|
m += strlen(&line[m]);
|
||||||
if (line[m-1] != '\n') continue;
|
if (line[m-1] != '\n') continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// continue reading if final printable char is & char
|
if (endfile) break;
|
||||||
// or if odd number of triple quotes
|
|
||||||
// else break with n = line with str terminator
|
// add # of triple quotes in just-read line to ntriple
|
||||||
|
|
||||||
|
ntriple += numtriple(&line[mstart]);
|
||||||
|
|
||||||
|
// trim whitespace from end of line
|
||||||
|
// line[m] = last printable char
|
||||||
|
|
||||||
m--;
|
m--;
|
||||||
while (m >= 0 && isspace(line[m])) m--;
|
while (m >= 0 && isspace(line[m])) m--;
|
||||||
if (m < 0 || line[m] != '&') {
|
|
||||||
if (numtriple(line) % 2) {
|
// continue reading if final printable char is "&"
|
||||||
|
|
||||||
|
if (m >= 0 && line[m] == '&') continue;
|
||||||
|
|
||||||
|
// continue reading if odd number of triple quotes
|
||||||
|
|
||||||
|
if (ntriple % 2) {
|
||||||
|
line[m+1] = '\n';
|
||||||
m += 2;
|
m += 2;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// done, break with n = length of line with str terminator
|
||||||
|
|
||||||
line[m+1] = '\0';
|
line[m+1] = '\0';
|
||||||
n = m+2;
|
n = m+2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// bcast the line
|
// bcast the line
|
||||||
// if n = 0, end-of-file
|
// if n = 0, end-of-file
|
||||||
@ -371,8 +394,9 @@ char *Input::one(const std::string &single)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
Send text to active echo file pointers
|
send text to active echo file pointers
|
||||||
------------------------------------------------------------------------- */
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
void Input::write_echo(const std::string &txt)
|
void Input::write_echo(const std::string &txt)
|
||||||
{
|
{
|
||||||
if (me == 0) {
|
if (me == 0) {
|
||||||
@ -399,34 +423,35 @@ void Input::parse()
|
|||||||
if (n > maxcopy) reallocate(copy,maxcopy,n);
|
if (n > maxcopy) reallocate(copy,maxcopy,n);
|
||||||
strcpy(copy,line);
|
strcpy(copy,line);
|
||||||
|
|
||||||
// strip any # comment by replacing it with 0
|
// strip a # comment by replacing it with 0
|
||||||
// do not strip from a # inside single/double/triple quotes
|
// do not treat a # inside single/double/triple quotes as a comment
|
||||||
// quoteflag = 1,2,3 when encounter first single/double,triple quote
|
|
||||||
// quoteflag = 0 when encounter matching single/double,triple quote
|
|
||||||
|
|
||||||
int quoteflag = 0;
|
char *ptrmatch;
|
||||||
char *ptr = copy;
|
char *ptr = copy;
|
||||||
|
|
||||||
while (*ptr) {
|
while (*ptr) {
|
||||||
if (*ptr == '#' && !quoteflag) {
|
if (*ptr == '#') {
|
||||||
*ptr = '\0';
|
*ptr = '\0';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (quoteflag == 0) {
|
if (*ptr == '\'') {
|
||||||
|
ptrmatch = strchr(ptr+1,'\'');
|
||||||
|
if (ptrmatch == NULL)
|
||||||
|
error->all(FLERR,"Unmatched single quote in command");
|
||||||
|
ptr = ptrmatch + 1;
|
||||||
|
} else if (*ptr == '"') {
|
||||||
if (strstr(ptr,"\"\"\"") == ptr) {
|
if (strstr(ptr,"\"\"\"") == ptr) {
|
||||||
quoteflag = 3;
|
ptrmatch = strstr(ptr+3,"\"\"\"");
|
||||||
ptr += 2;
|
if (ptrmatch == NULL)
|
||||||
}
|
error->all(FLERR,"Unmatched triple quote in command");
|
||||||
else if (*ptr == '"') quoteflag = 2;
|
ptr = ptrmatch + 3;
|
||||||
else if (*ptr == '\'') quoteflag = 1;
|
|
||||||
} else {
|
} else {
|
||||||
if (quoteflag == 3 && strstr(ptr,"\"\"\"") == ptr) {
|
ptrmatch = strchr(ptr+1,'"');
|
||||||
quoteflag = 0;
|
if (ptrmatch == NULL)
|
||||||
ptr += 2;
|
error->all(FLERR,"Unmatched double quote in command");
|
||||||
|
ptr = ptrmatch + 1;
|
||||||
}
|
}
|
||||||
else if (quoteflag == 2 && *ptr == '"') quoteflag = 0;
|
} else ptr++;
|
||||||
else if (quoteflag == 1 && *ptr == '\'') quoteflag = 0;
|
|
||||||
}
|
|
||||||
ptr++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (utils::has_utf8(copy)) {
|
if (utils::has_utf8(copy)) {
|
||||||
@ -534,16 +559,18 @@ void Input::substitute(char *&str, char *&str2, int &max, int &max2, int flag)
|
|||||||
{
|
{
|
||||||
// use str2 as scratch space to expand str, then copy back to str
|
// use str2 as scratch space to expand str, then copy back to str
|
||||||
// reallocate str and str2 as necessary
|
// reallocate str and str2 as necessary
|
||||||
// do not replace $ inside single/double/triple quotes
|
// do not replace variables inside single/double/triple quotes
|
||||||
// var = pts at variable name, ended by null char
|
// var = pts at variable name, ended by null char
|
||||||
// if $ is followed by '{', trailing '}' becomes null char
|
// if $ is followed by '{', trailing '}' becomes null char
|
||||||
// else $x becomes x followed by null char
|
// else $x becomes x followed by null char
|
||||||
// beyond = points to text following variable
|
// beyond = points to text following variable
|
||||||
|
|
||||||
int i,n,paren_count;
|
int i,n,paren_count,nchars;;
|
||||||
char immediate[256];
|
char immediate[256];
|
||||||
char *var,*value,*beyond;
|
char *var,*value,*beyond;
|
||||||
int quoteflag = 0;
|
int quoteflag = 0;
|
||||||
|
char *ptrmatch;
|
||||||
|
|
||||||
char *ptr = str;
|
char *ptr = str;
|
||||||
|
|
||||||
n = strlen(str) + 1;
|
n = strlen(str) + 1;
|
||||||
@ -637,34 +664,41 @@ void Input::substitute(char *&str, char *&str2, int &max, int &max2, int flag)
|
|||||||
if (echo_log && logfile) fprintf(logfile,"%s%s\n",str2,beyond);
|
if (echo_log && logfile) fprintf(logfile,"%s%s\n",str2,beyond);
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
// check for single/double/triple quotes and skip past them
|
||||||
}
|
|
||||||
|
|
||||||
// quoteflag = 1,2,3 when encounter first single/double,triple quote
|
} else if (*ptr == '\'') {
|
||||||
// quoteflag = 0 when encounter matching single/double,triple quote
|
ptrmatch = strchr(ptr+1,'\'');
|
||||||
// copy 2 extra triple quote chars into str2
|
if (ptrmatch == NULL)
|
||||||
|
error->all(FLERR,"Unmatched single quote in command");
|
||||||
if (quoteflag == 0) {
|
nchars = ptrmatch+1 - ptr;
|
||||||
|
strncpy(ptr2,ptr,nchars);
|
||||||
|
ptr += nchars;
|
||||||
|
ptr2 += nchars;
|
||||||
|
} else if (*ptr == '"') {
|
||||||
if (strstr(ptr,"\"\"\"") == ptr) {
|
if (strstr(ptr,"\"\"\"") == ptr) {
|
||||||
quoteflag = 3;
|
ptrmatch = strstr(ptr+3,"\"\"\"");
|
||||||
*ptr2++ = *ptr++;
|
if (ptrmatch == NULL)
|
||||||
*ptr2++ = *ptr++;
|
error->all(FLERR,"Unmatched triple quote in command");
|
||||||
}
|
nchars = ptrmatch+3 - ptr;
|
||||||
else if (*ptr == '"') quoteflag = 2;
|
strncpy(ptr2,ptr,nchars);
|
||||||
else if (*ptr == '\'') quoteflag = 1;
|
ptr += nchars;
|
||||||
|
ptr2 += nchars;
|
||||||
} else {
|
} else {
|
||||||
if (quoteflag == 3 && strstr(ptr,"\"\"\"") == ptr) {
|
ptrmatch = strchr(ptr+1,'"');
|
||||||
quoteflag = 0;
|
if (ptrmatch == NULL)
|
||||||
*ptr2++ = *ptr++;
|
error->all(FLERR,"Unmatched double quote in command");
|
||||||
*ptr2++ = *ptr++;
|
nchars = ptrmatch+1 - ptr;
|
||||||
}
|
strncpy(ptr2,ptr,nchars);
|
||||||
else if (quoteflag == 2 && *ptr == '"') quoteflag = 0;
|
ptr += nchars;
|
||||||
else if (quoteflag == 1 && *ptr == '\'') quoteflag = 0;
|
ptr2 += nchars;
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy current character into str2
|
// else copy current single character into str2
|
||||||
|
|
||||||
|
} else *ptr2++ = *ptr++;
|
||||||
|
|
||||||
|
// terminate current str2 so variable sub can perform strlen()
|
||||||
|
|
||||||
*ptr2++ = *ptr++;
|
|
||||||
*ptr2 = '\0';
|
*ptr2 = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user