//---------------------------------------------------------------------------- // EgalTech 2013-2014 //---------------------------------------------------------------------------- // File : StringUtils.cpp Data : 13.01.15 Versione : 1.6a2 // Contenuto : Implementazione delle funzioni di utilità per le stringhe. // // // // Modifiche : 20.01.13 DS Creazione modulo. // 02.12.13 DS Agg. FromString per Vector3d, Point3d e Point3d+W. // 19.01.14 DS Tokenize con Atom ora funziona su più livelli. // 17.03.14 DS Agg. CurrDateTime. // 13.01.15 DS Agg. CurrDateTime. // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "DllMain.h" #include "/EgtDEv/Include/EGnStringUtils.h" #include "/EgtDev/Include/EgtILogger.h" #include using namespace std ; //---------------------------------------------------------------------------- static inline void SkipSpaces( const char*& pC) { while ( *pC == ' ' || *pC == '\t') ++ pC ; } //---------------------------------------------------------------------------- static inline void SkipSpaces( char*& pC) { while ( *pC == ' ' || *pC == '\t') ++ pC ; } //---------------------------------------------------------------------------- bool FromString( const string& sVal, INTVECTOR& vnVal) { // pulisco il vettore dei risultati vnVal.clear() ; // reset errori di conversione errno = 0 ; // ciclo sui caratteri della stringa const char* pStart = sVal.c_str() ; SkipSpaces( pStart) ; while ( ( *pStart >= '0' && *pStart <= '9') || *pStart == '+' || *pStart == '-') { char* pStop ; int nVal = strtol( pStart, &pStop, 10) ; vnVal.push_back( nVal) ; SkipSpaces( pStop) ; if ( *pStop == '\0' && errno == 0) return true ; if ( *pStop != ',' || errno != 0) return false ; pStart = pStop + 1 ; SkipSpaces( pStart) ; } return ( *pStart == '\0' && errno == 0) ; } //---------------------------------------------------------------------------- bool FromString( const string& sVal, DBLVECTOR& vdVal) { // pulisco il vettore dei risultati vdVal.clear() ; // reset errori di conversione errno = 0 ; // ciclo sui caratteri della stringa const char* pStart = sVal.c_str() ; SkipSpaces( pStart) ; while ( ( *pStart >= '0' && *pStart <= '9') || *pStart == '+' || *pStart == '-' || *pStart == '.') { char* pStop ; double dVal = strtod( pStart, &pStop) ; vdVal.push_back( dVal) ; SkipSpaces( pStop) ; if ( *pStop == '\0' && errno == 0) return true ; if ( *pStop != ',' || errno != 0) return false ; pStart = pStop + 1 ; SkipSpaces( pStart) ; } return ( *pStart == '\0' && errno == 0) ; } //---------------------------------------------------------------------------- bool FromString( const string& sVal, STRVECTOR& vsVal) { return Tokenize( sVal, ",", vsVal) ; } //---------------------------------------------------------------------------- const string ToString( double dVal, int nPrec) { const double BIG_NUMBER = 1e10 ; const int BIG_DIGITNBR = 10 ; const int MAX_PREC = 12 ; // verifico la precisione bool bCutTrailingZero = ( nPrec >= 0) ; nPrec = min( abs( nPrec), MAX_PREC) ; // converto la mantissa char szBuff[24] ; int nErr, nDecimal, nSign ; if ( abs( dVal) < BIG_NUMBER) nErr = _fcvt_s( szBuff, dVal, nPrec, &nDecimal, &nSign) ; else nErr = _ecvt_s( szBuff, dVal, BIG_DIGITNBR + nPrec, &nDecimal, &nSign) ; // se errore, ritorno stringa opportuna if ( nErr != 0) { _ASSERT( 0) ; string sErr = "ToString Error : " + ToString( nErr) ; LOG_ERROR( GetEGnLogger(), sErr.c_str()) return "#Error" ; } // se buffer vuoto, risultato è numero 0 if ( szBuff[0] == '\0') return "0" ; // verifica per forma esponenziale int nExp ; if ( nDecimal > BIG_DIGITNBR) { nExp = nDecimal - 1 ; nDecimal = 1 ; } else nExp = 0 ; // puntatori a inizio stringhe char szDest[32] ; char* pBuff = szBuff ; char* pDest = szDest ; // eventuale inserimento segno '-' if ( nSign != 0) { *pDest = '-' ; pDest ++ ; } ; // gestione decimali dopo 0 if ( nDecimal <= 0) { *pDest = '0' ; pDest ++ ; *pDest = '.' ; pDest ++ ; for ( ; nDecimal < 0 ; nDecimal ++) { *pDest = '0' ; pDest ++ ; } nDecimal -- ; } // gestione cifre e . while ( *pBuff != '\0') { if ( *pBuff == '#') { // NAN, INFINITY, INDEFINITE _ASSERT( 0) ; string sErr = "ToString Error : " + string( szBuff) ; LOG_ERROR( GetEGnLogger(), sErr.c_str()) } if ( nDecimal == 0) { *pDest = '.' ; pDest ++ ; } nDecimal -- ; *pDest = *pBuff ; pDest ++ ; pBuff ++ ; } *pDest = '\0' ; // se abilitato e inserito un punto decimale tolgo i trailing zero if ( bCutTrailingZero && nDecimal < 0) { pDest -- ; while ( *pDest == '0') { *pDest = '\0' ; pDest -- ; } if ( *pDest == '.') *pDest = '\0' ; else pDest ++ ; } // aggiungo eventuale esponente (sempre compreso tra 9 e 308) if ( nExp > 0) { *pDest = 'e' ; pDest ++ ; int nTmp = nExp ; if ( nTmp >= 100) { *pDest = '0' + ( nTmp / 100) ; pDest ++ ; nTmp = nTmp % 100 ; } if ( nTmp >= 10 || nExp >= 100) { *pDest = '0' + ( nTmp / 10) ; pDest ++ ; nTmp = nTmp % 10 ; } *pDest = '0' + nTmp ; pDest ++ ; *pDest = '\0' ; } if ( szDest[0] == '-' && szDest[1] == '0' && szDest[2] == '\0') return "0" ; else return szDest ; } //---------------------------------------------------------------------------- const string ToString( const INTVECTOR& vnVal, int nPrec) { // se vettore vuoto, stringa vuota if ( vnVal.empty()) return "" ; // costruisco la stringa string sDest ; sDest.reserve( 8 * vnVal.size()) ; for ( size_t i = 0 ; i < vnVal.size() ; ++ i) sDest += ToString( vnVal[i], nPrec) + "," ; sDest.pop_back() ; return sDest ; } //---------------------------------------------------------------------------- const string ToString( const DBLVECTOR& vdVal, int nPrec) { // se vettore vuoto, stringa vuota if ( vdVal.empty()) return "" ; // costruisco la stringa string sDest ; sDest.reserve( 14 * vdVal.size()) ; for ( size_t i = 0 ; i < vdVal.size() ; ++ i) sDest += ToString( vdVal[i], nPrec) + "," ; sDest.pop_back() ; return sDest ; } //---------------------------------------------------------------------------- const string ToString( const STRVECTOR& vsVal) { // se vettore vuoto, stringa vuota if ( vsVal.empty()) return "" ; // costruisco la stringa int nLen = 0 ; for ( size_t i = 0 ; i < vsVal.size() ; ++ i) nLen += int( vsVal[i].length()) + 1 ; string sDest ; sDest.reserve( nLen) ; for ( size_t i = 0 ; i < vsVal.size() ; ++ i) sDest += vsVal[i] + "," ; sDest.pop_back() ; return sDest ; } //---------------------------------------------------------------------------- void Split( const string& sString, const string& sSeparator, bool bFirstVsLast, string& sFirst, string& sLast) { // verifico definizione separatore if ( sSeparator.empty()) { sFirst.clear() ; sLast.clear() ; return ; } // cerco il separatore string::size_type iPos = ( bFirstVsLast ? sString.find( sSeparator) : sString.rfind( sSeparator)) ; // se trovato if ( iPos != 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() ; } } //---------------------------------------------------------------------------- bool Tokenize( const string& sString, const string& sSeparators, STRVECTOR& vsTokens) { // pulisco il risultato vsTokens.clear() ; // parto dall'inizio string::size_type iPosStart = ( sString.empty() ? string::npos : 0) ; // mentre esiste un nuovo inizio di token while ( iPosStart != string::npos) { // cerco il primo separatore string::size_type iPosEnd = sString.find_first_of( sSeparators, iPosStart) ; // se arrivato alla fine, aggiungo il token al vettore if ( iPosEnd == string::npos) vsTokens.push_back( sString.substr( iPosStart)) ; // altrimenti aggiungo se separatore diverso da spazio o risultato non vuoto else if ( sString[iPosEnd] != ' ' || iPosEnd > iPosStart) vsTokens.push_back( sString.substr( iPosStart, iPosEnd - iPosStart)) ; // cerco l'inizio di un nuovo token iPosStart = ( iPosEnd != string::npos ? iPosEnd + 1 : string::npos) ; } return true ; } //---------------------------------------------------------------------------- bool TokenizePlus( const string& sString, const string& sHeaders, STRVECTOR& vsTokens) { // pulisco il risultato vsTokens.clear() ; // parto dall'inizio string::size_type iPosStart = ( sString.empty() ? string::npos : 0) ; // mentre esiste un nuovo inizio di token while ( iPosStart != string::npos) { // cerco il successivo carattere di intestazione string::size_type iPosEnd = sString.find_first_of( sHeaders, iPosStart + 1) ; // aggiungo il token al vettore vsTokens.push_back( sString.substr( iPosStart, iPosEnd - iPosStart)) ; // cerco l'inizio di un nuovo token iPosStart = iPosEnd ; } return true ; } //---------------------------------------------------------------------------- bool Tokenize( const string& sString, const string& sSeparators, const string& sAtomStarts, const string& sAtomEnds, STRVECTOR& vsTokens) { // i separatori devono essere diversi da inizio e fine di atomi if ( sAtomStarts.find_first_of( sSeparators) != string::npos || sAtomEnds.find_first_of( sSeparators) != string::npos) return false ; // pulisco il risultato vsTokens.clear() ; // se la stringa è vuota non c'è niente da cercare if ( sString.empty()) return true ; // parto dall'inizio int nOpenAtom = 0 ; string::size_type iPosStart = 0 ; string::size_type iPosEnd = iPosStart ; // mentre esiste un nuovo carattere while ( iPosEnd < sString.size()) { // trovo separatore non all'interno di un atomo if ( sSeparators.find( sString[iPosEnd]) != string::npos && nOpenAtom <= 0) { // aggiungo il token al vettore vsTokens.push_back( sString.substr( iPosStart, iPosEnd - iPosStart)) ; // passo al carattere successivo ++ iPosEnd ; // imposto nuovo inizio di token iPosStart = ( iPosEnd < sString.size() ? iPosEnd : string::npos) ; } // trovo inizio di atomo else if ( sAtomStarts.find( sString[iPosEnd]) != string::npos) { ++ nOpenAtom ; // passo al carattere successivo ++ iPosEnd ; } // trovo fine di atomo else if ( sAtomEnds.find( sString[iPosEnd]) != string::npos) { -- nOpenAtom ; // passo al carattere successivo ++ iPosEnd ; } // carattere normale, vado oltre else ++ iPosEnd ; } // se è rimasto un ultimo token if ( iPosStart != string::npos) vsTokens.push_back( sString.substr( iPosStart)) ; return true ; } //---------------------------------------------------------------------------- int ReplaceString( string& sString, const string& sOld, const string& sNew) { int nSubs = 0 ; size_t pos = 0 ; while ( ( pos = sString.find( sOld, pos)) != string::npos) { sString.replace( pos, sOld.length(), sNew) ; pos += sNew.length() ; nSubs ++ ; } return nSubs ; } //---------------------------------------------------------------------------- const string CurrDateTime( void) { // seconds elapsed since midnight, January 1, 1970 time_t _time ; time( &_time) ; // structured time tm _tm ; if ( localtime_s( &_tm, &_time) != 0) return "time/date error" ; // string format const int DT_LEN = 24 ; char szDateTime[DT_LEN] = { '\0'} ; strftime( szDateTime, DT_LEN, "%Y/%m/%d %H:%M:%S", &_tm) ; string sDateTime = szDateTime ; return sDateTime ; }