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

Obsah / Utility / TEXT / TextTrimList

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


TextTrimList - Ořezání znaků z textu podle seznamu zakázaných znaků

Funkce TextTrimList odstraní z textu znaky ze seznamu 1-bajtových znaků.


; -----------------------------------------------------------------------------
;                  Trim text using list of forbidden characters
; -----------------------------------------------------------------------------
; INPUT:	EAX = pointer to TEXT with list of forbidden 1-byte characters
;		EBX = pointer to TEXT
; OUTPUT:	CY = memory error (text not changed)
; NOTES:	One-byte characters from the list will be deleted.
; -----------------------------------------------------------------------------

Na vstupu funkce obsahuje registr EAX ukazatel na textovou proměnnou obsahující seznam zakázaných 1-bajtových znaků. Registr EBX obsahuje ukazatel na textovou proměnnou, ve které mají být znaky zredukovány. V případě chyby paměti funkce navrátí příznak chyby CY.

Text se seznamem zakázaných znaků se neinterpretuje jako text kódovaný v kódu UTF-8, ale jako prostý seznam 1-bajtových kódů znaků, proto lze tímto způsobem redukovat pouze znaky s kódem 0 až 7Fh. Případně je možné doplnit též bajty v rozsahu 80h až 0FFh (např. pokud je třeba redukovat synchronizační bajty 0FEh a 0FFh), ale budou redukovány jako samostatné bajty a ne jako celé znaky v kódu UTF-8.


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

TextTrimList:	push	eax		; push EAX
		push	ecx		; push ECX
		push	esi		; push ESI
		push	edi		; push EDI
		push	ebp		; push EBP
		sub	esp,8*4		; ESP <- create local buffer
		mov	ebp,esp		; EBP <- local variables

; ------------- Clear local buffer (size: 8*4*8 = 256 bits)

		xor	ecx,ecx		; ECX <- 0
		mov	[ebp+0*4],ecx	; clear local buffer, DWORD 1
		mov	[ebp+1*4],ecx	; clear local buffer, DWORD 2
		mov	[ebp+2*4],ecx	; clear local buffer, DWORD 3
		mov	[ebp+3*4],ecx	; clear local buffer, DWORD 4
		mov	[ebp+4*4],ecx	; clear local buffer, DWORD 5
		mov	[ebp+5*4],ecx	; clear local buffer, DWORD 6
		mov	[ebp+6*4],ecx	; clear local buffer, DWORD 7
		mov	[ebp+7*4],ecx	; clear local buffer, DWORD 8

Po úschově registrů je v zásobníku připraven buffer k uchování bitové mapy znaků. Buffer má velikost 256 bitů, nebo-li 8 dvojslov po 32 bitech. Buffer je inicializován naplněním nulou.


; ------------- Map list of characters

		mov	esi,[eax]	; ESI <- source TEXTDATA
		mov	ecx,[esi+TEXT_Length] ; ECX <- source text length
		xor	eax,eax		; EAX <- 0
		jecxz	TextTrimList8	; no data (here is NC)
		add	esi,TEXT_Text	; ESI <- start of text
TextTrimList2:	lodsb			; load 1 character
		bts	dword [ebp],eax	; set bit of character
		loop	TextTrimList2	; next character

Seznam znaků k redukci je zmapován a to tak, že text se seznamem znaků je procházen bajt po bajtu a podle hodnoty bajtu je nastaven příslušný bit v bitové mapě znaků. Je-li seznam znaků prázdný, nedochází k žádné redukci textu a funkce je ihned ukončena s vynulovaným příznakem chyby NC. Další část kódu je společná s funkcí TextTrimUnList.


; ------------- Copy text on write

TextTrimList4:	call	TextCopyWrite	; copy text on write
		jc	TextTrimList8	; memory error

Před zahájením redukce je redukovaný text připraven k zápisu, tj. je provedena jeho kopie pomocí funkce TextCopyWrite, aby data nebyla sdílena s více proměnnými. V případě chyby paměti je funkce ihned ukončena.


; ------------- Prepare registers

		mov	esi,[ebx]	; ESI <- pointer to TEXT
		mov	ecx,[esi+TEXT_Length] ; ECX <- text length
		add	esi,TEXT_Text	; ESI <- source pointer
		jecxz	TextTrimList8	; nothing to delete (here is NC)
		mov	edi,esi		; EDI <- destination pointer

Do registrů ESI a EDI jsou připraveny ukazatele na začátek textu, do registru ECX je připravena délka textu. V případě nulové délky textu je funkce ihned ukončena s navrácením vynulovaného příznaku chyby NC.


; ------------- Trim forbidden characters

TextTrimList6:	lodsb			; AL <- load one character
		bt	dword [ebp],eax	; check one character (CY=invalid)
		stosb			; store character
		sbb	edi,byte 0	; return pointer if invalid character
		loop	TextTrimList6	; next byte

Text je procházen bajt po bajtu a každý načtený znak je opět uložen zpět do bufferu textu. Ukládací ukazatel v registru EDI je navrácen zpět o 1 v případě, že byl přenesen zakázaný bajt. Bajt je zakázaný v případě, že v bitové mapě znaků je nastaven příslušný bit.


; ------------- Resize data buffer

		cmp	esi,edi		; text changed?
		mov	eax,[ebx]	; EAX <- data buffer
		je	TextTrimList8	; text not changed
		add	eax,TEXT_Text	; EAX <- start of text
		sub	edi,eax		; EDI <- new length
		xchg	eax,edi		; EAX <- new length
		call	TextResize	; resize data buffer

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

TextTrimList8:	lea	esp,[ebp+8*4]	; pop ESP
		pop	ebp		; pop EBP
		pop	edi		; pop EDI
		pop	esi		; pop ESI
		pop	ecx		; pop ECX
		pop	eax		; pop EAX
		ret

Po provedení redukce se porovná zdrojový a cílový ukazatel. Pokud nejsou shodné, došlo k redukci alespoň jednoho bajtu a je potřeba zmenšit velikost bufferu textu. Nová délka textu je zjištěna rozdílem ukládací adresy v registru EDI a adresy začátku textu v registru EAX. Velikost bufferu je opravena funkcí TextResize. Nakonec je obnoven ukazatel zásobníku a registry ze zásobníku.


Obsah / Utility / TEXT / TextTrimList