Jump to content
    

Преобразовать UTF-16 в CP-866

Потребовалось мне из UTF-16 конвертнуть строку в CP-866 (https://www.ascii-codes.com/cp866.html).

С первой половиной ascii-кодов, вроде, проблем не должно возникнуть, т.к. их числовые значения будут сопоставимы с кодами в UTF-16 (за ислкючением занимаемой памяти в расчете на 1 символ).

Но вот просмотрел список символов в Unicode-таблице, сопоставимых с соответствующей частью в CP-866 и... кто в лес, кто по дрова. Какие-то ряды букв идут подряд, какие-то идут в разрыв уже. Т.е. банальным арифметическим преобразованием (смещением некого числа) не обойтись. Да и табличный метод не особо применить. Не уж то плодить кучу if(), или я чего-то не замечаю и все не так страшно?

Share this post


Link to post
Share on other sites

Оба алфавита вполне себе отсекаются простыми преобразованиями, отдельно Ё, ё, №, °, ·, далее ничего интересного, но если надо, есть стандартный способ — поиск в таблице.

Share this post


Link to post
Share on other sites

34 минуты назад, andrew_b сказал:

Видимо мне стоило написать, что меня интересует исходный код:biggrin: Мне в микроконтроллер надо это прикрутить.

Ладно, утром почитал получше об этих форматах, мне проще вручную Солнце закатить.

Share this post


Link to post
Share on other sites

Думаю задача не так проста как кажется. Исходники нужно искать в OpenSource библиотеках. Явно это решённый вопрос. Хотя можно и тиблицу на 64 к запилить 🙂

Share this post


Link to post
Share on other sites

14 минут назад, MegaVolt сказал:

Думаю задача не так проста как кажется. Исходники нужно искать в OpenSource библиотеках. Явно это решённый вопрос. Хотя можно и тиблицу на 64 к запилить 🙂

Для общего случая не получится сделать таблицу на 64к, т.к. по описанию:

Цитата

 

UTF-16 (англ. Unicode Transformation Format) в информатике — один из способов кодирования символов из Юникода в виде последовательности 16-битных слов.

Данная кодировка позволяет записывать символы Юникода в диапазонах U+0000..U+D7FF и U+E000..U+10FFFF (общим количеством 1 112 064). При этом каждый символ записывается одним или двумя словами (последнее называется суррогатная пара). Кодировка UTF-16 описана в приложении Q к международному стандарту ISO/IEC 10646, а также ей посвящён IETF RFC 2781 «UTF-16, an encoding of ISO 10646».

 

Обратите внимание на выделенное.

Share this post


Link to post
Share on other sites

3 часа назад, Arlleex сказал:

Мне в микроконтроллер надо это прикрутить.

А что именно должен делать микроконтроллер? Мне на днях нужно было выводить на графический экран русские/английские сообщения из исходника, набранного в UTF-8. Преобразование UTF8->char16_t заняло 10 строк исходника и знакогенератор на 4 диапазона (как написал Plain) : U0020-U007F (ASCII), U0410-U044F (А-я), U0401 (Ё), U0451 (ё). Да, я не обрабатываю ошибки и всякие тонкости, потому что строковые литералы в моем исходнике не содержат запрещенных комбинаций и символов со всякими умляутами по определению. Может в вашей задаче тоже можно обойтись чем-то подобным, может вам не нужны прям все-все символы CP866?

Share this post


Link to post
Share on other sites

Все символы, может, и не нужны... Но парсить придется честно (с обработкой ошибок), так как символы летят по каналу связи без проверки фреймов на валидность...

МК должен принять строку в унифицированном формате, перекодировать в CP-866 и отправить получившееся в ModBus RTU (строка вывода, табло). На той же шине ModBus висит еще и другая строка, но она уже понимает UTF16.

Share this post


Link to post
Share on other sites

18 минут назад, Arlleex сказал:

Все символы, может, и не нужны...

А какие именно нужны символы? От этого зависит сложность.

Если только кириллица, то в чём сложность? Там со всеми проверками код немного больше пары десятков строчек.

Вот участок код парсера потока входных символов для кода МК, работающего с эмулятором терминала (типа Putty) в режиме UTF-8 из моего проекта на МК (участок как раз парсит UTF-8):

  static s32 arg;
  static u32 timeEsc;
  static u8 state = S_INIT;
  static u8 cnt;
  uint c, j;
...
        if (PARSE_UTF8_DEF && (c & B7)) {
          //преобразование UTF-8 в Win1251
          u32 cc = (u32)c << 25;
          if (j = CntLeadingZeros(~cc)) {
            if (j > 5 || state != S_NONE) return HEsc_ERROR;
            cnt = j;
            j += 26;
            arg = c << j >> j;
            state = S_UTF8;
          } else {
            if (state != S_UTF8) return HEsc_ERROR;
            arg = arg << 6 | cc >> 25;
            if (--cnt) continue;
            c = (cc = arg - 0x410) + 0xC0;
            if (cc > (uint)'я' - (uint)'А') {
              c = 'Ё';
              if (cc += 0x410u - 0x401u) {
                c = 'ё';
                if (cc += 0x401u - 0x451u) return HEsc_SKIP;
              }
            }
            state = S_INIT;
            return (HEsc)c;
          }
        } else if ((c & 0x7F) == 0x1B) {
...          

Все проверки на допустимость каждого байта вроде как имеются. При ошибках - возврат HEsc_ERROR, для ненужных (неподдерживаемых кодов) - HEsc_SKIP.

Вы больше все сообщения темы придумывали, чем кода тут.  :wink:

Только у меня преобразование в WIN1251, а не CP866.

Share this post


Link to post
Share on other sites

1 minute ago, jcxz said:

в режиме UTF-8 из моего проекта на МК

UTF-8 != UTF-16

 

Share this post


Link to post
Share on other sites

6 minutes ago, andrew_b said:

UTF-8 != UTF-16

Так это только способ упаковки уникода, я так понимаю. Правила распаковки символа только поменять.

Share this post


Link to post
Share on other sites

29 минут назад, andrew_b сказал:

UTF-8 != UTF-16

И что? UTF-16 парсить должно быть ещё проще, чем UTF-8.

21 минуту назад, kochevkv сказал:
  27 минут назад, andrew_b сказал:

Так это только способ упаковки уникода, я так понимаю.

Именно так.

Share this post


Link to post
Share on other sites

42 minutes ago, jcxz said:

И что? UTF-16 парсить должно быть ещё проще, чем UTF-8.

Да, я про замечание что они отличаются. Суть одна и код можно легко подогнать под UTF-16 если надо. Я бы просто таблицу u16 unicodeCp866[256] сделал если память позволяет. Самое простое и быстрое. И таблицу switch case обратно

Edited by kochevkv

Share this post


Link to post
Share on other sites

2 минуты назад, kochevkv сказал:

Да, я про замечание что они отличаются. Суть одна и код можно легко подогнать под UTF-16 если надо. Я бы просто таблицу u16 unicodeCp866[256] сделал если память позволяет. Самое простое и быстрое.

Вы в суть кодирования UTF-16 вникали? Не получится там так в лоб завести одну табличку на 256 значений.

1 час назад, jcxz сказал:

А какие именно нужны символы? От этого зависит сложность.

Если только кириллица, то в чём сложность? Там со всеми проверками код немного больше пары десятков строчек.

Кириллица + стандартный ASCII (коды 0...127), с возможностью отбраковки некорректно закодированных символов (по крайней мере, отсутствующих в CP-866).

Цитата

Вот участок код парсера потока входных символов для кода МК, работающего с эмулятором терминала (типа Putty) в режиме UTF-8 из моего проекта на МК (участок как раз парсит UTF-8):

Мне сначала прилетает поток байтов, которые (якобы) в UTF-16. Канал потенциально не надежный, т.е. мне надо каждый символ парсить на валидность в том числе, т.е. таблицу быстрого поиска организовать не достаточно.

В целом, я уже разобрался с UTF-16.

Share this post


Link to post
Share on other sites

8 minutes ago, Arlleex said:

Вы в суть кодирования UTF-16 вникали? Не получится там так в лоб завести одну табличку на 256 значений.

Из уникода в cp866 switch case. Насколько я помню, кириллица в уникоде в u16 умещается. Если там есть u32 значения то будет таблица  u32 unicodeCp866[256] и аналогично 256 case'ов

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...