new utility function fgets_trunc_nl()

This commit is contained in:
Axel Kohlmeyer
2021-04-27 16:11:37 -04:00
parent cce54b6ba5
commit b65bc86718
2 changed files with 53 additions and 4 deletions

View File

@ -165,6 +165,42 @@ const char *utils::guesspath(char *buf, int len, FILE *fp)
return buf;
}
// read line into buffer. if line is too long keep reading until EOL or EOF
// but return only the first part with a newline at the end.
char *utils::fgets_trunc_nl(char *buf, int size, FILE *fp)
{
constexpr int MAXDUMMY = 256;
char dummy[MAXDUMMY];
char *ptr = fgets(buf,size,fp);
// EOF
if (!ptr) return nullptr;
int n = strlen(buf);
// line is shorter than buffer, append newline if needed,
if (n < size-2) {
if (buf[n-1] != '\n') {
buf[n] = '\n';
buf[n+1] = '\0';
}
return buf;
// line fits exactly. overwrite last but one character.
} else buf[size-2] = '\n';
// continue reading into dummy buffer until end of line or file
do {
ptr = fgets(dummy,MAXDUMMY,fp);
if (ptr) n = strlen(ptr);
else n = 0;
} while (n == MAXDUMMY-1 && ptr[MAXDUMMY-1] != '\n');
// return first chunk
return buf;
}
#define MAXPATHLENBUF 1024
/* like fgets() but aborts with an error or EOF is encountered */
void utils::sfgets(const char *srcname, int srcline, char *s, int size,
@ -235,13 +271,12 @@ int utils::read_lines_from_file(FILE *fp, int nlines, int nmax,
if (me == 0) {
if (fp) {
for (int i = 0; i < nlines; i++) {
ptr = fgets(ptr,nmax,fp);
ptr = fgets_trunc_nl(ptr,nmax,fp);
if (!ptr) break; // EOF?
// advance ptr to end of string and append newline char if needed.
// advance ptr to end of string
ptr += strlen(ptr);
if (*(--ptr) != '\n') *(++ptr) = '\n';
// ensure buffer is null terminated. null char is start of next line.
*(++ptr) = '\0';
*ptr = '\0';
}
}
}

View File

@ -63,6 +63,20 @@ namespace LAMMPS_NS {
std::string getsyserror();
/** Wrapper around fgets() which reads whole lines but truncates the
* data to the buffer size and ensures a newline char at the end.
*
* This function is useful for reading line based text files with
* possible comments that should be parsed later. This applies to
* data files, potential files, atomfile variable files and so on.
* It is used instead of fgets() by utils::read_lines_from_file().
*
* \param s buffer for storing the result of fgets()
* \param size size of buffer s (max number of bytes returned)
* \param fp file pointer used by fgets() */
char *fgets_trunc_nl(char *s, int size, FILE *fp);
/** Safe wrapper around fgets() which aborts on errors
* or EOF and prints a suitable error message to help debugging.
*