/**
* Given a string that contains text separated by a @p delimiter, split it
* into its components; for each component, remove leading and trailing
- * spaces.
- *
- * The default value of the delimiter is a comma, so that the function
+ * spaces. The default value of the delimiter is a comma, so that the function
* splits comma separated lists of strings.
+ *
+ * To make data input from tables simpler, if the input string ends in
+ * a delimiter (possibly followed by an arbitrary amount of whitespace),
+ * then this last delimiter is ignored. For example,
+ * @code
+ * Utilities::split_string_list("abc; def; ghi; ", ';');
+ * @endcode
+ * yields the same 3-element list of output <code>{"abc","def","ghi"}</code>
+ * as you would get if the input had been
+ * @code
+ * Utilities::split_string_list("abc; def; ghi", ';');
+ * @endcode
+ * or
+ * @code
+ * Utilities::split_string_list("abc; def; ghi;", ';');
+ * @endcode
+ * As a consequence of this rule, a call like
+ * @code
+ * Utilities::split_string_list(" ; ", ';');
+ * @endcode
+ * yields a one-element list. Because of the trimming of
+ * whitespace, the single element is the empty string.
+ *
+ * This function can digest the case that the delimiter is a space. In this
+ * case, it returns all words in the string. Combined with the rules above,
+ * this implies that
+ * @code
+ * Utilities::split_string_list("abc def ghi ", ' ');
+ * @endcode
+ * yields again the 3-element list of output <code>{"abc","def","ghi"}</code>
+ * from above despite the presence of space at the end of the string.
+ * Furthermore,
+ * @code
+ * Utilities::split_string_list(" ", ' ');
+ * @endcode
+ * yields an empty list regardless of the number of spaces in the string.
*/
std::vector<std::string>
split_string_list (const std::string &s,
split_string_list (const std::string &s,
const char delimiter)
{
+ // keep the currently remaining part of the input string in 'tmp' and
+ // keep chopping elements of the list off the front
std::string tmp = s;
+
+ // as discussed in the documentation, eat whitespace from the end
+ // of the string
+ while (tmp.length() != 0 && tmp[tmp.length()-1] == ' ')
+ tmp.erase (tmp.length()-1, 1);
+
+ // split the input list until it is empty. since in every iteration
+ // 'tmp' is what's left of the string after the next delimiter,
+ // and since we've stripped trailing space already, 'tmp' will
+ // be empty at one point if 's' ended in a delimiter, even if
+ // there was space after the last delimiter. this matches what's
+ // discussed in the documentation
std::vector<std::string> split_list;
split_list.reserve (std::count (tmp.begin(), tmp.end(), delimiter)+1);
-
- // split the input list
while (tmp.length() != 0)
{
std::string name;
else
tmp = "";
- while ((name.length() != 0) &&
- (name[0] == ' '))
+ // strip spaces from this element's front and end
+ while ((name.length() != 0) && (name[0] == ' '))
name.erase (0,1);
-
while (name.length() != 0 && name[name.length()-1] == ' ')
name.erase (name.length()-1, 1);