#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/gmxassert.h"
#include "gromacs/utility/smalloc.h"
+#include "gromacs/utility/stringutil.h"
+#include "gromacs/utility/textwriter.h"
/********************************************************************
* gmx_ana_indexgrps_t functions
}
/*!
- * \param[in] fp Where to print the output.
+ * \param[in] writer Writer to use for output.
* \param[in] g Index groups to print.
* \param[in] maxn Maximum number of indices to print
* (-1 = print all, 0 = print only names).
*/
void
-gmx_ana_indexgrps_print(FILE *fp, gmx_ana_indexgrps_t *g, int maxn)
+gmx_ana_indexgrps_print(gmx::TextWriter *writer, gmx_ana_indexgrps_t *g, int maxn)
{
for (int i = 0; i < g->nr; ++i)
{
- fprintf(fp, " Group %2d \"%s\" ", i, g->names[i].c_str());
- gmx_ana_index_dump(fp, &g->g[i], maxn);
+ writer->writeString(gmx::formatString(" Group %2d \"%s\" ",
+ i, g->names[i].c_str()));
+ gmx_ana_index_dump(writer, &g->g[i], maxn);
}
}
}
/*!
- * \param[in] fp Where to print the output.
+ * \param[in] writer Writer to use for output.
* \param[in] g Index group to print.
* \param[in] maxn Maximum number of indices to print (-1 = print all).
*/
void
-gmx_ana_index_dump(FILE *fp, gmx_ana_index_t *g, int maxn)
+gmx_ana_index_dump(gmx::TextWriter *writer, gmx_ana_index_t *g, int maxn)
{
- int j, n;
-
- fprintf(fp, "(%d atoms)", g->isize);
+ writer->writeString(gmx::formatString("(%d atoms)", g->isize));
if (maxn != 0)
{
- fprintf(fp, ":");
- n = g->isize;
+ writer->writeString(":");
+ int n = g->isize;
if (maxn >= 0 && n > maxn)
{
n = maxn;
}
- for (j = 0; j < n; ++j)
+ for (int j = 0; j < n; ++j)
{
- fprintf(fp, " %d", g->index[j]+1);
+ writer->writeString(gmx::formatString(" %d", g->index[j]+1));
}
if (n < g->isize)
{
- fprintf(fp, " ...");
+ writer->writeString(" ...");
}
}
- fprintf(fp, "\n");
+ writer->writeLine();
}
int
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013,2014,2015, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/legacyheaders/types/simple.h"
#include "gromacs/topology/block.h"
+namespace gmx
+{
+class TextWriter;
+}
+
struct t_topology;
/** Stores a set of index groups. */
/** Writes out a list of index groups. */
void
-gmx_ana_indexgrps_print(FILE *fp, gmx_ana_indexgrps_t *g, int maxn);
+gmx_ana_indexgrps_print(gmx::TextWriter *writer, gmx_ana_indexgrps_t *g, int maxn);
/*@}*/
/*! \name Functions for handling gmx_ana_index_t
/** Writes out the contents of a index group. */
void
-gmx_ana_index_dump(FILE *fp, gmx_ana_index_t *g, int maxn);
+gmx_ana_index_dump(gmx::TextWriter *writer, gmx_ana_index_t *g, int maxn);
/*! \brief
* Returns maximum atom index that appears in an index group.
* methods and initializes the children of the method element.
* - selectioncollection.h, selectioncollection.cpp:
* These files define the high-level public interface to the parser
- * through SelectionCollection::parseFromStdin(),
- * SelectionCollection::parseFromFile() and
+ * through SelectionCollection::parseInteractive(),
+ * SelectionCollection::parseFromStdin(),
+ * SelectionCollection::parseFromFile(), and
* SelectionCollection::parseFromString().
*
* The basic control flow in the parser is as follows: when a parser function
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/smalloc.h"
#include "gromacs/utility/stringutil.h"
+#include "gromacs/utility/textwriter.h"
#include "keywords.h"
#include "poscalc.h"
catch (gmx::UserInputError &ex)
{
ex.prependContext(context);
- if (_gmx_sel_is_lexer_interactive(scanner))
+ gmx::TextWriter *statusWriter
+ = _gmx_sel_lexer_get_status_writer(scanner);
+ if (statusWriter != NULL)
{
- gmx::formatExceptionMessageToFile(stderr, ex);
+ gmx::formatExceptionMessageToWriter(statusWriter, ex);
return true;
}
throw;
root->fillNameIfMissing(_gmx_sel_lexer_pselstr(scanner));
/* Print out some information if the parser is interactive */
- if (_gmx_sel_is_lexer_interactive(scanner))
+ gmx::TextWriter *statusWriter = _gmx_sel_lexer_get_status_writer(scanner);
+ if (statusWriter != NULL)
{
- fprintf(stderr, "Selection '%s' parsed\n",
- _gmx_sel_lexer_pselstr(scanner));
+ const std::string message
+ = gmx::formatString("Selection '%s' parsed",
+ _gmx_sel_lexer_pselstr(scanner));
+ statusWriter->writeLine(message);
}
return root;
srenew(sc->varstrs, sc->nvars + 1);
sc->varstrs[sc->nvars] = gmx_strdup(pselstr);
++sc->nvars;
- if (_gmx_sel_is_lexer_interactive(scanner))
+ gmx::TextWriter *statusWriter = _gmx_sel_lexer_get_status_writer(scanner);
+ if (statusWriter != NULL)
{
- fprintf(stderr, "Variable '%s' parsed\n", pselstr);
+ const std::string message
+ = gmx::formatString("Variable '%s' parsed", pselstr);
+ statusWriter->writeLine(message);
}
return root;
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013,2014,2015, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
YY_RULE_SETUP
#line 137 "scanner.l"
{
- if (yytext[0] == ';' || state->bInteractive)
+ if (yytext[0] == ';' || state->statusWriter != NULL)
{
rtrim(state->pselstr);
state->bCmdStart = true;
#include "parser.h"
+namespace gmx
+{
+class TextWriter;
+}
+
struct gmx_ana_indexgrps_t;
struct gmx_ana_selcollection_t;
/** Initializes the selection scanner. */
void
_gmx_sel_init_lexer(yyscan_t *scannerp, struct gmx_ana_selcollection_t *sc,
- bool bInteractive, int maxnr, bool bGroups,
+ gmx::TextWriter *statusWriter, int maxnr, bool bGroups,
struct gmx_ana_indexgrps_t *grps);
/** Frees memory allocated for the selection scanner. */
void
void
_gmx_sel_lexer_rethrow_exception_if_occurred(yyscan_t scanner);
-/** Returns true if the scanner is interactive. */
-bool
-_gmx_sel_is_lexer_interactive(yyscan_t scanner);
+/** Returns writer for status output (if not NULL, the scanner is interactive). */
+gmx::TextWriter *
+_gmx_sel_lexer_get_status_writer(yyscan_t scanner);
/** Returns the selection collection for the scanner. */
struct gmx_ana_selcollection_t *
_gmx_sel_lexer_selcollection(yyscan_t scanner);
\\\n { _gmx_sel_lexer_add_token(yylloc, " ", 1, state); break; }
";"|\n {
- if (yytext[0] == ';' || state->bInteractive)
+ if (yytext[0] == ';' || state->statusWriter != NULL)
{
rtrim(state->pselstr);
state->bCmdStart = true;
void
_gmx_sel_init_lexer(yyscan_t *scannerp, struct gmx_ana_selcollection_t *sc,
- bool bInteractive, int maxnr, bool bGroups,
- struct gmx_ana_indexgrps_t *grps)
+ gmx::TextWriter *statusWriter, int maxnr,
+ bool bGroups, struct gmx_ana_indexgrps_t *grps)
{
int rc = _gmx_sel_yylex_init(scannerp);
if (rc != 0)
state->grps = grps;
state->nexpsel = (maxnr > 0 ? static_cast<int>(sc->sel.size()) + maxnr : -1);
- state->bInteractive = bInteractive;
+ state->statusWriter = statusWriter;
snew(state->pselstr, STRSTORE_ALLOCSTEP);
state->pselstr[0] = 0;
}
}
-bool
-_gmx_sel_is_lexer_interactive(yyscan_t scanner)
+gmx::TextWriter *
+_gmx_sel_lexer_get_status_writer(yyscan_t scanner)
{
gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(scanner);
- return state->bInteractive;
+ return state->statusWriter;
}
struct gmx_ana_selcollection_t *
namespace gmx
{
class SelectionParserSymbol;
+class TextWriter;
}
/* These need to be defined before including scanner_flex.h, because it
//! Number of selections at which the parser should stop.
int nexpsel;
- //! Whether the parser is interactive.
- bool bInteractive;
+ //! Writer to use for status output (if not NULL, parser is interactive).
+ gmx::TextWriter *statusWriter;
//! Pretty-printed version of the string parsed since last clear.
char *pselstr;
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/gmxassert.h"
#include "gromacs/utility/stringutil.h"
+#include "gromacs/utility/textwriter.h"
#include "selelem.h"
#include "selvalue.h"
fprintf(fp, " Group ");
gmx_ana_index_t g;
gmx_ana_index_set(&g, p.m.mapb.nra, p.m.mapb.a, 0);
- gmx_ana_index_dump(fp, &g, nmaxind);
+ TextWriter writer(fp);
+ gmx_ana_index_dump(&writer, &g, nmaxind);
fprintf(fp, " Block (size=%d):", p.m.mapb.nr);
if (!p.m.mapb.index)
#include <string>
#include <vector>
+#include <boost/scoped_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include "gromacs/fileio/trx.h"
#include "gromacs/utility/gmxassert.h"
#include "gromacs/utility/smalloc.h"
#include "gromacs/utility/stringutil.h"
+#include "gromacs/utility/textwriter.h"
#include "compiler.h"
#include "mempool.h"
/*! \brief
* Reads a single selection line from stdin.
*
- * \param[in] infile Stream to read from (typically the StandardInputStream).
- * \param[in] bInteractive Whether to print interactive prompts.
+ * \param[in] inputStream Stream to read from (typically the StandardInputStream).
+ * \param[in] statusWriter Stream to print prompts to (if NULL, no output is done).
* \param[out] line The read line in stored here.
* \returns true if something was read, false if at end of input.
*
* Handles line continuation, reading also the continuing line(s) in one call.
*/
-bool promptLine(TextInputStream *infile, bool bInteractive, std::string *line)
+bool promptLine(TextInputStream *inputStream, TextWriter *statusWriter,
+ std::string *line)
{
- if (bInteractive)
+ if (statusWriter != NULL)
{
- fprintf(stderr, "> ");
+ statusWriter->writeString("> ");
}
- if (!infile->readLine(line))
+ if (!inputStream->readLine(line))
{
return false;
}
while (endsWith(*line, "\\\n"))
{
line->resize(line->length() - 2);
- if (bInteractive)
+ if (statusWriter != NULL)
{
- fprintf(stderr, "... ");
+ statusWriter->writeString("... ");
}
std::string buffer;
// Return value ignored, buffer remains empty and works correctly
// if there is nothing to read.
- infile->readLine(&buffer);
+ inputStream->readLine(&buffer);
line->append(buffer);
}
if (endsWith(*line, "\n"))
{
line->resize(line->length() - 1);
}
- else if (bInteractive)
+ else if (statusWriter != NULL)
{
- fprintf(stderr, "\n");
+ statusWriter->writeLine();
}
return true;
}
/*! \brief
* Print current status in response to empty line in interactive input.
*
+ * \param[in] writer Writer to use for the output.
* \param[in] sc Selection collection data structure.
* \param[in] grps Available index groups.
* \param[in] firstSelection Index of first selection from this interactive
*
* Prints the available index groups and currently provided selections.
*/
-void printCurrentStatus(gmx_ana_selcollection_t *sc, gmx_ana_indexgrps_t *grps,
- size_t firstSelection, int maxCount,
- const std::string &context, bool bFirst)
+void printCurrentStatus(TextWriter *writer, gmx_ana_selcollection_t *sc,
+ gmx_ana_indexgrps_t *grps, size_t firstSelection,
+ int maxCount, const std::string &context, bool bFirst)
{
if (grps != NULL)
{
- std::fprintf(stderr, "Available static index groups:\n");
- gmx_ana_indexgrps_print(stderr, grps, 0);
+ writer->writeLine("Available static index groups:");
+ gmx_ana_indexgrps_print(writer, grps, 0);
}
- std::fprintf(stderr, "Specify ");
+ writer->writeString("Specify ");
if (maxCount < 0)
{
- std::fprintf(stderr, "any number of selections");
+ writer->writeString("any number of selections");
}
else if (maxCount == 1)
{
- std::fprintf(stderr, "a selection");
+ writer->writeString("a selection");
}
else
{
- std::fprintf(stderr, "%d selections", maxCount);
+ writer->writeString(formatString("%d selections", maxCount));
}
- std::fprintf(stderr, "%s%s:\n",
- context.empty() ? "" : " ", context.c_str());
- std::fprintf(stderr,
- "(one per line, <enter> for status/groups, 'help' for help%s)\n",
- maxCount < 0 ? ", Ctrl-D to end" : "");
+ writer->writeString(formatString("%s%s:\n",
+ context.empty() ? "" : " ", context.c_str()));
+ writer->writeString(formatString(
+ "(one per line, <enter> for status/groups, 'help' for help%s)\n",
+ maxCount < 0 ? ", Ctrl-D to end" : ""));
if (!bFirst && (sc->nvars > 0 || sc->sel.size() > firstSelection))
{
- std::fprintf(stderr, "Currently provided selections:\n");
+ writer->writeLine("Currently provided selections:");
for (int i = 0; i < sc->nvars; ++i)
{
- std::fprintf(stderr, " %s\n", sc->varstrs[i]);
+ writer->writeString(formatString(" %s\n", sc->varstrs[i]));
}
for (size_t i = firstSelection; i < sc->sel.size(); ++i)
{
- std::fprintf(stderr, " %2d. %s\n",
- static_cast<int>(i - firstSelection + 1),
- sc->sel[i]->selectionText());
+ writer->writeString(formatString(
+ " %2d. %s\n",
+ static_cast<int>(i - firstSelection + 1),
+ sc->sel[i]->selectionText()));
}
if (maxCount > 0)
{
const int remaining
= maxCount - static_cast<int>(sc->sel.size() - firstSelection);
- std::fprintf(stderr, "(%d more selection%s required)\n",
- remaining, remaining > 1 ? "s" : "");
+ writer->writeString(formatString(
+ "(%d more selection%s required)\n",
+ remaining, remaining > 1 ? "s" : ""));
}
}
}
/*! \brief
* Prints selection help in interactive selection input.
*
+ * \param[in] writer Writer to use for the output.
* \param[in] sc Selection collection data structure.
* \param[in] line Line of user input requesting help (starting with `help`).
*
* Initializes the selection help if not yet initialized, and finds the help
* topic based on words on the input line.
*/
-void printHelp(gmx_ana_selcollection_t *sc, const std::string &line)
+void printHelp(TextWriter *writer, gmx_ana_selcollection_t *sc,
+ const std::string &line)
{
if (sc->rootHelp.get() == NULL)
{
sc->rootHelp = createSelectionHelpTopic();
}
- HelpWriterContext context(&TextOutputFile::standardError(),
- eHelpOutputFormat_Console);
+ HelpWriterContext context(&writer->stream(), eHelpOutputFormat_Console);
HelpManager manager(*sc->rootHelp, context);
try
{
}
catch (const InvalidInputError &ex)
{
- fprintf(stderr, "%s\n", ex.what());
+ writer->writeLine(ex.what());
return;
}
manager.writeCurrentTopic();
* Helper function that runs the parser once the tokenizer has been
* initialized.
*
- * \param[in,out] scanner Scanner data structure.
- * \param[in] bStdIn Whether to use a line-based reading
+ * \param[in,out] scanner Scanner data structure.
+ * \param[in] inputStream Stream to use for input (currently only with
+ * `bInteractive==true`).
+ * \param[in] bInteractive Whether to use a line-based reading
* algorithm designed for interactive input.
* \param[in] maxnr Maximum number of selections to parse
* (if -1, parse as many as provided by the user).
* \throws std::bad_alloc if out of memory.
* \throws InvalidInputError if there is a parsing error.
*
- * Used internally to implement parseFromStdin(), parseFromFile() and
+ * Used internally to implement parseInteractive(), parseFromFile() and
* parseFromString().
*/
-SelectionList runParser(yyscan_t scanner, bool bStdIn, int maxnr,
- const std::string &context)
+SelectionList runParser(yyscan_t scanner, TextInputStream *inputStream,
+ bool bInteractive, int maxnr, const std::string &context)
{
boost::shared_ptr<void> scannerGuard(scanner, &_gmx_sel_free_lexer);
gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
{
boost::shared_ptr<_gmx_sel_yypstate> parserState(
_gmx_sel_yypstate_new(), &_gmx_sel_yypstate_delete);
- if (bStdIn)
+ if (bInteractive)
{
- TextInputStream &stdinFile(StandardInputStream::instance());
- const bool bInteractive = _gmx_sel_is_lexer_interactive(scanner);
- if (bInteractive)
+ TextWriter *statusWriter = _gmx_sel_lexer_get_status_writer(scanner);
+ if (statusWriter != NULL)
{
- printCurrentStatus(sc, grps, oldCount, maxnr, context, true);
+ printCurrentStatus(statusWriter, sc, grps, oldCount, maxnr, context, true);
}
std::string line;
int status;
- while (promptLine(&stdinFile, bInteractive, &line))
+ while (promptLine(inputStream, statusWriter, &line))
{
- if (bInteractive)
+ if (statusWriter != NULL)
{
line = stripString(line);
if (line.empty())
{
- printCurrentStatus(sc, grps, oldCount, maxnr, context, false);
+ printCurrentStatus(statusWriter, sc, grps, oldCount, maxnr, context, false);
continue;
}
if (startsWith(line, "help")
&& (line[4] == 0 || std::isspace(line[4])))
{
- printHelp(sc, line);
+ printHelp(statusWriter, sc, line);
continue;
}
}
return false;
}
-
SelectionList
-SelectionCollection::parseFromStdin(int nr, bool bInteractive,
+SelectionCollection::parseFromStdin(int count, bool bInteractive,
const std::string &context)
+{
+ return parseInteractive(count, &StandardInputStream::instance(),
+ bInteractive ? &TextOutputFile::standardError() : NULL,
+ context);
+}
+
+SelectionList
+SelectionCollection::parseInteractive(int count,
+ TextInputStream *inputStream,
+ TextOutputStream *statusStream,
+ const std::string &context)
{
yyscan_t scanner;
- _gmx_sel_init_lexer(&scanner, &impl_->sc_, bInteractive, nr,
- impl_->bExternalGroupsSet_,
- impl_->grps_);
- return runParser(scanner, true, nr, context);
+ boost::scoped_ptr<TextWriter> statusWriter;
+ if (statusStream != NULL)
+ {
+ statusWriter.reset(new TextWriter(statusStream));
+ }
+ _gmx_sel_init_lexer(&scanner, &impl_->sc_, statusWriter.get(),
+ count, impl_->bExternalGroupsSet_, impl_->grps_);
+ return runParser(scanner, inputStream, true, count, context);
}
yyscan_t scanner;
TextInputFile file(filename);
// TODO: Exception-safe way of using the lexer.
- _gmx_sel_init_lexer(&scanner, &impl_->sc_, false, -1,
+ _gmx_sel_init_lexer(&scanner, &impl_->sc_, NULL, -1,
impl_->bExternalGroupsSet_,
impl_->grps_);
_gmx_sel_set_lex_input_file(scanner, file.handle());
- return runParser(scanner, false, -1, std::string());
+ return runParser(scanner, NULL, false, -1, std::string());
}
catch (GromacsException &ex)
{
{
yyscan_t scanner;
- _gmx_sel_init_lexer(&scanner, &impl_->sc_, false, -1,
+ _gmx_sel_init_lexer(&scanner, &impl_->sc_, NULL, -1,
impl_->bExternalGroupsSet_,
impl_->grps_);
_gmx_sel_set_lex_input_str(scanner, str.c_str());
- return runParser(scanner, false, -1, std::string());
+ return runParser(scanner, NULL, false, -1, std::string());
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014,2015, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
class Options;
class SelectionCompiler;
class SelectionEvaluator;
+class TextInputStream;
+class TextOutputStream;
/*! \brief
* Collection of selections.
* initialization options.
*
* After setting the default values, one or more selections can be parsed with
- * one or more calls to parseFromStdin(), parseFromFile(), and/or
+ * one or more calls to parseInteractive(), parseFromStdin(), parseFromFile(), and/or
* parseFromString(). After all selections are parsed, the topology must be
* set with setTopology() unless requiresTopology() returns false (the topology
* can also be set earlier).
*/
SelectionList parseFromStdin(int count, bool bInteractive,
const std::string &context);
+ /*! \brief
+ * Parses selection(s) interactively using provided streams.
+ *
+ * \param[in] count Number of selections to parse
+ * (if -1, parse as many as provided by the user).
+ * \param[in] inputStream Stream to use for input.
+ * \param[in] outputStream Stream to use for output
+ * (if NULL, the parser runs non-interactively and does not
+ * produce any status messages).
+ * \param[in] context Context to print for interactive input.
+ * \returns Vector of parsed selections.
+ * \throws std::bad_alloc if out of memory.
+ * \throws InvalidInputError if there is a parsing error
+ * (an interactive parser only throws this if too few selections
+ * are provided and the user forced the end of input).
+ *
+ * Works the same as parseFromStdin(), except that the caller can
+ * provide streams to use instead of `stdin` and `stderr`.
+ *
+ * Mainly usable for unit testing interactive input.
+ */
+ SelectionList parseInteractive(int count,
+ TextInputStream *inputStream,
+ TextOutputStream *outputStream,
+ const std::string &context);
/*! \brief
* Parses selection(s) from a file.
*
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2011,2012,2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2011,2012,2013,2014,2015, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/errorcodes.h"
#include "gromacs/utility/gmxassert.h"
#include "gromacs/utility/stringutil.h"
+#include "gromacs/utility/textwriter.h"
#include "errorformat.h"
FILE *fp_;
};
+/*! \brief
+ * Exception information writer to format into a TextOutputStream.
+ */
+class MessageWriterTextWriter : public MessageWriterInterface
+{
+ public:
+ //! Initializes a writer that writes to the given stream.
+ explicit MessageWriterTextWriter(TextWriter *writer) : writer_(writer)
+ {
+ }
+
+ virtual void writeLine(const char *text, int indent)
+ {
+ // TODO: Line wrapping.
+ writer_->writeString(std::string(indent, ' '));
+ writer_->writeLine(text);
+ }
+ virtual void writeErrNoInfo(int errorNumber, const char *funcName,
+ int indent)
+ {
+ writeLine(formatString("Reason: %s", std::strerror(errorNumber)).c_str(),
+ indent);
+ if (funcName != NULL)
+ {
+ writeLine(formatString("(call to %s() returned error code %d)",
+ funcName, errorNumber).c_str(),
+ indent);
+ }
+ }
+
+ private:
+ TextWriter *writer_;
+};
+
/*! \brief
* Exception information writer to format into an std::string.
*/
formatExceptionMessageInternal(&writer, ex, 0);
}
+void formatExceptionMessageToWriter(TextWriter *writer,
+ const std::exception &ex)
+{
+ MessageWriterTextWriter messageWriter(writer);
+ formatExceptionMessageInternal(&messageWriter, ex, 0);
+}
+
int processExceptionAtExit(const std::exception & /*ex*/)
{
int returnCode = 1;
namespace gmx
{
+class TextWriter;
+
namespace internal
{
//! Internal container type for storing a list of nested exceptions.
* \throws std::bad_alloc if out of memory.
*/
void formatExceptionMessageToFile(FILE *fp, const std::exception &ex);
+/*! \brief
+ * Formats an error message for reporting an exception.
+ *
+ * \param writer Writer to use for writing the message.
+ * \param[in] ex Exception to format.
+ * \throws std::bad_alloc if out of memory.
+ */
+void formatExceptionMessageToWriter(TextWriter *writer,
+ const std::exception &ex);
/*! \brief
* Handles an exception that is causing the program to terminate.
*
{
}
+TextWriter::TextWriter(FILE *fp)
+ : impl_(new Impl(TextOutputStreamPointer(new TextOutputFile(fp))))
+{
+}
+
TextWriter::TextWriter(TextOutputStream *stream)
: impl_(new Impl(TextOutputStreamPointer(stream, no_delete<TextOutputStream>())))
{
#ifndef GMX_UTILITY_TEXTWRITER_H
#define GMX_UTILITY_TEXTWRITER_H
+#include <cstdio>
+
#include <string>
#include "gromacs/utility/classhelpers.h"
* a file, without the need to construct multiple objects.
*/
explicit TextWriter(const std::string &filename);
+ /*! \brief
+ * Creates a writer that writes to specified file.
+ *
+ * \param[in] fp File handle to write to.
+ * \throws std::bad_alloc if out of memory.
+ * \throws FileIOError on any I/O error.
+ *
+ * This constructor is provided for interoperability with C-like code
+ * for writing directly to an already opened file, without the need to
+ * construct multiple objects.
+ *
+ * The caller is responsible of closing \p fp; it is not allowed to
+ * call close() on the writer.
+ */
+ explicit TextWriter(FILE *fp);
/*! \brief
* Creates a writer that writes to specified stream.
*