mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
Loading...
Searching...
No Matches
stringUtils.hpp
Go to the documentation of this file.
1/** \file stringUtils.hpp
2 * \brief Utilities for working with strings
3 *
4 * \author Jared R. Males (jaredmales@gmail.com)
5 *
6 * \ingroup stringutils
7 *
8 */
9
10//***********************************************************************//
11// Copyright 2015, 2016, 2017 Jared R. Males (jaredmales@gmail.com)
12//
13// This file is part of mxlib.
14//
15// mxlib is free software: you can redistribute it and/or modify
16// it under the terms of the GNU General Public License as published by
17// the Free Software Foundation, either version 3 of the License, or
18// (at your option) any later version.
19//
20// mxlib is distributed in the hope that it will be useful,
21// but WITHOUT ANY WARRANTY; without even the implied warranty of
22// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23// GNU General Public License for more details.
24//
25// You should have received a copy of the GNU General Public License
26// along with mxlib. If not, see <http://www.gnu.org/licenses/>.
27//***********************************************************************//
28
29#ifndef ioutils_stringUtils_hpp
30#define ioutils_stringUtils_hpp
31
32#include <string>
33#include <sstream>
34#include <vector>
35#include <limits>
36#include <algorithm>
37
38#include "../meta/tagT.hpp"
39#include "../mxlib.hpp"
40
41namespace mx
42{
43namespace ioutils
44{
45
46/** \addtogroup stringutils
47 * @{
48 */
49
50/// Convert a numerical value to a string
51/** The default version uses the stream library to convert. A specialization is provided to prevent conversion of
52 std::string.
53 *
54 * The precision parameter is only used for floating point types. If the default precision==0 is passed, then the
55 maximum useful precision is
56 * used, from the value of std::numeric_limits<typeT>::max_digits10.
57 *
58 * The width and pad template parameters can be used to set a fixed maximum width and a pad character.
59 *
60 * Examples:
61 *
62 * To convert a double precision number to string:
63 * \code
64 double d = 2.898434;
65 std::string str;
66 str = convertToString(d); //note that you will not normally need to specify <typeT>
67 * \endcode
68 *
69 * To produce a fixed width 0 padded string from an integer:
70 * \code
71 int i = 23;
72 std::string str;
73 str = convertToString<int, 5, '0'>(i); //result is "00023".
74 * \endcode
75 *
76 * \tparam typeT is the type of value to convert
77 * \tparam width specifies the maximum width, not including the '\0'
78 * \tparam pad specifies the pad character
79 *
80 * \returns a string representation of value
81 *
82 */
83template <typename typeT, unsigned width = 0, char pad = ' '>
84[[deprecated( "Use std::format instead" )]]
85std::string convertToString(
86 const typeT &value, ///< [in] the value of type typeT to be converted
87 int precision = 0 ///< [in] [optional] the precision (see
88 ///< http://www.cplusplus.com/reference/ios/ios_base/precision/) to use for floating point types.
89)
90{
91
92 std::ostringstream convert;
93
94 if( std::is_floating_point<typeT>::value )
95 {
96 if( precision == 0 )
97 {
98 convert.precision( std::numeric_limits<typeT>::max_digits10 );
99 }
100 else
101 {
102 convert.precision( precision );
103 }
104 }
105
106 convert << value;
107
108 if( width == 0 )
109 {
110 return convert.str();
111 }
112 else
113 {
114 std::string c = convert.str();
115
116 if( c.length() > width )
117 {
118 c.erase( width, c.length() - width );
119 return c;
120 }
121
122 return std::string( width - c.length(), pad ) + c;
123 }
124}
125
126// Specialization of convertToString to avoid converting a string to a string
127template <>
128std::string convertToString<std::string>( const std::string &value, int precision );
129
130namespace stoTImpl
131{
132// tag overloads for stoT
133
134char stoT( const std::string &str, error_t *errc, meta::tagT<char> );
135signed char stoT( const std::string &str, error_t *errc, meta::tagT<signed char> );
136unsigned char stoT( const std::string &str, error_t *errc, meta::tagT<unsigned char> );
137short stoT( const std::string &str, error_t *errc, meta::tagT<short> );
138unsigned short stoT( const std::string &str, error_t *errc, meta::tagT<unsigned short> );
139int stoT( const std::string &str, error_t *errc, meta::tagT<int> );
140unsigned int stoT( const std::string &str, error_t *errc, meta::tagT<unsigned int> );
141long stoT( const std::string &str, error_t *errc, meta::tagT<long> );
142unsigned long stoT( const std::string &str, error_t *errc, meta::tagT<unsigned long> );
143long long stoT( const std::string &str, error_t *errc, meta::tagT<long long> );
144unsigned long long stoT( const std::string &str, error_t *errc, meta::tagT<unsigned long long> );
145bool stoT( const std::string &str, error_t *errc, meta::tagT<bool> );
146float stoT( const std::string &str, error_t *errc, meta::tagT<float> );
147double stoT( const std::string &str, error_t *errc, meta::tagT<double> );
148long double stoT( const std::string &str, error_t *errc, meta::tagT<long double> );
149
150std::string stoT( const std::string &str, error_t *errc, meta::tagT<std::string> );
151
152#ifdef HAS_QUAD
153__float128 stoT( const std::string &str, error_t *errc, meta::tagT<__float128> );
154#endif
155
156} // namespace stoTImpl
157
158/// Convert a string to a numerical value.
159/** Provides exception-less string conversion.
160 *
161 * Example:
162 * \code
163 * std::string str = "2.34567";
164 * mx::error_t errc;
165 * double d;
166 * d = stoT<double>(str, &errc);
167 * if(errc != mx::error_t::noerror)
168 * {
169 * //do something
170 * }
171 * \endcode
172 *
173 * Values of `typeT=bool` are converted from strings that start with 0/f/F an 1/t/T as false and
174 * true respectively. If that fails the string is converted to long long and then to bool, so if it is
175 * a valid number that fits in long long, it will evaluate to true or false based on whether or not it is 0.
176 *
177 * Complex types (`std::complex<realT>`) are not supported.
178 *
179 * \tparam typeT is the type of the numerical value desired
180 *
181 * \returns the converted numerical value.
182 *
183 * \b Error \b Codes
184 * - mx::error_t::noerror on success
185 * - mx::error_t::erange for an out of range value for typeT
186 * - mx::error_t::invalidarg for a string that can't be converted
187 */
188template <typename typeT>
189typeT stoT( const std::string &str, /**< [in] the string to convert*/
190 error_t *errc = nullptr /**< [out] [optional] pointer to an mxlib error code set during the conversion */
191)
192{
193 return stoTImpl::stoT( str, errc, meta::tagT<typeT>() );
194}
195
196/// Convert a string to a numerical value.
197/** Provides exception-less string conversion.
198 *
199 * \overload
200 *
201 * \tparam typeT is the type of the numerical value desired
202 *
203 * \returns the converted numerical value.
204 *
205 * \b Error \b Codes
206 * - mx::error_t::noerror on success
207 * - mx::error_t::erange for an out of range value for typeT
208 * - mx::error_t::invalidarg for a string that can't be converted
209 */
210template <typename typeT>
211typeT stoT( const std::string &str, /**< [in] the string to convert*/
212 error_t &errc /**< [out] [optional] mxlib error code set during the conversion */
213)
214{
215 return stoTImpl::stoT( str, &errc, meta::tagT<typeT>() );
216}
217
218/// Convert a string to a numerical value.
219/** see \ref stoT
220 *
221 * \deprecated
222 */
223template <typename typeT>
224[[deprecated( "Use mx::ioutils::stoT<typeT> instead" )]]
225typeT convertFromString( const std::string &str, /**< [in] the string to convert*/
226 error_t *errc = nullptr /**< [out] [optional] mxlib error code */ )
227{
228 // If no specialization exists, we try to cast
229 return stoT<typeT>( str, errc );
230}
231
232/// Convert a string to all lower case.
233/** Calls the c tolower function for each character in \p instr.
234 *
235 * \returns mx::error_t::noerror on success
236 * \returns mx::error_t::std_length_error if string::resize throws a length error
237 * \returns mx::error_t::std_bad_alloc if string::resize throws a bad alloc
238 * \returns mx::error_t::std_exception if string::resize throws a std::exception
239 * \returns mx::error_t::exception if string::resize throws any other exception
240 */
241mx::error_t toLower( std::string &outstr, ///< [out] will be resized and populated with the lower case characters
242 const std::string &instr ///< [in] is the string to convert
243);
244
245/// Convert a string to all lower case.
246/** Calls the c tolower function for each character in \p instr.
247 *
248 * \return the all lower case string
249 *
250 * \b Errors
251 * - mx::error_t::noerror on success
252 * - mx::error_t::std_length_error if string::resize throws a length error
253 * - mx::error_t::std_bad_alloc if string::resize throws a bad alloc
254 * - mx::error_t::std_exception if string::resize throws a std::exception
255 * - mx::error_t::exception if string::resize throws any other exception
256 *
257 */
258std::string toLower( const std::string &instr, /**< [in] is the string to convert*/
259 mx::error_t *errc = nullptr /**< [out] [optional] the error code indicating success or error */ );
260
261/// Convert a string to all upper case.
262/** Calls the c toupper function for each character in \p instr.
263 *
264 * \returns mx::error_t::noerror on success
265 * \returns mx::error_t::std_length_error if string::resize throws a length error
266 * \returns mx::error_t::std_bad_alloc if string::resize throws a bad alloc
267 * \returns mx::error_t::std_exception if string::resize throws a std::exception
268 * \returns mx::error_t::exception if string::resize throws any other exception
269 */
270mx::error_t toUpper( std::string &outstr, ///< [out] will be resized and populated with the lower case characters
271 const std::string &instr ///< [in] is the string to convert
272);
273
274/// Convert a string to all upper case.
275/** Calls the c toupper function for each character in \p instr.
276 *
277 * \returns the all upper case string
278 *
279 * \b Errors
280 * - mx::error_t::noerror on success
281 * - mx::error_t::std_length_error if string::resize throws a length error
282 * - mx::error_t::std_bad_alloc if string::resize throws a bad alloc
283 * - mx::error_t::std_exception if string::resize throws a std::exception
284 * - mx::error_t::exception if string::resize throws any other exception
285 */
286std::string toUpper( const std::string &instr, /**< [in] is the string to convert*/
287 mx::error_t *errc = nullptr /**< [out] [optional] the error code indicating success or error */ );
288
289/// Remove all white space from a string.
290/**
291 * Uses std::remove_if.
292 */
293void removeWhiteSpace( std::string &outstr, ///< [out] will contain the new string with no whitespace.
294 const std::string &instr ///< [in] is the string to remove whitespace from
295);
296
297/// Remove all white space from a string.
298/**
299 * Uses std::remove_if.
300 *
301 * \returns the modified string.
302 */
303std::string removeWhiteSpace( const std::string &instr /**< [in] is the string to remove whitespace from*/ );
304
305/// Wrap a string by breaking it into smaller sized portions of a desired width
306/** Whenever possible breaks at spaces. A single space is discarded at the break.
307 */
308int stringWrap( std::vector<std::string> &lines, /**< [out] each new entry contains a wrapped portion of the string.
309 Not cleared, so can accumulate. */
310 const std::string &str, ///< [in] the string to wrap
311 int width ///< [in] the maximum width of the output strings
312);
313
314/// Parses a string into a vector of tokens delimited by a character
315/** E.g., the string
316 * \code
317 std::string s={"0,1,2,3,4"};
318 std::vector<int> v;
319 parseStringVector(v,s);
320 \endcode
321 * is parsed to a vector as if it was initialized with
322 \code
323 std::vector<int> v = {0,1,2,3,4};
324 \endcode
325 *
326 * \tparam typeT the type to convert the tokens too.
327 */
328template <typename typeT>
330 std::vector<typeT> &v, ///< [out] the vector holding the parsed and converted tokens. Is cleared.
331 const std::string &s, ///< [in] the string to parse
332 char delim = ',' ///< [in] [optional] the delimiter. Default is comma \p ','.
333)
334{
335 size_t st;
336 size_t com;
337
338 st = 0;
339 com = s.find( delim, st );
340
341 v.clear();
342
343 while( com != std::string::npos )
344 {
345 v.push_back( convertFromString<typeT>( s.substr( st, com - st ) ) );
346 st = com + 1;
347 com = s.find( delim, st );
348 }
349 v.push_back( convertFromString<typeT>( s.substr( st, s.size() - st ) ) );
350}
351
352/// Parses a string into a vector of tokens delimited by a set of characters
353/** E.g., the string
354 * \code
355 std::string s={"0,1:2 3,4"};
356 std::vector<int> v;
357 parseStringVector(v, s, ",: ");
358 \endcode
359 * is parsed to a vector as if it was initialized with
360 \code
361 std::vector<int> v = {0,1,2,3,4};
362 \endcode
363 *
364 * \tparam typeT the type to convert the tokens too.
365 */
366template <typename typeT>
368 std::vector<typeT> &v, ///< [out] the vector holding the parsed and converted tokens. Is cleared.
369 const std::string &s, ///< [in] the string to parse
370 const std::string &delims ///< [in] the delimiters.
371)
372{
373 size_t st;
374 size_t com;
375
376 st = 0;
377 com = s.find_first_of( delims, st );
378
379 v.clear();
380
381 while( com != std::string::npos )
382 {
383 v.push_back( convertFromString<typeT>( s.substr( st, com - st ) ) );
384 st = com + 1;
385 com = s.find_first_of( delims, st );
386 }
387 v.push_back( convertFromString<typeT>( s.substr( st, s.size() - st ) ) );
388}
389/// @}
390
391} // namespace ioutils
392} // namespace mx
393
394#endif // ioutils_stringUtils_hpp
error_t
The mxlib error codes.
Definition error_t.hpp:26
int stringWrap(std::vector< std::string > &lines, const std::string &str, int width)
Wrap a string by breaking it into smaller sized portions of a desired width.
std::string convertToString(const typeT &value, int precision=0)
Convert a numerical value to a string.
void parseStringVector(std::vector< typeT > &v, const std::string &s, char delim=',')
Parses a string into a vector of tokens delimited by a character.
mx::error_t toLower(std::string &outstr, const std::string &instr)
Convert a string to all lower case.
mx::error_t toUpper(std::string &outstr, const std::string &instr)
Convert a string to all upper case.
void removeWhiteSpace(std::string &outstr, const std::string &instr)
Remove all white space from a string.
typeT convertFromString(const std::string &str, error_t *errc=nullptr)
Convert a string to a numerical value.
typeT stoT(const std::string &str, error_t *errc=nullptr)
Convert a string to a numerical value.
The mxlib c++ namespace.
Definition mxlib.hpp:37
Empty type for tag dispatching.
Definition tagT.hpp:44