Obsah / Utility / TEXTFORM / FormDateTimeN
Zdrojový kód: INCLUDE\UTIL\TEXTFORM.INC, UTIL\TEXTFORM.ASM
Související:
Formátovací řetězec funkce FormDateTime | ||
FormDateTime | Zformátování data a času do bufferu | |
FormAbsDateTimeN | Délka formátovaného textu absolutního času |
FormDateTimeN - Délka formátovaného textu data a času
Funkce FormDateTimeN zjistí délku zformátovaného textu data a času v bufferu.
|
Na vstupu funkce obsahuje registr EAX ukazatel na strukturu DATETIME s připravenými položkami údaje data a času. Nepoužité položky nemusí být platné. Registr EBX obsahuje délku zdrojového textu v bajtech. Registr ECX obsahuje ukazatel na popisovač národnostních informací NATIONAL. Ke zjištění implicitního popisovače národnostních informací lze použít makro DEFAULT_NAT. Registr EDX obsahuje ukazatel na zdrojový text ke zformátování. Zdrojový text je v kódu UTF-8. Na výstupu obsahuje registr ESI délku textu v bajtech.
|
Na začátku funkce jsou uschovány registry do zásobníku a ukazatel na strukturu DATETIME se připraví do registru EBP. Původní obsah registru ECX (tj. ukazatel na národnostní informace NATIONAL) zůstává přístupný přes zásobník jako lokální proměnná FDTNat. Tato proměnná je shodná s funkcí FormDateTime a proto musí být registry do zásobníku uschovány stejně. Registr ESI je vynulován a bude představovat střadač délky textu.
|
Dekrementací registru EBX se ověří, zda je ve zdrojovém bufferu připraven další znak. Pokud ne, funkce se ukončí. Jinak se z ukazatele EDX načte další zdrojový znak a ukazatel se inkrementuje.
|
Interpretace formátovacích znaků data a času závisí na tom, kolik znaků je za sebou uvedeno, proto je nutno spočítat za sebou následující stejné znaky. Čítač ECX se připraví na hodnotu 1 (první znak který byl načten). V cyklu se opakovaně testuje, zda je následující znak stejný jako dříve načtený znak a pokud ano, posunou se ukazatele a zvýší se čítač shodných znaků ECX. Cyklus se ukončí nalezením rozdílného znaku nebo nalezením konce zdrojového textu.
|
Po zjištění počtu znaků se provede skok na obsluhu znaku pomocí skokové tabulky FormDateTimNJmp, pouze znaky uvozovek se obslouží samostatně. Neplatné znaky zvýší střadač délky textu ESI o ECX znaků.
|
Znaky jednoduchých a dvojitých uvozovek ' a " uvozují text, který se do cílového bufferu uloží v nezměněném tvaru. Jsou-li tyto znaky uvedeny opakovaně za sebou, znamenají platný znak. Proto je počet znaků v registru ECX snížen na polovinu. Pokud nezůstal žádný lichý znak uvozovek, šlo pouze o platné znaky a ty se přičtou ke střadači délky textu. Pokud zůstal lichý znak, ale přitom byly zadány i platné párové znaky, lichý znak se navrátí (zpracování textu se nechá na později) a přičtou se nejdříve pouze párové znaky uvozovek.
V cyklu pro zpracování textu uvnitř uvozovek se testem registru EBX ověří, zda je připraven další znak ve zdrojovém bufferu. Pokud není, funkce se ukončí. Je-li připraven znak, načte se do registru AL a ukazatel EDX a čítač EBX se posunou.
Není-li nový znak shodný se znakem uvozovek (který je uchován v registru AH), inkrementuje se čítač délky textu.
Pokud byl nalezen znak uvozovek, otestuje se zda je připraven další zdrojový znak. Pokud ne, byl konec textu platný a funkce se ukončí. Je-li připraven další znak, zkontroluje se zda je to opět znak uvozovek. Pokud ano, je to platný znak uvnitř textu a tento znak uvozovek se přičte ke střadači textu. Je-li to jiný znak, obsluha textu v uvozovkách je ukončena.
|
Znak "h" označuje hodiny ve 12-hodinovém cyklu. Do registru AL se připraví údaj hodin. Přičtením 11 se údaj dekrementuje (aby mohl být výsledek v rozsahu 1 až 12), instrukcí AAM se převede do intervalu 0 až 11 a inkrementací se převede do intervalu 1 až 12 a přejde se na obsluhu zjištění délky čísla.
|
Znak "H" označuje hodiny ve 24-hodinovém cyklu. Do registru EAX se připraví údaj hodin a přejde se na obsluhu zjištění délky čísla.
|
Znak "d" označuje den v měsíci nebo den v týdnu. Je-li počet znaků "d" 1 nebo 2, jedná se o označení dne v měsíci. Do registru EAX se načte číslo dne v měsíci a přejde se na zjištění délky čísla.
Je-li počet znaků 3, jedná se o označení dne v týdnu v krátkém formátu jmen (3 znaky). Pro větší počet znaků se použije dlouhý formát jmen. Do registru EAX se připraví offset textu ve struktuře národnostních informací a s jeho pomocí se do registru ECX načte ukazatel na textová data s příslušným textem.
Do registru EAX se připraví délka textu. Z důvodu shody s obsluhou FormDateTime se délka načte jako bajt. Délka textu se přičte ke střadači délky.
|
Znak "a" označuje absolutní den v roce. Do registru EAX se připraví číslo dne v roce a inkrementací se posune na bázi 1. Voláním funkce UDWToTextBufN se zjstí délka textu čísla a přičte se ke střadači délky ESI.
|
Znak "m" označuje minuty. Do registru EAX se připraví údaj minut a přejde se na obsluhu zjištění délky čísla.
|
Znak "M" označuje měsíc. Do registru EAX se připraví údaj měsíce. Je-li počet znaků "M" 1 nebo 2, přejde se na obsluhu zjištění délky čísla.
Do registru AL se připraví offset tabulky jmen měsíců - pro 3 znaky tabulka krátkých jmen (3 znaky), pro 4 znaky tabulka dlouhých jmen ve skloňovaném tvaru pro použití v datu a pro více znaků tabulka jmen v 1. pádu. Poté se přejde na zjištění délky textu, registr ECX obsahuje index textu.
|
Znak "g" představuje označení letopočtu. Pro 1 znak "g" se do registru AL připraví offset krátkého označení letopočtu a pro více znaků offset dlouhého označení letopočtu. Testem absolutního čísla roku se rozliší, zda se jedná o rok našeho letopočtu nebo před naším letopočtem a podle toho je nastaven obsah registru na hodnotu 0 nebo 1. Poté se přejde na obsluhu zjištění délky textu.
|
Znak "t" představuje označení dopoledne nebo odpoledne. Pro 1 znak "t" se do registru AL připraví offset krátkého označení a pro více znaků offset dlouhého označení. Testem hodiny se rozliší, zda se jedná o dopoledne nebo odpoledne a podle toho je nastaven obsah registru na hodnotu 0 nebo 1. Poté se přejde na obsluhu zjištění délky textu.
|
Znak "s" označuje sekundy. Do registru EAX se připraví údaj sekund a přejde se na obsluhu zjištění délky čísla.
|
Znak "w" označuje číslo týdne v roce. Do registru EAX se připraví údaj čísla týdne v roce a přejde se na obsluhu zjištění délky čísla.
|
Znak "y" označuje číslo roku v absolutním tvaru (bez rozlišení letopočtu). Do registru EAX se připraví rok a upraví se rok před naším letopočtem na kladný údaj s bází 1.
Jsou-li zadány více než 3 znaky, není číslo nijak upravováno a přejde se přímo na obsluhu čísla s tím, že počet znaků udává minimální počet číslic. Pro menší počet znaků odpovídá skutečná délka čísla počtu znaků, takže může být střadač délky textu o tuto hodnotu přímo zvýšen.
|
Znak "Y" označuje číslo roku ve znaménkovém tvaru (rok před naším letopočtem má číslo 0, -1, -2, ...). Do registru EAX se připraví rok a pomocí funkce SDWToTextBufN se zjistí délka čísla.
|
Znak "f" označuje zlomkovou část sekund bez odstranění koncových nul. Počet znaků přitom odpovídá počtu číslic, takže může být střadač délky textu o tuto hodnotu přímo zvýšen.
|
Znak "F" označuje zlomkovou část sekund s odstraněním koncových nul. Pomocí funkce FormDateZFracN se zjistí délka čísla a ta se přičte ke střadači ESI..
|
Znak "j" označuje Juliánské datum a čas bez ořezání koncových nul. Počet znaků "j" představuje počet desetinných míst.
Datum a čas ve struktuře DATETIME se pomocí funkce DateTimeToAbs zkonvertuje na absolutní čas v registrovém páru EDX:EAX. Pomocí funkce AbsToJulian se zkonvertuje na Juliánský čas do registru ST0.
Do registru BL se načte požadovaná přesnost a pomocí funkce FltToTextBufN se zjistí délka textu čísla, která se přičte ke střadači ESI. V registru EBX je přitom nastaven příznak velkého písmene, který zajistí, že číslo se zaokrouhluje vždy dolů. Nakonec se číslo uvolní instrukcí ffreep ze zásobníku koprocesoru.
|
Znak "J" označuje Juliánské datum a čas s ořezáním koncových nul. Počet znaků "J" představuje počet desetinných míst.
Datum a čas ve struktuře DATETIME se pomocí funkce DateTimeToAbs zkonvertuje na absolutní čas v registrovém páru EDX:EAX. Dále se pokračuje společnou částí s obsluhou znaku "j" s tím rozdílem, že parametry v registru EBX zajistí ořezání koncových nul.
|
Funkce FormDateZFracN zjistí délku zlomkové části sekund s ořezáním koncových nul. Funkce je volána během obsluhy znaku "F". Na vstupu funkce obsahuje registr ECX požadovaný počet číslic. Registr ESI obsahuje střadač délky textu. Funkce zničí obsah registrů EAX a ECX.
|
Údaj zlomku sekund bude do bufferu ukládán od vyšších číslic, číslic bude maximálně 9. Proto se údaj převede na desetinné číslo a to tak, že se počet nanosekund vydělí číslem 1 000 000 000 (tedy maximálním možným údajem počtu nanosekund, tím se údaj dostane do rozsahu 0 až 0,999999999). Převod se provede vynásobením číslem 1 0000 0000 0000 0000h / 1 000 000 000 (ve 2 oddělených krocích), tím se v registrech EBX:EAX obdrží požadované desetinné číslo.
|
Požadovaný počet číslic se omezí na maximální povolenou hodnotu 9 a uschová se do registru EBP.
|
Číslice se postupně dekódují a to tak, že vynásobením desetinného čísla číslem 10 přeteče přes rozsah QWORD nová číslice.
Ořezání koncových nul je zajištěno tak, že vyskytne-li se v čísle nula, číslice se nezapočítává a pouze se dekrementuje čítač číslic ECX.
Vyskytne-li se v čísle nenulová číslice, je rozdílem registrů EBP a ECX zjištěn počet chybějících číslic a ty jsou přičteny ke střadači ESI.
Obsah / Utility / TEXTFORM / FormDateTimeN