#include "string.h" #include <util/string/ascii.h> #include <util/system/sanitizers.h> #include <util/system/sys_alloc.h> #include <util/charset/wide.h> #include <iostream> alignas(32) const char NULL_STRING_REPR[128] = {0}; std::ostream& operator<<(std::ostream& os, const TString& s) { return os.write(s.data(), s.size()); } std::istream& operator>>(std::istream& is, TString& s) { return is >> s.MutRef(); } template <> bool TBasicString<char, std::char_traits<char>>::to_lower(size_t pos, size_t n) { return Transform([](size_t, char c) { return AsciiToLower(c); }, pos, n); } template <> bool TBasicString<char, std::char_traits<char>>::to_upper(size_t pos, size_t n) { return Transform([](size_t, char c) { return AsciiToUpper(c); }, pos, n); } template <> bool TBasicString<char, std::char_traits<char>>::to_title(size_t pos, size_t n) { if (n == 0) { return false; } bool changed = to_upper(pos, 1); return to_lower(pos + 1, n - 1) || changed; } template <> TUtf16String& TBasicString<wchar16, std::char_traits<wchar16>>::AppendAscii(const ::TStringBuf& s) { ReserveAndResize(size() + s.size()); auto dst = begin() + size() - s.size(); for (const char* src = s.data(); dst != end(); ++dst, ++src) { *dst = static_cast<wchar16>(*src); } return *this; } template <> TUtf16String& TBasicString<wchar16, std::char_traits<wchar16>>::AppendUtf8(const ::TStringBuf& s) { size_t oldSize = size(); ReserveAndResize(size() + s.size() * 4); size_t written = 0; size_t pos = UTF8ToWideImpl(s.data(), s.size(), begin() + oldSize, written); if (pos != s.size()) { ythrow yexception() << "failed to decode UTF-8 string at pos " << pos << ::NDetail::InStringMsg(s.data(), s.size()); } resize(oldSize + written); return *this; } template <> bool TBasicString<wchar16, std::char_traits<wchar16>>::to_lower(size_t pos, size_t n) { return ToLower(*this, pos, n); } template <> bool TBasicString<wchar16, std::char_traits<wchar16>>::to_upper(size_t pos, size_t n) { return ToUpper(*this, pos, n); } template <> bool TBasicString<wchar16, std::char_traits<wchar16>>::to_title(size_t pos, size_t n) { return ToTitle(*this, pos, n); } template <> TUtf32String& TBasicString<wchar32, std::char_traits<wchar32>>::AppendAscii(const ::TStringBuf& s) { ReserveAndResize(size() + s.size()); auto dst = begin() + size() - s.size(); for (const char* src = s.data(); dst != end(); ++dst, ++src) { *dst = static_cast<wchar32>(*src); } return *this; } template <> TBasicString<char, std::char_traits<char>>& TBasicString<char, std::char_traits<char>>::AppendUtf16(const ::TWtringBuf& s) { const size_t oldSize = size(); ReserveAndResize(size() + WideToUTF8BufferSize(s.size())); size_t written = 0; WideToUTF8(s.data(), s.size(), begin() + oldSize, written); resize(oldSize + written); return *this; } template <> TUtf32String& TBasicString<wchar32, std::char_traits<wchar32>>::AppendUtf8(const ::TStringBuf& s) { size_t oldSize = size(); ReserveAndResize(size() + s.size() * 4); size_t written = 0; size_t pos = UTF8ToWideImpl(s.data(), s.size(), begin() + oldSize, written); if (pos != s.size()) { ythrow yexception() << "failed to decode UTF-8 string at pos " << pos << ::NDetail::InStringMsg(s.data(), s.size()); } resize(oldSize + written); return *this; } template <> TUtf32String& TBasicString<wchar32, std::char_traits<wchar32>>::AppendUtf16(const ::TWtringBuf& s) { size_t oldSize = size(); ReserveAndResize(size() + s.size() * 2); wchar32* oldEnd = begin() + oldSize; wchar32* end = oldEnd; NDetail::UTF16ToUTF32ImplScalar(s.data(), s.data() + s.size(), end); size_t written = end - oldEnd; resize(oldSize + written); return *this; } template <> bool TBasicString<wchar32, std::char_traits<wchar32>>::to_lower(size_t pos, size_t n) { return ToLower(*this, pos, n); } template <> bool TBasicString<wchar32, std::char_traits<wchar32>>::to_upper(size_t pos, size_t n) { return ToUpper(*this, pos, n); } template <> bool TBasicString<wchar32, std::char_traits<wchar32>>::to_title(size_t pos, size_t n) { return ToTitle(*this, pos, n); }