Obsah / Utility / CHARSET / CharUTF8Write
Zdrojový kód:
INCLUDE\UTIL\CHARSET.INC, UTIL\CHARSET.ASM
CharUTF8Write - Uložení
znaku do bufferu ve formátu UTF-8
Funkce CharUTF8Write uloží Unicode znak
do bufferu v kódu UTF-8.
; -----------------------------------------------------------------------------
; Write character into UTF-8 buffer
; -----------------------------------------------------------------------------
; INPUT: EAX = Unicode character (max. 31 bits)
; EDI = destination buffer
; EBP = remaining space in buffer
; OUTPUT: EDI = next destination buffer
; EBP = next remaining space in buffer
; DESTROYS: EAX
; -----------------------------------------------------------------------------
|
Na vstupu funkce obsahuje registr EAX
Unicode kód ukládaného znaku, registr EDI ukazatel do
výstupního bufferu a registr EBP čítač zbylých dat ve
výstupním bufferu. Na výstupu funkce je ukazatel v EDI posunut
na novou zápisovou pozici a registr EBP obsahuje nový čítač
zbylých dat v bufferu. Funkce zničí obsah registru EAX.
; ------------- 1 Byte (7 bits, 0xxxxxxx = 0..7F)
CharUTF8Write: or ebp,ebp ; check free space
jz CharUTF8Write24 ; buffer full
cmp eax,byte 7fh ; check character (7 bits)
ja CharUTF8Write2 ; character has more bytes
stosb ; store byte
dec ebp ; decrease remaining space
ret
|
Na začátku funkce se otestuje registr
EBP, zda je k dispozici místo pro uložení dalšího bajtu.
Pokud má ukládaný znak hodnotu 0 až 7Fh, uloží se jeho
hodnota ihned, protože znaky v tomto rozsahu (7 bitů) jsou v
kódu UTF-8 ukládány jako jeden bajt.
; ------------- 2 Bytes (11 bits, 110xxxxx 10xxxxxx = C0..DF 80..BF)
CharUTF8Write2: cmp eax,7ffh ; check character (11 bits)
ja CharUTF8Write3 ; character has more bytes
push eax ; push EAX
shr eax,6 ; AL <- get highest 5 bits
or al,0c0h ; add flags
CharUTF8Write22:stosb ; store byte
dec ebp ; decrease remaining space
pop eax ; pop EAX
jz CharUTF8Write24 ; buffer full
and al,3fh ; mask 6 bits
or al,80h ; add flags
stosb ; store byte
dec ebp ; decrease remaining space
CharUTF8Write24:ret
|
Znaky s hodnotou 80h až 7FFh (tj. 11
bitů) se v kódu UTF-8 uloží jako 2 bajty. Nejdříve jsou
uloženy bity 6 až 10 (tj. 5 bitů) jako první bajt, je k nim
přidána hodnota 0C0h jako příznak kódu se 2 bajty.
Nižších 6 bitů je uloženo jako druhý bajt kódu spolu s
hodnotou 80h jako příznak druhého bajtu.
; ------------- 3 Bytes (16 bits, 1110xxxx 10xxxxxx 10xxxxxx =
; E0..EF 80..BF 80..BF
CharUTF8Write3: cmp eax,0ffffh ; check character (16 bits)
ja CharUTF8Write4 ; character has more bytes
push eax ; push EAX
shr eax,12 ; AL <- get highest 4 bits
or al,0e0h ; add flags
CharUTF8Write32:stosb ; store byte
dec ebp ; decrease remaining space
pop eax ; pop EAX
jz CharUTF8Write24 ; buffer full
push eax ; push EAX
shr eax,6 ; AL <- get 6 bits
and al,3fh ; mask 6 bits
or al,80h ; add flags
jmp short CharUTF8Write22
|
Znaky s hodnotou 800h až 0FFFFh (tj. 16
bitů) se v kódu UTF-8 uloží jako 3 bajty. Nejdříve jsou
uloženy bity 12 až 15 (tj. 4 bity) jako první bajt, je k nim
přidána hodnota 0E0h jako příznak kódu se 3 bajty.
Nižších 12 bitů je uloženo postupně po 6 bitech jako druhý
a třetí bajt spolu s hodnotou 80h jako příznak datového
bajtu.
; ------------- 4 Bytes (21 bits, 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx =
; F0..F7 80..BF 80..BF 80..BF
CharUTF8Write4: cmp eax,1fffffh ; check character (21 bits)
ja CharUTF8Write5 ; character has more bytes
push eax ; push EAX
shr eax,18 ; AL <- get highest 3 bits
or al,0f0h ; add flags
CharUTF8Write42:stosb ; store byte
dec ebp ; decrease remaining space
pop eax ; pop EAX
jz CharUTF8Write24 ; buffer full
push eax ; push EAX
shr eax,12 ; AL <- get 6 bits
and al,3fh ; mask 6 bits
or al,80h ; add flags
jmp short CharUTF8Write32
|
Znaky s hodnotou 10000h až 1FFFFFh (tj. 21
bitů) se v kódu UTF-8 uloží jako 4 bajty. Nejdříve jsou
uloženy bity 18 až 20 (tj. 3 bity) jako první bajt, je k nim
přidána hodnota 0F0h jako příznak kódu se 4 bajty.
Nižších 18 bitů je uloženo postupně po 6 bitech jako
druhý, třetí a čtvrtý bajt spolu s hodnotou 80h jako
příznak datového bajtu.
; ------------- 5 Bytes (26 bits, 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
; = F8..FB 80..BF 80..BF 80..BF 80..BF
CharUTF8Write5: cmp eax,3ffffffh ; check character (26 bits)
ja CharUTF8Write6 ; character has more bytes
push eax ; push EAX
shr eax,24 ; AL <- get highest 2 bits
or al,0f8h ; add flags
CharUTF8Write52:stosb ; store byte
dec ebp ; decrease remaining space
pop eax ; pop EAX
jz CharUTF8Write24 ; buffer full
push eax ; push EAX
shr eax,18 ; AL <- get 6 bits
and al,3fh ; mask 6 bits
or al,80h ; add flags
jmp short CharUTF8Write42
|
Znaky s hodnotou 200000h až 3FFFFFFh (tj.
26 bitů) se v kódu UTF-8 uloží jako 5 bajtů. Nejdříve jsou
uloženy bity 24 až 25 (tj. 2 bity) jako první bajt, je k nim
přidána hodnota 0F8h jako příznak kódu s 5 bajty. Nižších
24 bitů je uloženo postupně po 6 bitech jako druhý, třetí,
čtvrtý a pátý bajt spolu s hodnotou 80h jako příznak
datového bajtu.
; ------------- 6 Bytes (31 bits, 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
; 10xxxxxx = FC..FD 80..BF 80..BF 80..BF 80..BF 80..BF
CharUTF8Write6: push eax ; push EAX
shr eax,30 ; AL <- get highest 1 bit
and al,1 ; mask 1 bit
or al,0fch ; add flags
stosb ; store byte
dec ebp ; decrease remaining space
pop eax ; pop EAX
jz CharUTF8Write24 ; buffer full
push eax ; push EAX
shr eax,24 ; AL <- get 6 bits
and al,3fh ; mask 6 bits
or al,80h ; add flags
jmp short CharUTF8Write52
|
Znaky s hodnotou 4000000h až 7FFFFFFFh
(tj. 31 bitů) se v kódu UTF-8 uloží jako 6 bajtů. Nejdříve
je uložen bit 30 jako první bajt, je k němu přidána hodnota
0FCh jako příznak kódu s 6 bajty. Nižších 30 bitů je
uloženo postupně po 6 bitech jako druhý, třetí, čtvrtý,
pátý a šestý bajt spolu s hodnotou 80h jako příznak
datového bajtu.
Obsah / Utility / CHARSET / CharUTF8Write