Files
EgtGeneral/StringUtils.cpp
T

329 lines
9.1 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2013-2013
//----------------------------------------------------------------------------
// File : StringUtils.cpp Data : 02.12.13 Versione : 1.4a1
// 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.
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "/EgtDEv/Include/EgnStringUtils.h"
using namespace std ;
//----------------------------------------------------------------------------
bool
FromString( const std::string& sVal, Vector3d& vtVal)
{
STRVECTOR vsParams ;
// divido la stringa in parametri
Tokenize( sVal, ",", vsParams) ;
// devono essere 3 parametri : x, y, z
if ( vsParams.size() != 3)
return false ;
// recupero il punto
return ( FromString( vsParams[0], vtVal.x) &&
FromString( vsParams[1], vtVal.y) &&
FromString( vsParams[2], vtVal.z)) ;
}
//----------------------------------------------------------------------------
bool
FromString( const std::string& sVal, Point3d& ptVal)
{
STRVECTOR vsParams ;
// divido la stringa in parametri
Tokenize( sVal, ",", vsParams) ;
// devono essere 3 parametri : x, y, z
if ( vsParams.size() != 3)
return false ;
// recupero il punto
return ( FromString( vsParams[0], ptVal.x) &&
FromString( vsParams[1], ptVal.y) &&
FromString( vsParams[2], ptVal.z)) ;
}
//----------------------------------------------------------------------------
bool
FromString( const std::string& sVal, Point3d& ptVal, double& dW)
{
STRVECTOR vsParams ;
// divido la stringa in parametri
Tokenize( sVal, ",", vsParams) ;
// devono essere 4 parametri : x, y, z, w
if ( vsParams.size() != 4)
return false ;
// recupero il punto
return ( FromString( vsParams[0], ptVal.x) &&
FromString( vsParams[1], ptVal.y) &&
FromString( vsParams[2], ptVal.z) &&
FromString( vsParams[3], dW)) ;
}
//----------------------------------------------------------------------------
const string
ToString( int nVal, int nPrec)
{
int nErr ;
int nLen ;
char szBuff[24] ;
// eseguo conversione
nErr = _itoa_s( nVal, szBuff, 10) ;
// se errore, ritorno stringa opportuna
if ( nErr != 0) {
_ASSERT( 0) ;
return "#Error" ;
}
// verifico lunghezza minima
if ( ( nLen = (int) strlen( szBuff)) >= nPrec)
return szBuff ;
// porto la stringa alla minima lunghezza
string sBuff( szBuff) ;
sBuff.insert( 0, ( nPrec - nLen), '0') ;
return sBuff ;
}
//----------------------------------------------------------------------------
const string
ToString( double dVal, int nPrec)
{
const double BIG_NUMBER = 1e10 ;
const int BIG_DIGITNBR = 10 ;
const int MAX_PREC = 12 ;
char szBuff[24] ;
char szDest[32] ;
char* pBuff ;
char* pDest ;
int nErr ;
int nDecimal ;
int nSign ;
int nExp ;
int nTmp ;
// verifico la precisione
nPrec = min( nPrec, MAX_PREC) ;
// converto la mantissa
if ( fabs( 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) ;
return "#Error" ;
}
// se buffer vuoto, risultato è numero 0
if ( szBuff[0] == '\0')
return "0" ;
// verifica per forma esponenziale
if ( nDecimal > BIG_DIGITNBR) {
nExp = nDecimal - 1 ;
nDecimal = 1 ;
}
else
nExp = 0 ;
// puntatori a inizio stringhe
pBuff = szBuff ;
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) ;
if ( nDecimal == 0) {
*pDest = '.' ;
pDest ++ ;
}
nDecimal -- ;
*pDest = *pBuff ;
pDest ++ ;
pBuff ++ ;
}
*pDest = '\0' ;
// se inserito un punto decimale tolgo i trailing zero
if ( 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 ++ ;
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 ;
}
//----------------------------------------------------------------------------
void
Split( const string& sString, const string& sSeparator, bool bFirstVsLast,
string& sFirst, string& sLast)
{
string::size_type iPos ;
// cerco il separatore
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)
{
string::size_type iPosStart ;
string::size_type iPosEnd ;
// pulisco il risultato
vsTokens.clear() ;
// parto dall'inizio
iPosStart = ( sString.empty() ? string::npos : 0) ;
// mentre esiste un nuovo inizio di token
while ( iPosStart != string::npos) {
// cerco il primo separatore
iPosEnd = sString.find_first_of( sSeparators, iPosStart) ;
// aggiungo il token al vettore
vsTokens.push_back( sString.substr( iPosStart, iPosEnd - iPosStart)) ;
// cerco l'inizio di un nuovo token
iPosStart = sString.find_first_not_of( sSeparators, iPosEnd) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
Tokenize( const string& sString, const string& sSeparators,
const string& sAtomStarts, const string& sAtomEnds, STRVECTOR& vsTokens)
{
string::size_type iPosStart ;
string::size_type iPosEnd ;
string::size_type iAtomStart ;
string::size_type iAtomEnd ;
// 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 ;
// parto dall'inizio
iPosStart = ( sString.empty() ? string::npos : 0) ;
// mentre esiste un nuovo inizio di token
while ( iPosStart != string::npos) {
// eventuale inizio e fine di parte atomica
iAtomStart = sString.find_first_of( sAtomStarts, iPosStart) ;
iAtomEnd = sString.find_first_of( sAtomEnds, iAtomStart) ;
// cerco il primo separatore
iPosEnd = sString.find_first_of( sSeparators, iPosStart) ;
// se separatore è nella parte atomica, lo ricerco dopo la sua fine
if ( iAtomStart != string::npos && iPosEnd != string::npos &&
iPosEnd > iAtomStart && iPosEnd < iAtomEnd)
iPosEnd = sString.find_first_of( sSeparators, iAtomEnd) ;
// aggiungo il token al vettore
vsTokens.push_back( sString.substr( iPosStart, iPosEnd - iPosStart)) ;
// cerco l'inizio di un nuovo token
iPosStart = sString.find_first_not_of( sSeparators, iPosEnd) ;
}
return true ;
}
//----------------------------------------------------------------------------
int
ReplaceString( std::string& sString, const std::string& sOld, const std::string& sNew)
{
int nSubs ;
size_t pos ;
nSubs = 0 ;
pos = 0 ;
while ( ( pos = sString.find( sOld, pos)) != std::string::npos) {
sString.replace( pos, sOld.length(), sNew) ;
pos += sNew.length() ;
nSubs ++ ;
}
return nSubs ;
}