LCOV - code coverage report
Current view: top level - ioutils - stringUtils.hpp (source / functions) Coverage Total Hit
Test: mxlib Lines: 100.0 % 2 2
Test Date: 2026-02-19 16:58:26 Functions: 100.0 % 1 1

            Line data    Source code
       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              : 
      41              : namespace mx
      42              : {
      43              : namespace 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              :   */
      83              : template <typename typeT, unsigned width = 0, char pad = ' '>
      84              : [[deprecated( "Use std::format instead" )]]
      85              : std::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
     127              : template <>
     128              : std::string convertToString<std::string>( const std::string &value, int precision );
     129              : 
     130              : namespace stoTImpl
     131              : {
     132              : // tag overloads for stoT
     133              : 
     134              : char stoT( const std::string &str, error_t *errc, meta::tagT<char> );
     135              : signed char stoT( const std::string &str, error_t *errc, meta::tagT<signed char> );
     136              : unsigned char stoT( const std::string &str, error_t *errc, meta::tagT<unsigned char> );
     137              : short stoT( const std::string &str, error_t *errc, meta::tagT<short> );
     138              : unsigned short stoT( const std::string &str, error_t *errc, meta::tagT<unsigned short> );
     139              : int stoT( const std::string &str, error_t *errc, meta::tagT<int> );
     140              : unsigned int stoT( const std::string &str, error_t *errc, meta::tagT<unsigned int> );
     141              : long stoT( const std::string &str, error_t *errc, meta::tagT<long> );
     142              : unsigned long stoT( const std::string &str, error_t *errc, meta::tagT<unsigned long> );
     143              : long long stoT( const std::string &str, error_t *errc, meta::tagT<long long> );
     144              : unsigned long long stoT( const std::string &str, error_t *errc, meta::tagT<unsigned long long> );
     145              : bool stoT( const std::string &str, error_t *errc, meta::tagT<bool> );
     146              : float stoT( const std::string &str, error_t *errc, meta::tagT<float> );
     147              : double stoT( const std::string &str, error_t *errc, meta::tagT<double> );
     148              : long double stoT( const std::string &str, error_t *errc, meta::tagT<long double> );
     149              : 
     150              : std::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              :  */
     188              : template <typename typeT>
     189           12 : typeT 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           12 :     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              :  */
     210              : template <typename typeT>
     211              : typeT 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              :  */
     223              : template <typename typeT>
     224              : [[deprecated( "Use mx::ioutils::stoT<typeT> instead" )]]
     225              : typeT 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              :  */
     241              : mx::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              :  */
     258              : std::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              :  */
     270              : mx::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              :  */
     286              : std::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              :  */
     293              : void 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              :  */
     303              : std::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              :  */
     308              : int 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              :   */
     328              : template <typename typeT>
     329              : void parseStringVector(
     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              :   */
     366              : template <typename typeT>
     367              : void parseStringVector(
     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
        

Generated by: LCOV version 2.0-1