e7e11a6d9ef5c9bf5d1d3a04a7a7dd22add7df77
[alexxy/gromacs.git] / src / gromacs / utility / stringutil.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2011,2012,2013,2014,2015, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35 /*! \file
36  * \brief
37  * Declares common string utility and formatting routines.
38  *
39  * \author Teemu Murtola <teemu.murtola@gmail.com>
40  * \inpublicapi
41  * \ingroup module_utility
42  */
43 #ifndef GMX_UTILITY_STRINGUTIL_H
44 #define GMX_UTILITY_STRINGUTIL_H
45
46 #include <cstring>
47
48 #include <string>
49 #include <vector>
50
51 namespace gmx
52 {
53
54 //! \addtogroup module_utility
55 //! \{
56
57 /*! \brief
58  * Tests whether a string is null or empty.
59  *
60  * Does not throw.
61  */
62 bool inline isNullOrEmpty(const char *str)
63 {
64     return str == NULL || str[0] == '\0';
65 }
66
67 /*! \brief
68  * Tests whether a string starts with another string.
69  *
70  * \param[in] str    String to process.
71  * \param[in] prefix Prefix to find.
72  * \returns   true if \p str starts with \p prefix.
73  *
74  * Returns true if \p prefix is empty.
75  * Does not throw.
76  */
77 bool inline startsWith(const std::string &str, const std::string &prefix)
78 {
79     return str.compare(0, prefix.length(), prefix) == 0;
80 }
81 //! \copydoc startsWith(const std::string &, const std::string &)
82 bool inline startsWith(const char *str, const char *prefix)
83 {
84     return std::strncmp(str, prefix, std::strlen(prefix)) == 0;
85 }
86
87 /*! \brief
88  * Tests whether a string ends with another string.
89  *
90  * \param[in] str    String to process.
91  * \param[in] suffix Suffix to find.
92  * \returns   true if \p str ends with \p suffix.
93  *
94  * Returns true if \p suffix is NULL or empty.
95  * Does not throw.
96  */
97 bool endsWith(const std::string &str, const char *suffix);
98
99 /*! \brief
100  * Removes a suffix from a string.
101  *
102  * \param[in] str    String to process.
103  * \param[in] suffix Suffix to remove.
104  * \returns   \p str with \p suffix removed, or \p str unmodified if it does
105  *      not end with \p suffix.
106  * \throws    std::bad_alloc if out of memory.
107  *
108  * Returns \p str if \p suffix is NULL or empty.
109  */
110 std::string stripSuffixIfPresent(const std::string &str, const char *suffix);
111 /*! \brief
112  * Removes leading and trailing whitespace from a string.
113  *
114  * \param[in] str  String to process.
115  * \returns   \p str with leading and trailing whitespaces removed.
116  * \throws    std::bad_alloc if out of memory.
117  */
118 std::string stripString(const std::string &str);
119
120 /*! \brief
121  * Formats a string (snprintf() wrapper).
122  *
123  * \throws  std::bad_alloc if out of memory.
124  *
125  * This function works like sprintf(), except that it returns an std::string
126  * instead of requiring a preallocated buffer.  Arbitrary length output is
127  * supported.
128  */
129 std::string formatString(const char *fmt, ...);
130
131 /*! \brief Function object that wraps a call to formatString() that
132  * expects a single conversion argument, for use with algorithms. */
133 class StringFormatter
134 {
135     public:
136         /*! \brief Constructor
137          *
138          * \param[in] format The printf-style format string that will
139          *     be applied to convert values of type T to
140          *     string. Exactly one argument to the conversion
141          *     specification(s) in `format` is supported. */
142         explicit StringFormatter(const char *format) : format_(format)
143         {
144         }
145
146         //! Implements the formatting functionality
147         template <typename T>
148         std::string operator()(const T &value) const
149         {
150             return formatString(format_, value);
151         }
152
153     private:
154         //! Format string to use
155         const char *format_;
156 };
157
158 /*! \brief Function object to implement the same interface as
159  * `StringFormatter` to use with strings that should not be formatted
160  * further. */
161 class IdentityFormatter
162 {
163     public:
164         //! Implements the formatting non-functionality
165         std::string operator()(const std::string &value) const
166         {
167             return value;
168         }
169 };
170
171 /*! \brief Formats all the range as strings, and then joins them with
172  * a separator in between.
173  *
174  * \param[in] begin      Iterator the beginning of the range to join.
175  * \param[in] end        Iterator the end of the range to join.
176  * \param[in] separator  String to put in between the joined strings.
177  * \param[in] formatter  Function object to format the objects in
178  *     `container` as strings
179  * \returns   All objects in the range from `begin` to `end` formatted
180  *     as strings and concatenated with `separator` between each pair.
181  * \throws    std::bad_alloc if out of memory.
182  */
183 template <typename InputIterator, typename FormatterType>
184 std::string formatAndJoin(InputIterator begin, InputIterator end, const char *separator, const FormatterType &formatter)
185 {
186     std::string result;
187     const char *currentSeparator = "";
188     for (InputIterator i = begin; i != end; ++i)
189     {
190         result.append(currentSeparator);
191         result.append(formatter(*i));
192         currentSeparator = separator;
193     }
194     return result;
195 }
196
197 /*! \brief Formats all elements of the container as strings, and then
198  * joins them with a separator in between.
199  *
200  * \param[in] container  Objects to join.
201  * \param[in] separator  String to put in between the joined strings.
202  * \param[in] formatter  Function object to format the objects in
203  *     `container` as strings
204  * \returns   All objects from `container` formatted as strings and
205  *     concatenated with `separator` between each pair.
206  * \throws    std::bad_alloc if out of memory.
207  */
208 template <typename ContainerType, typename FormatterType>
209 std::string formatAndJoin(const ContainerType &container, const char *separator, const FormatterType &formatter)
210 {
211     return formatAndJoin(container.begin(), container.end(), separator, formatter);
212 }
213
214 /*! \brief
215  * Joins strings from a range with a separator in between.
216  *
217  * \param[in] begin      Iterator the beginning of the range to join.
218  * \param[in] end        Iterator the end of the range to join.
219  * \param[in] separator  String to put in between the joined strings.
220  * \returns   All strings from (`begin`, `end`) concatenated with `separator`
221  *     between each pair.
222  * \throws    std::bad_alloc if out of memory.
223  */
224 template <typename InputIterator>
225 std::string joinStrings(InputIterator begin, InputIterator end,
226                         const char *separator)
227 {
228     return formatAndJoin(begin, end, separator, IdentityFormatter());
229 }
230
231 /*! \brief
232  * Joins strings from a container with a separator in between.
233  *
234  * \param[in] container  Strings to join.
235  * \param[in] separator  String to put in between the joined strings.
236  * \returns   All strings from `container` concatenated with `separator`
237  *     between each pair.
238  * \throws    std::bad_alloc if out of memory.
239  */
240 template <typename ContainerType>
241 std::string joinStrings(const ContainerType &container, const char *separator)
242 {
243     return joinStrings(container.begin(), container.end(), separator);
244 }
245
246 /*! \brief
247  * Joins strings from an array with a separator in between.
248  *
249  * \param[in] array      Array of strings to join.
250  * \param[in] separator  String to put in between the joined strings.
251  * \tparam    count      Deduced number of elements in \p array.
252  * \returns   All strings from `aray` concatenated with `separator`
253  *     between each pair.
254  * \throws    std::bad_alloc if out of memory.
255  */
256 template <size_t count>
257 std::string joinStrings(const char *const (&array)[count], const char *separator)
258 {
259     return joinStrings(array, array + count, separator);
260 }
261
262 /*! \brief
263  * Splits a string to whitespace separated tokens.
264  *
265  * \param[in] str  String to process.
266  * \returns   \p str split into tokens at each whitespace sequence.
267  * \throws    std::bad_alloc if out of memory.
268  *
269  * This function works like `split` in Python, i.e., leading and trailing
270  * whitespace is ignored, and consecutive whitespaces are treated as a single
271  * separator.
272  */
273 std::vector<std::string> splitString(const std::string &str);
274
275 /*! \brief
276  * Replace all occurrences of a string with another string.
277  *
278  * \param[in] input  Input string.
279  * \param[in] from   String to find.
280  * \param[in] to     String to use to replace \p from.
281  * \returns   Copy of \p input with all occurrences of \p from replaced with \p to.
282  * \throws    std::bad_alloc if out of memory.
283  *
284  * The replacement is greedy and not recursive: starting from the beginning of
285  * \p input, each match of \p from is replaced with \p to, and the search for
286  * the next match begins after the end of the previous match.
287  *
288  * Compexity is O(N), where N is length of output.
289  *
290  * \see replaceAllWords()
291  */
292 std::string replaceAll(const std::string &input,
293                        const char *from, const char *to);
294 //! \copydoc replaceAll(const std::string &, const char *, const char *)
295 std::string replaceAll(const std::string &input,
296                        const std::string &from, const std::string &to);
297 /*! \brief
298  * Replace whole words with others.
299  *
300  * \param[in] input  Input string.
301  * \param[in] from   String to find.
302  * \param[in] to     String to use to replace \p from.
303  * \returns   Copy of \p input with all \p from words replaced with \p to.
304  * \throws    std::bad_alloc if out of memory.
305  *
306  * Works as replaceAll(), but a match is only considered if it is delimited by
307  * non-alphanumeric characters.
308  *
309  * \see replaceAll()
310  */
311 std::string replaceAllWords(const std::string &input,
312                             const char *from, const char *to);
313 //! \copydoc replaceAllWords(const std::string &, const char *, const char *)
314 std::string replaceAllWords(const std::string &input,
315                             const std::string &from, const std::string &to);
316
317 class TextLineWrapper;
318
319 /*! \brief
320  * Stores settings for line wrapping.
321  *
322  * Methods in this class do not throw.
323  *
324  * \see TextLineWrapper
325  *
326  * \inpublicapi
327  */
328 class TextLineWrapperSettings
329 {
330     public:
331         /*! \brief
332          * Initializes default wrapper settings.
333          *
334          * Default settings are:
335          *  - No maximum line width (only explicit line breaks).
336          *  - No indentation.
337          *  - No continuation characters.
338          *  - Ignore whitespace after an explicit newline.
339          */
340         TextLineWrapperSettings();
341
342         /*! \brief
343          * Sets the maximum length for output lines.
344          *
345          * \param[in] length  Maximum length for the lines after wrapping.
346          *
347          * If this method is not called, or is called with zero \p length, the
348          * wrapper has no maximum length (only wraps at explicit line breaks).
349          */
350         void setLineLength(int length) { maxLength_ = length; }
351         /*! \brief
352          * Sets the indentation for output lines.
353          *
354          * \param[in] indent  Number of spaces to add for indentation.
355          *
356          * If this method is not called, the wrapper does not add indentation.
357          */
358         void setIndent(int indent) { indent_ = indent; }
359         /*! \brief
360          * Sets the indentation for first output line after a line break.
361          *
362          * \param[in] indent  Number of spaces to add for indentation.
363          *
364          * If this method is not called, or called with \p indent equal to -1,
365          * the value set with setIndent() is used.
366          */
367         void setFirstLineIndent(int indent) { firstLineIndent_ = indent; }
368         /*! \brief
369          * Sets whether to remove spaces after an explicit newline.
370          *
371          * \param[in] bStrip  If true, spaces after newline are ignored.
372          *
373          * If not removed, the space is added to the indentation set with
374          * setIndent().
375          * The default is to not strip such whitespace.
376          */
377         void setStripLeadingWhitespace(bool bStrip)
378         {
379             bStripLeadingWhitespace_ = bStrip;
380         }
381         /*! \brief
382          * Sets a continuation marker for wrapped lines.
383          *
384          * \param[in] continuationChar  Character to use to mark continuation
385          *      lines.
386          *
387          * If set to non-zero character code, this character is added at the
388          * end of each line where a line break is added by TextLineWrapper
389          * (but not after lines produced by explicit line breaks).
390          * The default (\c '\0') is to not add continuation markers.
391          *
392          * Note that currently, the continuation char may cause the output line
393          * length to exceed the value set with setLineLength() by at most two
394          * characters.
395          */
396         void setContinuationChar(char continuationChar)
397         {
398             continuationChar_ = continuationChar;
399         }
400
401         //! Returns the maximum length set with setLineLength().
402         int lineLength() const { return maxLength_; }
403         //! Returns the indentation set with setIndent().
404         int indent() const { return indent_; }
405         /*! \brief
406          * Returns the indentation set with setFirstLineIndent().
407          *
408          * If setFirstLineIndent() has not been called or has been called with
409          * -1, indent() is returned.
410          */
411         int firstLineIndent() const
412         {
413             return (firstLineIndent_ >= 0 ? firstLineIndent_ : indent_);
414         }
415
416     private:
417         //! Maximum length of output lines, or <= 0 if no limit.
418         int                     maxLength_;
419         //! Number of spaces to indent each output line with.
420         int                     indent_;
421         /*! \brief
422          * Number of spaces to indent the first line after a newline.
423          *
424          * If -1, \a indent_ is used.
425          */
426         int                     firstLineIndent_;
427         //! Whether to ignore or preserve space after a newline.
428         bool                    bStripLeadingWhitespace_;
429         //! If not \c '\0', mark each wrapping point with this character.
430         char                    continuationChar_;
431
432         //! Needed to access the members.
433         friend class TextLineWrapper;
434 };
435
436 /*! \brief
437  * Wraps lines to a predefined length.
438  *
439  * This utility class wraps lines at word breaks to produce lines that are not
440  * longer than a predefined length.  Explicit newlines ('\\n') are preserved.
441  * Only space is considered a word separator.  If a single word exceeds the
442  * maximum line length, it is still printed on a single line.
443  * Extra whitespace is stripped from the end of produced lines.
444  * Other options on the wrapping, such as the line length or indentation,
445  * can be changed using a TextLineWrapperSettings object.
446  *
447  * Two interfaces to do the wrapping are provided:
448  *  -# High-level interface using either wrapToString() (produces a single
449  *     string with embedded newlines) or wrapToVector() (produces a vector of
450  *     strings with each line as one element).
451  *     These methods operate on std::string and wrap the entire input string.
452  *  -# Low-level interface using findNextLine() and formatLine().
453  *     findNextLine() operates either on a C string or an std::string, and does
454  *     not do any memory allocation (so it does not throw).  It finds the next
455  *     line to be wrapped, considering the wrapping settings.
456  *     formatLine() does whitespace operations on the line found by
457  *     findNextLine() and returns an std::string.
458  *     These methods allow custom wrapping implementation to either avoid
459  *     exceptions or to wrap only a part of the input string.
460  *
461  * Typical usage:
462  * \code
463    gmx::TextLineWrapper wrapper;
464    wrapper.settings().setLineLength(78);
465    printf("%s\n", wrapper.wrapToString(textToWrap).c_str());
466    \endcode
467  *
468  * \inpublicapi
469  */
470 class TextLineWrapper
471 {
472     public:
473         /*! \brief
474          * Constructs a new line wrapper with default settings.
475          *
476          * Does not throw.
477          */
478         TextLineWrapper()
479         {
480         }
481         /*! \brief
482          * Constructs a new line wrapper with given settings.
483          *
484          * \param[in] settings  Wrapping settings.
485          *
486          * Does not throw.
487          */
488         explicit TextLineWrapper(const TextLineWrapperSettings &settings)
489             : settings_(settings)
490         {
491         }
492
493         /*! \brief
494          * Provides access to settings of this wrapper.
495          *
496          * \returns  The settings object for this wrapper.
497          *
498          * The returned object can be used to modify settings for the wrapper.
499          * All subsequent calls to wrapToString() and wrapToVector() use the
500          * modified settings.
501          *
502          * Does not throw.
503          */
504         TextLineWrapperSettings &settings() { return settings_; }
505
506         /*! \brief
507          * Finds the next line to be wrapped.
508          *
509          * \param[in] input     String to wrap.
510          * \param[in] lineStart Index of first character of the line to find.
511          * \returns   Index of first character of the next line.
512          *
513          * If this is the last line, returns the length of \p input.
514          * In determining the length of the returned line, this function
515          * considers the maximum line length, leaving space for indentation,
516          * and also whitespace stripping behavior.
517          * Thus, the line returned may be longer than the maximum line length
518          * if it has leading and/or trailing space.
519          * When wrapping a line on a space (not on an explicit line break),
520          * the returned index is always on a non-whitespace character after the
521          * space.
522          *
523          * To iterate over lines in a string, use the following code:
524          * \code
525            gmx::TextLineWrapper wrapper;
526            // <set desired wrapping settings>
527            size_t lineStart = 0;
528            size_t length = input.length();
529            while (lineStart < length)
530            {
531                size_t nextLineStart = wrapper.findNextLine(input, lineStart);
532                std::string line = wrapper.formatLine(input, lineStart, nextLineStart));
533                // <do something with the line>
534                lineStart = nextLineStart;
535            }
536            return result;
537            \endcode
538          *
539          * Does not throw.
540          */
541         size_t findNextLine(const char *input, size_t lineStart) const;
542         //! \copydoc findNextLine(const char *, size_t)const
543         size_t findNextLine(const std::string &input, size_t lineStart) const;
544         /*! \brief
545          * Formats a single line for output according to wrapping settings.
546          *
547          * \param[in] input     Input string.
548          * \param[in] lineStart Index of first character of the line to format.
549          * \param[in] lineEnd   Index of first character of the next line.
550          * \returns   The line with leading and/or trailing whitespace removed
551          *      and indentation applied.
552          * \throws    std::bad_alloc if out of memory.
553          *
554          * Intended to be used on the lines found by findNextLine().
555          * When used with the lines returned from findNextLine(), the returned
556          * line conforms to the wrapper settings.
557          * Trailing whitespace is always stripped (including any newlines,
558          * i.e., the return value does not contain a newline).
559          */
560         std::string formatLine(const std::string &input,
561                                size_t lineStart, size_t lineEnd) const;
562
563         /*! \brief
564          * Formats a string, producing a single string with all the lines.
565          *
566          * \param[in] input  String to wrap.
567          * \returns   \p input with added newlines such that maximum line
568          *      length is not exceeded.
569          * \throws    std::bad_alloc if out of memory.
570          *
571          * Newlines in the input are preserved, including terminal newlines.
572          * Note that if the input does not contain a terminal newline, the
573          * output does not either.
574          */
575         std::string wrapToString(const std::string &input) const;
576         /*! \brief
577          * Formats a string, producing a vector with all the lines.
578          *
579          * \param[in] input  String to wrap.
580          * \returns   \p input split into lines such that maximum line length
581          *      is not exceeded.
582          * \throws    std::bad_alloc if out of memory.
583          *
584          * The strings in the returned vector do not contain newlines at the
585          * end.
586          * Note that a single terminal newline does not affect the output:
587          * "line\\n" and "line" both produce the same output (but "line\\n\\n"
588          * produces two lines, the second of which is empty).
589          */
590         std::vector<std::string> wrapToVector(const std::string &input) const;
591
592     private:
593         TextLineWrapperSettings settings_;
594 };
595
596 //! \}
597
598 } // namespace gmx
599
600 #endif