diff --git a/EBs.h b/EBs.h new file mode 100644 index 0000000..0bddeaf --- /dev/null +++ b/EBs.h @@ -0,0 +1,19 @@ +//---------------------------------------------------------------------------- +// EgalTech 2025-2025 +//---------------------------------------------------------------------------- +// File : EBs.h Data : 24.01.25 Versione : 2.7a1 +// Contenuto : Dichiarazioni locali per moduli EBs. +// +// +// +// Modifiche : 24.01.25 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +#pragma once + +#include "/EgtDev/Include/EgtILogger.h" + +//---------------------------------------------------------------------------- +ILogger* GetLogger( void) ; diff --git a/EgtBasis.cpp b/EgtBasis.cpp index 0f57aa6..0731037 100644 --- a/EgtBasis.cpp +++ b/EgtBasis.cpp @@ -16,6 +16,7 @@ #include "/EgtDev/Include/EgtStringConverter.h" #include "/EgtDev/Include/SELkKeyProc.h" #include "/EgtDev/Include/SELkLockId.h" +#include using namespace std ; @@ -128,3 +129,13 @@ __stdcall EgtGetKeyOptLeftDays( int* pnOptLeftDays) *pnOptLeftDays = s_nKeyOptExpDays - GetCurrDay() ; return TRUE ; } + +//----------------------------------------------------------------------------- +BOOL +__stdcall EgtFreeMemory( void* pMem) +{ + if ( pMem == nullptr) + return FALSE ; + free( pMem) ; + return TRUE ; +} diff --git a/EgtBasis.rc b/EgtBasis.rc index a99d7bb..da5aebb 100644 Binary files a/EgtBasis.rc and b/EgtBasis.rc differ diff --git a/EgtBasis.vcxproj b/EgtBasis.vcxproj index 44a42d6..4b8b6a0 100644 --- a/EgtBasis.vcxproj +++ b/EgtBasis.vcxproj @@ -15,19 +15,19 @@ Win32Proj {69c15767-8e9e-42be-b8f8-aea49dc572ce} EgtBasis - 7.0 + 10.0 DynamicLibrary true - v141_xp + v143 Unicode DynamicLibrary false - v141_xp + v143 true Unicode @@ -117,12 +117,17 @@ + + + + + Create Create diff --git a/EgtBasis.vcxproj.filters b/EgtBasis.vcxproj.filters index 7aa1615..75a3a36 100644 --- a/EgtBasis.vcxproj.filters +++ b/EgtBasis.vcxproj.filters @@ -27,6 +27,12 @@ Header Files\Include + + Header Files + + + Header Files + @@ -38,6 +44,15 @@ Source Files + + Source Files + + + Source Files + + + Source Files + diff --git a/IniFile.cpp b/IniFile.cpp new file mode 100644 index 0000000..6f6d540 --- /dev/null +++ b/IniFile.cpp @@ -0,0 +1,44 @@ +//---------------------------------------------------------------------------- +// EgalTech 2025-2025 +//---------------------------------------------------------------------------- +// File : IniFile.cpp Data : 24.01.25 Versione : 2.7a1 +// Contenuto : Implementazione funzioni lettura/scrittura su INI file con UTF8. +// +// +// Modifiche : 24.01.25 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "StringUtils.h" + +using namespace std ; + +//---------------------------------------------------------------------------- +BOOL +__stdcall EgtGetStringUtf8FromIni( const wchar_t* wsSec, const wchar_t* wsKey, + const wchar_t* wsDef, wchar_t*& wsVal, const wchar_t* wsIniFile) +{ + // leggo la stringa dal file INI come ANSI/UTF-8 in WChar e metto in Char + wchar_t szBuffW[_MAX_PATH] ; + int nChar = GetPrivateProfileStringW( wsSec, wsKey, NULL, szBuffW, _MAX_PATH, wsIniFile) ; + + if ( nChar <= 0) + wsVal = _wcsdup( wsDef) ; + else { + string sVal = LPSTR( WtoAEX<>( szBuffW, CP_ACP)) ; + wsVal = _wcsdup( stringtoW( sVal)) ; + } + return (( wsVal == nullptr) ? FALSE : TRUE) ; +} + +//---------------------------------------------------------------------------- +BOOL +__stdcall EgtWriteStringUtf8ToIni( const wchar_t* wsSec, const wchar_t* wsKey, const wchar_t* wsVal, const wchar_t* wsIniFile) +{ + // salvo la stringa nel file INI come ANSI/UTF-8 ma scritta in variabile WChar + string sVal = wstrztoA( wsVal) ; + return WritePrivateProfileStringW( wsSec, wsKey, AtoWEX<>( sVal.data(), CP_ACP), wsIniFile) ; +} diff --git a/Logger.cpp b/Logger.cpp new file mode 100644 index 0000000..5df9f29 --- /dev/null +++ b/Logger.cpp @@ -0,0 +1,63 @@ +//---------------------------------------------------------------------------- +// EgalTech 2025-2025 +//---------------------------------------------------------------------------- +// File : Logger.cpp Data : 24.01.25 Versione : 2.7a1 +// Contenuto : Implementazione funzioni gestione outlog. +// +// +// Modifiche : 24.01.25 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "StringUtils.h" +#include "/EgtDev/Include/EBsAPI.h" +#include "/EgtDev/Include/EgtLogger.h" +#include + +using namespace std ; +using namespace egtlogger ; + +//---------------------------------------------------------------------------- +static int s_nDebugLev = 0 ; +static Logger* s_pGenLog = nullptr ; + +//----------------------------------------------------------------------------- +BOOL +__stdcall EgtInitLogger( int nDebug, const wchar_t* wsLogFile) +{ + // cancello eventuale vecchio logger + if ( s_pGenLog != nullptr) + delete s_pGenLog ; + // assegno il livello di debug + s_nDebugLev = max( nDebug, 0) ; + // creo il logger generale + s_pGenLog = new( nothrow) Logger( ( s_nDebugLev > 0 ? LL_DEBUG : LL_INFO), "EgtBasis") ; + if ( s_pGenLog == nullptr) + return FALSE ; + // assegno il file + s_pGenLog->AddOutputStream( new( nothrow) ofstream( wsLogFile), true) ; + return TRUE ; +} + +//----------------------------------------------------------------------------- +BOOL +__stdcall EgtOutLog( const wchar_t* wsMsg, int nDebugLevel) +{ + if ( s_pGenLog == nullptr) + return FALSE ; + if ( nDebugLevel == 0) + LOG_INFO( s_pGenLog, wstrztoA( wsMsg)) + else if ( s_nDebugLev >= nDebugLevel) + LOG_DBG_INFO( s_pGenLog, wstrztoA( wsMsg)) + return TRUE ; +} + +//----------------------------------------------------------------------------- +ILogger* +GetLogger( void) +{ + return s_pGenLog ; +} diff --git a/Messages.cpp b/Messages.cpp new file mode 100644 index 0000000..d02a316 --- /dev/null +++ b/Messages.cpp @@ -0,0 +1,98 @@ +//---------------------------------------------------------------------------- +// EgalTech 2025-2025 +//---------------------------------------------------------------------------- +// File : Messages.cpp Data : 24.01.25 Versione : 2.7a1 +// Contenuto : Implementazione funzioni gestione messaggi da file. +// +// +// Modifiche : 24.01.25 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "EBs.h" +#include "StringUtils.h" +#include "/EgtDev/Include/EBsAPI.h" +#include "/EgtDev/Include/EgtILogger.h" +#include +#include + +using namespace std ; + +//---------------------------------------------------------------------------- +typedef unordered_map< int, string> INTSTR_UMAP ; +static INTSTR_UMAP s_IdStringMap ; +static string s_sLanguage ; +static wstring s_wsMsg ; + +//---------------------------------------------------------------------------- +BOOL +__stdcall EgtLoadMessages( const wchar_t* wsMsgFilePath) +{ + // apro il file + string sMsgFilePath = wstrztoA( wsMsgFilePath) ; + fstream File( sMsgFilePath, ios::in) ; + if ( ! File.is_open()) + return FALSE ; + // pulisco la memoria + s_IdStringMap.clear() ; + s_wsMsg.clear() ; + // riservo spazio + s_IdStringMap.rehash( 4000) ; + s_wsMsg.reserve( 128) ; + // leggo le linee + string sLine ; + sLine.reserve( 128) ; + string sNum ; + sNum.reserve( 16) ; + string sMsg ; + sMsg.reserve( 128) ; + int nNum ; + int nCurrNum = - 1 ; + int nLineNum = 0 ; + while ( getline( File, sLine)) { + ++ nLineNum ; + // divido la linea in due parti sul token '=' + Split( sLine, "=", true, sNum, sMsg) ; + // la prima parte deve essere numerica + if ( sNum.empty() || ! FromString( sNum, nNum)) { + string sOut ; + sOut = "Problem in " + sMsgFilePath + " at line " + ToString( nLineNum) + " : " + sLine ; + LOG_WARN( GetLogger(), sOut.c_str()) + continue ; + } + // la numerazione deve essere crescente + if ( nNum <= nCurrNum) { + string sOut ; + sOut = "Error in " + sMsgFilePath + " at message " + sNum + " : " + sLine ; + LOG_ERROR( GetLogger(), sOut.c_str()) + return FALSE ; + } + nCurrNum = nNum ; + // converto i caratteri speciali + ReplaceString( sMsg, "
", "\n") ; // a capo + ReplaceString( sMsg, "?" "?" "?", "") ; // da tradurre + // inserisco il messaggio in tabella + if ( ! s_IdStringMap.emplace( nNum, sMsg).second) + return FALSE ; + // se messaggio 0 è la lingua + if ( nNum == 0) + s_sLanguage = sMsg ; + } + // chiudo + File.close() ; + return TRUE ; +} + +//---------------------------------------------------------------------------- +const wchar_t* +__stdcall EgtGetMsg( int nMsg) +{ + // recupero il messaggio + auto Iter = s_IdStringMap.find( nMsg) ; + string sMsg = ( Iter != s_IdStringMap.end() ? Iter->second : "Msg" + ToString( nMsg)) ; + s_wsMsg = stringtoW( sMsg) ; + return s_wsMsg.data() ; +} diff --git a/StringUtils.h b/StringUtils.h new file mode 100644 index 0000000..a7ca9fc --- /dev/null +++ b/StringUtils.h @@ -0,0 +1,341 @@ +//---------------------------------------------------------------------------- +// 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. +// +//---------------------------------------------------------------------------- + +#pragma once + +#include "/EgtDev/Include/EgtStringConverter.h" +#include "/EgtDev/Extern/fast_float/fast_float.h" +#include +#include +#include +#include + +//---------------------------------------------------------------------------- +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, 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 +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 +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 +bool FromString( const std::string& sVal, std::array& 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 +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 +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 +const std::string ToString( const std::array& 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 ; + }