Юникод

Kernel architecture questions
  • за либу спасибо :), а насчёт Колибри - я бы предложил специфицировать, как и где в системе применяется юникод.
  • Было бы хорошо, если бы везде применялся. Я однобайтовую кодировку использую только при прямом выводе на текстовую консоль, причем даже здесь при желании можно добиться одновременного отображения 512 различных символов.
  • GNU GPL v2 License as specified on http://www.gnu.org. All Rights Reserved.

    Code: Select all

    utf8_1stBait_validation:
      db 1,1,1,1,1,1,1,1
      db 1,1,1,1,1,1,1,1
      db 0,0,0,0,0,0,0,0
      db 2,2,2,2,3,3,4,0
    
    ;GNU GPL v2 License as specified on http://www.gnu.org. All Rights Reserved.
    
    ; Reads utf-8 symbol into EAX at ESI.
    ; If function completes without error - ESI advances to next potential symbol
    ; Function foesn't validate unicode ranges
    ;---------------------------------------------------------------------------------------------------
    ; input: esi - pointer to memory with 4bait read access
    ; return:
    ;        eax - value
    ;        ecx - number of baits in utf-8 symbol, or =0 if invalid symbol 
    ;        CF=0 if ecx !=0,  CF=1 if ecx=0
    ; detroyed:
    ;        eflags, edx, esi+=ecx
    
    utf8_nextChar:
      cld
      xor    eax ,eax
      lodsb
      xor    ecx, ecx
      movzx  edx, al
      shr    eax, 3
      and    edx, 1111111b
      add    cl, byte [utf8_1stBait_validation+eax]    ; cl = number of bytes in the utf8 symbol
      jz     .err2
      cmp    cl, 3
      ja     .4
      jz     .3
      jp     .2
      jmp    @f
    .2:
      lodsb
      and    edx, 11111b
      btr    eax, 7                              ; clear top bit and verify if bit is set
      jnc    .err
      shl    edx, 6
      test   al, $40
      jnz    .err
      or     edx, eax
    
      ; add your unicode range validation here for 2byte utf8 sequence
    
      jmp    @f
    .3:
      lodsw                                      ; load 2 bytes
      test   eax, 0100'0000'0100'0000b           ; verify that cleared bits are cleared
      jnz    .err
      not    eax
      test   eax, 1000'0000'1000'0000b           ; verify that set bits are set
      jnz    .err
      not    eax
      and    edx, 1111b                          ; only low 4bits of 1st bait are valid
      shl    eax, 2
      ror    ax, 8                               ; do
      shr    ah, 2                               ;  some
      shr    eax, 2                              ;     bit
      shl    edx, 12                             ;       swapping
      and    eax, $fff
      or     edx, eax
    
      ; add your unicode range validation here for 3byte utf8 sequence
    
      jmp    @f
    .4:
      dec    esi
      lodsd
      shl    edx, 8
      test   eax, $40404000
      jnz    .err
      not    eax
      test   eax, $80808000
      jnz    .err
      not    eax
    
      mov    dl, ah
      bswap  eax
      shl    dl, 2
      shl    eax, 2                              ; eax:  get rid of top 2bits in AL
      shl    edx, 10                             ; edx[20:12] filled
      shr    ah, 2                               ; eax:  bring AH & AL together in one 12bit chunk
      shr    eax, 2                              ; eax[11:0] filled
      and    edx, $1ff000
      and    eax, $fff
      or     edx, eax
    
      ; add your unicode range validation here for 4byte utf8 sequence
    
    @@:
      mov    eax, edx
      clc
    
    .exit:
    ret
    
    .err2:
      sub    esi, 1
    .err:
      sub    esi, ecx
      xor    ecx, ecx
      stc
      jmp    .exit
    
    сколько всяких проверок бля, в одной простой функции
    Last edited by ilya on Mon Jul 16, 2012 4:47 am, edited 2 times in total.
  • А можно хранить кодпойнты как последовательность не из четырёх, а трёх байт :) Ибо больше и не надо. При этом: a) данные, которые занимает текст в такой кодировке, в среднем всего на 50% длинее чем в UTF-16 (а в некоторых случаях даже до 30% процентов короче); б) данные всегда будут фиксированной длины, никаких суррогатных пар, random access к символам в строке.
    Единственный минус: в отличие от UTF-32, код-юниты не будут выравнены на 4-байтную границу, поэтому обработка будет чуть медленней (но это не критично).
    P.S. А назвать это можно будет "UTF-24".
  • не стоит придумывать нестандартные решения - в будущем это сулит кучу проблем. Тем более выигрыш действительно невелик, возможно даже иллюзорен.
  • Я это в качестве внутреннего формата (для хранения строк, например, в ОЗУ) предложил. Преобразование UTF-24-to-UTF-x реализовать будет несложно.
  • UCS-2?
  • Не стоит окончательно отказываться от суррогатных пар. Просто начинать нужно с поддержки базовой плоскости. Считать все символы из дополнительных плоскостей некорректными для служебного применения (например, в именах файлов). Их коды можно рассматривать как некорректный символ с модификатором или как два некорректных символа.
    Joaquin wrote:А можно хранить кодпойнты как последовательность не из четырёх, а трёх байт :) Ибо больше и не надо.
    А можно и как двух байт ;) "Ибо больше и не надо" на практике, и остаешься в рамках стандарта.
  • У меня есть такая гипотеза, что проще всего будет перейти именно на UTF-8:
    - разработан в группе Plan9 (те же создатели UNIX и их ученики);
    - одобрен авторитетными стандартами;
    - все алгоритмы, не использующие тот факт, что длина и позиция измеряется именно в символах, будут продолжать адекватно работать.

    Предполагаю главные проблемы:
    - вычисление длины строки в символах (а это может быть нужно для пользователя и пользовательского интерфейса) будет работать в несколько раз медленнее;
    - символ уже больше не умещается даже в int (но это происходит крайне редко), а поиск (подсчёт) вхождения символа потребуется реализовывать как поиск (подсчёт) вхождения подстроки длиной в 1 - 6 байт (в контексте UTF-8 длина строки в символах <= длине строки в байтах - число ненулевых байтов до первого нулевого).
  • Требования к API Юникода есть?

    Пишу сейчас реализацию, которую, как мне кажется, достаточно легко абстрагировать, ибо зависимостей минимум. TRawCodePage даже готов реализовать сам, если о формате таблиц перекодировок договоримся. Для "Колибри" вариантов два: или как-то собрать в FPC, или перенести код из дизассемблера, а потом переписать, если хочется. Есть добровольцы? Пример вывода DCU32Int прикладываю (оригинал на Паскале).

    Что реализовано или будет реализовано в ближайшее время:
    • Перекодировка между представлениями Юникода (UTF-xx).
    • Перекодировка между legacy-кодировками и Юникодом.
    • Перекодировка из одной legacy-кодировки в другую через Юникод.
    • Верхний-нижний регистр -- тоже через Юникод, для всех языков сразу.
    Наборы символов и кодировки:
    • UTF-8 (включая CESU-8 и модифицированный UTF-8), UTF-16 (включая суррогатные пары, BE и LE), UTF-32 (BE и LE).
    • 7-битная ASCII и ISO-8859-1 (Latin-1), не требующие таблицы перекодировки (для полноты концепций). :)
    • Однобайтовые (включая EBCDIC) и двухбайтовые кодовые страницы (Shift-JIS, Big5 и пр.)
    Перекодировки UTF делаются алгоритмически. Таблицы соответствия legacy- и Юникода могут храниться во внешнем файле или ресурсах (?). Сейчас они берутся из Windows. Реализовать TRawCodePage и нагенерить для неё таблиц, -- проще простого, повторюсь.

    Хранимые данные для однобайтовой кодовой страницы -- 128 × SizeOf(WideChar) = 256 байт -- для Windows- или OEM-кодировок, и вплоть до 512 байт для EBCDIC. Таблица обратной трансляции строится уже в памяти, для Windows-1251 занимает порядка 8 КБ.

    Все перекодировки делаются без потерь диакритик, появления кракозяблов и вопросиков. Именно поэтому мне и потребовалось писать собственную реализацию. Если строку нельзя представить в затребованном представлении -- это ошибка. При включённом бите coForceInvalid ошибочные символы заменяются "квадратиками".

    Что пока не планируется к реализации, так это композиция-декомпозиция (NFD, NFKC, NFKD), UTF-7 и прочая редко используемая байда. Не думаю, что это актуально для "Колибри". :)
    Attachments
    Downloaded 430 times
  • Offtop: Для Колибри? На паскале? Юникод? - Дайте два! :mrgreen:

    Мне так кажется это все надо в либу пихать.
  • Набросал примерный API. Высказываемся.
    Attachments
    Kolibri.pas (5.26 KiB)
    Downloaded 427 times
  • Я в паскале "не в зуб ногой". Лучше бы сделал текстовое описание. Как показывает практика даже хорошо прокомментированный код не всегда понятен, что уж говорить о известном только автору коде с мизером комментариев. Навык телепатии не прокачан.
  • Словесное описание -- парой сообщений выше. :)
  • Who is online

    Users browsing this forum: No registered users and 5 guests