LCOV - code coverage report
Current view: top level - source/ioutils - stringUtils.cpp (source / functions) Coverage Total Hit
Test: mxlib Lines: 63.1 % 222 140
Test Date: 2026-08-30 22:23:37 Functions: 65.4 % 26 17

            Line data    Source code
       1              : /** \file stringUtils.cpp
       2              :  * \brief Implementation of utilities for working with strings
       3              :  *
       4              :  * \author Jared R. Males (jaredmales@gmail.com)
       5              :  *
       6              :  * \ingroup stringutils
       7              :  *
       8              :  */
       9              : 
      10              : //***********************************************************************//
      11              : // Copyright 2020 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              : #include "../../include/ioutils/stringUtils.hpp"
      30              : 
      31              : namespace mx
      32              : {
      33              : namespace ioutils
      34              : {
      35              : 
      36              : // Specialization of convertToString to avoid converting a string to a string
      37              : template <>
      38            0 : std::string convertToString<std::string>( const std::string &value, int precision )
      39              : {
      40              :     static_cast<void>( precision );
      41            0 :     return value;
      42              : }
      43              : 
      44              : namespace stoTImpl
      45              : {
      46              : 
      47              : template <typename typeT>
      48          106 : typeT stoInt32s( const std::string &str, error_t *errc )
      49              : {
      50              :     error_t _errc;
      51              : 
      52          106 :     long val = stoT( str, &_errc, meta::tagT<long>() );
      53              : 
      54          106 :     if( _errc == error_t::noerror )
      55              :     {
      56           96 :         if( val < std::numeric_limits<typeT>::lowest() )
      57              :         {
      58            3 :             _errc = error_t::erange;
      59            3 :             val = std::numeric_limits<typeT>::lowest();
      60              :         }
      61           93 :         else if( val > std::numeric_limits<typeT>::max() )
      62              :         {
      63            5 :             _errc = error_t::erange;
      64            5 :             val = std::numeric_limits<typeT>::max();
      65              :         }
      66              :     }
      67              : 
      68          106 :     if( errc )
      69              :     {
      70           73 :         *errc = _errc;
      71              :     }
      72              : 
      73          106 :     return static_cast<typeT>( val );
      74              : }
      75              : 
      76            8 : char stoT( const std::string &str, error_t *errc, meta::tagT<char> )
      77              : {
      78            8 :     return stoInt32s<char>( str, errc );
      79              : }
      80              : 
      81            0 : signed char stoT( const std::string &str, error_t *errc, meta::tagT<signed char> )
      82              : {
      83            0 :     return stoInt32s<signed char>( str, errc );
      84              : }
      85              : 
      86            5 : unsigned char stoT( const std::string &str, error_t *errc, meta::tagT<unsigned char> )
      87              : {
      88            5 :     return stoInt32s<unsigned char>( str, errc );
      89              : }
      90              : 
      91            6 : short stoT( const std::string &str, error_t *errc, meta::tagT<short> )
      92              : {
      93            6 :     return stoInt32s<short>( str, errc );
      94              : }
      95              : 
      96            5 : unsigned short stoT( const std::string &str, error_t *errc, meta::tagT<unsigned short> )
      97              : {
      98            5 :     return stoInt32s<unsigned short>( str, errc );
      99              : }
     100              : 
     101           82 : int stoT( const std::string &str, error_t *errc, meta::tagT<int> )
     102              : {
     103           82 :     return stoInt32s<int>( str, errc );
     104              : }
     105              : 
     106            5 : unsigned int stoT( const std::string &str, error_t *errc, meta::tagT<unsigned int> )
     107              : {
     108              :     error_t _errc;
     109              : 
     110            5 :     unsigned long val = stoT( str, &_errc, meta::tagT<unsigned long>() );
     111              : 
     112            5 :     if( _errc == error_t::noerror )
     113              :     {
     114            4 :         if( val > std::numeric_limits<unsigned int>::max() )
     115              :         {
     116            1 :             _errc = error_t::erange;
     117            1 :             val = std::numeric_limits<unsigned int>::max();
     118              :         }
     119              :     }
     120              : 
     121            5 :     if( errc )
     122              :     {
     123            4 :         *errc = _errc;
     124              :     }
     125              : 
     126            5 :     return static_cast<unsigned int>( val );
     127              : }
     128              : 
     129          112 : long stoT( const std::string &str, error_t *errc, meta::tagT<long> )
     130              : {
     131              :     error_t _errc;
     132              : 
     133              :     char *end;
     134              : 
     135          112 :     errno = 0;
     136              : 
     137          112 :     long val = std::strtol( str.c_str(), &end, 10 );
     138              : 
     139          112 :     if( errno != 0 )
     140              :     {
     141            3 :         _errc = errno2error_t( errno );
     142              :     }
     143          109 :     else if( end == str.c_str() )
     144              :     {
     145           10 :         _errc = error_t::invalidarg;
     146              :     }
     147              :     else
     148              :     {
     149           99 :         _errc = error_t::noerror;
     150              :     }
     151              : 
     152          112 :     if( errc )
     153              :     {
     154          111 :         *errc = _errc;
     155              :     }
     156              : 
     157          112 :     return val;
     158              : }
     159              : 
     160           10 : unsigned long stoT( const std::string &str, error_t *errc, meta::tagT<unsigned long> )
     161              : {
     162              :     error_t _errc;
     163              : 
     164              :     char *end;
     165              : 
     166           10 :     errno = 0;
     167              : 
     168           10 :     unsigned long val = std::strtoul( str.c_str(), &end, 10 );
     169              : 
     170           10 :     if( errno != 0 )
     171              :     {
     172            1 :         _errc = errno2error_t( errno );
     173              :     }
     174            9 :     else if( end == str.c_str() )
     175              :     {
     176            2 :         _errc = error_t::invalidarg;
     177              :     }
     178              :     else
     179              :     {
     180            7 :         _errc = error_t::noerror;
     181              :     }
     182              : 
     183           10 :     if( errc )
     184              :     {
     185            9 :         *errc = _errc;
     186              :     }
     187              : 
     188           10 :     return val;
     189              : }
     190              : 
     191            9 : long long stoT( const std::string &str, error_t *errc, meta::tagT<long long> )
     192              : {
     193              :     error_t _errc;
     194              : 
     195              :     char *end;
     196              : 
     197            9 :     errno = 0;
     198              : 
     199            9 :     long long val = std::strtoll( str.c_str(), &end, 10 );
     200              : 
     201            9 :     if( errno != 0 )
     202              :     {
     203            2 :         _errc = errno2error_t( errno );
     204              :     }
     205            7 :     else if( end == str.c_str() )
     206              :     {
     207            2 :         _errc = error_t::invalidarg;
     208              :     }
     209              :     else
     210              :     {
     211            5 :         _errc = error_t::noerror;
     212              :     }
     213              : 
     214            9 :     if( errc )
     215              :     {
     216            8 :         *errc = _errc;
     217              :     }
     218              : 
     219            9 :     return val;
     220              : }
     221              : 
     222            5 : unsigned long long stoT( const std::string &str, error_t *errc, meta::tagT<unsigned long long> )
     223              : {
     224              :     error_t _errc;
     225              : 
     226              :     char *end;
     227              : 
     228            5 :     errno = 0;
     229              : 
     230            5 :     unsigned long long val = std::strtoull( str.c_str(), &end, 10 );
     231              : 
     232            5 :     if( errno != 0 )
     233              :     {
     234            1 :         _errc = errno2error_t( errno );
     235              :     }
     236            4 :     else if( end == str.c_str() )
     237              :     {
     238            1 :         _errc = error_t::invalidarg;
     239              :     }
     240              :     else
     241              :     {
     242            3 :         _errc = error_t::noerror;
     243              :     }
     244              : 
     245            5 :     if( errc )
     246              :     {
     247            4 :         *errc = _errc;
     248              :     }
     249              : 
     250            5 :     return val;
     251              : }
     252              : 
     253              : /* bool specialization
     254              :  * First looks for 0/1, f/t, or F/T in the first non-space character of str.
     255              :  * Otherwise, uses long long and casts to bool.
     256              :  *
     257              :  * returns the converted numerical value.
     258              :  */
     259           34 : bool stoT( const std::string &str, error_t *errc, meta::tagT<bool> )
     260              : {
     261           34 :     char c = str[0];
     262           34 :     size_t i = 0;
     263           36 :     while( i < str.length()-1 && isspace( c ) )
     264              :     {
     265            2 :         ++i;
     266            2 :         c = str[i];
     267              :     }
     268              : 
     269           34 :     if( c == '0' || c == 'f' || c == 'F' )
     270              :     {
     271           13 :         if(errc)
     272              :         {
     273            3 :             *errc = error_t::noerror;
     274              :         }
     275              : 
     276           13 :         return false;
     277              :     }
     278           21 :     else if( c == '1' || c == 't' || c == 'T' )
     279              :     {
     280           18 :         if(errc)
     281              :         {
     282            3 :             *errc = error_t::noerror;
     283              :         }
     284              : 
     285           18 :         return true;
     286              :     }
     287              : 
     288            3 :     return static_cast<bool>( stoT( str, errc, meta::tagT<long long>() ) );
     289              : }
     290              : 
     291           67 : float stoT( const std::string &str, error_t *errc, meta::tagT<float> )
     292              : {
     293              :     error_t _errc;
     294              : 
     295              :     char *end;
     296              : 
     297           67 :     errno = 0;
     298              : 
     299           67 :     float val = std::strtof( str.c_str(), &end );
     300              : 
     301           67 :     if( errno != 0 )
     302              :     {
     303            2 :         _errc = errno2error_t( errno );
     304              :     }
     305           65 :     else if( end == str.c_str() )
     306              :     {
     307            2 :         _errc = error_t::invalidarg;
     308              :     }
     309              :     else
     310              :     {
     311           63 :         _errc = error_t::noerror;
     312              :     }
     313              : 
     314           67 :     if( errc )
     315              :     {
     316           50 :         *errc = _errc;
     317              :     }
     318              : 
     319           67 :     return val;
     320              : }
     321              : 
     322           97 : double stoT( const std::string &str, error_t *errc, meta::tagT<double> )
     323              : {
     324              :     error_t _errc;
     325              : 
     326              :     char *end;
     327              : 
     328           97 :     errno = 0;
     329              : 
     330           97 :     double val = std::strtod( str.c_str(), &end );
     331              : 
     332           97 :     if( errno != 0 )
     333              :     {
     334            2 :         _errc = errno2error_t( errno );
     335              :     }
     336           95 :     else if( end == str.c_str() )
     337              :     {
     338            2 :         _errc = error_t::invalidarg;
     339              :     }
     340              :     else
     341              :     {
     342           93 :         _errc = error_t::noerror;
     343              :     }
     344              : 
     345           97 :     if( errc )
     346              :     {
     347           11 :         *errc = _errc;
     348              :     }
     349              : 
     350           97 :     return val;
     351              : }
     352              : 
     353            5 : long double stoT( const std::string &str, error_t *errc, meta::tagT<long double> )
     354              : {
     355              :     error_t _errc;
     356              : 
     357              :     char *end;
     358              : 
     359            5 :     errno = 0;
     360              : 
     361            5 :     long double val = std::strtold( str.c_str(), &end );
     362              : 
     363            5 :     if( errno != 0 )
     364              :     {
     365            2 :         _errc = errno2error_t( errno );
     366              :     }
     367            3 :     else if( end == str.c_str() )
     368              :     {
     369            1 :         _errc = error_t::invalidarg;
     370              :     }
     371              :     else
     372              :     {
     373            2 :         _errc = error_t::noerror;
     374              :     }
     375              : 
     376            5 :     if( errc )
     377              :     {
     378            4 :         *errc = _errc;
     379              :     }
     380              : 
     381            5 :     return val;
     382              : }
     383              : 
     384              : #ifdef HAS_QUAD
     385            0 : __float128 stoT( const std::string &str, error_t *errc, meta::tagT<__float128> )
     386              : {
     387              :     error_t _errc;
     388              : 
     389              :     char *end;
     390              : 
     391            0 :     errno = 0;
     392              : 
     393            0 :     __float128 val = ::strtof128( str.c_str(), &end );
     394              : 
     395            0 :     if( errno != 0 )
     396              :     {
     397            0 :         _errc = errno2error_t( errno );
     398              :     }
     399            0 :     else if( end == str.c_str() )
     400              :     {
     401            0 :         _errc = error_t::invalidarg;
     402              :     }
     403              :     else
     404              :     {
     405            0 :         _errc = error_t::noerror;
     406              :     }
     407              : 
     408            0 :     if( errc )
     409              :     {
     410            0 :         *errc = _errc;
     411              :     }
     412              : 
     413            0 :     return val;
     414              : }
     415              : 
     416              : #endif // has_quad
     417              : 
     418          114 : std::string stoT( const std::string &str, error_t *errc, meta::tagT<std::string> )
     419              : {
     420          114 :     if(errc)
     421              :     {
     422           22 :         *errc = mx::error_t::noerror;
     423              :     }
     424              : 
     425          114 :     return str;
     426              : }
     427              : 
     428              : } // namespace stoTImpl
     429              : 
     430              : // Convert a string to all lower case.
     431            0 : mx::error_t toLower( std::string &outstr, const std::string &instr )
     432              : {
     433              :     try
     434              :     {
     435            0 :         outstr.resize( instr.size() );
     436              :     }
     437            0 :     catch( const std::length_error &e )
     438              :     {
     439            0 :         return mx::error_t::std_length_error;
     440            0 :     }
     441            0 :     catch( const std::bad_alloc &e )
     442              :     {
     443            0 :         return mx::error_t::std_bad_alloc;
     444            0 :     }
     445            0 :     catch( const std::exception &e )
     446              :     {
     447            0 :         return mx::error_t::std_exception;
     448            0 :     }
     449            0 :     catch( ... )
     450              :     {
     451            0 :         return mx::error_t::exception;
     452            0 :     }
     453              : 
     454            0 :     for( size_t i = 0; i < instr.size(); ++i )
     455              :     {
     456            0 :         outstr[i] = tolower( instr[i] );
     457              :     }
     458              : 
     459            0 :     return mx::error_t::noerror;
     460              : }
     461              : 
     462              : // Convert a string to all lower case.
     463            0 : std::string toLower( const std::string &instr, mx::error_t *errc )
     464              : {
     465            0 :     std::string outstr;
     466              : 
     467            0 :     mx::error_t _errc = toLower( outstr, instr );
     468              : 
     469            0 :     if( errc )
     470              :     {
     471            0 :         *errc = _errc;
     472              :     }
     473              : 
     474            0 :     return outstr;
     475            0 : }
     476              : 
     477              : // Convert a string to all upper case.
     478            0 : mx::error_t toUpper( std::string &outstr, const std::string &instr )
     479              : {
     480              :     try
     481              :     {
     482            0 :         outstr.resize( instr.size() );
     483              :     }
     484            0 :     catch( const std::length_error &e )
     485              :     {
     486            0 :         return mx::error_t::std_length_error;
     487            0 :     }
     488            0 :     catch( const std::bad_alloc &e )
     489              :     {
     490            0 :         return mx::error_t::std_bad_alloc;
     491            0 :     }
     492            0 :     catch( const std::exception &e )
     493              :     {
     494            0 :         return mx::error_t::std_exception;
     495            0 :     }
     496            0 :     catch( ... )
     497              :     {
     498            0 :         return mx::error_t::exception;
     499            0 :     }
     500              : 
     501            0 :     for( size_t i = 0; i < instr.size(); ++i )
     502              :     {
     503            0 :         outstr[i] = toupper( instr[i] );
     504              :     }
     505              : 
     506            0 :     return mx::error_t::noerror;
     507              : }
     508              : 
     509              : // Convert a string to all upper case.
     510            0 : std::string toUpper( const std::string &instr, mx::error_t *errc )
     511              : {
     512            0 :     std::string outstr;
     513              : 
     514            0 :     mx::error_t _errc = toUpper( outstr, instr );
     515              : 
     516            0 :     if( errc )
     517              :     {
     518            0 :         *errc = _errc;
     519              :     }
     520              : 
     521            0 :     return outstr;
     522            0 : }
     523              : 
     524              : // Remove all white space from a string.
     525            0 : void removeWhiteSpace( std::string &outstr, const std::string &instr )
     526              : {
     527            0 :     outstr = instr;
     528              : 
     529            0 :     outstr.erase( std::remove_if( outstr.begin(), outstr.end(), ::isspace ), outstr.end() );
     530            0 : }
     531              : 
     532              : // Remove all white space from a string.
     533            0 : std::string removeWhiteSpace( const std::string &instr )
     534              : {
     535            0 :     std::string outstr;
     536              : 
     537            0 :     removeWhiteSpace( outstr, instr );
     538              : 
     539            0 :     return outstr;
     540            0 : }
     541              : 
     542              : // Wrap a string by breaking it into smaller sized portions of a desired width
     543           14 : int stringWrap( std::vector<std::string> &lines, const std::string &str, int width )
     544              : {
     545           14 :     int L = str.length();
     546              : 
     547           14 :     if( L == 0 )
     548            1 :         return 0;
     549              :     int startPos, tmpPos, endPos;
     550              : 
     551           13 :     bool done = false;
     552              : 
     553           13 :     startPos = 0;
     554              : 
     555           26 :     while( !done )
     556              :     {
     557           13 :         if( startPos == L )
     558            0 :             --startPos; // Just to make sure
     559              : 
     560           13 :         endPos = startPos + width;
     561              : 
     562           13 :         if( endPos >= L )
     563              :         {
     564           13 :             lines.push_back( str.substr( startPos, L - startPos ) );
     565           13 :             done = true;
     566              :         }
     567              :         else
     568              :         {
     569              :             // Backup to nearest space
     570            0 :             tmpPos = endPos;
     571            0 :             while( !isspace( str[tmpPos] ) && tmpPos >= startPos )
     572            0 :                 --tmpPos;
     573              : 
     574              :             // If we aren't at the beginning (i.e. splitting consecutive characters) we use new end position
     575            0 :             if( tmpPos > startPos )
     576            0 :                 endPos = tmpPos;
     577              : 
     578            0 :             lines.push_back( str.substr( startPos, endPos - startPos ) );
     579              : 
     580            0 :             startPos = endPos;
     581              : 
     582              :             // Clear 1 space
     583            0 :             if( str[startPos] == ' ' )
     584            0 :                 ++startPos;
     585              :         }
     586              :     }
     587              : 
     588           13 :     return 0;
     589              : }
     590              : 
     591              : } // namespace ioutils
     592              : } // namespace mx
        

Generated by: LCOV version 2.0-1