Files
Dario Sassi da2af7c039 EgtBasis 3.1a1 :
- aggiunta gestione X64.
2026-01-09 15:55:41 +01:00

342 lines
13 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2013-2014
//----------------------------------------------------------------------------
// File : EGnStringUtils.h Data : 17.03.14 Versione : 1.5c2
// Contenuto : Dichiarazione delle funzioni di utilità per le stringhe.
//
//
//
// Modifiche : 20.11.13 DS Creazione modulo.
// 20.10.15 DS Agg. FromString e ToString per std::array<double,N>.
//
//----------------------------------------------------------------------------
#pragma once
#include "/EgtDev/Include/EgtStringConverter.h"
#include "/EgtDev/Extern/fast_float/fast_float.h"
#include <string>
#include <algorithm>
#include <array>
#include <charconv>
//----------------------------------------------------------------------------
inline std::string&
TrimLeft( std::string& sString, const char* szTarget = " \t\r\n")
{ size_t iStartPos = sString.find_first_not_of( szTarget) ;
if ( iStartPos != std::string::npos)
sString.erase( 0, iStartPos) ;
else
sString.clear() ;
return sString ; }
inline std::string&
TrimRight( std::string& sString, const char* szTarget = " \t\r\n")
{ size_t iEndPos = sString.find_last_not_of( szTarget) ;
if ( iEndPos != std::string::npos)
sString.erase( iEndPos + 1) ;
else
sString.clear() ;
return sString ; }
inline std::string&
Trim( std::string& sString, const char* szTarget = " \t\r\n")
{ return TrimLeft( TrimRight( sString, szTarget), szTarget) ; }
inline std::string&
TrimUtf8Bom( std::string& sString)
{ if ( sString[0] == '\xef' && sString[1] == '\xbb' && sString[2] == '\xbf')
sString.erase( 0, 3) ;
return sString ; }
//----------------------------------------------------------------------------
inline std::string&
ToUpper( std::string& sString)
{ std::transform( sString.begin(), sString.end(), sString.begin(), ::toupper) ;
return sString ; }
inline std::string&
ToLower( std::string& sString)
{ std::transform( sString.begin(), sString.end(), sString.begin(), ::tolower) ;
return sString ; }
inline bool
EqualNoCase( const std::string& sL, const std::string& sR)
{ return ( sL.size() == sR.size() &&
std::equal( sL.cbegin(), sL.cend(), sR.cbegin(),
[]( std::string::value_type cL, std::string::value_type cR)
{ return tolower( cL) == tolower( cR); })) ; }
//----------------------------------------------------------------------------
inline bool
IsEmptyOrSpaces( const std::string& sName)
{ return ( sName.empty() ||
sName.find_first_not_of( " \t\r\n") == std::string::npos) ; }
//----------------------------------------------------------------------------
inline bool
IsNullOrSpace( char cChar)
{ return ( cChar == '\0' || cChar == ' ' || cChar == '\t' || cChar == '\r' || cChar == '\n') ; }
//----------------------------------------------------------------------------
inline bool
IsValidFileName( const std::string& sName)
{
if ( sName.empty())
return false ;
return ( sName.find_first_of( "<>/\\\":?*|", 0) == std::string::npos) ;
}
//----------------------------------------------------------------------------
inline bool
ValidateFileName( std::string& sName)
{
std::string::size_type i ;
while ( ( i = sName.find_first_of( "<>/\\\":?*|")) != std::string::npos)
sName[i] = '_' ;
return true ;
}
//----------------------------------------------------------------------------
inline bool
IsValidDxfName( const std::string& sName, bool bAdvanced)
{
if ( sName.empty())
return false ;
std::string sOut = "<>/\\\":;?*|='" ;
if ( ! bAdvanced)
sOut += " ." ;
return ( sName.find_first_of( sOut, 0) == std::string::npos) ;
}
//----------------------------------------------------------------------------
inline bool
ValidateDxfName( std::string& sName, bool bAdvanced)
{
std::string sOut = "<>/\\\":;?*|='" ;
if ( ! bAdvanced)
sOut += " ." ;
std::string::size_type i ;
while ( ( i = sName.find_first_of( sOut)) != std::string::npos)
sName[i] = '_' ;
return true ;
}
//----------------------------------------------------------------------------
#define FAST_FLOAT_FMT fast_float::chars_format::general | fast_float::chars_format::allow_leading_plus | fast_float::chars_format::skip_white_space
#define FAST_FLOAT_OPTS fast_float::parse_options( FAST_FLOAT_FMT)
inline bool
FromString( const std::string& sVal, int& nVal)
{ auto answer = fast_float::from_chars_advanced( sVal.data(), sVal.data() + sVal.size(), nVal, FAST_FLOAT_OPTS) ;
return ( answer.ec == std::errc() && answer.ptr != sVal.data()) ; }
inline bool
FromString( const std::string& sVal, unsigned int& nVal)
{ auto answer = fast_float::from_chars_advanced( sVal.data(), sVal.data() + sVal.size(), nVal, FAST_FLOAT_OPTS) ;
return ( answer.ec == std::errc() && answer.ptr != sVal.data()) ; }
inline bool
FromString( const std::string& sVal, bool& bVal)
{ int nTmp ;
if ( ! FromString( sVal, nTmp))
return false ;
bVal = ( nTmp != 0) ;
return true ; }
inline bool
FromString( const std::string& sVal, double& dVal)
{ auto answer = fast_float::from_chars( sVal.data(), sVal.data() + sVal.size(), dVal, FAST_FLOAT_FMT) ;
return ( answer.ec == std::errc() && answer.ptr != sVal.data()) ; }
template <size_t size>
bool FromString( const std::string& sVal, int (&nVal)[size])
{ const char* pFirst = sVal.data() ;
for ( int i = 0 ; i < size ; ++ i) {
auto answer = fast_float::from_chars_advanced( pFirst, sVal.data() + sVal.size(), nVal[i], FAST_FLOAT_OPTS) ;
if ( answer.ec != std::errc() || ( i < size - 1 && answer.ptr[0] != ','))
return false ;
pFirst = answer.ptr + 1 ;
}
return true ;
}
template <size_t size>
bool FromString( const std::string& sVal, double (&dVal)[size])
{ const char* pFirst = sVal.data() ;
for ( int i = 0 ; i < size ; ++ i) {
auto answer = fast_float::from_chars( pFirst, sVal.data() + sVal.size(), dVal[i], FAST_FLOAT_FMT) ;
if ( answer.ec != std::errc() || ( i < size - 1 && answer.ptr[0] != ','))
return false ;
pFirst = answer.ptr + 1 ;
}
return true ;
}
template <size_t size>
bool FromString( const std::string& sVal, std::array<double,size>& dVal)
{ const char* pFirst = sVal.data() ;
for ( int i = 0 ; i < size ; ++ i) {
auto answer = fast_float::from_chars( pFirst, sVal.data() + sVal.size(), dVal[i], FAST_FLOAT_FMT) ;
if ( answer.ec != std::errc() || ( i < size - 1 && answer.ptr[0] != ','))
return false ;
pFirst = answer.ptr + 1 ;
}
return true ;
}
//----------------------------------------------------------------------------
inline const std::string
ToString( int nVal, int nPrec = 1, int nRadix = 10, int* pnErr = nullptr)
{
// eseguo conversione
const int nBuffSize = 36 ;
char szBuff[nBuffSize]{} ;
auto Res = std::to_chars( szBuff, szBuff + nBuffSize - 1, nVal, nRadix) ;
if ( Res.ec != std::errc()) {
if ( pnErr != nullptr)
*pnErr = int( Res.ec) ;
return "#Error" ;
}
// gestione codice di errore
if ( pnErr != nullptr)
*pnErr = 0 ;
// verifico lunghezza minima
int nLen = (int) strlen( szBuff) ;
if ( nLen >= nPrec)
return szBuff ;
// porto la stringa alla minima lunghezza
std::string sBuff( szBuff) ;
sBuff.insert( 0, ( nPrec - nLen), '0') ;
return sBuff ;
}
inline const std::string
ToString( unsigned int nVal, int nPrec = 1, int nRadix = 10, int* pnErr = nullptr)
{
// eseguo conversione
const int nBuffSize = 36 ;
char szBuff[nBuffSize]{} ;
auto Res = std::to_chars( szBuff, szBuff + nBuffSize - 1, nVal, nRadix) ;
if ( Res.ec != std::errc()) {
if ( pnErr != nullptr)
*pnErr = int( Res.ec) ;
return "#Error" ;
}
// gestione codice di errore
if ( pnErr != nullptr)
*pnErr = 0 ;
// verifico lunghezza minima
int nLen = (int) strlen( szBuff) ;
if ( nLen >= nPrec)
return szBuff ;
// porto la stringa alla minima lunghezza
std::string sBuff( szBuff) ;
sBuff.insert( 0, ( nPrec - nLen), '0') ;
return szBuff ;
}
template <size_t size>
const std::string ToString( const int (&nVal)[size], int nPrec = 1)
{ std::string sDest ; sDest.reserve( 8 * size) ;
for ( const auto& nV : nVal)
sDest += ToString( nV, nPrec) + "," ;
sDest.pop_back() ;
return sDest ; }
inline const std::string
ToString( bool bVal)
{ return std::string( ( bVal ? "1" : "0")) ; }
inline const std::string
ToString( double dVal, int nPrec, int* pnErr)
{
const double BIG_NUMBER = 1e10 ;
const int MAX_PREC = 12 ;
// verifiche (precisione e grande numero)
bool bCutTrailingZero = ( nPrec > 0) ;
nPrec = std::min( abs( nPrec), MAX_PREC) ;
bool bStdNbr = ( abs( dVal) < BIG_NUMBER) ;
// converto in stringa
const int nBuffSize = 32 ;
char szBuff[nBuffSize]{} ;
auto Res = ( bStdNbr ? std::to_chars( szBuff, szBuff + nBuffSize - 1, dVal, std::chars_format::fixed, nPrec) :
std::to_chars( szBuff, szBuff + nBuffSize - 1, dVal, std::chars_format::scientific)) ;
if ( Res.ec != std::errc()) {
std::string sOut = make_error_code( Res.ec).message() ;
//LOG_ERROR( GetEGnLogger(), sOut.c_str())
if ( pnErr != nullptr)
*pnErr = int( Res.ec) ;
return "#Error" ;
}
// se abilitato e inserito un punto decimale tolgo i trailing zero
if ( bCutTrailingZero && bStdNbr) {
char* pDest = Res.ptr ;
pDest -- ;
while ( *pDest == '0') {
*pDest = '\0' ;
pDest -- ;
}
if ( *pDest == '.')
*pDest = '\0' ;
}
if ( pnErr != nullptr)
*pnErr = 0 ;
if ( szBuff[0] == '-' && szBuff[1] == '0' && szBuff[2] == '\0')
return "0" ;
else
return szBuff ;
}
template <size_t size>
const std::string ToString( const double (&dVal)[size], int nPrec = 6)
{ std::string sDest ; sDest.reserve( 14 * size) ;
for ( const auto& dV : dVal)
sDest += ToString( dV, nPrec) + "," ;
sDest.pop_back() ;
return sDest ; }
template <size_t size>
const std::string ToString( const std::array<double,size>& dVal, int nPrec = 6)
{ std::string sDest ; sDest.reserve( 14 * size) ;
for ( const auto& dV : dVal)
sDest += ToString( dV, nPrec) + "," ;
sDest.pop_back() ;
return sDest ; }
//----------------------------------------------------------------------------
inline void
Split( const std::string& sString, const std::string& sSeparator, bool bFirstVsLast,
std::string& sFirst, std::string& sLast)
{
// verifico definizione separatore
if ( sSeparator.empty()) {
sFirst.clear() ;
sLast.clear() ;
return ;
}
// cerco il separatore
auto iPos = ( bFirstVsLast ? sString.find( sSeparator) : sString.rfind( sSeparator)) ;
// se trovato
if ( iPos != std::string::npos) {
if ( iPos > 0)
sFirst = sString.substr( 0, iPos) ;
else
sFirst.clear() ;
if ( ( iPos + 1) < sString.length())
sLast = sString.substr( iPos + 1) ;
else
sLast.clear() ;
}
// altrimenti
else {
sFirst = sString ;
sLast.clear() ;
}
}
inline void
SplitFirst( const std::string& sString, const std::string& sSeparator, std::string& sFirst, std::string& sLast)
{ Split( sString, sSeparator, true, sFirst, sLast) ; }
inline void
SplitLast( const std::string& sString, const std::string& sSeparator, std::string& sFirst, std::string& sLast)
{ Split( sString, sSeparator, false, sFirst, sLast) ; }
//----------------------------------------------------------------------------
inline int
ReplaceString( std::string& sString, const std::string& sOld, const std::string& sNew)
{
int nSubs = 0 ;
size_t pos = 0 ;
while ( ( pos = sString.find( sOld, pos)) != std::string::npos) {
sString.replace( pos, sOld.length(), sNew) ;
pos += sNew.length() ;
nSubs ++ ;
}
return nSubs ;
}