Перевести текст из UTF8 в CP1251

vegas

Известный
Автор темы
640
445
Я получаю сообщения из телеграмм чата с ботом, и как бы все хорошо но пока не начну отправлять русские символы ибо они превращаются вот в это "\u041f\u0440\u0438\u0432\u0435\u0442"(Это слово "Привет"). Как мне перевести этот текст как я понял из формата UTF8 в CP1251? Много каких-то функций с разных форумов попробовал но не одна не помогла :P
 
Решение
Причем тут это, проблема в том что при входе Английской буквы в твою функцию cp_to_utf8 игра крашит
Сказал бы сразу

C++:
#include <string>
#include <vector>
#include <regex>
#include <charconv>

std::vector<std::string> split(const std::string& str, const std::string& delim) {
    std::vector<std::string> strings;
    size_t start;
    size_t end = 0;
    while ((start = str.find_first_not_of(delim, end)) != std::string::npos) {
        end = str.find(delim, start);
        strings.push_back(str.substr(start, end - start));
    }
    return strings;
}

std::uint32_t utf8_encode(char* out, uint32_t utf)
{
    if (utf <= 0x7F) {
        // Plain ASCII
        out[0] = (char)utf;
        out[1] = 0;
        return 1;
    }
    else...

kin4stat

mq-team · kin4@naebalovo.team
Всефорумный модератор
2,731
4,720
Я получаю сообщения из телеграмм чата с ботом, и как бы все хорошо но пока не начну отправлять русские символы ибо они превращаются вот в это "\u041f\u0440\u0438\u0432\u0435\u0442"(Это слово "Привет"). Как мне перевести этот текст как я понял из формата UTF8 в CP1251? Много каких-то функций с разных форумов попробовал но не одна не помогла :P
использовать UTF-8 IO, и будет тебе счастье
 

kin4stat

mq-team · kin4@naebalovo.team
Всефорумный модератор
2,731
4,720
Причем тут это, проблема в том что при входе Английской буквы в твою функцию cp_to_utf8 игра крашит
Сказал бы сразу

C++:
#include <string>
#include <vector>
#include <regex>
#include <charconv>

std::vector<std::string> split(const std::string& str, const std::string& delim) {
    std::vector<std::string> strings;
    size_t start;
    size_t end = 0;
    while ((start = str.find_first_not_of(delim, end)) != std::string::npos) {
        end = str.find(delim, start);
        strings.push_back(str.substr(start, end - start));
    }
    return strings;
}

std::uint32_t utf8_encode(char* out, uint32_t utf)
{
    if (utf <= 0x7F) {
        // Plain ASCII
        out[0] = (char)utf;
        out[1] = 0;
        return 1;
    }
    else if (utf <= 0x07FF) {
        // 2-byte unicode
        out[0] = (char)(((utf >> 6) & 0x1F) | 0xC0);
        out[1] = (char)(((utf >> 0) & 0x3F) | 0x80);
        out[2] = 0;
        return 2;
    }
    else if (utf <= 0xFFFF) {
        // 3-byte unicode
        out[0] = (char)(((utf >> 12) & 0x0F) | 0xE0);
        out[1] = (char)(((utf >> 6) & 0x3F) | 0x80);
        out[2] = (char)(((utf >> 0) & 0x3F) | 0x80);
        out[3] = 0;
        return 3;
    }
    else if (utf <= 0x10FFFF) {
        // 4-byte unicode
        out[0] = (char)(((utf >> 18) & 0x07) | 0xF0);
        out[1] = (char)(((utf >> 12) & 0x3F) | 0x80);
        out[2] = (char)(((utf >> 6) & 0x3F) | 0x80);
        out[3] = (char)(((utf >> 0) & 0x3F) | 0x80);
        out[4] = 0;
        return 4;
    }
    else {
        // error - use replacement character
        out[0] = (char)0xEF;
        out[1] = (char)0xBF;
        out[2] = (char)0xBD;
        out[3] = 0;
        return 0;
    }
}

std::string cp_to_utf8(const std::string& input) {
    std::string out;

    std::regex re(R"((?:(?:\\\\)|(?:\\[uU](?:[0-9a-fA-F]{8}|[0-9a-fA-F]{4})))|(?:.))");
    std::regex_token_iterator it(input.cbegin(), input.cend(), re);
    decltype(it) end;

    for (; it != end; ++it) {
        auto ms = it->str();
        if (ms.rfind("\\u") == 0 ||
            ms.rfind("\\U") == 0) {
            auto s = ms.substr(2);
            unsigned int value;
            auto [ptr, err] = std::from_chars(s.c_str(), s.c_str() + s.size(), value, 16);
            if (err == std::errc()) {
                char buf[8];
                auto len = utf8_encode(buf, value);
                if (!len) {
                    throw std::invalid_argument{ "Invalid unicode codepoint 0x"s + hex };
                }
                out.append(std::string{ buf, len });
            }
            else if (err == std::errc::invalid_argument)
            {
                throw std::invalid_argument{ s };
            }
            else if (err == std::errc::result_out_of_range)
            {
                throw std::out_of_range{ s };
            }
        }
        else {
            out.append(ms);
        }
    }
    return out;
}
same shit без регулярок:

C++:
#include <string>
#include <vector>
#include <charconv>
#include <stdexcept>

std::vector<std::string> split(const std::string& str, const std::string& delim) {
    std::vector<std::string> strings;
    size_t start;
    size_t end = 0;
    while ((start = str.find_first_not_of(delim, end)) != std::string::npos) {
        end = str.find(delim, start);
        strings.push_back(str.substr(start, end - start));
    }
    return strings;
}

std::uint32_t utf8_encode(char* out, uint32_t utf)
{
    if (utf <= 0x7F) {
        // Plain ASCII
        out[0] = (char)utf;
        out[1] = 0;
        return 1;
    }
    else if (utf <= 0x07FF) {
        // 2-byte unicode
        out[0] = (char)(((utf >> 6) & 0x1F) | 0xC0);
        out[1] = (char)(((utf >> 0) & 0x3F) | 0x80);
        out[2] = 0;
        return 2;
    }
    else if (utf <= 0xFFFF) {
        // 3-byte unicode
        out[0] = (char)(((utf >> 12) & 0x0F) | 0xE0);
        out[1] = (char)(((utf >> 6) & 0x3F) | 0x80);
        out[2] = (char)(((utf >> 0) & 0x3F) | 0x80);
        out[3] = 0;
        return 3;
    }
    else if (utf <= 0x10FFFF) {
        // 4-byte unicode
        out[0] = (char)(((utf >> 18) & 0x07) | 0xF0);
        out[1] = (char)(((utf >> 12) & 0x3F) | 0x80);
        out[2] = (char)(((utf >> 6) & 0x3F) | 0x80);
        out[3] = (char)(((utf >> 0) & 0x3F) | 0x80);
        out[4] = 0;
        return 4;
    }
    else {
        // error - use replacement character
        out[0] = (char)0xEF;
        out[1] = (char)0xBF;
        out[2] = (char)0xBD;
        out[3] = 0;
        return 0;
    }
}

std::string cp_to_utf8(const std::string& input) {
    using namespace std::string_literals;

    std::string out;

    for (auto i = 0u; i < input.size(); i++) {
        std::string hex{};
        auto first_two = input.substr(i, 2);
        if (first_two == u8"\\u") {
            hex = input.substr(i + 2, 4);
        }
        else if (first_two == u8"\\U") {
            hex = input.substr(i + 2, 4);
        }
        if (!hex.empty()) {
          
            unsigned int value;
            auto [ptr, err] = std::from_chars(hex.c_str(), hex.c_str() + hex.size(), value, 16);
            if (err == std::errc()) {
                char buf[8];
                auto len = utf8_encode(buf, value);
                out.append(std::string{ buf, len });
            }
            else if (err == std::errc::invalid_argument)
            {
                throw std::invalid_argument{ "Bad unicode escape: "s + first_two + hex};
            }
            i += ptr - hex.c_str() + 1;
        }
        else {
            unsigned char c = input[i];
            int n;
            if ((c & 0x80) == 0)    n = 1;
            else if ((c & 0xE0) == 0xC0) n = 2;
            else if ((c & 0xF0) == 0xE0) n = 3;
            else if ((c & 0xF8) == 0xF0) n = 4;

            if (input.size() - i < n) {
                throw std::invalid_argument{ "Invalid utf-8 string" };
            }
            for (unsigned int k = i + 1; k < i + n; ++k) {
                if ((input[k] & 0xC0) != 0x80) {
                    throw std::runtime_error("Expected continuation byte at "s + std::to_string(i));
                }
            }
            out += input.substr(i, n);
            i += n - 1;
        }
    }
    return out;
}
Ну и тест:

C++:
#include <iostream>

int main() {

    setlocale(LC_ALL, "en_US.utf8");

    std::string input = u8R"(КекЛолPizda\u041f\u0440\u0438\u0432\u0435\u0442)";

    std::cout << cp_to_utf8(input) << std::endl;
}
 
Последнее редактирование:
  • Нравится
Реакции: F0RQU1N and и vegas

vegas

Известный
Автор темы
640
445

zTechnology

Известный
1,101
485
Я получаю сообщения из телеграмм чата с ботом, и как бы все хорошо но пока не начну отправлять русские символы ибо они превращаются вот в это "\u041f\u0440\u0438\u0432\u0435\u0442"(Это слово "Привет"). Как мне перевести этот текст как я понял из формата UTF8 в CP1251? Много каких-то функций с разных форумов попробовал но не одна не помогла :P
C++:
std::string UTF8_to_CP1251(std::string const & utf8)
{
    if(!utf8.empty())
    {
        int wchlen = MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), utf8.size(), NULL, 0);
        if(wchlen > 0 && wchlen != 0xFFFD)
        {
            std::vector<wchar_t> wbuf(wchlen);
            MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), utf8.size(), &wbuf[0], wchlen);
            std::vector<char> buf(wchlen);
            WideCharToMultiByte(1251, 0, &wbuf[0], wchlen, &buf[0], wchlen, 0, 0);
 
            return std::string(&buf[0], wchlen);
        }
    }
    return std::string();
}
credits: https://www.cyberforum.ru/cpp-beginners/thread1249547.html
никогда не поздно научиться гуглить
 

vegas

Известный
Автор темы
640
445
C++:
std::string UTF8_to_CP1251(std::string const & utf8)
{
    if(!utf8.empty())
    {
        int wchlen = MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), utf8.size(), NULL, 0);
        if(wchlen > 0 && wchlen != 0xFFFD)
        {
            std::vector<wchar_t> wbuf(wchlen);
            MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), utf8.size(), &wbuf[0], wchlen);
            std::vector<char> buf(wchlen);
            WideCharToMultiByte(1251, 0, &wbuf[0], wchlen, &buf[0], wchlen, 0, 0);
 
            return std::string(&buf[0], wchlen);
        }
    }
    return std::string();
}
credits: https://www.cyberforum.ru/cpp-beginners/thread1249547.html
никогда не поздно научиться гуглить
C++:
regex_search(response.c_str(), res, regex("\"text\":\"(.+)\""));
string message = res[1];

SF->Log("\u041f\u0440\u0438\u0432\u0435\u0442");
SF->Log(res[1]);
SF->Log(UTF8_to_CP1251(res[1]));

1646474835936.png

Ничего не изменилось
 

vegas

Известный
Автор темы
640
445

zTechnology

Известный
1,101
485
у меня тоже самое что и у тебя. Только не работает скорее всего из-за того что я хочу изменить текст который получаю из вне плагина, а не указываю изначально где-то
напиши в вк/кинь под хайд полный код получения, попробую сделать готовый вариант для тебя