Merge pull request #2727 from akohlmey/refactor-read-lines-from-file

Move "read_lines_from_file" utility function from Comm class to utils namespace
This commit is contained in:
Axel Kohlmeyer
2021-04-26 13:24:24 -04:00
committed by GitHub
14 changed files with 142 additions and 108 deletions

View File

@ -12,11 +12,18 @@ reduces redundant implementations and encourages consistent behavior.
I/O with status check I/O with status check
^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^
These are wrappers around the corresponding C library calls like The the first two functions are wrappers around the corresponding C
``fgets()`` or ``fread()``. They will check if there were errors library calls ``fgets()`` or ``fread()``. They will check if there
on reading or an unexpected end-of-file state was reached. In that were errors on reading or an unexpected end-of-file state was reached.
case, the functions will stop the calculation with an error message, In that case, the functions will stop with an error message, indicating
indicating the name of the problematic file, if possible. the name of the problematic file, if possible unless the *error* argument
is a NULL pointer.
The :cpp:func:`read_lines_from_file` function will read the requested
number of lines of a maximum length into a buffer and will return 0
if successful or 1 if not. It also guarantees that all lines are
terminated with a newline character and the entire buffer with a
NULL character.
---------- ----------
@ -26,6 +33,9 @@ indicating the name of the problematic file, if possible.
.. doxygenfunction:: sfread .. doxygenfunction:: sfread
:project: progguide :project: progguide
.. doxygenfunction:: read_lines_from_file
:project: progguide
---------- ----------
String to number conversions with validity check String to number conversions with validity check

View File

@ -2190,6 +2190,7 @@ nl
nlayers nlayers
nlen nlen
Nlines Nlines
nlines
nlo nlo
nlocal nlocal
Nlocal Nlocal
@ -2281,6 +2282,7 @@ Ntype
ntypes ntypes
Ntypes Ntypes
nucleotides nucleotides
nullptr
num num
numa numa
numactl numactl

View File

@ -26,6 +26,7 @@
#include "bond.h" // bond potentials #include "bond.h" // bond potentials
#include "comm.h" // #include "comm.h" //
#include "fix.h" #include "fix.h"
#include "utils.h"
// ATC includes // ATC includes
#include "ATC_Error.h" #include "ATC_Error.h"
@ -47,6 +48,7 @@ using std::pair;
using std::string; using std::string;
using std::set; using std::set;
using LAMMPS_NS::bigint; using LAMMPS_NS::bigint;
using LAMMPS_NS::utils::read_lines_from_file;
namespace ATC { namespace ATC {
@ -236,7 +238,7 @@ std::string LammpsInterface::read_file(std::string filename) const
std::stringstream s; std::stringstream s;
bool eof = false; bool eof = false;
while ( ! eof) { while ( ! eof) {
eof = lammps_->comm->read_lines_from_file(fp,1,MAXLINE,buffer); eof = read_lines_from_file(fp,1,MAXLINE,buffer,comm_rank(),lammps_->world);
s << buffer; s << buffer;
} }
fclose(fp); fclose(fp);

View File

@ -436,9 +436,10 @@ void NEB::readfile(char *file, int flag)
while (nread < nlines) { while (nread < nlines) {
nchunk = MIN(nlines-nread,CHUNK); nchunk = MIN(nlines-nread,CHUNK);
if (flag == 0) if (flag == 0)
eofflag = comm->read_lines_from_file_universe(fp,nchunk,MAXLINE,buffer); eofflag = utils::read_lines_from_file(fp,nchunk,MAXLINE,buffer,
universe->me,universe->uworld);
else else
eofflag = comm->read_lines_from_file(fp,nchunk,MAXLINE,buffer); eofflag = utils::read_lines_from_file(fp,nchunk,MAXLINE,buffer,me,world);
if (eofflag) error->all(FLERR,"Unexpected end of NEB file"); if (eofflag) error->all(FLERR,"Unexpected end of NEB file");
buf = buffer; buf = buffer;

View File

@ -2302,7 +2302,7 @@ void FixRigid::readfile(int which, double *vec,
int nread = 0; int nread = 0;
while (nread < nlines) { while (nread < nlines) {
nchunk = MIN(nlines-nread,CHUNK); nchunk = MIN(nlines-nread,CHUNK);
eofflag = comm->read_lines_from_file(fp,nchunk,MAXLINE,buffer); eofflag = utils::read_lines_from_file(fp,nchunk,MAXLINE,buffer,me,world);
if (eofflag) error->all(FLERR,"Unexpected end of fix rigid file"); if (eofflag) error->all(FLERR,"Unexpected end of fix rigid file");
buf = buffer; buf = buffer;

View File

@ -2475,7 +2475,7 @@ void FixRigidSmall::readfile(int which, double **array, int *inbody)
int nread = 0; int nread = 0;
while (nread < nlines) { while (nread < nlines) {
nchunk = MIN(nlines-nread,CHUNK); nchunk = MIN(nlines-nread,CHUNK);
eofflag = comm->read_lines_from_file(fp,nchunk,MAXLINE,buffer); eofflag = utils::read_lines_from_file(fp,nchunk,MAXLINE,buffer,me,world);
if (eofflag) error->all(FLERR,"Unexpected end of fix rigid/small file"); if (eofflag) error->all(FLERR,"Unexpected end of fix rigid/small file");
buf = buffer; buf = buffer;

View File

@ -430,9 +430,10 @@ void NEBSpin::readfile(char *file, int flag)
while (nread < nlines) { while (nread < nlines) {
nchunk = MIN(nlines-nread,CHUNK); nchunk = MIN(nlines-nread,CHUNK);
if (flag == 0) if (flag == 0)
eofflag = comm->read_lines_from_file_universe(fp,nchunk,MAXLINE,buffer); eofflag = utils::read_lines_from_file(fp,nchunk,MAXLINE,buffer,
universe->me,universe->uworld);
else else
eofflag = comm->read_lines_from_file(fp,nchunk,MAXLINE,buffer); eofflag = utils::read_lines_from_file(fp,nchunk,MAXLINE,buffer,me,world);
if (eofflag) error->all(FLERR,"Unexpected end of neb/spin file"); if (eofflag) error->all(FLERR,"Unexpected end of neb/spin file");
buf = buffer; buf = buffer;

View File

@ -1240,71 +1240,3 @@ void Comm::rendezvous_stats(int n, int nout, int nrvous, int nrvous_out,
utils::logmesg(lmp,mesg); utils::logmesg(lmp,mesg);
} }
} }
/* ----------------------------------------------------------------------
proc 0 reads Nlines from file into buf and bcasts buf to all procs
caller allocates buf to max size needed
each line is terminated by newline, even if last line in file is not
return 0 if successful, 1 if get EOF error before read is complete
------------------------------------------------------------------------- */
int Comm::read_lines_from_file(FILE *fp, int nlines, int maxline, char *buf)
{
int m;
if (me == 0) {
m = 0;
for (int i = 0; i < nlines; i++) {
if (!fgets(&buf[m],maxline,fp)) {
m = 0;
break;
}
m += strlen(&buf[m]);
}
if (m) {
if (buf[m-1] != '\n') strcpy(&buf[m++],"\n");
m++;
}
}
MPI_Bcast(&m,1,MPI_INT,0,world);
if (m == 0) return 1;
MPI_Bcast(buf,m,MPI_CHAR,0,world);
return 0;
}
/* ----------------------------------------------------------------------
proc 0 reads Nlines from file into buf and bcasts buf to all procs
caller allocates buf to max size needed
each line is terminated by newline, even if last line in file is not
return 0 if successful, 1 if get EOF error before read is complete
------------------------------------------------------------------------- */
int Comm::read_lines_from_file_universe(FILE *fp, int nlines, int maxline,
char *buf)
{
int m;
int me_universe = universe->me;
MPI_Comm uworld = universe->uworld;
if (me_universe == 0) {
m = 0;
for (int i = 0; i < nlines; i++) {
if (!fgets(&buf[m],maxline,fp)) {
m = 0;
break;
}
m += strlen(&buf[m]);
}
if (m) {
if (buf[m-1] != '\n') strcpy(&buf[m++],"\n");
m++;
}
}
MPI_Bcast(&m,1,MPI_INT,0,uworld);
if (m == 0) return 1;
MPI_Bcast(buf,m,MPI_CHAR,0,uworld);
return 0;
}

View File

@ -114,9 +114,6 @@ class Comm : protected Pointers {
int (*)(int, char *, int &, int *&, char *&, void *), int (*)(int, char *, int &, int *&, char *&, void *),
int, char *&, int, void *, int statflag=0); int, char *&, int, void *, int statflag=0);
int read_lines_from_file(FILE *, int, int, char *);
int read_lines_from_file_universe(FILE *, int, int, char *);
// extract data useful to other classes // extract data useful to other classes
virtual void *extract(const char *, int &) {return nullptr;} virtual void *extract(const char *, int &) {return nullptr;}

View File

@ -1226,7 +1226,7 @@ void ReadData::atoms()
while (nread < natoms) { while (nread < natoms) {
nchunk = MIN(natoms-nread,CHUNK); nchunk = MIN(natoms-nread,CHUNK);
eof = comm->read_lines_from_file(fp,nchunk,MAXLINE,buffer); eof = utils::read_lines_from_file(fp,nchunk,MAXLINE,buffer,me,world);
if (eof) error->all(FLERR,"Unexpected end of data file"); if (eof) error->all(FLERR,"Unexpected end of data file");
atom->data_atoms(nchunk,buffer,id_offset,mol_offset,toffset,shiftflag,shift); atom->data_atoms(nchunk,buffer,id_offset,mol_offset,toffset,shiftflag,shift);
nread += nchunk; nread += nchunk;
@ -1282,7 +1282,7 @@ void ReadData::velocities()
while (nread < natoms) { while (nread < natoms) {
nchunk = MIN(natoms-nread,CHUNK); nchunk = MIN(natoms-nread,CHUNK);
eof = comm->read_lines_from_file(fp,nchunk,MAXLINE,buffer); eof = utils::read_lines_from_file(fp,nchunk,MAXLINE,buffer,me,world);
if (eof) error->all(FLERR,"Unexpected end of data file"); if (eof) error->all(FLERR,"Unexpected end of data file");
atom->data_vels(nchunk,buffer,id_offset); atom->data_vels(nchunk,buffer,id_offset);
nread += nchunk; nread += nchunk;
@ -1324,7 +1324,7 @@ void ReadData::bonds(int firstpass)
while (nread < nbonds) { while (nread < nbonds) {
nchunk = MIN(nbonds-nread,CHUNK); nchunk = MIN(nbonds-nread,CHUNK);
eof = comm->read_lines_from_file(fp,nchunk,MAXLINE,buffer); eof = utils::read_lines_from_file(fp,nchunk,MAXLINE,buffer,me,world);
if (eof) error->all(FLERR,"Unexpected end of data file"); if (eof) error->all(FLERR,"Unexpected end of data file");
atom->data_bonds(nchunk,buffer,count,id_offset,boffset); atom->data_bonds(nchunk,buffer,count,id_offset,boffset);
nread += nchunk; nread += nchunk;
@ -1398,7 +1398,7 @@ void ReadData::angles(int firstpass)
while (nread < nangles) { while (nread < nangles) {
nchunk = MIN(nangles-nread,CHUNK); nchunk = MIN(nangles-nread,CHUNK);
eof = comm->read_lines_from_file(fp,nchunk,MAXLINE,buffer); eof = utils::read_lines_from_file(fp,nchunk,MAXLINE,buffer,me,world);
if (eof) error->all(FLERR,"Unexpected end of data file"); if (eof) error->all(FLERR,"Unexpected end of data file");
atom->data_angles(nchunk,buffer,count,id_offset,aoffset); atom->data_angles(nchunk,buffer,count,id_offset,aoffset);
nread += nchunk; nread += nchunk;
@ -1472,7 +1472,7 @@ void ReadData::dihedrals(int firstpass)
while (nread < ndihedrals) { while (nread < ndihedrals) {
nchunk = MIN(ndihedrals-nread,CHUNK); nchunk = MIN(ndihedrals-nread,CHUNK);
eof = comm->read_lines_from_file(fp,nchunk,MAXLINE,buffer); eof = utils::read_lines_from_file(fp,nchunk,MAXLINE,buffer,me,world);
if (eof) error->all(FLERR,"Unexpected end of data file"); if (eof) error->all(FLERR,"Unexpected end of data file");
atom->data_dihedrals(nchunk,buffer,count,id_offset,doffset); atom->data_dihedrals(nchunk,buffer,count,id_offset,doffset);
nread += nchunk; nread += nchunk;
@ -1546,7 +1546,7 @@ void ReadData::impropers(int firstpass)
while (nread < nimpropers) { while (nread < nimpropers) {
nchunk = MIN(nimpropers-nread,CHUNK); nchunk = MIN(nimpropers-nread,CHUNK);
eof = comm->read_lines_from_file(fp,nchunk,MAXLINE,buffer); eof = utils::read_lines_from_file(fp,nchunk,MAXLINE,buffer,me,world);
if (eof) error->all(FLERR,"Unexpected end of data file"); if (eof) error->all(FLERR,"Unexpected end of data file");
atom->data_impropers(nchunk,buffer,count,id_offset,ioffset); atom->data_impropers(nchunk,buffer,count,id_offset,ioffset);
nread += nchunk; nread += nchunk;
@ -1613,7 +1613,7 @@ void ReadData::bonus(bigint nbonus, AtomVec *ptr, const char *type)
while (nread < natoms) { while (nread < natoms) {
nchunk = MIN(natoms-nread,CHUNK); nchunk = MIN(natoms-nread,CHUNK);
eof = comm->read_lines_from_file(fp,nchunk,MAXLINE,buffer); eof = utils::read_lines_from_file(fp,nchunk,MAXLINE,buffer,me,world);
if (eof) error->all(FLERR,"Unexpected end of data file"); if (eof) error->all(FLERR,"Unexpected end of data file");
atom->data_bonus(nchunk,buffer,ptr,id_offset); atom->data_bonus(nchunk,buffer,ptr,id_offset);
nread += nchunk; nread += nchunk;
@ -1739,7 +1739,7 @@ void ReadData::mass()
char *next; char *next;
char *buf = new char[ntypes*MAXLINE]; char *buf = new char[ntypes*MAXLINE];
int eof = comm->read_lines_from_file(fp,ntypes,MAXLINE,buf); int eof = utils::read_lines_from_file(fp,ntypes,MAXLINE,buf,me,world);
if (eof) error->all(FLERR,"Unexpected end of data file"); if (eof) error->all(FLERR,"Unexpected end of data file");
char *original = buf; char *original = buf;
@ -1759,7 +1759,7 @@ void ReadData::paircoeffs()
char *next; char *next;
char *buf = new char[ntypes*MAXLINE]; char *buf = new char[ntypes*MAXLINE];
int eof = comm->read_lines_from_file(fp,ntypes,MAXLINE,buf); int eof = utils::read_lines_from_file(fp,ntypes,MAXLINE,buf,me,world);
if (eof) error->all(FLERR,"Unexpected end of data file"); if (eof) error->all(FLERR,"Unexpected end of data file");
char *original = buf; char *original = buf;
@ -1785,7 +1785,7 @@ void ReadData::pairIJcoeffs()
int nsq = ntypes * (ntypes+1) / 2; int nsq = ntypes * (ntypes+1) / 2;
char *buf = new char[nsq * MAXLINE]; char *buf = new char[nsq * MAXLINE];
int eof = comm->read_lines_from_file(fp,nsq,MAXLINE,buf); int eof = utils::read_lines_from_file(fp,nsq,MAXLINE,buf,me,world);
if (eof) error->all(FLERR,"Unexpected end of data file"); if (eof) error->all(FLERR,"Unexpected end of data file");
char *original = buf; char *original = buf;
@ -1811,7 +1811,7 @@ void ReadData::bondcoeffs()
char *next; char *next;
char *buf = new char[nbondtypes*MAXLINE]; char *buf = new char[nbondtypes*MAXLINE];
int eof = comm->read_lines_from_file(fp,nbondtypes,MAXLINE,buf); int eof = utils::read_lines_from_file(fp,nbondtypes,MAXLINE,buf,me,world);
if (eof) error->all(FLERR,"Unexpected end of data file"); if (eof) error->all(FLERR,"Unexpected end of data file");
char *original = buf; char *original = buf;
@ -1836,7 +1836,7 @@ void ReadData::anglecoeffs(int which)
char *next; char *next;
char *buf = new char[nangletypes*MAXLINE]; char *buf = new char[nangletypes*MAXLINE];
int eof = comm->read_lines_from_file(fp,nangletypes,MAXLINE,buf); int eof = utils::read_lines_from_file(fp,nangletypes,MAXLINE,buf,me,world);
if (eof) error->all(FLERR,"Unexpected end of data file"); if (eof) error->all(FLERR,"Unexpected end of data file");
char *original = buf; char *original = buf;
@ -1862,7 +1862,7 @@ void ReadData::dihedralcoeffs(int which)
char *next; char *next;
char *buf = new char[ndihedraltypes*MAXLINE]; char *buf = new char[ndihedraltypes*MAXLINE];
int eof = comm->read_lines_from_file(fp,ndihedraltypes,MAXLINE,buf); int eof = utils::read_lines_from_file(fp,ndihedraltypes,MAXLINE,buf,me,world);
if (eof) error->all(FLERR,"Unexpected end of data file"); if (eof) error->all(FLERR,"Unexpected end of data file");
char *original = buf; char *original = buf;
@ -1892,7 +1892,7 @@ void ReadData::impropercoeffs(int which)
char *next; char *next;
char *buf = new char[nimpropertypes*MAXLINE]; char *buf = new char[nimpropertypes*MAXLINE];
int eof = comm->read_lines_from_file(fp,nimpropertypes,MAXLINE,buf); int eof = utils::read_lines_from_file(fp,nimpropertypes,MAXLINE,buf,me,world);
if (eof) error->all(FLERR,"Unexpected end of data file"); if (eof) error->all(FLERR,"Unexpected end of data file");
char *original = buf; char *original = buf;
@ -1922,7 +1922,7 @@ void ReadData::fix(int ifix, char *keyword)
bigint nread = 0; bigint nread = 0;
while (nread < nline) { while (nread < nline) {
nchunk = MIN(nline-nread,CHUNK); nchunk = MIN(nline-nread,CHUNK);
eof = comm->read_lines_from_file(fp,nchunk,MAXLINE,buffer); eof = utils::read_lines_from_file(fp,nchunk,MAXLINE,buffer,me,world);
if (eof) error->all(FLERR,"Unexpected end of data file"); if (eof) error->all(FLERR,"Unexpected end of data file");
modify->fix[ifix]->read_data_section(keyword,nchunk,buffer,id_offset); modify->fix[ifix]->read_data_section(keyword,nchunk,buffer,id_offset);
nread += nchunk; nread += nchunk;

View File

@ -225,6 +225,36 @@ void utils::sfread(const char *srcname, int srcline, void *s, size_t size,
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* read N lines and broadcast */
int utils::read_lines_from_file(FILE *fp, int nlines, int nmax,
char *buffer, int me, MPI_Comm comm)
{
char *ptr = buffer;
*ptr = '\0';
if (me == 0) {
if (fp) {
for (int i = 0; i < nlines; i++) {
ptr = fgets(ptr,nmax,fp);
if (!ptr) break; // EOF?
// advance ptr to end of string and append newline char if needed.
ptr += strlen(ptr);
if (*(--ptr) != '\n') *(++ptr) = '\n';
// ensure buffer is null terminated. null char is start of next line.
*(++ptr) = '\0';
}
}
}
int n = strlen(buffer);
MPI_Bcast(&n,1,MPI_INT,0,comm);
if (n == 0) return 1;
MPI_Bcast(buffer,n+1,MPI_CHAR,0,comm);
return 0;
}
/* ------------------------------------------------------------------ */
std::string utils::check_packages_for_style(const std::string &style, std::string utils::check_packages_for_style(const std::string &style,
const std::string &name, const std::string &name,
LAMMPS *lmp) LAMMPS *lmp)

View File

@ -17,9 +17,12 @@
/*! \file utils.h */ /*! \file utils.h */
#include "lmptype.h" #include "lmptype.h"
#include <mpi.h>
#include <cstdio>
#include <string> #include <string>
#include <vector> #include <vector>
#include <cstdio>
namespace LAMMPS_NS { namespace LAMMPS_NS {
@ -52,7 +55,7 @@ namespace LAMMPS_NS {
void logmesg(LAMMPS *lmp, const std::string &mesg); void logmesg(LAMMPS *lmp, const std::string &mesg);
/** return a string representing the current system error status /** Return a string representing the current system error status
* *
* This is a wrapper around calling strerror(errno). * This is a wrapper around calling strerror(errno).
* *
@ -60,8 +63,10 @@ namespace LAMMPS_NS {
std::string getsyserror(); std::string getsyserror();
/** safe wrapper around fgets() which aborts on errors /** Safe wrapper around fgets() which aborts on errors
* or EOF and prints a suitable error message to help debugging * or EOF and prints a suitable error message to help debugging.
*
* Use nullptr as the error parameter to avoid the abort on EOF or error.
* *
* \param srcname name of the calling source file (from FLERR macro) * \param srcname name of the calling source file (from FLERR macro)
* \param srcline line in the calling source file (from FLERR macro) * \param srcline line in the calling source file (from FLERR macro)
@ -69,13 +74,15 @@ namespace LAMMPS_NS {
* \param size size of buffer s (max number of bytes read by fgets()) * \param size size of buffer s (max number of bytes read by fgets())
* \param fp file pointer used by fgets() * \param fp file pointer used by fgets()
* \param filename file name associated with fp (may be a null pointer; then LAMMPS will try to detect) * \param filename file name associated with fp (may be a null pointer; then LAMMPS will try to detect)
* \param error pointer to Error class instance (for abort) */ * \param error pointer to Error class instance (for abort) or nullptr */
void sfgets(const char *srcname, int srcline, char *s, int size, void sfgets(const char *srcname, int srcline, char *s, int size,
FILE *fp, const char *filename, Error *error); FILE *fp, const char *filename, Error *error);
/** safe wrapper around fread() which aborts on errors /** Safe wrapper around fread() which aborts on errors
* or EOF and prints a suitable error message to help debugging * or EOF and prints a suitable error message to help debugging.
*
* Use nullptr as the error parameter to avoid the abort on EOF or error.
* *
* \param srcname name of the calling source file (from FLERR macro) * \param srcname name of the calling source file (from FLERR macro)
* \param srcline line in the calling source file (from FLERR macro) * \param srcline line in the calling source file (from FLERR macro)
@ -84,11 +91,31 @@ namespace LAMMPS_NS {
* \param num number of data elements read by fread() * \param num number of data elements read by fread()
* \param fp file pointer used by fread() * \param fp file pointer used by fread()
* \param filename file name associated with fp (may be a null pointer; then LAMMPS will try to detect) * \param filename file name associated with fp (may be a null pointer; then LAMMPS will try to detect)
* \param error pointer to Error class instance (for abort) */ * \param error pointer to Error class instance (for abort) or nullptr */
void sfread(const char *srcname, int srcline, void *s, size_t size, void sfread(const char *srcname, int srcline, void *s, size_t size,
size_t num, FILE *fp, const char *filename, Error *error); size_t num, FILE *fp, const char *filename, Error *error);
/** Read N lines of text from file into buffer and broadcast them
*
* This function uses repeated calls to fread() to fill a buffer with
* newline terminated text. If a line does not end in a newline (e.g.
* at the end of a file), it is added. The caller has to allocate an
* nlines by nmax sized buffer for storing the text data.
* Reading is done by MPI rank 0 of the given communicator only, and
* thus only MPI rank 0 needs to provide a valid file pointer.
*
* \param fp file pointer used by fread
* \param nlines number of lines to be read
* \param nmax maximum length of a single line
* \param buffer buffer for storing the data.
* \param me MPI rank of calling process in MPI communicator
* \param comm MPI communicator for broadcast
* \return 1 if the read was short, 0 if read was successful */
int read_lines_from_file(FILE *fp, int nlines, int nmax,
char *buffer, int me, MPI_Comm comm);
/** Report if a requested style is in a package or may have a typo /** Report if a requested style is in a package or may have a typo
* *
* \param style type of style that is to be checked for * \param style type of style that is to be checked for

View File

@ -5176,7 +5176,7 @@ int VarReader::read_peratom()
bigint nread = 0; bigint nread = 0;
while (nread < nlines) { while (nread < nlines) {
nchunk = MIN(nlines-nread,CHUNK); nchunk = MIN(nlines-nread,CHUNK);
eof = comm->read_lines_from_file(fp,nchunk,MAXLINE,buffer); eof = utils::read_lines_from_file(fp,nchunk,MAXLINE,buffer,me,world);
if (eof) return 1; if (eof) return 1;
char *buf = buffer; char *buf = buffer;

View File

@ -11,13 +11,13 @@
See the README file in the top-level LAMMPS directory. See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
#include "../testing/core.h"
#include "info.h" #include "info.h"
#include "input.h" #include "input.h"
#include "lammps.h" #include "lammps.h"
#include "utils.h" #include "utils.h"
#include "gmock/gmock.h" #include "gmock/gmock.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "../testing/core.h"
#include <cstdio> #include <cstdio>
#include <mpi.h> #include <mpi.h>
@ -28,6 +28,7 @@ using namespace LAMMPS_NS;
using testing::MatchesRegex; using testing::MatchesRegex;
using testing::StrEq; using testing::StrEq;
using utils::read_lines_from_file;
using utils::sfgets; using utils::sfgets;
using utils::sfread; using utils::sfread;
using utils::split_words; using utils::split_words;
@ -124,6 +125,37 @@ TEST_F(FileOperationsTest, safe_fread)
fclose(fp); fclose(fp);
} }
TEST_F(FileOperationsTest, read_lines_from_file)
{
char *buf = new char[MAX_BUF_SIZE];
FILE *fp = nullptr;
MPI_Comm world = MPI_COMM_WORLD;
int me, rv;
memset(buf, 0, MAX_BUF_SIZE);
rv = utils::read_lines_from_file(nullptr, 1, MAX_BUF_SIZE, buf, me, world);
ASSERT_EQ(rv, 1);
MPI_Comm_rank(world, &me);
if (me == 0) {
fp = fopen("safe_file_read_test.txt", "r");
ASSERT_NE(fp, nullptr);
} else
ASSERT_EQ(fp, nullptr);
rv = utils::read_lines_from_file(fp, 2, MAX_BUF_SIZE / 2, buf, me, world);
ASSERT_EQ(rv, 0);
ASSERT_THAT(buf, StrEq("one line\ntwo_lines\n"));
rv = utils::read_lines_from_file(fp, 2, MAX_BUF_SIZE / 2, buf, me, world);
ASSERT_EQ(rv, 0);
ASSERT_THAT(buf, StrEq("\nno newline\n"));
rv = utils::read_lines_from_file(fp, 2, MAX_BUF_SIZE / 2, buf, me, world);
ASSERT_EQ(rv, 1);
delete[] buf;
}
TEST_F(FileOperationsTest, logmesg) TEST_F(FileOperationsTest, logmesg)
{ {
char buf[8]; char buf[8];