"follow the instructions in the README file provided.",
"This template implements a simple analysis programs that calculates",
"average distances from a reference group to one or more",
- "analysis groups.",
- NULL
+ "analysis groups."
};
- options_.setDescription(desc);
+ options_.setDescription(concatenateStrings(desc));
options_.addOption(FileNameOption("o")
.filetype(eftPlot).outputFile()
*/
#include "gromacs/options/options.h"
-#include <cctype>
-#include <cstring>
-
#include "gromacs/options/abstractoption.h"
#include "gromacs/options/abstractoptionstorage.h"
#include "gromacs/utility/exceptions.h"
+#include "gromacs/utility/format.h"
#include "gromacs/utility/gmxassert.h"
#include "gromacs/utility/messagestringcollector.h"
namespace gmx
{
-// TODO: Move this into the utility module
-static std::string composeString(const char *const *sarray)
-{
- std::string result;
-
- for (int i = 0; sarray[i] != NULL; ++i)
- {
- if (sarray[i][0] != '\0')
- {
- result.append(sarray[i]);
- char lastchar = sarray[i][std::strlen(sarray[i])-1];
- if (!std::isspace(lastchar))
- {
- result.append(" ");
- }
- }
- }
- result.resize(result.find_last_not_of(" \n\r\t") + 1);
- return result;
-}
-
/********************************************************************
* Options::Impl
*/
return _impl->_description;
}
-void Options::setDescription(const char *const *desc)
+void Options::setDescription(const std::string &desc)
{
- _impl->_description = composeString(desc);
+ _impl->_description = desc;
}
void Options::addSubSection(Options *section)
/*! \brief
* Sets the full description of the option collection.
*
- * \param[in] desc Array of strings to form the description, terminated
- * by a NULL pointer.
+ * \param[in] desc String to set as the description.
*
- * The strings in the \p desc array are concatenated to form the
- * description, adding a single space between the strings if there is
- * no whitespace in the end of a string.
+ * concatenateStrings() is useful for forming the input string.
*/
- void setDescription(const char *const *desc);
+ void setDescription(const std::string &desc);
//int addBugs(int nbugs, const char *const *bugs);
/*! \brief
#include "trajectoryanalysis/analysissettings.h"
#include "trajectoryanalysis/cmdlinerunner.h"
#include "utility/exceptions.h"
+#include "utility/format.h"
#endif
"supported for static selections).",
"[TT]-od[tt] can be used to dump all the individual angles,",
"each on a separate line. This format is better suited for",
- "further processing, e.g., if angles from multiple runs are needed.",
- NULL
+ "further processing, e.g., if angles from multiple runs are needed."
};
static const char *const cGroup1TypeEnum[] =
{ "angle", "dihedral", "vector", "plane", NULL };
static const char *const cGroup2TypeEnum[] =
{ "none", "vector", "plane", "t0", "z", "sphnorm", NULL };
- _options.setDescription(desc);
+ _options.setDescription(concatenateStrings(desc));
_options.addOption(FileNameOption("o").filetype(eftPlot).outputFile()
.store(&_fnAngle).defaultValueIfSet("angle"));
#include "gromacs/selection/selectionoption.h"
#include "gromacs/trajectoryanalysis/analysissettings.h"
#include "gromacs/utility/exceptions.h"
+#include "gromacs/utility/format.h"
namespace gmx
{
static const char *const desc[] = {
"g_dist can calculate the distance between two positions as",
"a function of time. The total distance and its",
- "x, y and z components are plotted.",
- NULL
+ "x, y and z components are plotted."
};
- _options.setDescription(desc);
+ _options.setDescription(concatenateStrings(desc));
_options.addOption(FileNameOption("o").filetype(eftPlot).outputFile()
.store(&_fnDist).defaultValue("dist"));
"one frame, and contains either 0/1 for each atom/residue/molecule",
"possibly selected. 1 stands for the atom/residue/molecule being",
"selected for the current frame, 0 for not selected.",
- "With [TT]-dump[tt], the frame time is omitted from the output.",
- NULL
+ "With [TT]-dump[tt], the frame time is omitted from the output."
};
- _options.setDescription(desc);
+ _options.setDescription(concatenateStrings(desc));
_options.addOption(FileNameOption("os").filetype(eftPlot).outputFile()
.store(&_fnSize).defaultValueIfSet("size"));
#include <gromacs/trajectoryanalysis/analysissettings.h>
#include <gromacs/trajectoryanalysis/cmdlinerunner.h>
#include <gromacs/utility/exceptions.h>
+#include <gromacs/utility/format.h>
namespace gmx
{
SelectionTester::initOptions(TrajectoryAnalysisSettings * /*settings*/)
{
static const char *const desc[] = {
- "This is a test program for selections.",
- NULL
+ "This is a test program for selections."
};
- _options.setDescription(desc);
+ _options.setDescription(concatenateStrings(desc));
_options.addOption(SelectionOption("select").storeVector(&_selections)
.required().multiValue().allowMultiple()
*/
#include "gromacs/utility/format.h"
+#include <cctype>
#include <cstdio>
#include <cstdarg>
+#include <cstring>
#include <algorithm>
#include <string>
}
}
+std::string concatenateStrings(const char *const *sarray, size_t count)
+{
+ std::string result;
+
+ for (size_t i = 0; i < count && sarray[i] != NULL; ++i)
+ {
+ if (sarray[i][0] != '\0')
+ {
+ result.append(sarray[i]);
+ char lastchar = sarray[i][std::strlen(sarray[i])-1];
+ if (!std::isspace(lastchar))
+ {
+ result.append(" ");
+ }
+ }
+ }
+ result.resize(result.find_last_not_of(" \n\r\t") + 1);
+ return result;
+}
+
/********************************************************************
* TextLineWrapper::Impl
*/
*/
std::string formatString(const char *fmt, ...);
+/*! \brief
+ * Joins strings in an array to a single string.
+ *
+ * \param[in] sarray Array of strings to concatenate.
+ * \param[in] count Number of elements in \p sarray to concatenate.
+ * \returns All strings in \p sarray joined, ensuring at least one space
+ * between the strings.
+ * \throws std::bad_alloc if out of memory.
+ *
+ * The strings in the \p sarray array are concatenated, adding a single space
+ * between the strings if there is no whitespace in the end of a string.
+ * Terminal whitespace is removed.
+ *
+ * \inpublicapi
+ */
+std::string concatenateStrings(const char * const *sarray, size_t count);
+/*! \brief
+ * Convenience overload for joining strings in a C array (static data).
+ *
+ * \param[in] sarray Array of strings to concatenate.
+ * \tparam count Deduced number of elements in \p sarray.
+ * \returns All strings in \p sarray joined, ensuring at least one space
+ * between the strings.
+ * \throws std::bad_alloc if out of memory.
+ *
+ * \see concatenateStrings(const char * const *, size_t)
+ *
+ * \inpublicapi
+ */
+template <size_t count>
+std::string concatenateStrings(const char * const (&sarray)[count])
+{
+ return concatenateStrings(sarray, count);
+}
+
/*! \brief
* Wraps lines to a predefined length.
*
EXPECT_EQ("x10", longString.substr(1999));
}
+/********************************************************************
+ * Tests for concatenateStrings()
+ */
+
+typedef FormatTestBase ConcatenateStringsTest;
+
+TEST_F(ConcatenateStringsTest, HandlesDifferentStringEndings)
+{
+ static const char * const strings[] = {
+ "First string",
+ "Second string ",
+ "Third string\n",
+ "Fourth string",
+ ""
+ };
+ checkFormatting(gmx::concatenateStrings(strings), "CombinedStrings");
+}
+
/********************************************************************
* Tests for TextLineWrapper
*/
--- /dev/null
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+ <String Name="CombinedStrings"><![CDATA[
+First string Second string Third string
+Fourth string]]></String>
+</ReferenceData>