From c3024cbcc9f270f5914424b436c9f8faabe64b22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 18 Apr 2022 21:26:17 +0200 Subject: [PATCH] Platform: port EmscriptenApplication away from std::string. Co-authored-by: Squareys --- src/Magnum/Platform/EmscriptenApplication.cpp | 50 ++++++++++--------- src/Magnum/Platform/EmscriptenApplication.h | 24 ++++++--- .../Test/EmscriptenApplicationTest.cpp | 5 +- 3 files changed, 46 insertions(+), 33 deletions(-) diff --git a/src/Magnum/Platform/EmscriptenApplication.cpp b/src/Magnum/Platform/EmscriptenApplication.cpp index fb9095474..dce134886 100644 --- a/src/Magnum/Platform/EmscriptenApplication.cpp +++ b/src/Magnum/Platform/EmscriptenApplication.cpp @@ -51,6 +51,8 @@ namespace Magnum { namespace Platform { +using namespace Containers::Literals; + namespace { typedef EmscriptenApplication::KeyEvent::Key Key; @@ -181,7 +183,7 @@ namespace { return Key::Unknown; } - std::string canvasId() { + Containers::String canvasId() { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" /* Note: can't use let or const, as that breaks closure compiler: @@ -195,9 +197,7 @@ namespace { return memory; })); #pragma GCC diagnostic pop - std::string str = id; - std::free(id); - return str; + return Containers::String{id, [](char* data, std::size_t) { std::free(data); }}; } bool checkForDeprecatedEmscriptenTargetBehavior() { @@ -243,18 +243,18 @@ EmscriptenApplication::EmscriptenApplication(const Arguments& arguments, NoCreat /* Save command-line arguments */ if(args.value("log") == "verbose") _verboseLog = true; - const std::string dpiScaling = args.value("dpi-scaling"); + const Containers::StringView dpiScaling = args.value("dpi-scaling"); /* Use physical DPI scaling */ - if(dpiScaling == "default" || dpiScaling == "physical") { + if(dpiScaling == "default"_s || dpiScaling == "physical"_s) { /* Use explicit dpi scaling vector */ - } else if(dpiScaling.find_first_of(" \t\n") != std::string::npos) - _commandLineDpiScaling = args.value("dpi-scaling"); + } else if(dpiScaling.containsAny(" \t\n"_s)) + _commandLineDpiScaling = args.value("dpi-scaling"_s); /* Use explicit dpi scaling scalar */ else - _commandLineDpiScaling = Vector2{args.value("dpi-scaling")}; + _commandLineDpiScaling = Vector2{args.value("dpi-scaling"_s)}; } EmscriptenApplication::~EmscriptenApplication() { @@ -318,7 +318,7 @@ bool EmscriptenApplication::tryCreate(const Configuration& configuration) { Debug{verbose} << "Platform::EmscriptenApplication::tryCreate(): using old Emscripten target behavior"; } - _canvasTarget = (_deprecatedTargetBehavior ? "" : "#") + canvasId(); + _canvasTarget = (_deprecatedTargetBehavior ? canvasId() : "#"_s + canvasId()); /* Get CSS canvas size and cache it. This is used later to detect canvas resizes in emscripten_set_resize_callback() and fire viewport events, @@ -408,7 +408,7 @@ bool EmscriptenApplication::tryCreate(const Configuration& configuration, const /* Get the canvas ID from Module.canvas, either set by EmscriptenApplication.js or overridden/manually set by the user. */ - _canvasTarget = (_deprecatedTargetBehavior ? "" : "#") + canvasId(); + _canvasTarget = (_deprecatedTargetBehavior ? canvasId() : "#"_s + canvasId()); /* Get CSS canvas size and cache it. This is used later to detect canvas resizes in emscripten_set_resize_callback() and fire viewport events, @@ -469,23 +469,27 @@ Vector2i EmscriptenApplication::framebufferSize() const { } #endif -void EmscriptenApplication::setWindowTitle(const std::string& title) { +void EmscriptenApplication::setWindowTitle(const Containers::StringView title) { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdollar-in-identifier-extension" - EM_ASM_({document.title = UTF8ToString($0);}, title.data()); + EM_ASM_({document.title = UTF8ToString($0, $1);}, title.data(), title.size()); #pragma GCC diagnostic pop } -void EmscriptenApplication::setContainerCssClass(const std::string& cssClass) { +void EmscriptenApplication::setContainerCssClass(const Containers::StringView cssClass) { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdollar-in-identifier-extension" EM_ASM_({ /* Handle also the classic #container for backwards compatibility. We also need to preserve the mn-container otherwise next time we'd have - no way to look for it anymore. */ + no way to look for it anymore. + + Using UTF8ToString() instead of AsciiToString() as it has an + explicit size parameter and thus doesn't need a null-terminated + input, which would potentially require yet another allocation. */ (Module['canvas'].closest('.mn-container') || - document.getElementById('container')).className = (['mn-container', AsciiToString($0)]).join(' '); - }, cssClass.data()); + document.getElementById('container')).className = (['mn-container', UTF8ToString($0, $1)]).join(' '); + }, cssClass.data(), cssClass.size()); #pragma GCC diagnostic pop /* Trigger a potential viewport event -- we don't poll the canvas size like @@ -605,17 +609,15 @@ void EmscriptenApplication::setupCallbacks(bool resizable) { })); #pragma GCC diagnostic pop - std::string keyboardListeningElementString; + Containers::String keyboardListeningElementStorage; if(keyboardListeningElement == EMSCRIPTEN_EVENT_TARGET_DOCUMENT) { keyboardListeningElement = _deprecatedTargetBehavior ? "#document" : keyboardListeningElement; } else if(keyboardListeningElement == EMSCRIPTEN_EVENT_TARGET_WINDOW) { keyboardListeningElement = _deprecatedTargetBehavior ? "#window" : keyboardListeningElement; - } else if(keyboardListeningElement) { - if(!_deprecatedTargetBehavior) - keyboardListeningElementString = "#"; - keyboardListeningElementString += keyboardListeningElement; + } else if(keyboardListeningElement && !_deprecatedTargetBehavior) { + keyboardListeningElementStorage = "#"_s + Containers::StringView{keyboardListeningElement}; std::free(const_cast(keyboardListeningElement)); - keyboardListeningElement = keyboardListeningElementString.data(); + keyboardListeningElement = keyboardListeningElementStorage.data(); } /* Happens only if keyboardListeningElement was set, but did not have an @@ -918,7 +920,7 @@ Key EmscriptenApplication::KeyEvent::key() const { return toKey(_event.key, _event.code); } -std::string EmscriptenApplication::KeyEvent::keyName() const { +Containers::StringView EmscriptenApplication::KeyEvent::keyName() const { if((_event.key[0] >= 'a' && _event.key[0] <= 'z') || (_event.key[0] >= 'A' && _event.key[0] <= 'Z')) return _event.key; diff --git a/src/Magnum/Platform/EmscriptenApplication.h b/src/Magnum/Platform/EmscriptenApplication.h index dd5f307e4..18d2488af 100644 --- a/src/Magnum/Platform/EmscriptenApplication.h +++ b/src/Magnum/Platform/EmscriptenApplication.h @@ -34,12 +34,11 @@ */ #endif -#include #include - /* Needed by the MAGNUM_EMSCRIPTENAPPLICATION_MAIN() macro */ /** @todo use an Optional */ #include +#include /** @todo PIMPL Configuration instead? */ #include "Magnum/Magnum.h" #include "Magnum/Tags.h" @@ -52,6 +51,11 @@ #include "Magnum/Platform/GLContext.h" #endif +#ifdef MAGNUM_BUILD_DEPRECATED +/* Some APIs used to take or return a std::string before */ +#include +#endif + #if defined(CORRADE_TARGET_EMSCRIPTEN) || defined(DOXYGEN_GENERATING_OUTPUT) #ifndef DOXYGEN_GENERATING_OUTPUT @@ -521,7 +525,7 @@ class EmscriptenApplication { * * The @p title is expected to be encoded in UTF-8. */ - void setWindowTitle(const std::string& title); + void setWindowTitle(Containers::StringView title); /** * @brief Set container CSS class @@ -542,7 +546,7 @@ class EmscriptenApplication { * @cb{.html}
@ce is not found. This * compatibility is scheduled to be removed in the future. */ - void setContainerCssClass(const std::string& cssClass); + void setContainerCssClass(Containers::StringView cssClass); /** * @brief Swap buffers @@ -906,7 +910,7 @@ class EmscriptenApplication { Cursor _cursor; bool _deprecatedTargetBehavior{}; - std::string _canvasTarget; + Containers::String _canvasTarget; #ifdef MAGNUM_TARGET_GL EMSCRIPTEN_WEBGL_CONTEXT_HANDLE _glContext{}; @@ -1845,8 +1849,14 @@ class EmscriptenApplication::KeyEvent: public EmscriptenApplication::InputEvent */ Key key() const; - /** @brief Key name */ - std::string keyName() const; + /** + * @brief Key name + * + * The returned view is always + * @relativeref{Corrade,Containers::StringViewFlag::NullTerminated} and + * is valid until the event is destroyed. + */ + Containers::StringView keyName() const; /** @brief Modifiers */ Modifiers modifiers() const; diff --git a/src/Magnum/Platform/Test/EmscriptenApplicationTest.cpp b/src/Magnum/Platform/Test/EmscriptenApplicationTest.cpp index f78cb01b6..dcf466ee9 100644 --- a/src/Magnum/Platform/Test/EmscriptenApplicationTest.cpp +++ b/src/Magnum/Platform/Test/EmscriptenApplicationTest.cpp @@ -36,6 +36,7 @@ namespace Magnum { namespace Platform { namespace Test { +using namespace Containers::Literals; using namespace Math::Literals; struct EmscriptenApplicationTest: Platform::Application { @@ -108,10 +109,10 @@ struct EmscriptenApplicationTest: Platform::Application { stopTextInput(); } else if(event.key() == KeyEvent::Key::F) { Debug{} << "toggling fullscreen"; - setContainerCssClass((_fullscreen ^= true) ? "mn-fullsize" : ""); + setContainerCssClass((_fullscreen ^= true) ? "mn-fullsizeX"_s.exceptSuffix(1) : ""); } else if(event.key() == KeyEvent::Key::T) { Debug{} << "setting window title"; - setWindowTitle("This is a UTF-8 Window Title™!"); + setWindowTitle("This is a UTF-8 Window Title™ and it should have no exclamation mark!!"_s.exceptSuffix(2)); } else if(event.key() == KeyEvent::Key::H) { Debug{} << "toggling hand cursor"; setCursor(cursor() == Cursor::Arrow ? Cursor::Hand : Cursor::Arrow);