diff --git a/include/eepp/core/string.hpp b/include/eepp/core/string.hpp index c12b7f309..210fbd7e4 100644 --- a/include/eepp/core/string.hpp +++ b/include/eepp/core/string.hpp @@ -13,6 +13,18 @@ namespace EE { +template struct FormatArg { + static const T& get( const T& arg ) { return arg; } +}; + +template <> struct FormatArg { + static const char* get( const std::string& arg ) { return arg.c_str(); } +}; + +template <> struct FormatArg { + static const char* get( const std::string_view& arg ) { return arg.data(); } +}; + /* ** The class was modified to fit EEPP own needs. This is not the original implementation from SFML2. ** Functions and methods are the same that in std::string to facilitate portability. @@ -70,13 +82,6 @@ class EE_API String { return 0; } - static constexpr String::HashType hashCombine( String::HashType& hash, const char* str, - Int64 len ) { - while ( --len >= 0 ) - hash = ( ( hash << 5 ) + hash ) + *str++; - return hash; - } - static constexpr String::HashType hash( const char* str, Int64 len ) { String::HashType hash = 5381; while ( --len >= 0 ) @@ -336,14 +341,20 @@ class EE_API String { return !( iss >> f >> t ).fail(); } - /** Returning a std::string from a formated string */ - static std::string format( const char* format, ... ) -#ifdef __GNUC__ - /* This attribute is nice: it even works through gettext invokation. For - example, gcc will complain that StrFormat(_("%s"), 42) is ill-formed. */ - __attribute__( ( format( printf, 1, 2 ) ) ) -#endif - ; + template + static std::string format( std::string_view format, Args&&... args ) { + int size = + std::snprintf( nullptr, 0, format.data(), + FormatArg>::get( std::forward( args ) )... ) + + 1; + std::string result( size, 0 ); + if ( size > 0 ) { + std::snprintf( &result[0], size, format.data(), + FormatArg>::get( std::forward( args ) )... ); + result.resize( size - 1 ); + } + return result; + } /** Format a char buffer */ static void formatBuffer( char* Buffer, int BufferSize, const char* format, ... ); diff --git a/include/eepp/system/log.hpp b/include/eepp/system/log.hpp index b4e4e1791..1b5ded329 100644 --- a/include/eepp/system/log.hpp +++ b/include/eepp/system/log.hpp @@ -151,31 +151,45 @@ class EE_API Log : protected Mutex { } template static void debug( const char* format, Args&&... args ) { - Log::instance()->writef( LogLevel::Debug, format, std::forward( args )... ); + Log::instance()->writef( + LogLevel::Debug, format, + FormatArg>::get( std::forward( args ) )... ); } template static void info( const char* format, Args&&... args ) { - Log::instance()->writef( LogLevel::Info, format, std::forward( args )... ); + Log::instance()->writef( + LogLevel::Info, format, + FormatArg>::get( std::forward( args ) )... ); } template static void notice( const char* format, Args&&... args ) { - Log::instance()->writef( LogLevel::Notice, format, std::forward( args )... ); + Log::instance()->writef( + LogLevel::Notice, format, + FormatArg>::get( std::forward( args ) )... ); } template static void warning( const char* format, Args&&... args ) { - Log::instance()->writef( LogLevel::Warning, format, std::forward( args )... ); + Log::instance()->writef( + LogLevel::Warning, format, + FormatArg>::get( std::forward( args ) )... ); } template static void error( const char* format, Args&&... args ) { - Log::instance()->writef( LogLevel::Error, format, std::forward( args )... ); + Log::instance()->writef( + LogLevel::Error, format, + FormatArg>::get( std::forward( args ) )... ); } template static void critical( const char* format, Args&&... args ) { - Log::instance()->writef( LogLevel::Critical, format, std::forward( args )... ); + Log::instance()->writef( + LogLevel::Critical, format, + FormatArg>::get( std::forward( args ) )... ); } template static void assertLog( const char* format, Args&&... args ) { - Log::instance()->writef( LogLevel::Assert, format, std::forward( args )... ); + Log::instance()->writef( + LogLevel::Assert, format, + FormatArg>::get( std::forward( args ) )... ); } protected: diff --git a/src/eepp/core/string.cpp b/src/eepp/core/string.cpp index 6eeef172d..bd778ed8d 100644 --- a/src/eepp/core/string.cpp +++ b/src/eepp/core/string.cpp @@ -917,34 +917,6 @@ void String::formatBuffer( char* Buffer, int BufferSize, const char* format, ... va_end( args ); } -std::string String::format( const char* format, ... ) { - int n, size = 256; - std::string tstr( size, '\0' ); - - va_list args; - - va_start( args, format ); - - while ( 1 ) { - n = vsnprintf( &tstr[0], size, format, args ); - - if ( n > -1 && n < size ) { - tstr.resize( n ); - - va_end( args ); - - return tstr; - } - - if ( n > -1 ) // glibc 2.1 - size = n + 1; // precisely what is needed - else // glibc 2.0 - size *= 2; // twice the old size - - tstr.resize( size ); - } -} - String::String() {} String::String( char ansiChar, const std::locale& locale ) { diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index 18acddfde..a88785399 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -63,8 +63,8 @@ bool App::onCloseRequestCallback( EE::Window::Window* ) { saveConfig(); mWindow->close(); } ); - msgBox->setTitle( String::format( i18n( "close_title", "Close %s?" ).toUtf8().c_str(), - mWindowTitle.c_str() ) ); + msgBox->setTitle( + String::format( i18n( "close_title", "Close %s?" ).toUtf8(), mWindowTitle ) ); msgBox->center(); msgBox->showWhenReady(); return false; @@ -527,7 +527,7 @@ bool App::loadConfig( const LogLevel& logLevel, const Sizeu& displaySize, bool s if ( !mArgs.empty() ) { std::string strargs( String::join( mArgs ) ); - Log::info( "ecode starting with these command line arguments: %s", strargs.c_str() ); + Log::info( "ecode starting with these command line arguments: %s", strargs ); } initPluginManager(); @@ -1602,12 +1602,11 @@ void App::updateDocInfo( TextDocument& doc ) { mDocInfo->setVisible( true ); updateDocInfoLocation(); String infoStr( String::format( - "%s: %lld / %zu %s: %lld %s %s", i18n( "line_abbr", "line" ).toUtf8().c_str(), + "%s: %lld / %zu %s: %lld %s %s", i18n( "line_abbr", "line" ).toUtf8(), doc.getSelection().start().line() + 1, doc.linesCount(), - i18n( "col_abbr", "col" ).toUtf8().c_str(), - mSplitter->getCurEditor()->getCurrentColumnCount(), - doc.getSyntaxDefinition().getLanguageName().c_str(), - TextDocument::lineEndingToString( doc.getLineEnding() ).c_str() ) ); + i18n( "col_abbr", "col" ).toUtf8(), mSplitter->getCurEditor()->getCurrentColumnCount(), + doc.getSyntaxDefinition().getLanguageName(), + TextDocument::lineEndingToString( doc.getLineEnding() ) ) ); mDocInfo->debounce( [this, infoStr] { mDocInfo->setText( infoStr ); }, Time::Zero, String::hash( "ecode::doc_info::update" ) ); } @@ -1659,8 +1658,8 @@ void App::onColorSchemeChanged( const std::string& ) { } mNotificationCenter->addNotification( - String::format( i18n( "color_scheme_set", "Color scheme: %s" ).toUtf8().c_str(), - mSplitter->getCurrentColorScheme().getName().c_str() ) ); + String::format( i18n( "color_scheme_set", "Color scheme: %s" ).toUtf8(), + mSplitter->getCurrentColorScheme().getName() ) ); } void App::cleanUpRecentFiles() { @@ -2619,7 +2618,7 @@ void App::loadDirTree( const std::string& path ) { Clock* clock = eeNew( Clock, () ); mDirTreeReady = false; mDirTree = std::make_shared( path, mThreadPool, this ); - Log::info( "Loading DirTree: %s", path.c_str() ); + Log::info( "Loading DirTree: %s", path ); mDirTree->scan( [&, clock]( ProjectDirectoryTree& dirTree ) { Log::info( "DirTree read in: %.2fms. Found %ld files.", @@ -3337,8 +3336,8 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe mConfig.context.SharedGLContext = true; mWindow = engine->createWindow( winSettings, mConfig.context ); - Log::info( "%s (codename: \"%s\") initializing", ecode::Version::getVersionFullName().c_str(), - ecode::Version::getCodename().c_str() ); + Log::info( "%s (codename: \"%s\") initializing", ecode::Version::getVersionFullName(), + ecode::Version::getCodename() ); if ( mWindow->isOpen() ) { // Only verify GPU driver availability on Windows. @@ -3499,7 +3498,7 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe font-size: %s; } )css", - mConfig.ui.panelFontSize.toString().c_str() ) ); + mConfig.ui.panelFontSize.toString() ) ); mUISceneNode->combineStyleSheet( panelUI, false, APP_LAYOUT_STYLE_MARKER ); const auto baseUI = ( diff --git a/src/tools/ecode/plugins/git/git.cpp b/src/tools/ecode/plugins/git/git.cpp index 885f30067..c4e206f50 100644 --- a/src/tools/ecode/plugins/git/git.cpp +++ b/src/tools/ecode/plugins/git/git.cpp @@ -45,7 +45,7 @@ void Git::git( const std::string& args, const std::string& projectDir, std::stri void Git::gitSubmodules( const std::string& args, const std::string& projectDir, std::string& buf ) { - git( String::format( "submodule foreach \"git %s\"", args.c_str() ), projectDir, buf ); + git( String::format( "submodule foreach \"git %s\"", args ), projectDir, buf ); } std::string Git::branch( const std::string& projectDir ) { @@ -227,7 +227,7 @@ Git::Blame Git::blame( const std::string& filepath, std::size_t line ) const { auto commitMessage = getText( "summary"sv ); - git( String::format( "rev-parse --short %s", commitHash.c_str() ), workingDir, buf ); + git( String::format( "rev-parse --short %s", commitHash ), workingDir, buf ); auto commitShortHash = String::rTrim( buf, '\n' ); diff --git a/src/tools/ecode/plugins/pluginmanager.cpp b/src/tools/ecode/plugins/pluginmanager.cpp index 512745258..f7b9a809c 100644 --- a/src/tools/ecode/plugins/pluginmanager.cpp +++ b/src/tools/ecode/plugins/pluginmanager.cpp @@ -20,7 +20,7 @@ PluginManager::PluginManager( const std::string& resourcesPath, const std::strin PluginManager::~PluginManager() { mClosing = true; for ( auto& plugin : mPlugins ) { - Log::debug( "PluginManager: unloading plugin %s", plugin.second->getTitle().c_str() ); + Log::debug( "PluginManager: unloading plugin %s", plugin.second->getTitle() ); eeDelete( plugin.second ); } unsubscribeFileSystemListener(); @@ -49,7 +49,7 @@ bool PluginManager::setEnabled( const std::string& id, bool enable, bool sync ) mPluginsEnabled[id] = enable; Plugin* plugin = get( id ); if ( enable && plugin == nullptr && hasDefinition( id ) ) { - Log::debug( "PluginManager: loading plugin %s", mDefinitions[id].name.c_str() ); + Log::debug( "PluginManager: loading plugin %s", mDefinitions[id].name ); Plugin* newPlugin = sync && mDefinitions[id].creatorSyncFn ? mDefinitions[id].creatorSyncFn( this ) : mDefinitions[id].creatorFn( this ); @@ -59,7 +59,7 @@ bool PluginManager::setEnabled( const std::string& id, bool enable, bool sync ) return true; } if ( !enable && plugin != nullptr ) { - Log::debug( "PluginManager: unloading plugin %s", mDefinitions[id].name.c_str() ); + Log::debug( "PluginManager: unloading plugin %s", mDefinitions[id].name ); mThreadPool->run( [plugin]() { eeDelete( plugin ); } ); { Lock l( mSubscribedPluginsMutex );