9bbb8506e9
- aggiunta funzione ToString per C vector unsigned int.
383 lines
16 KiB
C++
383 lines
16 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2013-2025
|
|
//----------------------------------------------------------------------------
|
|
// File : EGnStringUtils.h Data : 18.09.25 Versione : 2.7i1
|
|
// 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>.
|
|
// 18.09.25 DS Agg. FromString e ToString per long long.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#pragma once
|
|
|
|
#include "/EgtDev/Include/EgtStringBase.h"
|
|
#include "/EgtDev/Include/EgtNumCollection.h"
|
|
#include "/EgtDev/Extern/fast_float/fast_float.h"
|
|
#include <algorithm>
|
|
#include <array>
|
|
#include <charconv>
|
|
|
|
//----------------------- Macro per import/export -----------------------------
|
|
#undef EGN_EXPORT
|
|
#if defined( I_AM_EGN) // da definirsi solo nella DLL
|
|
#define EGN_EXPORT __declspec( dllexport)
|
|
#else
|
|
#define EGN_EXPORT __declspec( dllimport)
|
|
#endif
|
|
|
|
//----------------------------------------------------------------------------
|
|
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 == nullptr || 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 == nullptr || 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 == nullptr || 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, long long& 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 ;
|
|
}
|
|
EGN_EXPORT bool FromString( const std::string& sVal, INTVECTOR& vnVal) ;
|
|
EGN_EXPORT bool FromString( const std::string& sVal, DBLVECTOR& vdVal) ;
|
|
EGN_EXPORT bool FromString( const std::string& sVal, STRVECTOR& vsVal) ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
inline const std::string
|
|
ToStringAdv( 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( int nVal, int nPrec = 1, int nRadix = 10, int* pnErr = nullptr)
|
|
{
|
|
// se necessario processing avanzato
|
|
if ( nPrec > 1 || nRadix < 6)
|
|
return ToStringAdv( nVal, nPrec, nRadix, pnErr) ;
|
|
// eseguo conversione
|
|
const int nBuffSize = 16 ;
|
|
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 ;
|
|
return szBuff ;
|
|
}
|
|
|
|
inline const std::string
|
|
ToStringAdv( 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 sBuff ;
|
|
}
|
|
inline const std::string
|
|
ToString( unsigned int nVal, int nPrec = 1, int nRadix = 10, int* pnErr = nullptr)
|
|
{
|
|
// se necessario processing avanzato
|
|
if ( nPrec > 1 || nRadix < 6)
|
|
return ToStringAdv( nVal, nPrec, nRadix, pnErr) ;
|
|
// eseguo conversione
|
|
const int nBuffSize = 16 ;
|
|
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 ;
|
|
return szBuff ;
|
|
}
|
|
template <size_t size>
|
|
const std::string ToString( const unsigned 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
|
|
ToStringAdv( long long nVal, int nPrec = 1, int nRadix = 10, int* pnErr = nullptr)
|
|
{
|
|
// eseguo conversione
|
|
const int nBuffSize = 68 ;
|
|
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( long long nVal, int nPrec = 1, int nRadix = 10, int* pnErr = nullptr)
|
|
{
|
|
// se necessario processing avanzato
|
|
if ( nPrec > 1 || nRadix < 6)
|
|
return ToStringAdv( nVal, nPrec, nRadix, pnErr) ;
|
|
// eseguo conversione
|
|
const int nBuffSize = 16 ;
|
|
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 ;
|
|
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")) ; }
|
|
EGN_EXPORT const std::string ToString( double dVal, int nPrec = 6, int* pnErr = nullptr) ;
|
|
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 ; }
|
|
EGN_EXPORT const std::string ToString( const INTVECTOR& vnVal, int nPrec = 1) ;
|
|
EGN_EXPORT const std::string ToString( const DBLVECTOR& vdVal, int nPrec = 6) ;
|
|
EGN_EXPORT const std::string ToString( const STRVECTOR& vsVal) ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
EGN_EXPORT void Split( const std::string& sString, const std::string& sSeparator, bool bFirstVsLast,
|
|
std::string& sFirst, std::string& sLast) ;
|
|
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) ; }
|
|
|
|
//----------------------------------------------------------------------------
|
|
EGN_EXPORT bool Tokenize( const std::string& sString, const std::string& sSeparators, STRVECTOR& vsTokens) ;
|
|
EGN_EXPORT bool TokenizePlus( const std::string& sString, const std::string& sHeaders, STRVECTOR& vsTokens) ;
|
|
EGN_EXPORT bool Tokenize( const std::string& sString, const std::string& sSeparators,
|
|
const std::string& sAtomStarts, const std::string& sAtomEnds, STRVECTOR& vsTokens) ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
EGN_EXPORT int ReplaceString( std::string& sString, const std::string& sOld, const std::string& sNew) ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
EGN_EXPORT const std::string CurrDateTime( void) ;
|