jcxz 245 23 октября Опубликовано 23 октября · Жалоба 17 минут назад, Arlleex сказал: Кириллица + стандартный ASCII (коды 0...127), с возможностью отбраковки некорректно закодированных символов (по крайней мере, отсутствующих в CP-866). У меня - аналогично. Только ->Win1251. 17 минут назад, Arlleex сказал: Мне сначала прилетает поток байтов, которые (якобы) в UTF-16. Канал потенциально не надежный, т.е. мне надо каждый символ парсить на валидность в том числе, т.е. таблицу быстрого поиска организовать не достаточно. У меня всё то же самое. Тоже ненадёжный и тоже - полная проверка с отбраковкой. Только UTF-8 и Win1251. И плюс ещё - у меня ещё и ESC-коды ходят по этому каналу. И парсер и их парсит (те участки я вырезал). Этот парсер использую во многих проектах. Везде, где у меня управление/конфигурирование сделано через Putty-подобные терминалы. Т.е. - проверен многократно. 6 минут назад, kochevkv сказал: Насколько я помню, кириллица в уникоде в u16 умещается. UTF-8, UTF-16 - это просто разные способы упаковки Unicode-символов. А у Unicode кириллица занимает вполне определённый диапазон кодов. И ей достаточно 16 бит. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 190 28 октября Опубликовано 28 октября · Жалоба В 22.10.2024 в 22:07, Arlleex сказал: Но вот просмотрел список символов в Unicode-таблице, сопоставимых с соответствующей частью в CP-866 и... кто в лес, кто по дрова. Какие-то ряды букв идут подряд, какие-то идут в разрыв уже. Т.е. банальным арифметическим преобразованием (смещением некого числа) не обойтись. Да и табличный метод не особо применить. Не уж то плодить кучу if(), или я чего-то не замечаю и все не так страшно? Латиница + все русские буквы + символ '№' (остальное мне не нужно, расширенные 32-битные коды вовсе пропускаются) static u32 convToCP866(u8 const src[], u8 dst[], u32 len) { u32 i = 0; while(len > 1) { u32 utf16 = *src++; utf16 |= *src++ << 8; if(utf16 < 0x80) dst[i++] = utf16; else if(utf16 >= 0x410 && utf16 < 0x450) { if((utf16 -= 0x390) >= 0xB0) utf16 += 0x30; dst[i++] = utf16; } else if(utf16 == 0x401) dst[i++] = 0xF0; else if(utf16 == 0x451) dst[i++] = 0xF1; else if(utf16 == 0x2116) dst[i++] = 0xFC; len -= 2; } return i; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 245 28 октября Опубликовано 28 октября · Жалоба 51 минуту назад, Arlleex сказал: Латиница + все русские буквы + символ '№' (остальное мне не нужно, расширенные 32-битные коды вовсе пропускаются) static u32 convToCP866(u8 const src[], u8 dst[], u32 len) { u32 i = 0; while(len > 1) { u32 utf16 = *src++; ... Зачем так неоптимально? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 190 28 октября Опубликовано 28 октября · Жалоба 1 час назад, jcxz сказал: Зачем так неоптимально? Да, по-другому уже немного написал, но суть та же static u32 convToCP866(u16 const src[], u8 dst[], u32 len) { u32 i = 0; while(len-- > 0) { u32 utf16 = *src++; if(utf16 < 0x80) dst[i++] = utf16; else if(utf16 >= 0x410 && utf16 < 0x450) { if((utf16 -= 0x390) >= 0xB0) utf16 += 0x30; dst[i++] = utf16; } else if(utf16 == 0x401) dst[i++] = 0xF0; else if(utf16 == 0x451) dst[i++] = 0xF1; else if(utf16 == 0x2116) dst[i++] = 0xFC; } return i; } Всякими хитрыми преобразованиями сейчас некогда заниматься. Может быть потом вернусь к этому вопросу (нет). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 245 28 октября Опубликовано 28 октября · Жалоба 1 час назад, Arlleex сказал: Всякими хитрыми преобразованиями сейчас некогда заниматься. Может быть потом вернусь к этому вопросу (нет). Вот так: u32 convToCP866_2(u16 const src[], u8 dst[], u32 len) { u8 *s = dst; while ((s32)--len >= 0) { u32 j, c = *(s8 *)src++; if ((s32)(j = c) < 0) { j = 0xF0; if (c -= 0x401) { j = 0xF1; if (c -= 0x451 - 0x401) { j = 0xFC; if (c != 0x2116 - 0x451) { if ((c = c + 0x451 - 0x410) >= 0x450u - 0x410u) continue; if (c >= 0x30) c += 0x30; c += 0x80; } } } } *s++ = j; } return s - dst; } вроде получается покороче и побыстрее. По-крайней мере при Medium-оптимизации IAR. 60 байт против 98-и исходных. Накидал по-быстрому. Может конечно где напутал. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 190 28 октября Опубликовано 28 октября · Жалоба Да на самом деле даже мой вариант компилятор CLang перетасовал на свой вкус так, что от моего там остался только LDRH и декремент счетчика в конце😄 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 245 28 октября Опубликовано 28 октября · Жалоба 4 минуты назад, Arlleex сказал: Да на самом деле даже мой вариант компилятор CLang перетасовал на свой вкус так, что от моего там остался только LDRH и декремент счетчика в конце😄 И какой размер у него получился в итоге? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yes 8 28 октября Опубликовано 28 октября · Жалоба Может не в тему, просто столкнулся с такой фигней, в rust-е стандартные строки utf-16 и есть их преобразование в байты. Наверно с учётом всех исключений и всей этой разноразмерности (я в ютф не вникал). Предполагаю, что растовские сорцы можно понять, если даже раньше не Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 245 28 октября Опубликовано 28 октября · Жалоба 4 часа назад, Arlleex сказал: Латиница + все русские буквы + символ '№' (остальное мне не нужно, расширенные 32-битные коды вовсе пропускаются) У меня много где используется символ '°' (Unicode==0xB0). Температуры, угловые градусы (для управления моторами и данные гироскопа). А вот '№' никогда не требовался. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 190 28 октября Опубликовано 28 октября · Жалоба 18 минут назад, jcxz сказал: У меня много где используется символ '°' (Unicode==0xB0). Температуры, угловые градусы (для управления моторами и данные гироскопа). А вот '№' никогда не требовался. У меня поезд, на маршрутных табло никогда градуса не будет. А вот номер - вполне может быть, наверное. Какая-нибудь надпись типа "Тупик №234" (для маршрутов внутри депо). 1 час назад, jcxz сказал: И какой размер у него получился в итоге? По ходу отладки выяснил, что мне нужно разворачивать декодированную строку в буфере-приемнике, т.е. класть в dst в виде "АБВГД" -> "ДГВБА", поэтому *src++ заменил на *src--. Листинг 0x080017D6 2100 MOVS r1,#0x00 31: while(len-- > 0) { 0x080017D8 F242622C MOVW r2,#0x262C 0x080017DC F2C20200 MOVT r2,#0x2000 0x080017E0 EB020240 ADD r2,r2,r0,LSL #1 32: u32 utf16 = *src--; 33: 0x080017E4 F8322C02 LDRH r2,[r2,#-0x02] 34: if(utf16 < 0x80) 35: dst[i++] = utf16; 0x080017E8 2A7F CMP r2,#0x7F 0x080017EA D90B BLS 0x08001804 36: else if(utf16 >= 0x410 && utf16 < 0x450) { 0x080017EC F5A26382 SUB r3,r2,#0x410 0x080017F0 B29B UXTH r3,r3 0x080017F2 2B3F CMP r3,#0x3F 0x080017F4 D812 BHI 0x0800181C 37: if((utf16 -= 0x390) >= 0xB0) 38: utf16 += 0x30; 39: 40: dst[i++] = utf16; 41: } 0x080017F6 F5A27364 SUB r3,r2,#0x390 0x080017FA 2BAF CMP r3,#0xAF 0x080017FC BF88 IT HI 0x080017FE F10203A0 ADD r3,r2,#0xA0 0x08001802 461A MOV r2,r3 0x08001804 F242632C MOVW r3,#0x262C 0x08001808 F2C20300 MOVT r3,#0x2000 0x0800180C 440B ADD r3,r3,r1 0x0800180E 3101 ADDS r1,r1,#0x01 0x08001810 F88321FB STRB r2,[r3,#0x1FB] 0x08001814 3801 SUBS r0,r0,#0x01 0x08001816 D1DF BNE 0x080017D8 0x08001818 E0EB B 0x080019F2 0x0800181A BF00 NOP 42: else if(utf16 == 0x401) 0x0800181C F2404301 MOVW r3,#0x401 0x08001820 429A CMP r2,r3 0x08001822 D00B BEQ 0x0800183C 0x08001824 F2421316 MOVW r3,#0x2116 0x08001828 429A CMP r2,r3 0x0800182A D005 BEQ 0x08001838 0x0800182C F2404351 MOVW r3,#0x451 0x08001830 429A CMP r2,r3 0x08001832 D1EF BNE 0x08001814 0x08001834 22F1 MOVS r2,#0xF1 0x08001836 E7E5 B 0x08001804 0x08001838 22FC MOVS r2,#0xFC 0x0800183A E7E3 B 0x08001804 0x0800183C 22F0 MOVS r2,#0xF0 0x0800183E E7E1 B 0x08001804 На самом деле мне не очень важно, сколько оно будет занимать, главное чтобы работало и (если бонусом) побыстрее. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Plain 228 28 октября Опубликовано 28 октября · Жалоба 27 минут назад, Arlleex сказал: поезд, на маршрутных табло никогда градуса не будет Сейчас в любом транспорте показов разных температур навалом, на некоем служебном табло забортная температура вполне может быть указана как причина отмены рейса. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 190 28 октября Опубликовано 28 октября · Жалоба 6 минут назад, Plain сказал: Сейчас в любом транспорте показов разных температур навалом, на некоем служебном табло забортная температура вполне может быть указана как причина отмены рейса. На табло внутри вагона градусы показываются. У меня табло намордное - т.е. лобовое, т.е. только маршрут следования и ничего более. 2 часа назад, jcxz сказал: Накидал по-быстрому. Может конечно где напутал. Не, тот вариант не работает корректно. Я особо в код не вникал, ибо там какая-то магия происходит, но сразу кинулась в глаза строчка u32 j, c = *(s8 *)src++; if ((s32)(j = c) < 0) { которая никогда не зайдет в этот if() при любых входящих символах из списка ASCII + А...Я + а...я + Ё + ё + №🙂 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 245 28 октября Опубликовано 28 октября · Жалоба 2 часа назад, Arlleex сказал: Не, тот вариант не работает корректно. Я особо в код не вникал, ибо там какая-то магия происходит, но сразу кинулась в глаза строчка u32 j, c = *(s8 *)src++; if ((s32)(j = c) < 0) { которая никогда не зайдет в этот if() при любых входящих символах из списка ASCII + А...Я + а...я + Ё + ё + №🙂 Да, там перепутал. У вас же не UTF-8, а UTF-16. Исправил: u32 convToCP866(u16 const src[], u8 dst[], u32 len) { u8 *s = dst; while ((s32)--len >= 0) { u32 j, c = *src++; if ((s32)(j = (s8)c) < 0) { j = 0xF0; if (c -= 0x401) { j = 0xF1; if (c -= 0x451 - 0x401) { j = 0xFC; if (c != 0x2116 - 0x451) { if ((j = c + 0x451 - 0x410) >= 0x450u - 0x410u) continue; if (j >= 0x30) j += 0x30; j += 0x80; } } } } *s++ = j; } return s - dst; } 3 часа назад, Arlleex сказал: Листинг Как-то многовато: 0x1840-0x17D6 = 106 байт! Мой вариант (выше) = 68 байт: u32 convToCP866(u16 const src[], u8 dst[], u32 len) { _Z11convToCP866PKtPhm: (+1) 00000000 0xB570 PUSH {R4-R6,LR} u8 *s = dst; 00000002 0x460B MOV R3,R1 00000004 0xF641 0x46C5 MOVW R6,#+7365 00000008 0xE018 B.N ??convToCP866_0 while ((s32)--len >= 0) { u32 j, c = *src++; ??convToCP866_1: (+1) 0000000A 0xF830 0x4B02 LDRH R4,[R0], #+2 if ((s32)(j = (s8)c) < 0) { 0000000E 0xB265 SXTB R5,R4 00000010 0x2D00 CMP R5,#+0 00000012 0xD511 BPL.N ??convToCP866_2 j = 0xF0; 00000014 0x25F0 MOVS R5,#+240 if (c -= 0x401) { 00000016 0xF2A4 0x4401 SUBW R4,R4,#+1025 0000001A 0xB16C CBZ.N R4,??convToCP866_2 j = 0xF1; 0000001C 0x25F1 MOVS R5,#+241 if (c -= 0x451 - 0x401) { 0000001E 0x3C50 SUBS R4,R4,#+80 00000020 0xBF1C ITT NE 00000022 0x25FC MOVNE R5,#+252 00000024 0x42B4 CMPNE R4,R6 j = 0xFC; if (c != 0x2116 - 0x451) { 00000026 0xD007 BEQ.N ??convToCP866_2 if ((j = c + 0x451 - 0x410) >= 0x450u - 0x410u) continue; 00000028 0xF104 0x0541 ADD R5,R4,#+65 0000002C 0x2D40 CMP R5,#+64 0000002E 0xD205 BCS.N ??convToCP866_0 if (j >= 0x30) j += 0x30; 00000030 0x2D30 CMP R5,#+48 00000032 0xBF28 IT CS 00000034 0x3530 ADDCS R5,R5,#+48 j += 0x80; 00000036 0x3580 ADDS R5,R5,#+128 } } } } *s++ = j; ??convToCP866_2: (+1) 00000038 0xF803 0x5B01 STRB R5,[R3], #+1 } ??convToCP866_0: (+1) 0000003C 0x1E52 SUBS R2,R2,#+1 0000003E 0xD5E4 BPL.N ??convToCP866_1 return s - dst; 00000040 0x1A58 SUBS R0,R3,R1 00000042 0xBD70 POP {R4-R6,PC} ;; return } 3 часа назад, Arlleex сказал: главное чтобы работало и (если бонусом) побыстрее. Должно работать. И команд меньше - может по-быстрее будет. По крайней мере - выполнившихся условных переходов внутри цикла должно быть не много. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 190 28 октября Опубликовано 28 октября · Жалоба Завтра проверю ради интереса. P.S. Хотя все равно уже вижу, что работать не будет правильно😉 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 245 29 октября Опубликовано 29 октября · Жалоба 22 часа назад, Arlleex сказал: P.S. Хотя все равно уже вижу, что работать не будет правильно😉 Почему? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться