diff options
author | Noel Grandin <noelgrandin@gmail.com> | 2021-07-18 10:07:57 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2021-07-19 08:54:40 +0200 |
commit | 7712eb23bc97090fdd655a36dfca0019d43799e6 (patch) | |
tree | edb6a035ecad3a05f15ac44caa81a517dae594f4 | |
parent | 4408001f5c0a76107d8fe01053a0e6348100a878 (diff) |
tdf#143409: fix Translation is not applied in some UI
regression from
commit 0771ac00acc8730f77db76b901724f1513a32723
Author: Noel Grandin <noel@peralex.com>
Date: Tue Jun 15 21:12:25 2021 +0200
use string_view in the Translate API
Because I mixed string_view with C-style null-terminated
strings.
We are using string_view.data() to pass stuff to boost,
but of course, doing that loses the fact that the string data
has associated length, as it finds the length by looking for
a terminating NULL.
Change-Id: Ia0eb7be5621506dfe0a40a21f360da1b446f5591
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/119120
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
-rw-r--r-- | unotools/source/i18n/resmgr.cxx | 43 |
1 files changed, 33 insertions, 10 deletions
diff --git a/unotools/source/i18n/resmgr.cxx b/unotools/source/i18n/resmgr.cxx index cdca420e2636..d35282025c4e 100644 --- a/unotools/source/i18n/resmgr.cxx +++ b/unotools/source/i18n/resmgr.cxx @@ -48,6 +48,7 @@ #include <boost/locale.hpp> #include <boost/locale/gnu_gettext.hpp> +#include <array> #include <unordered_map> #include <memory> @@ -199,27 +200,49 @@ namespace Translate OUString get(std::string_view sContextAndId, const std::locale &loc) { - std::string_view sContext; - std::string_view sId; - const char *p = strchr(sContextAndId.data(), '\004'); - if (!p) - sId = sContextAndId; + constexpr int BUFLEN = 128; + // this function is performance-sensitive, so we allocate string data on stack + std::array<char, BUFLEN> sStackBuffer; + std::unique_ptr<char[]> xHeapBuffer; + char* pBuffer; + if (sContextAndId.size() < BUFLEN - 1) + pBuffer = sStackBuffer.data(); else { - sContext = std::string_view(sContextAndId.data(), p - sContextAndId.data()); - sId = sContextAndId.substr(p - sContextAndId.data() + 1); - assert(!strchr(sId.data(), '\004') && "should be using nget, not get"); + xHeapBuffer = std::make_unique<char[]>(sContextAndId.size()+1); + pBuffer = xHeapBuffer.get(); + } + + const char* pContext; + const char* pId; + auto idx = sContextAndId.find('\004'); + memcpy(pBuffer, sContextAndId.data(), sContextAndId.size()); + if (idx == std::string_view::npos) + { + pBuffer[sContextAndId.size()] = 0; + // point pContext at the null byte so it is an empty string + pContext = pBuffer + sContextAndId.size(); + pId = pBuffer; + } + else + { + // stick a null byte in the middle to split it into two null-terminated strings + pBuffer[idx] = 0; + pBuffer[sContextAndId.size()] = 0; + pContext = pBuffer; + pId = pBuffer + idx + 1; + assert(!strchr(pId, '\004') && "should be using nget, not get"); } //if it's a key id locale, generate it here if (std::use_facet<boost::locale::info>(loc).language() == "qtz") { OString sKeyId(genKeyId(OString(sContextAndId).replace('\004', '|'))); - return OUString::fromUtf8(sKeyId) + u"\u2016" + createFromUtf8(sId.data(), sId.size()); + return OUString::fromUtf8(sKeyId) + u"\u2016" + createFromUtf8(pId, strlen(pId)); } //otherwise translate it - const std::string ret = boost::locale::pgettext(sContext.data(), sId.data(), loc); + const std::string ret = boost::locale::pgettext(pContext, pId, loc); OUString result(ExpandVariables(createFromUtf8(ret.data(), ret.size()))); if (comphelper::LibreOfficeKit::isActive()) |