Проблема: Существует метод с соответствующим тестовым сценарием, который работает на одной машине и не работает с другой (подробнее см. Ниже). Я предполагаю, что что-то не так с кодом, заставляя его работать случайно на одной машине. К сожалению, я не могу найти проблему.
Обратите внимание, что использование кодировок std::string и utf-8 - это требования, на которые я не влияю. Использование С++-методов было бы вполне нормально, но, к сожалению, я ничего не нашел. Следовательно, использование С-функций.
Метод:
std::string firstCharToUpperUtf8(const string& orig) {
std::string retVal;
retVal.reserve(orig.size());
std::mbstate_t state = std::mbstate_t();
char buf[MB_CUR_MAX + 1];
size_t i = 0;
if (orig.size() > 0) {
if (orig[i] > 0) {
retVal += toupper(orig[i]);
++i;
} else {
wchar_t wChar;
int len = mbrtowc(&wChar, &orig[i], MB_CUR_MAX, &state);
// If this assertion fails, there is an invalid multi-byte character.
// However, this usually means that the locale is not utf8.
// Note that the default locale is always C. Main classes need to set them
// To utf8, even if the system default is utf8 already.
assert(len > 0 && len <= static_cast<int>(MB_CUR_MAX));
i += len;
int ret = wcrtomb(buf, towupper(wChar), &state);
assert(ret > 0 && ret <= static_cast<int>(MB_CUR_MAX));
buf[ret] = 0;
retVal += buf;
}
}
for (; i < orig.size(); ++i) {
retVal += orig[i];
}
return retVal;
}
Тест:
TEST(StringUtilsTest, firstCharToUpperUtf8) {
setlocale(LC_CTYPE, "en_US.utf8");
ASSERT_EQ("Foo", firstCharToUpperUtf8("foo"));
ASSERT_EQ("Foo", firstCharToUpperUtf8("Foo"));
ASSERT_EQ("#foo", firstCharToUpperUtf8("#foo"));
ASSERT_EQ("ßfoo", firstCharToUpperUtf8("ßfoo"));
ASSERT_EQ("Éfoo", firstCharToUpperUtf8("éfoo"));
ASSERT_EQ("Éfoo", firstCharToUpperUtf8("Éfoo"));
}
Неудавшийся тест (происходит только на одной из двух машин):
Failure
Value of: firstCharToUpperUtf8("ßfoo")
Actual: "\xE1\xBA\x9E" "foo"
Expected: "ßfoo"
На обеих машинах установлена локаль en_US.utf8. Однако они используют разные версии libc. Он работает на машине с GLIBC_2.14 независимо от того, где она была скомпилирована и не работает на другой машине, тогда как ее можно скомпилировать только там, потому что в противном случае она не имеет надлежащей версии libc.
В любом случае, есть машина, которая компилирует этот код и запускает его, пока он терпит неудачу. Что-то не так с кодом, и мне интересно, что. Указание на методы С++ (в частности, STL) также будет отличным. Boost и другие библиотеки следует избегать из-за других внешних требований.