Tvůrce webu je i pro tebe! Postav třeba web. Bez grafika. Bez kodéra. Hned.
wz

Obsah / Utility / UNICHAR / Funkce typů znaků

Zdrojový kód: INCLUDE\UTIL\UNICHAR.INC, UTIL\UNICHAR.ASM.


Funkce typů znaků

GetUniType   Vyhledání ukazatele na popisovač typu Unicode znaku
GetUniTypeFlags   Zjištění příznaků typu Unicode znaku
CheckUniChar   Kontrola platnosti Unicode znaku
CheckUniLetter   Test, zda je Unicode znak písmenem
UniCharToASCII   Konverze Unicode znaku na ASCII alternativu
UniCharSort   Zjištění abecední třídicí hodnoty Unicode znaku s rozlišením
UniCharSortCap   Zjištění abecední třídicí hodnoty Unicode znaku bez rozlišení
UniCharToSmall   Konverze Unicode znaku na malé písmeno
UniCharToCap   Konverze Unicode znaku na velké písmeno
UniCharToSmaCap   Konverze Unicode znaku na velké/malé písmeno (inverze)


; -----------------------------------------------------------------------------
;                   Get Unicode character type descriptor
; -----------------------------------------------------------------------------
; INPUT:	EAX = Unicode character
; OUTPUT:	EBX = pointer to Unicode character type descriptor UNITYPE
; -----------------------------------------------------------------------------

; ------------- Check range of Unicode character

GetUniType:	cmp	eax,CHTYPEMAX	; check maximal Unicode character
		ja	GetUniType4	; invalid character

; ------------- Push registers

                push	eax		; push EAX

; ------------- Get pointer to descriptor (-> EBX)

		GETUNITYPE eax,al,ah,eax,ebx ; get pointer to descriptor

; ------------- Pop registers

		pop	eax		; pop EAX
		ret

; ------------- Invalid Unicode character (character is out of range)

GetUniType4:	mov	ebx,CHTypeInv	; EBX <- invalid character
		ret

Funkce GetUniType slouží k vyhledání ukazatele na popisovač typu Unicode znaku. Vstupem funkce je Unicode kód znaku v registru EAX. Výstupem je ukazatel na popisovač typu znaku v registru EBX.

Na začátku funkce je nejdříve ověřena platnost Unicode znaku. Pokud je mimo podporovaný rozsah, navrátí se ukazatel na popisovač neplatného znaku. Jinak se pokračuje vyhledáním ukazatele na popisovač typu znaku pomocí makra GETUNITYPE.


; -----------------------------------------------------------------------------
;                      Get flags of Unicode character type
; -----------------------------------------------------------------------------
; INPUT:	EAX = Unicode character
; OUTPUT:	DL = flags of Unicode character type (see CHNONE, CHCTR, ...)
; -----------------------------------------------------------------------------

; ------------- Check range of Unicode character

GetUniTypeFlags:cmp	eax,CHTYPEMAX	; check maximal Unicode character
		ja	GetUniTypeFlgs4	; invalid character

; ------------- Push registers

                push	eax		; push EAX
		push	ebx		; push EBX

; ------------- Get flags (-> DL)

		movzx	ebx,ah		; EBX <- character HIGH
		mov	ebx,[CHTypeTab+ebx*4] ; EBX <- subtable
		movzx	eax,al		; EAX <- character LOW
		mov	dl,[ebx+eax*UNITYPE_size+UNI_Flags] ; DL <- flags

; ------------- Pop registers

		pop	ebx		; pop EBX
		pop	eax		; pop EAX
		ret

; ------------- Invalid Unicode character (character is out of range)

GetUniTypeFlgs4:mov	dl,CHNONE	; DL <- invalid character
		ret

Funkce GetUniTypeFlags slouží ke zjištění příznaků typu Unicode znaku. Vstupem funkce je Unicode kód znaku v registru EAX. Výstupem jsou příznaky typu znaku v registru EBX (CHNONE, CHCTR atd. - viz UNITYPE).

Na začátku funkce je nejdříve ověřena platnost Unicode znaku. Pokud je mimo podporovaný rozsah, navrátí se příznaky pro neplatný znak. Jinak se pokračuje načtením příznaků z popisovače znaku. Do registru EBX je připraven vyšší bajt kódu znaku a s jeho pomocí načten do registru EBX ukazatel na podtabulku typů znaků (z pole ukazatelů CHTypeTab). Do registru EAX je připraven nižší bajt kódu znaku a po sloučení s ukazatelem na podtabulku jsou z příslušného popisovače načteny do registru DL příznaky typu znaku.


; -----------------------------------------------------------------------------
;                      Check if Unicode character is valid
; -----------------------------------------------------------------------------
; INPUT:	EAX = Unicode character
; OUTPUT:	CY = character is not valid
; -----------------------------------------------------------------------------

; ------------- Check range of Unicode character

CheckUniChar:	cmp	eax,CHTYPEMAX	; check maximal Unicode character
		ja	CheckUniChar4	; invalid character

; ------------- Push registers

                push	eax		; push EAX
		push	ebx		; push EBX

; ------------- Check if character is valid (-> CY = character is not valid)

		movzx	ebx,ah		; EBX <- character HIGH
		mov	ebx,[CHTypeTab+ebx*4] ; EBX <- subtable
		movzx	eax,al		; EAX <- character LOW
		cmp	byte [ebx+eax*UNITYPE_size+UNI_Flags],1 ; check flags

; ------------- Pop registers

		pop	ebx		; pop EBX
		pop	eax		; pop EAX
		ret

; ------------- Invalid Unicode character (character is out of range)

CheckUniChar4:	stc			; set error flag
		ret

Funkce CheckUniChar testuje, zda je Unicode znak platný, tj. podporovaný tabulkami systému Litos. Vstupem funkce je Unicode kód znaku v registru EAX. Výstupem je příznak CF, který je nastaven v případě neplatnosti znaku (tj. stav NC pro platný znak, stav CY pro neplatný znak).

Na začátku funkce je nejdříve ověřena platnost Unicode znaku. Pokud je mimo podporovaný rozsah, navrátí se nastavený příznak CY jako příznak neplatnosti znaku. Jinak se pokračuje testem příznaků v popisovači znaku. Do registru EBX je připraven vyšší bajt kódu znaku a s jeho pomocí načten do registru EBX ukazatel na podtabulku typů znaků (z pole ukazatelů CHTypeTab). Do registru EAX je připraven nižší bajt kódu znaku a po sloučení s ukazatelem na podtabulku je v příslušném popisovači proveden test platnosti znaku - pokud je bajt příznaků nastaven na hodnotu 0, jedná se o neplatný znak.


; -----------------------------------------------------------------------------
;          Check if Unicode character is a letter (small or capital)
; -----------------------------------------------------------------------------
; INPUT:	EAX = Unicode character
; OUTPUT:	NZ = character is a letter
; -----------------------------------------------------------------------------

; ------------- Check range of Unicode character

CheckUniLetter:	cmp	eax,CHTYPEMAX	; check maximal Unicode character
		ja	CheckUniLetter4	; invalid character

; ------------- Push registers

                push	eax		; push EAX
		push	ebx		; push EBX

; ------------- Check if character is a letter

		movzx	ebx,ah		; EBX <- character HIGH
		mov	ebx,[CHTypeTab+ebx*4] ; EBX <- subtable
		movzx	eax,al		; EAX <- character LOW
		test	byte [ebx+eax*UNITYPE_size+UNI_Flags],CHCAP+CHSMA

; ------------- Pop registers

		pop	ebx		; pop EBX
		pop	eax		; pop EAX
		ret

; ------------- Invalid Unicode character (character is out of range)

CheckUniLetter4:cmp	eax,eax		; set ZF (character is not a letter)
		ret

Funkce CheckUniLetter testuje, zda je Unicode znak písmenem. Vstupem funkce je Unicode kód znaku v registru EAX. Výstupem je příznak ZF, který je nastaven v případě, že znak není písmeno (tj. stav NZ znamená písmeno, stav ZY jiný znak než písmeno).

Na začátku funkce je nejdříve ověřena platnost Unicode znaku. Pokud je mimo podporovaný rozsah, navrátí se nastavený příznak ZY jako příznak, že znak není písmenem. Jinak se pokračuje testem příznaků v popisovači znaku. Do registru EBX je připraven vyšší bajt kódu znaku a s jeho pomocí načten do registru EBX ukazatel na podtabulku typů znaků (z pole ukazatelů CHTypeTab). Do registru EAX je připraven nižší bajt kódu znaku a po sloučení s ukazatelem na podtabulku je v příslušném popisovači proveden test, zda je znak písmenem - je-li nastaven příznak CHCAP nebo CHSMA bude navrácen příznak NZ.


; -----------------------------------------------------------------------------
;                Convert Unicode character to ASCII alternative
; -----------------------------------------------------------------------------
; INPUT:	EAX = Unicode character
; OUTPUT:	EAX = ASCII alternative
; -----------------------------------------------------------------------------

; ------------- Check range of Unicode character

UniCharToASCII:	cmp	eax,CHTYPEMAX	; check maximal Unicode character
		ja	UniCharToASCII4	; invalid character

; ------------- Push registers

		push	ebx		; push EBX

; ------------- Get ASCII alternative (-> EAX)

		movzx	ebx,ah		; EBX <- character HIGH
		mov	ebx,[CHTypeTab+ebx*4] ; EBX <- subtable
		movzx	eax,al		; EAX <- character LOW
		mov	al,[ebx+eax*UNITYPE_size+UNI_ASCII] ; EAX <- ASCII

; ------------- Pop registers

		pop	ebx		; pop EBX
		ret

; ------------- Invalid Unicode character (character is out of range)

UniCharToASCII4:mov	eax,UNINOASC	; EAX <- invalid character
		ret

Funkce UniCharToASCII zkonvertuje Unicode znak na ASCII alternativu. Vstupem funkce je Unicode kód znaku v registru EAX. Výstupem je ASCII alternativa znaku v registru EAX.

Na začátku funkce je nejdříve ověřena platnost Unicode znaku. Pokud je mimo podporovaný rozsah, navrátí se implicitní kód neplatného znaku UNINOASC. Jinak se pokračuje načtením ASCII alternativy z popisovače znaku. Do registru EBX je připraven vyšší bajt kódu znaku a s jeho pomocí načten do registru EBX ukazatel na podtabulku typů znaků (z pole ukazatelů CHTypeTab). Do registru EAX je připraven nižší bajt kódu znaku a po sloučení s ukazatelem na podtabulku je z příslušného popisovače načtena do registru AL ASCII alternativa znaku.


; -----------------------------------------------------------------------------
;      Get alphabetic sorting value of Unicode character - case sensitive
; -----------------------------------------------------------------------------
; INPUT:	EAX = Unicode character
;		EDI = pointer to nationality descriptor NATION
; OUTPUT:	EAX = alphabetic sorting value
;			B0..B15 = unicode character
;			B16..B23 = ASCII alternative
;			B24..B31 = character flags (character group)
; -----------------------------------------------------------------------------

; ------------- Check range of Unicode character

UniCharSort:	cmp	eax,CHTYPEMAX	; check maximal Unicode character
		ja	UniCharSort8	; invalid character

; ------------- Push registers

		push	ebx		; push EBX
		push	ecx		; push ECX

; ------------- Prepare table address (-> EBX,ECX)

UniCharSort2:	movzx	ebx,ah		; EBX <- character HIGH
		movzx	ecx,al		; EAX <- character LOW
		mov	ebx,[CHTypeTab+ebx*4] ; EBX <- subtable

; ------------- Get sorting value (-> EAX)

UniCharSort4:	shl	eax,16		; EAX <- shift Unicode character left
		mov	ax,[ebx+ecx*UNITYPE_size] ; AX <- Flags + ASCII
		xchg	al,ah		; AL <- ASCII, AH <- Flags
		ror	eax,16		; do correction of bit position

; ------------- Prepare sorting table

		movzx	ebx,ah		; EBX <- character HIGH
		shl	ebx,2		; EBX <- character HIGH * 4
		add	ebx,[edi+NAT_AlphaHash] ; EBX <- pointer to hash table
		mov	ebx,[ebx]	; EBX <- hash table

; ------------- Get sorting value

		cmp	byte [ebx+ecx],0 ; is sorting value valid?
		je	UniCharSort6	; sorting value is not valid
		ror	eax,16		; shift bits
		mov	al,[ebx+ecx]	; AL <- get sorting value
		ror	eax,16		; shift bits

; ------------- Pop registers

UniCharSort6:	pop	ecx		; pop ECX
		pop	ebx		; pop EBX
		ret

; ------------- Invalid Unicode character (character is out of range)

UniCharSort8:	mov	eax,UNINOASC	; EAX <- invalid character
		ret

Funkce UniCharSort navrátí abecední třídicí klíč pro Unicode znak (s rozlišením velkých a malých písmen). Vstupem funkce je Unicode kód znaku v registru EAX a ukazazatel na popisovač národnostních informací NATIONAL v registru EDI. Výstupem je abecední třídicí klíč v registru EAX.

Třídicí klíč se skládá z 16 nižších bitů Unicode kódu znaku, 8 bitů ASCII alternativy znaku a 8 bitů kategorie znaku. Při třídění textů se porovnáním třídicího klíče znaky rozdělí do skupin nejdříve podle kategorií (tj. řídicí znaky, potom mezera, za ní značky atd.), potom podle ASCII alternativy a nakonec podle nižších 16 bitů Unicode ködu (které se uplatní pokud znaky nemají dostatečné rozlišení ASCII alternativou). Namísto ASCII alternativy se použíje köd z třídicí tabulky znaků, je-li k dispozici.

Na začátku funkce je nejdříve ověřena platnost Unicode znaku. Pokud je mimo podporovaný rozsah, navrátí se implicitní kód neplatného znaku UNINOASC. Jinak se pokračuje vygenerováním třídicího klíče. Do registru EBX je připraven vyšší bajt kódu znaku a s jeho pomocí načten do registru EBX ukazatel na podtabulku typů znaků (z pole ukazatelů CHTypeTab).

Rotací registru EAX doleva o 16 bitů se uchová nižší slovo registru. Do registru ECX je připraven nižší bajt kódu znaku a po sloučení s ukazatelem na podtabulku je z příslušného popisovače načtena do registru AX ASCII alternativa znaku spolu s příznaky, Je opraveno pořadí bajtů, aby se příznaky nacházely ve vyšším bajtu a poté se rotací data přesunou do vyššího slova registru EAX a do nižšího slova se navrátí původních 16 bitů kódu znaku.

Do registru EBX se připraví vyšší bajt kódu znaku a použije se k načtení adresy hashovací podtabulky třídění znaků z popisovače národnostních informací. Má-li znak platnou třídicí hodnotu (tj. obsahuje bajt 80h a více), použije se tato hodnota namísto ASCII alternativy znaku.


; -----------------------------------------------------------------------------
;       Get alphabetic sorting value of Unicode character - capital case
; -----------------------------------------------------------------------------
; INPUT:	EAX = Unicode character
;		EDI = pointer to nationality descriptor NATIONAL
; OUTPUT:	EAX = alphabetic sorting value
;			B0..B15 = unicode character
;			B16..B23 = ASCII alternative
;			B24..B31 = character flags (character group)
; -----------------------------------------------------------------------------

; ------------- Check range of Unicode character

UniCharSortCap:	cmp	eax,CHTYPEMAX	; check maximal Unicode character
		ja	UniCharSort8	; invalid character

; ------------- Push registers

		push	ebx		; push EBX
		push	ecx		; push ECX

; ------------- Prepare table address (-> EBX,ECX)

		movzx	ebx,ah		; EBX <- character HIGH
		movzx	ecx,al		; EAX <- character LOW
		mov	ebx,[CHTypeTab+ebx*4] ; EBX <- subtable

; ------------- Check if it has valid capital letter

		test	byte [ebx+ecx*UNITYPE_size+UNI_Flags],CHSMA ; small?
		jz	UniCharSort4	; not small letter
		cmp	word [ebx+ecx*UNITYPE_size+UNI_Change],0 ; change?
		je	UniCharSort4	; no change

; ------------- Change to capital letter

		mov	ax,[ebx+ecx*UNITYPE_size+UNI_Change] ; capital letter
		jmp	short UniCharSort2

Funkce UniCharSortCap je podobná funkci UniCharSort s tím rozdílem, ž třídicí klíč nerozlišuje mezi velkými a malými písmeny, protože funkce znak nejdříve zkonvertuje na velké písmeno.


; -----------------------------------------------------------------------------
;                 Convert Unicode character to small letter
; -----------------------------------------------------------------------------
; INPUT:	EAX = Unicode character
; OUTPUT:	EAX = small letter
; -----------------------------------------------------------------------------

; ------------- Check range of Unicode character

UniCharToSmall:	cmp	eax,CHTYPEMAX	; check maximal Unicode character
		ja	UniCharToSmall4	; invalid character

; ------------- Push registers

		push	ebx		; push EBX
		push	ecx		; push ECX

; ------------- Get type descriptor (-> ECX)

		movzx	ebx,ah		; EBX <- character HIGH
		movzx	ecx,al		; ECX <- character LOW
		mov	ebx,[CHTypeTab+ebx*4] ; EBX <- subtable
		mov	ecx,[ebx+ecx*UNITYPE_size] ; ECX <- descriptor

; ------------- Check if character is a capital letter

		test	cl,CHCAP	; is it a capital letter?
		jz	UniCharToSmall2	; it is not capital letter

; ------------- Convert to small letter

		shr	ecx,16		; ECX <- small letter
		jz	UniCharToSmall2	; there is no small letter
		xchg	eax,ecx		; EAX <- small letter

; ------------- Pop registers

UniCharToSmall2:pop	ecx		; pop ECX
		pop	ebx		; pop EBX
UniCharToSmall4:ret

Funkce UniCharToSmall zkonvertuje znak na malé písmeno. Vstupem fukce je Unicode köd znaku v registru EAX, výstupem je znak převedený na malé písmeno, opět v registru EAX.

Na začátku funkce je nejdříve ověřena platnost Unicode znaku. Pokud je mimo podporovaný rozsah, funkce se navrátí bez změny znaku.

Je-li znak platný, je do registru EBX připraven vyšší bajt ködu znaku a z tabulky CHTypeTab načten ukazatel na podtabulku popisovače typu znaku. Do registru ECX je připraven nižší bajt ködu znaku a z podtabulky popisovače je do registru ECX načten popisovač typu znaku.

Není-li znakem velké písmeno, funkce se ukončí bez dalších operací. Jinak se z popisovače typu vyjme köd párového malého písmene (rotací ECX o 16 bitů vpravo) a pokud je köd malého písmene platný, je navrácen funkcí jako nový köd znaku.


; -----------------------------------------------------------------------------
;                 Convert Unicode character to capital letter
; -----------------------------------------------------------------------------
; INPUT:	EAX = Unicode character
; OUTPUT:	EAX = capital letter
; -----------------------------------------------------------------------------

; ------------- Check range of Unicode character

UniCharToCap:	cmp	eax,CHTYPEMAX	; check maximal Unicode character
		ja	UniCharToCap4	; invalid character

; ------------- Push registers

		push	ebx		; push EBX
		push	ecx		; push ECX

; ------------- Get type descriptor (-> ECX)

		movzx	ebx,ah		; EBX <- character HIGH
		mov	ebx,[CHTypeTab+ebx*4] ; EBX <- subtable
		movzx	ecx,al		; ECX <- character LOW
		mov	ecx,[ebx+ecx*UNITYPE_size] ; ECX <- descriptor

; ------------- Check if character is a small letter

		test	cl,CHSMA	; is it a small letter?
		jz	UniCharToCap2	; it is not small letter

; ------------- Convert to capital letter

		shr	ecx,16		; ECX <- capital letter
		jz	UniCharToCap2	; there is no capital letter
		xchg	eax,ecx		; EAX <- capital letter

; ------------- Pop registers

UniCharToCap2:	pop	ecx		; pop ECX
		pop	ebx		; pop EBX
UniCharToCap4:	ret

Funkce UniCharToCap zkonvertuje znak na velké písmeno. Vstupem fukce je Unicode köd znaku v registru EAX, výstupem je znak převedený na velké písmeno, opět v registru EAX.

Na začátku funkce je nejdříve ověřena platnost Unicode znaku. Pokud je mimo podporovaný rozsah, funkce se navrátí bez změny znaku.

Je-li znak platný, je do registru EBX připraven vyšší bajt ködu znaku a z tabulky CHTypeTab načten ukazatel na podtabulku popisovače typu znaku. Do registru ECX je připraven nižší bajt ködu znaku a z podtabulky popisovače je do registru ECX načten popisovač typu znaku.

Není-li znakem malé písmeno, funkce se ukončí bez dalších operací. Jinak se z popisovače typu vyjme köd párového velkého písmene (rotací ECX o 16 bitů vpravo) a pokud je köd velkého písmene platný, je navrácen funkcí jako nový köd znaku.


; -----------------------------------------------------------------------------
;          Convert Unicode character to small/capital letter (invert)
; -----------------------------------------------------------------------------
; INPUT:	EAX = Unicode character
; OUTPUT:	EAX = small/capital letter
; -----------------------------------------------------------------------------

; ------------- Check range of Unicode character

UniCharToSmaCap:cmp	eax,CHTYPEMAX	; check maximal Unicode character
		ja	UniCharToSmaCa4	; invalid character

; ------------- Push registers

		push	ebx		; push EBX
		push	ecx		; push ECX

; ------------- Get small/capital letter (-> ECX)

		movzx	ebx,ah		; EBX <- character HIGH
		mov	ebx,[CHTypeTab+ebx*4] ; EBX <- subtable
		movzx	ecx,al		; ECX <- character LOW
		movzx	ecx,word [ebx+ecx*UNITYPE_size+UNI_Change] ;ECX<-letter

; ------------- Convert to small/capital letter

		jecxz	UniCharToSmaCa2	; there is no small/capital letter
		xchg	eax,ecx		; EAX <- small/capital letter

; ------------- Pop registers

UniCharToSmaCa2:pop	ecx		; pop ECX
		pop	ebx		; pop EBX
UniCharToSmaCa4:ret

Funkce UniCharToSmaCap zkonvertuje znak na opačné velké/malé písmeno. Vstupem fukce je Unicode köd znaku v registru EAX, výstupem je znak převedený na velké/malé písmeno, opět v registru EAX.

Na začátku funkce je nejdříve ověřena platnost Unicode znaku. Pokud je mimo podporovaný rozsah, funkce se navrátí bez změny znaku.

Je-li znak platný, je do registru EBX připraven vyšší bajt ködu znaku a z tabulky CHTypeTab načten ukazatel na podtabulku popisovače typu znaku. Do registru ECX je připraven nižší bajt ködu znaku a z podtabulky popisovače je do registru ECX načten köd párového velkého/malého písmene. Pokud je köd párového velkého/malého písmene platný, je navrácen funkcí jako nový köd znaku.


Obsah / Utility / UNICHAR / Funkce typů znaků