*/
#include "cmdlinehelpwriter.h"
-#include <cstdio>
-#include <cstdlib>
-
#include <string>
#include "gromacs/legacyheaders/smalloc.h"
#include "gromacs/options/timeunitmanager.h"
#include "gromacs/selection/selectionfileoptioninfo.h"
#include "gromacs/selection/selectionoptioninfo.h"
+#include "gromacs/utility/file.h"
#include "gromacs/utility/format.h"
#include "cmdlinehelpwriter-impl.h"
{
public:
//! Creates a helper object for writing section descriptions.
- explicit DescriptionWriter(FILE *fp) : fp_(fp) {}
+ explicit DescriptionWriter(File *file) : file_(*file) {}
virtual void visitSubSection(const Options §ion);
virtual void visitOption(const OptionInfo & /*option*/) { }
private:
- FILE *fp_;
+ File &file_;
};
void DescriptionWriter::visitSubSection(const Options §ion)
const std::string &title = section.title();
if (!title.empty())
{
- fprintf(fp_, "%s\n\n", title.c_str());
+ file_.writeLine(title);
+ file_.writeLine();
}
TextLineWrapper wrapper;
wrapper.setLineLength(78);
std::string description(substituteMarkup(section.description()));
- fprintf(fp_, "%s\n\n", wrapper.wrapToString(description).c_str());
+ file_.writeLine(wrapper.wrapToString(description));
+ file_.writeLine();
}
OptionsIterator(section).acceptSubSections(this);
}
{
public:
//! Creates a helper object for writing file parameters.
- explicit FileParameterWriter(FILE *fp);
+ explicit FileParameterWriter(File *file);
//! Returns true if anything was written out.
bool didOutput() const { return formatter_.didOutput(); }
virtual void visitOptionType(const FileNameOptionInfo &option);
private:
- FILE *fp_;
+ File &file_;
TextTableFormatter formatter_;
};
-FileParameterWriter::FileParameterWriter(FILE *fp)
- : fp_(fp)
+FileParameterWriter::FileParameterWriter(File *file)
+ : file_(*file)
{
formatter_.addColumn("Option", 6, false);
formatter_.addColumn("Filename", 12, false);
}
// Do the formatting.
- std::string row = formatter_.formatRow();
- fprintf(fp_, "%s", row.c_str());
+ file_.writeString(formatter_.formatRow());
}
{
public:
//! Creates a helper object for writing non-file parameters.
- ParameterWriter(FILE *fp, const char *timeUnit);
+ ParameterWriter(File *file, const char *timeUnit);
//! Sets the writer to show hidden options.
void setShowHidden(bool bSet) { bShowHidden_ = bSet; }
virtual void visitOption(const OptionInfo &option);
private:
- FILE *fp_;
+ File &file_;
TextTableFormatter formatter_;
const char *timeUnit_;
bool bShowHidden_;
};
-ParameterWriter::ParameterWriter(FILE *fp, const char *timeUnit)
- : fp_(fp), timeUnit_(timeUnit), bShowHidden_(false)
+ParameterWriter::ParameterWriter(File *file, const char *timeUnit)
+ : file_(*file), timeUnit_(timeUnit), bShowHidden_(false)
{
formatter_.addColumn("Option", 12, false);
formatter_.addColumn("Type", 6, false);
formatter_.setColumnFirstLineOffset(3, 1);
}
- std::string row = formatter_.formatRow();
- fprintf(fp_, "%s", row.c_str());
+ file_.writeString(formatter_.formatRow());
}
{
public:
//! Creates a helper object for writing selection parameters.
- explicit SelectionParameterWriter(FILE *fp);
+ explicit SelectionParameterWriter(File *file);
//! Returns true if anything was written out.
bool didOutput() const { return formatter_.didOutput(); }
virtual void visitOption(const OptionInfo &option);
private:
- FILE *fp_;
+ File &file_;
TextTableFormatter formatter_;
};
-SelectionParameterWriter::SelectionParameterWriter(FILE *fp)
- : fp_(fp)
+SelectionParameterWriter::SelectionParameterWriter(File *file)
+ : file_(*file)
{
formatter_.addColumn("Selection", 10, false);
formatter_.addColumn("Description", 67, true);
std::string name(formatString("-%s", option.name().c_str()));
formatter_.addColumnLine(0, name);
formatter_.addColumnLine(1, substituteMarkup(option.description()));
- std::string row = formatter_.formatRow();
- fprintf(fp_, "%s", row.c_str());
+ file_.writeString(formatter_.formatRow());
// TODO: What to do with selection variables?
// They are not printed as values for any option.
{
std::string value(option.formatValue(i));
// TODO: Wrapping
- fprintf(fp_, " %s\n", value.c_str());
+ file_.writeLine(formatString(" %s", value.c_str()));
}
}
return *this;
}
-void CommandLineHelpWriter::writeHelp(FILE *fp)
+void CommandLineHelpWriter::writeHelp(File *file)
{
if (impl_->bShowDescriptions_)
{
- fprintf(fp, "DESCRIPTION\n"
- "-----------\n\n");
- DescriptionWriter(fp).visitSubSection(impl_->options_);
+ file->writeLine("DESCRIPTION");
+ file->writeLine("-----------");
+ file->writeLine();
+ DescriptionWriter(file).visitSubSection(impl_->options_);
}
{
- FileParameterWriter writer(fp);
+ FileParameterWriter writer(file);
writer.visitSubSection(impl_->options_);
if (writer.didOutput())
{
- fprintf(fp, "\n");
+ file->writeLine();
}
}
{
- ParameterWriter writer(fp, impl_->timeUnit_.c_str());
+ ParameterWriter writer(file, impl_->timeUnit_.c_str());
writer.setShowHidden(impl_->bShowHidden_);
writer.visitSubSection(impl_->options_);
if (writer.didOutput())
{
- fprintf(fp, "\n");
+ file->writeLine();
}
}
{
- SelectionParameterWriter writer(fp);
+ SelectionParameterWriter writer(file);
writer.visitSubSection(impl_->options_);
if (writer.didOutput())
{
- fprintf(fp, "\n");
+ file->writeLine();
}
}
}
#ifndef GMX_COMMANDLINE_CMDLINEHELPWRITER_H
#define GMX_COMMANDLINE_CMDLINEHELPWRITER_H
-#include <cstdio>
-
#include "../utility/common.h"
namespace gmx
{
+class File;
class Options;
/*! \brief
/*! \brief
* Writes the help.
*
- * \param[in] fp File to write the help to.
+ * \param[in] file File to write the help to.
*/
- void writeHelp(FILE *fp);
+ void writeHelp(File *file);
private:
class Impl;
void CommandLineHelpWriterTest::checkHelp(gmx::CommandLineHelpWriter *writer)
{
gmx::File file(helpfile_, "w");
- writer->writeHelp(file.handle());
+ writer->writeHelp(&file);
file.close();
checkFileContents(helpfile_, "HelpText");
#include "gromacs/trajectoryanalysis/cmdlinerunner.h"
#include "gromacs/trajectoryanalysis/runnercommon.h"
#include "gromacs/utility/exceptions.h"
+#include "gromacs/utility/file.h"
#include "gromacs/utility/gmxassert.h"
namespace gmx
.setShowDescriptions(flags & TrajectoryAnalysisRunnerCommon::efHelpShowDescriptions)
.setShowHidden(flags & TrajectoryAnalysisRunnerCommon::efHelpShowHidden)
.setTimeUnitString(settings.timeUnitManager().timeUnitAsString())
- .writeHelp(stderr);
+ .writeHelp(&File::standardError());
}
}
#include <cerrno>
#include <cstdio>
+#include <cstring>
#include <algorithm>
#include <string>
namespace gmx
{
-File::File(const char *filename, const char *mode)
- : fp_(NULL)
+/*! \internal \brief
+ * Private implementation class for File.
+ *
+ * \ingroup module_utility
+ */
+class File::Impl
{
- open(filename, mode);
-}
+ public:
+ /*! \brief
+ * Initialize a file object with the given handle.
+ *
+ * \param[in] fp File handle to use (may be NULL).
+ * \param[in] bClose Whether this object should close its file handle.
+ */
+ Impl(FILE *fp, bool bClose);
+ ~Impl();
-File::File(const std::string &filename, const char *mode)
- : fp_(NULL)
+ //! File handle for this object (may be NULL).
+ FILE *fp_;
+ /*! \brief
+ * Whether \p fp_ should be closed by this object.
+ *
+ * Can be true if \p fp_ is NULL.
+ */
+ bool bClose_;
+};
+
+File::Impl::Impl(FILE *fp, bool bClose)
+ : fp_(fp), bClose_(bClose)
{
- open(filename, mode);
}
-File::~File()
+File::Impl::~Impl()
{
- if (fp_ != NULL)
+ if (fp_ != NULL && bClose_)
{
if (fclose(fp_) != 0)
{
}
}
+File::File(const char *filename, const char *mode)
+ : impl_(new Impl(NULL, true))
+{
+ open(filename, mode);
+}
+
+File::File(const std::string &filename, const char *mode)
+ : impl_(new Impl(NULL, true))
+{
+ open(filename, mode);
+}
+
+File::File(FILE *fp, bool bClose)
+ : impl_(new Impl(fp, bClose))
+{
+}
+
+File::~File()
+{
+}
+
void File::open(const char *filename, const char *mode)
{
- GMX_RELEASE_ASSERT(fp_ == NULL,
+ GMX_RELEASE_ASSERT(impl_->fp_ == NULL,
"Attempted to open the same file object twice");
// TODO: Port all necessary functionality from ffopen() here.
- fp_ = fopen(filename, mode);
- if (fp_ == NULL)
+ impl_->fp_ = fopen(filename, mode);
+ if (impl_->fp_ == NULL)
{
GMX_THROW_WITH_ERRNO(
FileIOError(formatString("Could not open file '%s'", filename)),
void File::close()
{
- GMX_RELEASE_ASSERT(fp_ != NULL,
+ GMX_RELEASE_ASSERT(impl_->fp_ != NULL,
"Attempted to close a file object that is not open");
- bool bOk = (fclose(fp_) == 0);
- fp_ = NULL;
+ GMX_RELEASE_ASSERT(impl_->bClose_,
+ "Attempted to close a file object that should not be");
+ bool bOk = (fclose(impl_->fp_) == 0);
+ impl_->fp_ = NULL;
if (!bOk)
{
GMX_THROW_WITH_ERRNO(
FILE *File::handle()
{
- GMX_RELEASE_ASSERT(fp_ != NULL,
+ GMX_RELEASE_ASSERT(impl_->fp_ != NULL,
"Attempted to access a file object that is not open");
- return fp_;
+ return impl_->fp_;
}
void File::readBytes(void *buffer, size_t bytes)
{
- GMX_RELEASE_ASSERT(fp_ != NULL,
- "Attempted to access a file object that is not open");
errno = 0;
+ FILE *fp = handle();
// TODO: Retry based on errno or something else?
- size_t bytesRead = std::fread(buffer, 1, bytes, fp_);
+ size_t bytesRead = std::fread(buffer, 1, bytes, fp);
if (bytesRead != bytes)
{
- if (feof(fp_))
+ if (feof(fp))
{
GMX_THROW(FileIOError(
formatString("Premature end of file\n"
}
}
+void File::writeString(const char *str)
+{
+ if (fprintf(handle(), "%s", str) < 0)
+ {
+ GMX_THROW_WITH_ERRNO(FileIOError("Writing to file failed"),
+ "fprintf", errno);
+ }
+}
+
+void File::writeLine(const char *line)
+{
+ size_t length = std::strlen(line);
+
+ writeString(line);
+ if (length == 0 || line[length-1] != '\n')
+ {
+ writeString("\n");
+ }
+}
+
+void File::writeLine()
+{
+ writeString("\n");
+}
+
+// static
+File &File::standardError()
+{
+ static File stderrObject(stderr, false);
+ return stderrObject;
+}
+
// static
std::string File::readToString(const char *filename)
{
*
* \param[in] filename Path of the file to open.
* \param[in] mode Mode to open the file in (for fopen()).
+ * \throws std::bad_alloc if out of memory.
* \throws FileIOError on any I/O error.
*
* \see open(const char *, const char *)
*/
void readBytes(void *buffer, size_t bytes);
+ /*! \brief
+ * Writes a string to the file.
+ *
+ * \param[in] str String to write.
+ * \throws FileIOError on any I/O error.
+ *
+ * The file must be open.
+ */
+ void writeString(const char *str);
+ //! \copydoc writeString(const char *)
+ void writeString(const std::string &str) { writeString(str.c_str()); }
+ /*! \brief
+ * Writes a line to the file.
+ *
+ * \param[in] line Line to write.
+ * \throws FileIOError on any I/O error.
+ *
+ * If \p line does not end in a newline, one newline is appended.
+ * Otherwise, works as writeString().
+ *
+ * The file must be open.
+ */
+ void writeLine(const char *line);
+ //! \copydoc writeLine(const char *)
+ void writeLine(const std::string &line) { writeLine(line.c_str()); }
+ /*! \brief
+ * Writes a newline to the file.
+ *
+ * \throws FileIOError on any I/O error.
+ */
+ void writeLine();
+
+ /*! \brief
+ * Returns a File object for accessing stderr.
+ *
+ * \throws std::bad_alloc if out of memory.
+ */
+ static File &standardError();
+
/*! \brief
* Reads contents of a file to a std::string.
*
static std::string readToString(const std::string &filename);
private:
- FILE *fp_;
+ /*! \brief
+ * Initialize file object from an existing file handle.
+ *
+ * \param[in] fp File handle to use (may be NULL).
+ * \param[in] bClose Whether this object should close its file handle.
+ * \throws std::bad_alloc if out of memory.
+ *
+ * Used internally to implement standardError().
+ */
+ File(FILE *fp, bool bClose);
+
+ class Impl;
- GMX_DISALLOW_COPY_AND_ASSIGN(File);
+ PrivateImplPointer<Impl> impl_;
};
} // namespace gmx