provide more generic implementation of Comm::read_lines_from_file() in utils

This commit is contained in:
Axel Kohlmeyer
2021-04-24 21:05:11 -04:00
parent 93691ca939
commit 539ab02365
3 changed files with 87 additions and 2 deletions

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 maxline,
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,maxline,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,
const std::string &name,
LAMMPS *lmp)

View File

@ -17,9 +17,12 @@
/*! \file utils.h */
#include "lmptype.h"
#include <mpi.h>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdio>
namespace LAMMPS_NS {
@ -89,6 +92,26 @@ namespace LAMMPS_NS {
void sfread(const char *srcname, int srcline, void *s, size_t size,
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 maxline 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 maxline 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 succesful */
int read_lines_from_file(FILE *fp, int nlines, int maxline,
char *buffer, int me, MPI_Comm comm);
/** 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

View File

@ -11,13 +11,13 @@
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "../testing/core.h"
#include "info.h"
#include "input.h"
#include "lammps.h"
#include "utils.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "../testing/core.h"
#include <cstdio>
#include <mpi.h>
@ -28,6 +28,7 @@ using namespace LAMMPS_NS;
using testing::MatchesRegex;
using testing::StrEq;
using utils::read_lines_from_file;
using utils::sfgets;
using utils::sfread;
using utils::split_words;
@ -124,6 +125,37 @@ TEST_F(FileOperationsTest, safe_fread)
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)
{
char buf[8];