MASARYKOVA UNIVERZITA FAKULTA INFORMATIKY
Knihovny pro práci v jazyce C se "znaky" a řetězci v kódování UTF-8 BAKALÁŘSKÁ PRÁCE
Lukáš Meloun Brno, jaro 2011
Vedoucí práce: RNDr. Aleš Zlámal
Prohlášení Prohlašuji, že tato bakalářská práce je mým původním autorským dílem, které jsem vypracoval samostatně. Všechny zdroje, prameny a literaturu, které jsem při vypracování používal nebo z nich čerpal, v práci řádně cituji s uvedením úplného odkazu na příslušný zdroj.
Shrnutí Řetězce jsou v programovacím jazyce C reprezentovány polem znaků. Jednotlivé znaky představují konkrétní posloupnosti bitů, které jsou charakteristické pro dané kódování. Cílem této bakalářské práce je vytvořit přehled existujících knihoven pro práci s řetězci a znaky v kódování UTF-8, vybrat nejvhodnější a detailně je představit.
Klíčová slova ICU4C, UTF-8, Unicode, programovací jazyk C, znaková sada, kódování znaků
Obsah 1. Úvod
............................................. 1
1.1. Cíle práce a metodika ........................ 1 1.2. Struktura .......................................... 1 1.3. Kódování UTF-8 a programovací jazyk C 1 2. Definice použitých pojmů ....... 4 2.1. Znaková sada
.................................... 4
2.1.1. Unicode ........................................ 4 2.2. Kódování znaků ................................ 4 2.2.1. Široké znaky ................................. 4 2.2.2. Vícebajtové znaky ........................ 5 3. Analýza vybraných knihoven . 7 3.1. Požadavky ........................................ 7 3.2. Ustanovení specifických kritérií ....... 7 3.2.1. Zajištění funkcionality dodávané standardní knihovnou jazyka C 3.2.2. Další nabízená funkcionalita ....... 10 3.2.3. Portabilita .................................... 10 3.2.4. Dostupná dokumentace ................ 11 3.2.5. Podpora ........................................ 11 3.2.6. Korektnost, ošetření výjimek a jiné 12 3.3. Východiska a dostupné zdroje .......... 12 3.4. Kandidátské knihovny ...................... 14
7
3.4.1. GNU C Library ............................ 14 3.4.2. Libiconv ....................................... 15 3.4.3. Libutf8 .......................................... 16 3.4.4. Utf8proc ....................................... 17 3.4.5. Další knihovny ............................. 18 3.5. Nejlépe ohodnocená knihovna .......... 19 3.5.1. ICU4C .......................................... 19 4. Instalace ...................................... 23 4.1. Softwarové požadavky ...................... 23 4.2. Binární soubory ................................ 23 4.3. Nastavení nástroje Microsoft Visual Studio 5. Referenční příručka .................. 25
23
5.1. Výstupní formát ............................... 25 5.2. Organizace funkcí a jejich popis ....... 25 v
Knihovny pro práci v jazyce C se "znaky" a řetězci v kódování UTF-8 6. Závěr 1. Příloha
............................................ 27 ......................................... 28
vi
Kapitola 1. Úvod 1.1. Cíle práce a metodika V rámci této bakalářské práce jsou analyzovány a podrobně popsány knihovny programovacího jazyka C pro práci s řetězci a znaky v kódování UTF-81 (UCS Transformation Format). Na demonstrativních příkladech jsou odhaleny jejich přednosti a nedostatky, u vybraných z nich jsou nalezena moţná rozšíření a ta jsou následně v prostředí jazyka C implementována. Dle stanovených kritérií jsou zvoleni nejvhodnější kandidáti, jejichţ výčet a příslušný popis je přístupný prostřednictvím uţivatelské referenční příručky ve formě webových stránek splňujících základní poţadavky pro dobře strukturovaný web. Za účelem lepší dostupnosti získaných poznatků je příručka zároveň přeloţena i do anglického jazyka. Jako nástroj pro analýzu jednotlivých knihoven zde slouţí především teoretické znalosti chování korektních funkcí pro práci s řetězci a znaky s ohledem na zvolené národní prostředí. Teoretické výsledky jsou podloţeny praktickou ukázkou konkrétních příkladů. Nutno poznamenat, ţe v rozsahu této práce nejsou detailně vysvětleny principy kódování UTF-8, a proto je vhodné tuto oblast nejprve dobře nastudovat. Techniky pouţití tohoto kódování v POSIX systémech (Linux, Unix) ve svém odborném článku na webových stránkách University of Cambridge velice vyčerpávajícím způsobem vysvětluje Dr. Markus Kuhn [4].
1.2. Struktura Úkolem úvodní kapitoly je vytyčit cíle této bakalářské práce, stručně popsat její kompletní obsah, představit základní principy a motivaci pro pouţívání kódování UTF-8 a provést základní charakteristiku vývoje jazyka C. V rámci druhé kapitoly se pozornost přesouvá k podrobnému popisu odborných pojmů pouţitých v této práci. Jsou definovány pojmy znaková sada a kódování znaků. Jejich pochopení je pro porozumění dané problematiky nezbytné, neboť se od nich odvíjí mnoho dalších terminologických pojmů. Třetí kapitola se věnuje analýze vybraných knihoven. Nejprve jsou stanova pevná kritéria, dle kterých jsou následně jednotlivé balíčky hodnoceny, jejich případné nedostatky pojmenovány a jejich přednosti zvýrazněny. Zároveň je uvedeno, jaké zdroje byly pro získání analyzovaného materiálu pouţity. Čtvrtá kapitola souhrnně popisuje návod pro instalaci zvolené nejvhodnější knihovny. Text doprovází názorné ukázky představované konkrétními snímky z vývojového prostředí pro programovací jazyk C. Šestá kapitola se zaměřuje na představení přiloţené referenční příručky dokumentující funkce pro práci se zvoleno knihovnou. Na vybrané funkci je demonstrováno, jakým způsobem je provedena její charakteristika a popis vstupních parametrů a návratových hodnot. V sedmé kapitole je zhodnocen přínos této práce a představena cílová skupina, pro kterou je určena. Na úplný závěr je ponechána diskuse na téma vize a další vývoj standardní knihovny jazyka C. Krátká zmínka je věnována připravovanému standardu C1X, který plánuje rozšířit knihovnu o podporu kódování UTF-8.
1.3. Kódování UTF-8 a programovací jazyk C 1.
1
Terminologický pojem kódování2 v kontextu této bakalářské práce představuje způsob transformace číselného kódu znaku do uspořádané posloupnosti bitů. Algoritmy pro různá kódování se mohou lišit, o čemţ však bude zmínka později. Při pohledu do roku 1963 zaznamenáváme vznik první verze ASCII (American Standard Code for Information Interchange), později ISO 646, která poloţila základy její rozšířené verzi ISO 8859 pro evropské jazyky a ISO 2022 pro východoasijské jazyky. Obě zachovávají původní mohutnost 256 znaků, avšak jejich rozloţení se liší. Středem našeho zájmu jsou především kódování pro evropské státy, nicméně zmíněny jsou i ostatní. Rodina ISO 8859 je v našem prostředí velice známá a často pouţívaná. Mezi její členy patří např. ISO 8859-2, obsahující znaky pro středoevropské státy, ISO 8859-1, pouţívaná v západoevropských zemích, která je mimo jiné první znakovou sadou odvozenou od ISO 8859. Takto lze jmenovat několik desítek dalších uspořádaných mnoţin znaků (ISO 8859-3, ISO 8859-4 a další). Jelikoţ sada ASCII je velice populární, byla převzata i asijskými státy a vznikly tak sady TIS 620 (Thai Industrial Standard), ISCII (Indian Script Code for Information Interchange), VISCII (Vietnamese Standard Code for Information Interchange) anebo JIS X 0201 (Japanese Industrial Standards). Nicméně ne všechny firmy telekomunikačního a počítačového průmyslu respektují a pouţívají výše zmíněné standardy. Americká společnost IBM3 (International Business Machines) si můţe díky svému dominantnímu postavení na trhu dovolit zavést svůj vlastní, zprvu šestibitový, kód BCDIC (Binary Coded Decimal Interchange Code), později osmibitový EBCDIC (Extended Binary Coded Decimal Interchange Code) a zřejmě si tak strategicky udrţovat a získávat nové klienty. Podobný obchodní tah provádí i Microsoft a Apple. Jiţ platné standardy rodiny ISO 8859 nepouţívá a vytváří své vlastní. V jazyce C je moţné programovat široce portabilní systémy a aplikace, ovšem problém nastává v případech, kdy je poţadováno vyvinout programy korektně fungující nejen na strojích různé architektury a operačního systému, ale zároveň je očekáváno, ţe veškeré znaky, které je třeba tisknout na obrazovku, budou správně interpretovány. Při pouţití sady ASCII tento problém nelze jednoduše řešit. Motivace pro odstranění těchto nedostatků je umocněna v osmdesátých letech minulého století, coţ přímo souvisí s rozvojem internetové sítě a potřebou šířit aplikace po celém světě. Ukazuje se, ţe řešení mnoha stovek odlišných znakových sad je silně nevyhovující a je třeba je sjednotit a vytvořit tak jednu velkou obsáhlou znakovou sadu. Paralelně jsou vypracovávány tři nezávislé projekty: ISO/IEC 10646 (International Organization for Standardization a International Electrotechnical Commission) v roce 1984 TRON v roce 1984 Unicode Consortium v roce 1988 Co se týče multijazyčné sady TRON, je dobré ji zmínit, nicméně nemá smysl se s ní dále více seznamovat, jelikoţ její struktura a rozloţení znaků je optimalizováno pro východoasijské státy (Čína, Japonsko, Korea), a zajímat se budeme především o západní státy. 2. 3.
2
Často je mylně zaměňován pojem Unicode a ISO 10646. Přestoţe obě znakové sady jsou dnes jiţ v obou směrech kompatibilní a je moţné mezi sebou jednotlivé znaky převádět, v určitých aspektech se liší. Kaţdá z nich je schopna obsáhnout všechny pouţívané znaky nehledě na národní a kulturní prostředí, nicméně neplatí tvrzení, ţe stejný znak je v obou sadách reprezentován stejným číselným kódem. Jelikoţ většina současných verzí ASCII a jejich odnoţí je osmibitová, není třeba aplikovat ţádné sofistikované kódování, kaţdý znak je uloţen v jednom bajtu. Co se týče ISO 10646 a Unicode, jeden znak můţe být uloţen ve více bajtech. Na základě tohoto principu bylo navrţeno kódování UTF-8, UTF-16, UTF-32, UCS-2, UCS-4. UTF-8 a UTF-16 se však liší od UTF-32 a skupiny UCS (Universal Character Set) proměným počtem bajtů, do kterých je příslušný znak uloţen, tj. je alokováno tolik bajtů, kolik je nezbytně nutné, zatímco pro UCS platí, ţe pro všechny zakódované znaky je vyhraněn stejný počet bajtů. Toto je výhoda kódování UTF-8 a UTF-16, neboť díky úspoře bajtů je moţné výrazně sníţit objem dat textových dokumentů, coţ zavádí motivaci pro vypracování této bakalářské práce, tj. analyzovat dostupné knihovny pro jazyk C pro práci s řetězci a znaky v kódovaní UTF-8. Tímto jsme na úvod provedli základní charakteristiku vybraných znakových sad a k nim příslušících kódování4. Prostor je téţ ponechán lehkému seznámení s programovacím jazykem C. V letech 1969-1973 byl uveden programovací jazyk C jako široce portabilní nástroj pro vývoj především operačních systémů Unix, díky čemuţ se stal velice populární. Na základě jeho předchůdců B5 a BCPL6 (Basic Combined Programming Language) lze odvodit, ţe se jedná o imperativní jazyk. Po šesti letech od svého uvedení Brian Wilson Kernighan a Dennis MacAlistair Ritchie sepsali podrobný manuál ve své knize The C Programming Language [1], avšak svého prvního oficiálního standardu ANSI X3 (ANSI C), se dočkal aţ v osmdesátých letech. Jelikoţ ANSI7 (American National Standards Institute) je pouze národní instituce, ANSI C byl z důvodu zajištění dalšího vývoje standardizace osvojen mezinárodní organizací ISO8 (International Organization for Standardization) a po drobných úpravách přejmenován na ISO/IEC 9899:1990 (C90). Jazyk C prošel dalšími standardizacemi, přičemţ od roku 2007 je plánované uvést nový standard C1X. Samotný jazyk C ve své podstatě poskytuje jen úzkou paletu nástrojů, pomocí které lze však programovat systémy na velice nízké úrovni, tj. C spadá do kategorie nízkoúrovňových programovacích jazyků. Na druhou stranu postrádá hotové rozhraní pro komunikaci s okolím (vstupní, výstupní operace apod.). Z tohoto důvodu je třeba vyuţít soustavu hlavičkových souborů ze standardní knihovny pro jazyk C. Ta je podporována všemi překladači (GNU Compiler Collection9, Intel C++ Compiler10, Microsoft Visual Studio11, C++ Builder12 či Watcom C/C++13), které dodrţují standard ANSI C, a obsahuje nejen procedury potřebné pro komunikaci s okolním světem, ale i mnoho dalších (např. matematické funkce, konverze mezi datovými a časovými formáty, zpracování chybových kódů generovaných procedurami standardní knihovny či práce s řetězci a znaky). Nicméně tato knihovna neobsahuje funkce pro práci s řetězci a znaky podporující kódování UTF-8. Z tohoto důvodu je třeba najít knihovny, které tuto podporu dodávají. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13.
3
Kapitola 2. Definice použitých pojmů 2.1. Znaková sada Tento termín ve své podstatě definuje dva lehce odlišné pojmy. Prvním z nich, který však není v rámci této práce příliš důleţitý, charakterizuje znakovou sadu jako neuspořádanou mnoţinu všech existujících znaků, které jsou širokou veřejností uznávány a pouţívány. Takové znaky mohou být reprezentovány písmeny, číslicemi, interpunkčními znaménky, matematickými symboly, chemickými značkami a dalšími speciálními znaky. Motivací pro zadefinování znaků je mít k dispozici nástroj pro uchopení informace. V kaţdém případě se však jedná o její abstrakci, kterou je moţné interpretovat lehce odlišnými vizuálními podobami. Nicméně vţdy musí být moţné daný znak rozpoznat a odlišit ho od ostatních. Typickým příkladem je změna pouţitého fontu. Podoba znaku se změní, přesto však zachovává jeho abstrakci a lze ho správně pojmenovat. Druhý způsob, který je pro následující část kapitoly výchozí, definuje znakovou sadu jako uspořádanou mnoţinu vybraných znaků omezenou ve smyslu svého moţného rozsahu. Důvodem tohoto omezení jsou hardwarové prostředky, které jsou v současné době k dispozici. Jednotlivé znaky, ke kterým jsou přiřazeny unikátní celé kladné číselné hodnoty, lze kombinovat a definovat pomocí nich další. Mnoho znakových sad1 (např. rodina ISO 8859 nebo znaková sada MS Windows), které se dnes pouţívají, jsou osmibitové a poskytují tedy 256 pozic. Ty přímo či nepřímo vycházejí z jiţ zmíněné sady ASCII. Existují ovšem i jiné sady, které nabízejí mnohem větší prostor. [5]
2.1.1. Unicode Jedná se o konkrétní typ znakové sady2, jeţ vznikla na základě potřeby uchovávat všechny námi definované znaky (viz 2.1 Znaková sada), v jedné společné struktuře. Její mohutnost činí 1 114 112 pozic, které však nejsou všechny obsazeny. Pro zajištění zpětné kompatibility je rozvrţení prvních 128 pozic shodné s ASCII. Ze stejného důvodu je rozloţení znaků na následujících 128 pozicích stejné jako v ISO 8859-1. Jak jiţ bylo v úvodu zmíněno, projekt Unicode byl navrhován v přibliţně stejné době jako ISO/IEC 10646 3. Od chvíle jejich spolupráce jsou oba standardy vyvíjeny tak, aby bylo moţné mezi nimi jednotlivé znaky bez jakýchkoliv omezení převádět. S postupem času přibývají nové znaky, které jsou zároveň přidávány i do sady Unicode. Ţádná tato úprava však nikterak nezmění strukturu doposud obsazených pozic, není tedy třeba obávat se, ţe dříve navrţená aplikace pouţívající sadu Unicode přestane z tohoto důvodu korektně pracovat.
2.2. Kódování znaků Ve chvíli, kdy je zadefinována konkrétní znaková sada, je třeba zváţit, jaký algoritmus aplikovat pro převod číselného kódu určitého znaku do binární formy. V případech, kdy je sada nejvýše osmibitová, tj. obsahuje 256 znaků, je převod triviální, neboť kód kteréhokoliv znaku lze zakódovat do jednoho bajtu, tj. do osmi bitů. V ostatních situacích je nutné převést ho do dvou a více bajtů, coţ způsobuje komplikace spojené s rozlišením jednotlivých znaků řetězce a práce s těmito znaky.
2.2.1. Široké znaky 1. 2. 3.
4
Tento termín označuje všechny typy kódování pouţívající pro převod kaţdého znaku v souboru do binární podoby dva a více bajtů, přičemţ počet těchto rezervovaných bajtů je pro kaţdý znak stejný (např. kaţdý znak v souboru je kódován do 16 bitů). Široké znaky jsou implementovány např. v těchto kódováních: UCS-2, dva bajty pro kaţdý znak UCS-4, čtyři bajty pro kaţdy znak UTF-32, čtyři bajty pro kaţdy znak Výhodou tohoto způsobu kódování je snadná manipulace s jednotlivými znaky a rychlé operace nad nimi. Na druhou stranu ne všechny znaky ve skutečnosti potřebují více bajtů pro jejich přepis, zbývající bajty tedy nebudou vůbec pouţity.
2.2.2. Vícebajtové znaky Pod tímto pojmem se rozumí kódování znaků do sekvence bajtů různé délky. Je vţdy vybrána taková velikost, která je nezbytně nutná pro převod číselného reprezentanta znaku do posloupnosti bitů. Jelikoţ znaky, které jsou nejčastěji pouţívány, jsou umístěny na prvních pozicích většiny pouţívaných sad a jejich číselný kód má tedy nízkou hodnotu, pro jejich zakódování postačí jeden bajt. Tímto způsobem je moţné ušetřit signifikantní počet jednotek datového prostoru, neboť bajty, které jsou pro totoţnou sadu znaků v kódování širokých znaků rezervovány, ale nevyuţity, nejsou v případě kódování vícebajtových znaků vůbec alokovány. Nicméně toto řešení přináší i jisté nevýhody, jelikoţ není explicitně zřejmé, kolik bajtů je pro jednotlivé znaky vyhrazeno. Znaky totiţ mohou mít různou délku. Některé operace nad takovými řetězci jsou časově náročnější neţ nad řetězci kódovanými nad širokými znaky. Níţe je uvedeno několik typů vícebajtových kódování pro Unicode. UTF-8, znaky kódované v jedné či více osmibitových sekvencích UTF-16, znaky kódované v jedné či více šestnáctibitových sekvencích Smyslem této podkapitoly je zaměřit se na kódování UTF-8 a provést jeho podrobnější charakteristiku. Bylo navrţeno pro sadu Unicode čítající přes jeden milion znaků. Maximální moţný rozsah, který dovoluje definovat za pouţití 6 bajtů, je 0 aţ 7FFFFFFF (zapsáno v hexadecimální soustavě). V současné době se však standardně pouţívá jeden aţ čtyři bajty. Ty mimo informace o kódovaném znaku obsahují i příznak toho, kolik bajtů je pro daný znak vyhrazeno a kde je počátek kaţdého z nich. Příznaky prvního bajtu mají tuto pevně definovanou posloupnost bitů: 0, 110, 1110, 11110, 111110 nebo 1111110. Posloupnost 0 určuje, ţe znak je zakódovaný do jednoho bajtu, posloupnost 1111110 předepisuje pouţití šesti bajtů. Kaţdý následující bajt je na svém počátku definován sekvencí 10, čímţ jsou od sebe jednotlivé oktety odlišeny. Z doposud zmíněné charakteristiky je moţné odvodit, jaké obecné rozloţení bitů májí znaky z rozsahu své pozice 0 aţ 128. Tento konkrétní bajt 0xxxxxxx, kde x představuje volný bit, má první pozici pevně vyhrazenou sekvencí 0 a ostatních 7 bitů volných pro zápis reprezentanta znaku v binární podobě. Tento prostor nabízí 2^7 moţných kombinací. Toto řešení bylo záměrně takto navrţeno, aby prvních 128 5
znaků ze sady Unicode, kódovaných prostřednictvím UTF-8, bylo kompatibilních se sedmibitovou verzí sady ASCII. Do dvou bajtů jsou kódovány znaky latinky s diakritikou, azbuky a koptské, arménské, hebrejské, arabské, syrské a thaanské abecedy. Do tří bajtů se kódují ostatní známé znaky pouţívané ve více jazycích a v posledním případě jsou do čtyř bajtů ukládány například čínské, japonské či korejské znaky a jiné vzácně pouţívané. Unicode spolu s UTF-8 je prohlašován za univerzální znakovou sadu a kódování. Nicméně pokud nebude tento standard respektován a pouţíván na většině platforem, systémů, aplikací a v internetové síti, nebude mít tento projekt příliš velký význam. Za poslední léta se však naštěstí toto kódování úspěšně rozšiřuje a tím naplňuje svou vizi -univerzální nástroj pro kódování všech existujících znaků do transportních kanálů a datových uloţišť.
6
Kapitola 3. Analýza vybraných knihoven 3.1. Požadavky Externí knihovna programovacího jazyka C rozšiřuje stávající vývojové prostředí o nové nástroje, které umoţňují programátorům psát systémy, aplikace a jiné programy podporující kódování UTF-8. Ti i nadále mají k dispozici minimálně stejně široké spektrum funkcí a maker pro práci s řetězci a znaky v tomto kódování jako nabízí standardní knihovna jazyka C [2]. Knihovna případně dodává další rozšiřující funkce, jejichţ vyuţití je přínosné a přímo souvisí s novými moţnostmi, které s sebou kódování UTF-8 přináší. Pro úsporu času je navíc programátor schopen snadno a rychle se v ní orientovat, bez potíţí vyuţít její moţnosti. K tomuto účelu má k dispozici manuálové stránky (dále referenční příručka) s podrobným popisem jednotlivých funkcí a příkladnými ukázkami. V případě, ţe v nich nenachází hledané informace, druhou moţností nápovědy je navštívení s diskusního fóra související s tématem, oficiálních stránek apod. Není zcela vyloučeno, ţe obecné principy a algoritmy, na kterých je postavena příslušná znaková sada a kódování, mohou být více či méně poupraveny. Na tuto situaci je schopen autor knihovny patřičně zareagovat a vzniklé nesrovnalosti opravit. Stejná odezva je očekávána při zjištění nově nalezené chyby. Autorovou iniciativou je daný nedostatek odstranit. Takových případů se však při práci s knihovnou vyskytuje minimální mnoţství a v ţádném případě by neměla způsobit vaţné škody.
3.2. Ustanovení specifických kritérií Námi zvolená kritéria slouţí jako parametry pro hodnocení a ocenění jednotlivých knihoven, z nichţ je nakonec vybrán nejvhodnější kandidát. Je snahou zvolit taková kritéria, která protínají co nejširší spektrum pouţitelnosti (od méně zkušených programátorů po náročné vývojáře zabývající se velice detailními a specifickými rysy). Méně pokročilí mohou vybírat knihovny, jejichţ uţivatelské rozhraní zachovává transparentnost a pouţití je na první pohled zřejmé, zatímco experti mohou vyhledávat balíčky, které dodávají širokou funkcionalitu a zaručují portabilitu v rámci operačních systémů a strojů, pro které jsou programy navrhovány. Je velmi pravděpodobné, ţe potencionálních vývojářů, hledajících vhodnou knihovnu jazyka C pro práci s řetězci a znaky v kódování UTF-8, je velké mnoţství. Zkušenosti a znalosti jednotlivých vývojářů se však s jistotou liší, proto není snadné stanovit priority jednotlivých kritérií při hodnocení konkrétních knihoven. Za ideální lze povaţovat takovou, která nabízí více úrovní pouţití - nezbytné základní, na první pohled velice zřejmé, funkce spolu s pokročilými, které v jistém slova smyslu rozšiřují moţnosti práce s řetězci a znaky. Tyto dvě úrovně však zůstávají odděleny a nejsou na sobě přímo závislé.
3.2.1. Zajištění funkcionality dodávané standardní knihovnou jazyka C Jak bylo zmíněno v úvodu práce, programovací jazyk C jiţ existuje pár desítek let a bylo vydáno několik standardů pro práci s ním. Nyní se však odkazujeme na aktuálně platný standard ISO/IEC 9899:1999, neboť je dobré respektovat společné konvence a vyvíjet tak kvalitní software. Od počátku standardizace jazyka C je snahou pečlivě zdokumentovat standardní knihovnu a práci s ní. Ta je v současné době podporována drtivou většinou překladačů a většina programátorů se s ní prakticky neustále setkává, neboť její vyuţívání přispívá především k portabilitě finálních aplikací a systémů. Tato knihovna však podporuje práci pouze se znaky z tabulky ASCII, tedy znaky kódované do osmi bitů. Nicméně v nedávné 7
době došlo k její rozšíření a byly definovány nové funkce pro práci s širokými znaky. Jejich názvy se téměř shodují s funkcemi pro práci s osmibitovými znaky. Před jejich název byla přidána předpona wcs (wide character string). Funkcionalita je zachována, rozdíl je tedy pouze ten, ţe jejich vstupními parametry jsou řetězce sloţené z širokých znaků. Stávající funkce byly totiţ nedostačující a nedokázaly s nimi pracovat. Mezi zmíněnými funkcemi lze však nalézt takové, které v jistém slova smyslu nejsou závislé na konkrétním kódování [2] (nejen s osmibitovými znaky pracují korektně). Přesto je třeba dodrţovat konvenci ukončování kaţdého znaku binární nulou -- ukončovacím znakem. Proveďme výčet některých takových funkcí:
void * memcpy ( void * destination, const void * source, size_t num ); Funkce kopíruje binární data z paměťového prostoru proměnné source do prostoru proměnné destination. Mnoţství kopírovaných dat určuje hodnota třetího argumentu num v jednotkách bajtů (přehlíţí význam binární nuly, ta je kopírována stejným způsobem jako ostatní data bloku). Tuto funkci lze aplikovat i na znakové řetězce kódované v UTF-8, neboť není rozlišováno, jakého typu jsou vstupní argumenty. Pouze binární data, o jejichţ sémantice funkce nic neví, jsou kopírována po sekvencích bytů.
char * strcpy ( char * destination, const char * source ); Funkce kopíruje celý řetězec uloţený v proměnné source do vyhrazeného prostoru proměnné destination. Délka kopírovaného řetězce je určena binární nulou, která definuje jeho konec. Přestoţe tato funkce je navrţena pro osmibitové znaky, je moţné jejím prostřednictvím provádět stejnou operaci i nad vícebajtovými znaky kódované v UTF-8. Ty jsou reprezentovány jedním a více bajty. Jeden znak se můţe na výstupním zařízení zobrazit jako více nesmyslných znaků, nicméně jejich struktura je při kopírování zachována a po opětovném čtení zkopírovaného řetězce pomocí nástroje podporujícího kódování UTF-8 řetězec odpovídá původní podobě. Jeho správnou interpretaci v tomto případě opět zajišťuje schéma pevně definovaných horních bitů (viz obrázek 1.1). Je však třeba pamatovat, ţe velikost vícebajtového znaku se nerovná velikosti jednobajtového znaku. Při alokaci paměti je vhodné rezervovat prostor odpovídající strlen(source)+1 pozic. Jeden bajt navíc je rezervován pro ukončující znak.
char * strcat ( char * destination, const char * source );
8
Funkce spojuje dva řetězce v jeden. Vedoucí řetězec je určen proměnnou destination, za něj je připojen řetězec proměnné source, přičemţ jeho první znak nahrazuje ukončovací znak řetězce destination. I v tomto případě lze spojovat dva řetězce v kódování UTF-8, přestoţe při návrhu této funkce nebyla tato moţnost uvaţována. Jednotlivé znaky jsou opět rozloţeny na více osmibitových znaků, které při pouţití standardních výstupních funkcí jsou interpretovány jako nesmyslná posloupnost znaků, jen vzdáleně podobající se původnímu řetězci. Nicméně jednotlivé bajty (téţ znaky) jsou při zachování správného pořadí za sebe naskládány a opět uloţeny v posloupnost, která odpovídá kódování UTF-8. Konec řetězce je ukončen binární nulou. Při opětovném zobrazení vidíme oba poţadované řetězce spojené v jeden.
int memcmp ( const void * ptr1, const void * ptr2, size_tm num ); Funkce porovnává obsah dvou paměťových bloků určených ukazateli ptr1 a ptr2, jejichţ velikost je definována počtem bajtů v proměnné num. V našem případě porovnáváme dva řetězce, které jsou kódované stejným způsobem (vícebajtovými znaky). Jelikoţ kódování UTF-8 je deterministické, tj. kaţdý znak je reprezentován jedinečnou sekvencí bitů, binární data obou řetězců jsou shodná. Tato funkce porovnává jednotlivé bajty, ty se v tomto případě shodují.
int strcmp ( const char * str1, const char * str2 ); Funkce postupně, prvním počínaje, porovnává jednotlivé znaky řetězce proměnné str1 a řetězce proměnné str2, dokud nenarazí na odlišnou dvojici nebo u jednoho z řetězců dosáhne ukončovacího znaku. Jestliţe porovnání všech znaků proběhlo úspěšně a funkce nebyla ukončena předčasně, řetězce jsou prohlášeny za shodné. V konkrétních situacích, kdy jsou oba řetězce kódované v UTF-8, existují znaky reprezentovány více bajty (z pohledu této funkce více znaky). Tento fakt však není nikterak znepokojující, neboť tyto sekvence bitů bytů budou téţ stejné. Je vhodné zmínit moţné komplikace, které mohou nastat v souvislosti s ukončovacím znakem. Intuitivně je moţné usoudit, ţe mezi osmibitovými znaky získanými rozloţením vícebajtového znaku kódovaného v UTF-8 se můţe v jistých případech objevit sekvence bitů odpovídající binární nule, který ve výše zmíněných funkcích způsobí chybná vyhodnocení. Tento případ však nemůţe nastat, neboť, jak jiţ je patrné z uvedeného schématu kódování UTF-8, všechny vícebajtové znaky mají předpis takový, ţe mezi jejich horními bity se vyskytuje alespoň jeden s hodnotou 1 (viz obrázek).Pouze jednobajtové znaky mají svůj horní bit pevně definovaný hodnotou 0. Nicméně řídící UTF-8 znak reprezentovaný zápisem 0000000 (U+0000) odpovídá osmibitovému znaku ze sady ASCII, tj. představuje binární nulu.
9
3.2.2. Další nabízená funkcionalita Výrazným aspektem při hodnocení vybraných knihoven je i to, jakou rozšiřující funkcionalitu nabízejí. Moţností rozšíření je mnoho, některé jsou pro vývoj aplikací a systémů v kódování UTF-8 velice přínosné, zatímco implementaci jiných funkcí lze získat připojením dalších jednoduchých knihoven nebo pomocí jiţ dostupných nástrojů vytvořit vlastní. Z tohoto pohledu je porovnávání jednotlivých knihoven mezi sebou velice subjektivní a závislé na konkrétních případech. Jak jiţ bylo zmíněno, funkcionalita dodávaná standardní knihovnou jazyka C je pro základní práci s řetězci a znaky dostačující, nicméně způsob reprezentace znaků v kódování UTF-8 a zápis jednotlivých bajtů v jistých ohledech práci s těmito řetězci nepříjemně ztěţuje. Na druhou stranu lze díky ní snadno získat některé základní informace o konkrétních znacích. Jako demonstrativní příklad lze uvést práci s diakritickými znaménky. Zajímavostí kódování UTF-8 je vytváření sloţitějších znaků skládáním několika jednodušších. Např. české písmeno "ř" je moţné rozloţit na dva znaky "r" a "ˇ". Tímto způsobem jsou kombinovány i jiné národní znaky. Na základě této znalosti je moţné zadefinovat funkci, která odstraňuje zmíněná diakritická znaménka a písmena ponechává v jejich základní podobě, která jiţ rozpoznává základní sada ASCII. Taková funkce i dnes najde uplatnění v aplikacích, které nepodporují stejné znakové sady a kódování. Praktické vyuţití si můţeme představit např. pro transformaci textu v e-mailových zprávách.
3.2.3. Portabilita Počítačový průmysl registruje nepřeberné mnoţství firem vyvíjejících vlastní operační systémy, případně i překladače pro programy psané v jazyce C. Mezi nejznámější světové značky na trhu beze sporu patří Microsoft1, Red Hat2 či Apple3. Co se týče společností Microsoft a Apple, jejich vývoj aplikací a systémů je velice uzavřený ve smyslu ochrany a nezveřejňování svých zdrojových kódu. Zároveň svou obchodní strategii staví na vytváření produktů, jejichţ uţití či poskytované vývojové prostředí se na první pohled nepatrným, přesto však zásadním, rozdílem liší. Pro podobnou ilustraci poslouţí např. odkaz na mezinárodní společnost IBM a vývoj její vlastní znakové sady EBCDIC, přestoţe v té době jiţ existovala vyhovující sada. Stejným způsobem se v této oblasti zachoval i Microsoft a Apple. Jiný přístup si zachovává americká společnost Red Hat distribuující operační systém Linux. Její kódy jsou otevřené a aplikace volně dostupné. Existuje mnoho operačních systémů, mezi které lze uvést AIX4 (Advanced Interactive Executive), HP-UX5 (Hewlett Packard Unix), Red Hat Enterprise Linux, Solaris6, Mac OS X7 a jiné. Nicméně naším předním zájmem je sledovat především systémy Windows a distribuce Linux, případně Mac OS X. Některé vývojářské firmy implementují svůj vlastní překladač pro kompilaci programů psaných v jazyce C. Například Windows poskytuje překladač MS Visual Studio, Linux a Mac OS X vyuţívají překladač gcc. Kritérium portabilita je v této práci povaţováno za velice podstatné, neboť čím více operačních systémů dokáţe s vybranou knihovnou správně pracovat, tím více se stává 1. 2. 3. 4. 5. 6. 7.
10
univerzální a roste o ni zájem.
3.2.4. Dostupná dokumentace Kvalitně sepsaná dokumentace kteréhokoliv programu je nezbytná, zvláště jedná-li se o rozsáhlé a sloţité knihovny, protoţe uţivateli slouţí jako pomůcka, pomocí které se dokáţe lépe orientovat v nabízených funkcích a makrech, popisuje jakou úlohu či operace konkrétní funkce nabízí a jak s nimi správně zacházet. Knihovny, které ji postrádají, nutí uţivatele nahlédnout do jejich zdrojových kódů, jsou-li volně dostupné. V horším případě zbývá studovat funkce metodou náhodného zkoušení, coţ je ve velkých projektech prakticky velice obtíţné. Knihovny, které patří svým rozsahem mezi malé a jejichţ pojmenování funkcí je na první pohled intuitivní, je eventuálně moţné pouţívat s pomocí přiloţených hlavičkových souborů, kde lze minimálně zjistit prototyp jednotlivých funkcí. Nicméně ani toto není z uţivatelovy strany příliš vítaná alternativa. Vhodným způsobem je řešená dokumentace a popis chování programu v jazyce Java 8, kde javadoc9 je prakticky nedílnou součástí deklarace kaţdé metody. Podobný nástroj existuje pro jazyk C. Jeho konvence pro strukturování komentářů dodrţuje i přiloţená referenční příručka, která je součástí práce. Pečlivý popis a vysvětlení jednotlivých funkcí je důleţité zejména pro začátečníky, kteří zatím nemají tolik zkušeností s programováním a nedovedou se dobře orientovat ve zdrojovém kódu. Takoví lidé doprovodný text, který popisuje kompletní knihovnu, zajisté uvítají. Správně řešená dokumentace by měla obsahovat: Název funkce Prototyp funkce Popis pouţitých parametrů Popis návratové hodnoty Celkový popis Příkladná ukázka typického pouţití Dokumentace je v ideálním případě dostupná ve formátu textového dokumentu přiloţeného ke zdrojovým souborům knihovny či na webových stránkách, kde ji autor publikuje.
3.2.5. Podpora Podpora pro vybranou knihovnu jsou téţ významný faktor. Software, který se totiţ nevyvíjí, nemá velké předpoklady pro udrţení se ve světě informačních technologií. 8. 9.
11
Omezenou dobu sice funguje tak, jak bylo při jeho návrhu zamýšleno, nicméně pokud existují vývojáři, kteří ho spravují a aktualizují, je velice pravděpodobné, ţe i po mnoha letech bude korektně zastávat svůj účel a plnit dané úkoly. První externí knihovny jazyka C pro práci se znaky a řetězci v kódování UTF-8 se objevily v době, kdy toto kódování začalo být aktuální, často diskutované a podporované v internetové síti. Jelikoţ ho standardní knihovna jazyka C zatím nepodporuje, někteří programátoři si pro své potřeby píší své vlastní knihovny. Podobně mají tendenci vytvářet vlastní soubory funkcí i pro jiná kódování. Na internetu jsou publikovány více či méně dokonalé knihovny, které splňují jen část poţadované funkcionality. Jejich rozsah je často odrazem potřeb jednotlivých programátorů. Postupem času se však objevují sofistikovanější a rozsáhlejší balíčky podporující kódování UTF-8. Bohuţel ty, na jejichţ vývoji se podílel malý okruh programátorů či pouze jeden člověk, se většinou od svého vzniku uţ příliš nevyvíjejí a nejsou nadále aktualizovány. Zatímco pokud se vývoje knihovny ujímá početnější uskupení, v mnoha případech její podpora přetrvává a i dnes se stále rozšiřují, přestoţe se občas odklání od původního tématu (práce s řetězci a znaky v kódování UTF-8). Takové knihovny jsou velice zajímavé a je dobré věnovat jim zvláštní pozornost, zatímco ty, jejichţ vývoj se zastavil, více nezkoumáme. Mnohdy k nim totiţ ani není přiloţena adekvátní dokumentace. Jako konkrétní přínos zajištení podpory knihovny lze pro příklad uvést zpětnou vazbu autorů. V situaci, kdy náhodný uţivatel balíčku nachází chybové místo, existuje moţnost podat hlášení o nalezeném nedostatku přímo autorům, kteří mohou příslušně zareagovat a chybu odstranit. Pokud komunikace mezi uţivateli a autory je aktivní a oboustranně akceptována, knihovna má předpoklad k úspěšnému vývoji. V tuto chvíli samotní uţivatelé zastávají pozici testerů a představují pomocnou sílu vývojářů. Shrnutě řečeno, aktivní podpora pro vybranou knihovnu přináší signifikantní výhodu, neboť je zajištěna minimálně snaha pro odstraňování chyb, jejího zdokonalování a rozšiřování.
3.2.6. Korektnost, ošetření výjimek a jiné Korektní fungování všech zkoumaných knihoven je nutným předpokladem, přesto se nejedná o faktor, který je zkoumán ihned po kontaktu s některou z nich. První chyby jsou většinou vypozorovány aţ po několika týdnech. Při hledání eventuálních chyb můţe pomoci navštívení některých tématicky zaměřených diskusních fór. V rámci naší vlastní iniciativy je náhodně vygenerována sadu znaků v kódování UTF-8, která slouţí jako vstup pro některé obsaţené funkce. Objevené chyby jsou případně zmíněny. Jako typický způsob testování mimo jiné slouţí předávání konkrétním funkcím jiné vstupní parametry, neţ je očekáváno. Nemá však příliš velký význam na vstupu testovat proměnné, jejichţ datový typ se od definice prototypu funkce liší, protoţe toto omezení jiţ ošetřuje samotný překladač při kompilaci zdrojového kódu, nikoliv implementace knihovny. Pozornost je přikládána vstupním datům, jejichţ datový typ vyhovuje, ale jejich hodnota nebyla ze strany autora funkce uvaţována. Při testování pozorujeme, jakým způsobem funkce na eventuální chybu reagují, zda se nečekaně ukončí celá aplikace nebo zda jsou problémy odchytávány pomocí tzv. výjimek a dále zpracovávány, přičemţ o celé události je uţivatel příslušně informován prostřednictvím chybového hlášení. Dalším hlediskem pozorování je posuzování korektnosti návratových hodnot -- jestli skutečně odpovídají popisu funkce. Mohou se téţ vyskytnout další kritéria, která jsou však natolik specifická, ţe je vhodné uvést je aţ v konkrétních případech.
12
3.3. Východiska a dostupné zdroje V rámci této bakalářské práce jsou vybrány a hodnoceny knihovny, jejichţ pouţívání není placené. Tento faktor tedy zadává další jejich omezující kritérium, které striktně souvisí s kaţdou z nich. Z právního hlediska rozlišujeme několik způsobů licenčního ujednání spojené s pouţíváním daného produktu. Níţe je shrnut jejich výčet, přičemţ definice kaţdého z nich je citována z českého webového portálu společnosti pro výzkum a podporu open source OSS Alliance10. Public Domain: „... je software bez vyhrazených práv, tzn. že není nijak chráněný. Jinými slovy je možné jej libovolně používat, kopírovat, popř. měnit. Laicky řečeno u Public Domain se jedná o software, se kterým můžeme libovolně nakládat, aniž bychom se museli strachovat, že porušujeme autorská práva. Příkladem z praxe mohou být počítačové programy, kterým uplynula doba trvání majetkových práv (doba majetkových práv trvá 70 let od smrti autora a po uplynutí této doby je možno software volně používat).“[3] Open source představuje: „... aplikace, které jsou šířeny se zachováním určitých práv a svobod pro jejich koncového uživatele (tedy nabyvatele licence). Jde o práva spouštět program za jakýmkoliv účelem, studovat, jak program pracuje a přizpůsobit ho svým potřebám (předpokladem k tomu je přístup ke zdrojovému kódu), redistribuovat kopie dle svobodné vůle, vylepšovat program a zveřejňovat tato zlepšení.“[3] Svobodný software definuje téměř stejné licenční ujednání jako Open Source, jinak řečeno: „... základní idea sdílení souborů (zdrojového kódu) je stejná. V praxi tedy oba pojmy mají v zásadě shodný obsah, tedy jde o distribuci softwaru takovým způsobem, že koncový uživatel má vždy právo na získaní zdrojového kódu programu a dále má právo tento zdrojový kód upravovat a distribuovat.“[3] Copyleft software: „... je svobodný software bez všech dalších omezení při rozšiřování nebo jeho změně. Copyleftovaný software je typ svobodného software, který nedovoluje přidávat nějaká další omezení, pokud někdo programový kód modifikuje či dále distribuuje. Znamená to, že každá další kopie, dokonce i když byla změněna, musí zůstat svobodným softwarem. To představuje určité nebezpečí pro softwarové společnosti, které využijí při vývoji svého programu copyleftovaný software, protože potom celý nově vyvinutý program musí zůstat svobodný (tedy musí být zveřejněn zdrojový kód). Hovoří se o tzv. infikování proprietárního software.“[3] Freeware: „... je software, který je šířen zdarma, například na internetu nebo na různých CD. Program je možno provozovat zdarma po neomezenou dobu a je možno jej i zdarma šířit dále. Není však dovoleno (stejně jako u shareware) šířit jej za úplatu. Z původní definice freeware také plyne, že autorská práva k takovému programu drží jeho autor a není tedy dovoleno bez jeho souhlasu program jakkoliv měnit či upravovat pro komerční účely. Typickým příkladem freeware je dnes velmi rozšířená Java od Sun Microsystems.“[3] Tímto jsme zadefinovali všechna potřebná licenční ujednání spojená se selekcí zkoumaných knihoven. Jako zdroj pro vyhledávání jednotlivých balíčků slouţí internetová síť a webové stránky, na kterých autoři publikují své produkty. 10.
13
3.4. Kandidátské knihovny 3.4.1. GNU C Library Knihovna GNU C Library (dále glibc) jiţ byla v této práci několikrát zmíněna, jenomţe pod jiným názvem (standardní knihovna programovacího jazyka C). Jedná se o ekvivalentní pojménování, které lze v obou směrech volně zaměňovat. Její vyuţívání je velmi rozšířené, neboť jak bylo uvedeno, její přítomnost je podporována převáţnou většinou překladačů jazyka C, tudíţ není třeba připojovat a instalovat další balíčky funkcí a maker pro práci v tomto vývojovém prostředí. Zároveň nabízí poměrně širokou funkcionalitu v mnoho oblastech (viz výše). Co se týče práce s řetězci a znaky, tato knihovna dlouho dobu disponovala funkcemi navrţenými pouze pro jednobajtové znaky. Později byla rozšířena o funkce pro práci se širokými znaky, coţ výrazně přispělo k vývoji univerzálních aplikací ve smyslu mezinárodního pouţití. Z hlediska přenositelnosti, je glibc ve velké míře instalována na mnohé operační systémy Linux, nicméně existuje i alternativa pro systémy Windows - cygwin. Tato knihovna je velice objemná, coţ můţe některým méně zkušeným programátorům při psaní kódu způsobovat problémy. Na druhou stranu díky své rozšířenosti a popularitě existuje příslušná rozsáhlá dokumentace. Kvalitně je zpracován slovní popis knihovny a dále publikován na oficiálních stránkách projektu GNU11. Jestliţe však programujeme a v danou chvíli potřebujeme znát stručný popis jednotlivých funkcí s uvedenými prototypy, vstupními parametry a návratovými hodnotami, je vhodné navštívit stránky The C++ Resources12. Z hlediska podpory tohoto softwarového balíčku, v dřívějších letech byl vyvíjen společností FSF13 (Free Software Foundation). V současné době je pod dohledem a správou Ulricha Dreppera ze společnosti Red Hat. Práce a vývoj této knihovny je tedy stále aktivní a výhledově i na dále zajištěn. Tuto zásluhu je moţné přisoudit jejímu velkému vyuţití v Linuxových distribucích, jejichţ je součástí. Tímto byly zhodnoceny pozitivní charakteristické přednosti této knihovny. Nyní si uvedeme její nedostatky a hlavní důvody, proč tato knihovna nebyla vybrána jako nejvhodnější pro práci se znaky a řetězci v kódování UTF-8. Dlouhou dobu glibc prakticky nepodporoval UTF-8 ani ţádné jiné druhy kódování vícebajtových znaků. Nicméně s příchodem verze glibc 2.2 se tato moţnost částečně objevuje. V GNU C Library jsou implementovány funkce (iconv, mbrtowc, mbsrtowcs, wcrtomb, wcsrtombs), které umoţňují převod znaků a řetězců mezi jednotlivými typy kódování. Tato konverze však, nejen s ohledem na zadání této práce, obsahuje silné nedostatky. V situacích, kdy je prováděna konverze mezi zdrojovými řetězci v jistém kódování a cílovým řetězcem v jiném kódování, je třeba během této operace měnit hodnotu kategorie LC_TYPE, určující aktuální lokální prostředí, ve kterém je míněno pracovat. Tyto změny, nutné pro převod mezi jednotlivými typy kódování, mohou způsobovat ve zbylé části zdrojového kódu programu problémy spojené s korektním fungováním funkcí, které jsou lokálně závislé. Jedná se například o klasifikační funkce pro práci s jednotlivými znaky z hlavičkového souboru ctype.h. 11. 12. 13.
14
islower isupper isalpha isdigit isalnum
isxdigit ispunct isspace isblank isgraph
isprint iscntrl isascii
Jako moţné řešení tohoto problému se nabízí paralelní nastavení kategorie LC_TYPE (nastavení této hodnoty pro kaţdé vlákno zvlášť). Toto řešení však prakticky není moţné provést, neboť kategorie LC_TYPE je globální -- sdílena v rozsahu celého programu. Dalším faktorem, který řadí tuto knihovnu mezi nevhodné pro práci s řetězci a znaky v kódování UTF-8, je omezení spojené s nabízenými funkcemi. Ty jsou totiţ navrţeny pouze pro jednobajtové znaky a široké znaky. Vícebajtové řetězce a znaky tedy při konverzi ztrácejí některé informace, které jsou například pro UTF-8 charakteristické. V opačném případě je nutné takové funkce doimplementovat.
3.4.2. Libiconv Libiconv14 je volně dostupná s licenčním ujednáním LGPL15 (licence svobodného softwaru). Jedná se o jednoduchou knihovnu ve smyslu svého malého rozsahu, která poskytuje pouze pět funkcí, jejichţ pouţití zajišťuje jedinou funkcionalitu (převod řetězců určitého typu kódování do řetězců v jiném kódování, tj. konverze mezi vybranými druhy kódování). Níţe je uveden výčet funkcí, které jsou zde implementovány. iconv_t iconv_open ( const char * destination, const char * source ); size_t iconv ( iconv_t cd, const char * * inbuf, size_t * inbytesleft, char * * outbuf, size_t * outbytesleft ); int iconv_close ( iconv_t cd ); int iconvctl ( iconv_t cd , int request, void * argument ); int iconv_open_into ( const char * destination, const char * source, iconv_allocation_t * resultp ); 14. 15.
15
Motivace pro zavedení libiconv je dodat systému či aplikaci nástroj, díky kterému je schopna správně dekódovat a interpretovat znaky v jiných kódováních (ISO-8859-1, ISO-8859-2, ISO-8859-3, ISO-8859-4, KOI8-R, CP 1250, CP 1251, Mac CentralEurope, Mac Greek, UTF-8, UTF-16, UTF-32, UCS-2, UCS-4, EUC-JP, EUC-CN, EUC-KR a mnoho dalších). Úplný přehled všech podporovaných kódování je k nahlédnutí na oficiálních stránkách autora knihovny. Funkcionalita libiconv analogicky odpovídá funkci iconv z GNU C Library. Charakteristika a kritika těchto dvou knihoven (libiconv a glibc) je tedy velice podobná. Dokumentace funkcí je velice krátká a stručná, coţ odpovídá rozsahu samotné knihovny. Dostupná je pouze ve formě webových stránek. Své vyuţití libiconv nachází u aplikací, které nejsou náročné a nevyţadují sloţité funkce pro práci s řetězci a znaky v jiných kódováních, tzn. i v UTF-8. Hlavním zájmem je správná interpretace textu nezávisle na jeho typu kódování. Ostatní poţadovaná funkcionalita je zajištěna jinými knihovnami. Libiconv tedy zdaleka není kandidátem na nejvhodnější knihovnu pro práci s řetězci a znaky v kódování UTF-8.
3.4.3. Libutf8 Libutf816 je volně šiřitelná knihovna označená licencí svobodný software. Vznikla jako nástroj pro zavedení podpory kódování UTF-8 v systémech, které ji postrádají. Její funkcionalita je velice specifická, neboť je vyhrazena pouze pro práci s řetězci a znaky. K dispozici je malý počet funkcí operující s vícebajtovými znaky a jejich řetězci, většinové zastoupení zde mají funkce pro práci s širokými znaky, které jsou však téměř shodné s funkcemi ze standardní knihovny jazyka C. Jsou zde implementovány jejich různé variace, lišící se velice nepatrně (zahrnutí rozšiřujícího vstupního parametru, způsob vykonání dané operace či podobně). Libutf8 zahrnuje funkce pro konverzi mezi vícebajtovými a širokými znaky, resp. řetězci pro zajištění jiţ zmiňované podpory vícebajtových znaků a operací nad nimi. Níţe je proveden výčet všech zmíněných funkcí, které knihovna nabízí. btowc mbstowcs wcsncmp iswalnum mbtowc wcsncpy iswalpha towctrans wcsnlen iswblank towlower wcsnrtombs iswcntrl towupper wcspbrk iswctype wcpcpy wcsrchr iswdigit wcpncpy wcsrtombs iswgraph wcrtomb wcsspn islower wcscasecmp wcsstr iswprint wcscat wcstok iswpunct wcschr wcstombs iswspace wcscmp wcswidth iswupper wcscpy wctob iswxdigit wcscspn wctrans mbrlen wcsdup wctype mbrtowc wcslen wcwidth mbsnrtowcs wcsncasecmp mbstrowcs wcsncat Po provedeném výčtu lze prohlásit, ţe převáţná část funkcí je zastoupena v hlavičkovém souboru wctype.h a wchar.h knihovny GNU C Library. Nových a rozšiřujících funkcí je zde velice málo. Pro příkladnou ukázku si uvedeme jednu z nich. 16.
16
int mblen ( const char* s, size_t n ); Mblen vrací celočíselnou hodnotu představující informaci o délce prvního znaku, tj. počet bajtů v řetězci s v maximálním rozsahu n bajtů. Nutno zmínit, ţe v tomto případě pracujeme ve vícebajtovém kódování (UTF-8). Tato knihovna tedy ţádným výrazným způsobem nerozšiřuje funkcionalitu GNU C Library, jejím smyslem je zastoupit ji. Zdrojové kódy definují i další funkcionalitu pro práci s řetězci a znaky, které však doposud nebyly zmíněny, protoţe v rámci této práce nejsou zajímavé. Tyto funkce operují se vstupními a výstupními daty (fgetwc, fgetws, fputwc fputws, ...) nebo se starají o správu a manipulaci paměťových bloků (wmemcmp, wmemcpy, ...). Tato verze knihovny byla vydána především pro systémy Linux, Solaris a OSF/1. Její autor Bruno Haible však napsal verzi i pro operační systém Windows, k jejichţ zdrojovým kódům je navíc přiloţena dokumentace implementovaných funkcí a maker. Dokumentace verze pro Linux17, Solaris a OSF/1 není dostupná, nicméně repertoár funkcí obou verzí je stejný, tudíţ onu jedinou dokumentaci lze pouţít pro obě verze stejně hodnotně. Co se týče podpory pro tento software, na vývoji se podílí Bruno Haible, přičemţ poslední aktualizace byla zaznamenána v roce 2009. Není tedy zcela jisté, jakou vizi má tato knihovna do budoucna, zda se bude rozšiřovat, anebo bude její vývoj ukončen. Jak tvrdí autor, libutf8 byla navrţena jako tzv. záplata pro systémy, které postrádají podporu pro kódování širokých a vícebajtových znaků. Tato podpora je dnes jiţ zaručena alespoň pro široké znaky (viz GNU C Library), pro vícebajtové znaky se zatím vyvíjí. Ani tato knihovna nebyla vybrána jako nejvhodnější kandidát, protoţe její perspektiva je nejistá a funkcionalitu, kterou dodává, standardní knihovna z velké části zaručuje. a zároveň protoţe funcionalitu, kterou dodává, standardní knihovna z velké části zaručuje.
3.4.4. Utf8proc Utf8proc18 představuje odlehčenou verzi knihovny pro práci s řetězci a znaky v kódování UTF-8. Disponuje omezeným mnoţstvím nástrojů operujících v tomto kódování a ani další připojené hlavičkové soubory nezahrnují další funkce typické pro standardní knihovnu jazyka C. Konkrétně je zmínka o hlavičkových souborech wchar.h a wctype.h. Motivací pro zavedení utf8proc je uchopit kódování UTF-8 a vytvořit pro něj úzkou sadu nástrojů, které jsou velice specifické a silně zaměřené pro toto kódování. Pro komplexnější programování je však nepostačující, proto je vhodné připojit k ní další knihovnu nebo případně potřebné funkce dodatečně doimplementovat. Všechny obsaţené komponenty souhrnně umoţňují rozkládat sloţené znaky a naopak skládat více znaků v jeden dle principů definovaných v sadě Unicode (odstraňovat řídící znaky typické pro kódování UTF-8, které jsou většinou umisťovány na začátek souboru, hledat v řetězcích nesrovnalosti spojené se strukturou a korektním rozloţením bajtů jako například znaky s nedefinovanými přiřazenými číselnými hodnotami, odstraňovat diakritická znaménka u tisknutelných znaků a další). utf8proc_errmsg utf8proc_get_property utf8proc_NFD utf8proc_iterate utf8proc_decompose_char utf8proc_NFKD utf8proc_codepoint_valid utf8proc_reencode utf8proc_encode_char utf8proc_map
17. 18.
17
To, ţe se jedná o jednoduší verzi knihovny pro podporu kódování UTF-8, zvyšuje popularitu mezi méně náročnými programátory, jenomţe právě z tohoto důvodu je třeba být při psaní kódu a jejího pouţívání velice opatrný. Některé funkce jsou totiţ náchylné na nedefinovaná vstupní data a mohou způsobovat pád celé aplikace (např. utf8proc_get_property). const utf8proc_property_t * utf8proc_get_property( int32_t uc ); Její návratová hodnota obsahuje informaci charakterizující vstupní znak. Tato informace je typicky kódována u znaků sady Unicode. Za předpokladu, ţe se budeme pokoušet tento údaj zjistit u prvků, které nejsou součástí této sady a není v ní tedy definován (číselný reprezentant znaku spadá mimo definovaný rozsah 0x0000 aţ 0x10FFFF), program bude neočekávaně ukončen. Dostupnost informací a popisu tohoto celého balíčku jsou poměrně uspokojivé. Na webových stránkách distributora a zároveň autora knihovny je vystavena příslušná dokumentace, která se však obsahově zcela shoduje s dokumentací samotných hlavičkových souborů. Pokud tedy programujeme bez připojení k internetové síti, komentáře v souboru utf8proc.h zcela postačí. Na uvedených stránkách je zároveň proveden přehled nejnovějších aktualizací této knihovny a k nim jsou připojeny odkazy pro staţení nejnovější verze utf8proc. Uţivatelé, kteří eventuálně naleznou chybu nebo jiný nedostatek, o tom mohou poreferovat samotným autorům knihovny prostřednictvím příslušného webového formuláře. Tento software je téţ moţné vyuţívat bez placení a jeho kopie lze bez postihů volně šířit. Z obecného hlediska je tento nástroj vhodný pro programátory, kteří hledají jednoduchou knihovnu pro práci s řetězci a znaky v kódování UTF-8, z čehoţ na druhou stranu vyplývá, ţe náročnější vývojáři budou muset pro naplnění svých potřeb připojit rozšiřující knihovny nebo pouţít zcela jinou.
3.4.5. Další knihovny Tato podkapitola provádí pouze stručný výčet knihoven, které jsou téţ podrobeny naší analýze, nicméně nebude jiţ proveden tak detailní rozbor jako u předchozích. Některé jejich charakteristiky se totiţ velice podobají a porušují specifická kritéria, která jsou v rámci hodnocení pokládána za důleţitá a nutná. Nejčastěji není splněno kritérium momentálně aktivní podpory. Ta je důleţitá z hlediska jejího dalšího eventuálního vývoje, případně pro poţadovanou komunikaci mezi autory a uţivateli, jak jiţ bylo definováno (viz 3.2 Ustavení specifických kritérií). Poněkud nedostačující je i jejich dokumentace či existence tématicky souvisejících informačních zdrojů. Ty jsou důleţité pro nové potencionální uţivatele, kteří se s knihovnou teprve seznamují a hledají potřebné rady. Dále mnohé knihovny jsou úzce vyhraněny a implementovány pro velmi specifické problémy (implementace wcwidth() od Markuse Kuhna či Transtab). Jejich vyuţití spíše dobře poslouţí pouze jako rozšiřující nástroj. Balíčky funkcí libunicode a Photon library jsou naopak součástí konkrétních operačních systémů, čímţ některé ztrácejí moţnost portability v rámci jiných systémů. Libunicode je knihovna19, která je součástí zdrojového kódu 19.
18
pracovního prostředí GNOME. Zajišťuje konverzi mezi vybranými znakovými sadami, vyhledává rozšiřující informace o znacích ze sady Unicode, provádí nad nimi operace pro jejich rozkládání a skládání na úrovni binárního zápisu aj. Libutf je balíček20 funkcí podporujících práci v kódování UTF-8, který je implementován pro operační systém Plan9. Implementace wcwidth()21 od Markuse Kuhna slouţí jako nástroj pro vypočítávání potřebného místa na výstupním zařízení pro tisk vícebajtových znaků. Transtab převádí22 znaky ze sady Unicode na znaky ze sady ASCII. Hovoříme o tzv. transliteraci -- pro vícebajtové znaky je hledán osmibitový, který se mu vizuálně nejvíce podobá a bude ho zastupovat. Photon library je k dispozici23 v operačním systému QNX, vyvíjeným společností QNX Software Systems. Nabízí typické operace pro práci s řetězci v kódování UTF-8 (utf8len, utf8strblen, utf8strchr, utf8strichr, utf8strirchr, utf8strlen, utf8strnchr a další).
3.5. Nejlépe ohodnocená knihovna 3.5.1. ICU4C ICU24 (International Components for Unicode) je projekt, jehoţ cílem je sjednocení všech existujících znakových sad a vytvoření nástroje, který aplikacím umoţní mezi sebou korektně komunikovat bez ohledu na národní prostředí. V rámci tohoto softwarového balíčku jsou paralelně vyvíjeny dvě knihovny - ICU4J a ICU4C. V našem případě budeme dále studovat pouze ICU4C, coţ je knihovna určená pro programovací jazyk C a C++, zatímco ICU4J je implementována pro jazyk Java. Stejně jako některé výše zmíněné knihovny i tato obsahuje funkce pro konverzi mezi znakovými sadami. Snahou ICU je pokrýt co nejširší spektrum všech existujících sad. Mimo jiné téţ implementuje funkcionalitu, která umoţňuje vyvíjet aplikace, jejichţ správné fungování je zajištěno na kterémkoliv místě ve světě. Není tedy nutné vytvářet aplikace pro různá národní prostředí zvlášť ani dodávat další program, který provádí konverzi mezi dvěma a více cílovými stanicemi. Balíček ICU4C pro jazyk C zahrnuje nejen hlavičkové soubory pro práci s vícebajtovými znaky a řetězci, ale i jiné. Jejich výčet provádí níţe uvedený seznam. S ohledem na zadání této práce je pozornost věnována pouze souborům ustring.h a uchar.h. utypes.h umsg.h usprep.h 20. 21. 22. 23. 24.
19
ustring.h unum.h uidna.h utf.h utrans.h uspoof.h uchar.h ubidi.h utmscale.h ucnv.h ushape.h ustdio.h uloc.h ucol.h ures.h usearch.h unorm.h ubrk.h ucal.h uset.h udat.h uregex.h Pro práci s řetězci tato knihovna nabízí nejen typické funkce pro porovnávání, vyhledávání, kopírování řetězců a znaků, ale i mnoho rozšiřujících. Mimo to je navíc dodávána i funkcionalita pro formátování číselných hodnot, času či data. Jejich vizuální reprezentace se můţe lišit u čísel vyšších řádů, desetinných čísel. Obdobně je například definovaná konvence pro zobrazování uvozovek. Všechny uvedené operace jsou samozřejmě vykonávány v závislosti na příslušné lokalizaci. Knihovna definuje i práci s oboustraně psaným textem. Seznam funkcí z hlavičkového souboru ustring.h: u_strlen u_austrcpy u_countChar32 u_austrncpy u_strHasMoreChar32Than u_memcpy u_strcat u_memmove u_strncat u_memset u_strstr u_memcmp u_strFindFirst u_memcmpCodePointOrder u_strchr u_memchr u_strchr32 u_memchr32 u_strrstr u_memrchr u_strFindLast u_memrchr32 u_strrchr u_unescape u_strrchr32 u_unescapeAt u_strpbrk u_strToUpper u_strcspn u_strToLower u_strspn u_strToTitle u_strtok_r u_strFoldCase u_strcmp u_strToWCS u_strcmpCodePointOrder u_strFromWCS u_strCompare u_strToUTF8 u_strCompareIter u_strFromUTF8 u_strCaseCompare u_strToUTF8WithSub u_strncmp u_strFromUTF8WithSub u_strncmpCodePointOrder u_strFromUTF8Lenient u_strcasecmp u_strToUTF32 u_strncasecmp u_strFromUTF32 u_memcasecmp u_strToUTF32WithSub u_strcpy u_strFromUTF32WithSub u_strncpy u_strToJavaModifiedUTF8 u_uastrcpy u_strFromJavaModifiedUTF8WithSub u_uastrncpy Seznam funkcí z hlavičkového souboru uchar.h: u_hasBinaryProperty u_charMirror 20
u_isUAlphabetic u_charType u_isULowercase u_enumCharTypes u_isUUppercase u_getCombiningClass u_isUWhiteSpace u_charDigitValue u_getIntPropertyValue ublock_getCode u_getIntPropertyMinValue u_charName u_getIntPropertyMaxValue u_getISOComment u_getNumericValue u_charFromName u_islower u_enumCharNames u_isupper u_getPropertyName u_istitle u_getPropertyEnum u_isdigit u_getPropertyValueName u_isalpha u_getPropertyValueEnum u_isalnum u_isIDStart u_isxdigit u_isIDPart u_ispunct u_isIDIgnorable u_isgraph u_isJavaIDStart u_isblank u_isJavaIDPart u_isdefined u_tolower u_isspace u_toupper u_isJavaSpaceChar u_totitle u_isWhitespace u_foldCase u_iscntrl u_digit u_isISOControl u_forDigit u_isprint u_charAge u_isbase u_getUnicodeVersion u_charDirection u_getFC_NFKC_Closure u_isMirrored ICU4C lze povaţovat za široce portabilní knihovnu. Ze strany jejich tvůrců je pravidelně testována. Získané výsledky jsou publikovány na oficiálních stránkách projektu. Pro testování je vybrán operační systém AIX25, HP/UX26, Red Hat Enterprise Linux, Solaris, Windows, MacOSX, a další). Úplný výčet testovaných operačních systémů a jejich výsledků provádí (obrázek). Pro naše potřeby zcela postačí informace o testování na třech nejrozšířenějších systémech (Linux, Mac OSX a Windows). Dokumentace tohoto balíčku je ve srovnání s ostatními analyzovanými knihovnami velmi rozsáhlá. Dostupná je v několika formátech (např. na oficiálních stránkách projektu ve formátu HTML či volně ke staţení ve formátu PDF). Jednotlivé funkce, konstanty a makra jsou relativně podrobně pospány, nicméně pro méně pokročilé programátory a nové uţivatele zde chybí názorné demonstrativní ukázky jejich pouţití. I podpora ICU4C je velice uspokojivá. Je distribuována s licencí open software. Přestoţe její pouţívání je bezplatné, do jejího vývoje jsou investovány významné finanční prostředky. Na práci se podílí softwaroví inţenýři a programátoři ze společnosti IBM, která zároveň ICU4C financuje. Její stabilní vývoj je tedy pevně zajištěn a s tím i její budoucí perspektiva. Pro knihovnu je zároveň zachována permanentní snaha odstraňovat objevené nedostatky a rozšiřovat funkcionalitu v závislosti na potřebách samotných uţivatelů, mezi které patří i samotná společnost IBM. Jelikoţ je široce pouţívaná a světově známá, mimo oficiální podporu ze strany autorů 25. 26.
21
existuje i mnoho vedlejších nezávislých zdrojů pro získávání informací spojených s vývojem v jejím prostředí. ICU uvádí i některé zajímavé výsledky srovnávacích testů, kterým byly knihovny ICU4C (ICU4C 3.8) a GNU C Library (glibc 2.12.3-2) podrobeny. Testována byla rychlost vykonání operace porovnávání řetězců vygenerovaných pro vybraná národní prostředí. Konkrétní výsledné hodnoty prezentuje obrázek 3.2. Sledován je parametr strcoll (doba pro porovnání řetězců v jednotkách nanosekund), keygen (doba pro vytvoření srovnávacích klíčů v jednotkách nanosekund) a keylen (průměrná délka srovnávacích klíčů v jednotkách bajtů pro jeden znak). Výsledky tohoto testu jsou uvedeny za účelem ukázat, ţe ICU4C lze výkonostně srovnávat s GNU C Library široce vyuţívanou v programovacím jazyce C.
22
Kapitola 4. Instalace 4.1. Softwarové požadavky Cílem této kapitoly je představit uţivatelům způsob, jak nainstalovat balíček ICU, konkrétně ICU4C verze 4.6.1 pro operační systém Windows. Pro psaní aplikací v programovacím jazyce C je v tomto systému doporučeno pouţívat vývojové prostředí Microsoft Visual Studio1. Tento průvodce instalací byl vytvořen konkrétně pro Microsoft Visual Studio verze 2010. Pro orientaci v tomto programu jsou zde přiloţeny zachycené snímky obrazovky v určitých krocích. Dle obrázku 3.1 je mimo jiné zřejmé, ţe podpora této knihovny pro systém Windows je pečlivě testována, tudíţ její korektní fungování je dobře zajištěno.
4.2. Binární soubory Instalaci zahájíme tím, ţe si knihovnu2 nejprve stáhneme do počítače. Existují dva způsoby, jak získat potřebné binární soubory pro její zprovoznění. Na oficiálních stránkách jsou k dispozici ke staţení jiţ hotové binární soubory nebo zdrojové kódy, pomocí kterých si je můţeme sami vytvořit. V případě, ţe se rozhodneme pro balíček s binárními soubory, je moţné zbytek kapitoly přeskočit a pokračovat na následující kapitole (3.3 Nastavení nástroje Microsoft Visual Studio). Vygenerování vlastních binárních souborů je sice komplikovanější a časově náročnější, nicméně zajišťuje, ţe knihovna bude na daném stroji a operačním systému skutečně správně pracovat. Obě verze jsou zkomprimovány do formátu ZIP i TGZ. Je tedy třeba mít nainstalovaný program, který je dokáţe dekomprimovat. Po otevření souboru projektů $PATH\source\allinone\allinone.sln v prostředí Microsoft Visual Studio (dále MVS), je v levém panelu (Solution Explorer) proveden výčet všech obsaţených projektů, pomocí kterých jsou vygenerovány binární soubory knihovny. Jakmile je vše úspěšně načteno, zahájíme kompilaci (Build Solution). Po několik minut se generují konečné soubory, které jiţ budeme při práci s knihovnou pouţívat. O úspěšném překladu balíčku jsme informováni adekvátní zprávou (viz obrázek 4.2). Pro ověření korektnosti provedené operace jsou připraveny speciální testy. Prostřednictvím příkazové řádky (windows command line) spustíme jeden z následujících příkazů: $PATH\source\allinone\icucheck.bat x86 Debug $PATH\source\allinone\icucheck.bat x86 Release $PATH\source\allinone\icucheck.bat x64 Release Pro naše účely je postačující test s parametry x86 a Debug. Jedná se pouze o specifikaci pouţívaného typu procesoru (32-bitový a 64-bitový).
4.3. Nastavení nástroje Microsoft Visual Studio Nyní jiţ jsou potřebné binární soubory připraveny. V posledním kroku je třeba provést takové nastavení, aby MVS měl přístup k potřebným souborům pro běh aplikací vyuţívajících ICU4C knihovnu. Konkrétně se jedná o adresáře bin obsahující knihovny potřebné pro volání poţadované funkcionality ICU, include zahrnující hlavičkové soubory a lib s linkovanými knihovnami uvnitř. Aby MVS mohl operovat s DLL knihovnami, je třeba podat MVS informaci o tom, kde přesně je uloţen. Nabízí se dvě moţnosti provedení. Jednodušší varianta je, ţe všechny 1. 2.
23
knihovny, které aplikace pro svůj chod pouţívá, přiloţíme k jejímu spouštěcímu souboru (typicky s příponou .exe). Druhá varianta je umístit zmíněné knihovny do jednoho společného adresáře a v programu MVS k němu uvést cestu. V takovém případě není rozhodující, na kterém místě se adresář nachází, neboť jeho lokalizace je známa. Provádíme dílčí kroky: i. ii. iii. iv.
Properties C/C++ General Additional Include Directories (viz obrázek 4.3)
Aby bylo moţné aplikaci zkompilovat, přiloţíme adresář include k jejím ostatním souborům. Posledním krokem je uvést prostředí do stavu, kdy je moţné aplikaci linkovat. To vyţaduje zveřejnit cestu ke sloţce lib. V panelu Solution Explorer provedeme nad naším aktuálním projektem následující úkony: i. ii. iii. iv.
Properties Linker General Additional Library Directories (viz obrázek 4.4)
V případě potřeby přidáme poţadované soubory s koncovkou .lib. Navigace k nastavení formuláře je téměř shodná s předcházejícím: i. ii. iii. iv.
Properties Linker Input Additional Dependencies (viz obrázek 4.5)
V tuto chvíli je vývojové prostředí MVS připraveno k práci s knihovnou ICU4C a jejími funkcemi. Výčet hlavičkových souborů, definujících její funkce, provádí přiloţený seznam. Jejich podrobnější popis je k nalezení v dokumentaci knihovny.
24
Kapitola 5. Referenční příručka 5.1. Výstupní formát Jako výstupní formát pro tuto příručku je vybrán HTML1. Je téţ uvaţováno vytvořit komplexnější dynamické stránky s podporou PHP2, avšak tím by pominula moţnost vyuţívat tento dokument bez připojení k internetu. Bylo by totiţ nutné umístit je na některý vhodný server, který podporuje PHP skriptování. V takovém případě lze povaţovat dokument za dostupný pouze po připojení do internetové sítě. Při návrhu této dokumentace je dále uvaţováno, zda popis jednotlivých funkcí uspořádat do jedné sekce v rozsahu jedné stránky nebo kaţdou funkci umístit do jedné sekce zvlášť. Výhodou první varianty je moţnost tisknout příručku jako jeden kompletní dokument a pohodlně vyhledávat klíčová slova za pouţití vyhledávacího formuláře integrovaného v internetovém prohlíţeči. Výhodou druhé varianty je úplné oddělení jednotlivých funkcí od sebe a moţnost tisknout jednotlivé funkce zvlášť. Na základě předpokladu, ţe tato dokumentace bude vyuţívána především v elektronické podobě, je vybrána první varianta vyhotovení. Navigaci v obou verzích zaručuje levý panel, kde je proveden výčet zdokumentovaných hlavičkových souborů. Důraz při vytváření příručky je kladen na pouţití minimálního počtu prvků navrhnout minimalistický vzhled. I při psaní zdrojového kódu je snaha vybírat takové HTML značky, aby byla vytvořena stránka, která je v rámci pouţití kaskádových stylů univerzální a je snadné ji formátovat. Díky tomu je dokument dobře čitelný a je moţné ho tisknout i bez pouţití jakýchkoliv kaskádových stylů. Adresářová struktura je triviální. Jednotlivé soubory popisuje následující seznam: $PATH/index-cz.html obsahuje českou verzi dokumentu. $PATH/index-en.html obsahuje anglickou verzi dokumentu. $PATH/css/default.css nastavuje formátování stránky. $PATH/pictures/ zahrnuje všechny pouţité obrázky.
5.2. Organizace funkcí a jejich popis Pro zachování transparentnosti se snaţíme vytvořit dokumentaci knihovny ICU4C, ve které je vyhledávání informací rychlé, na první pohled zřejmé a intuitivní. Její struktura a rozloţení prvků byla inspirována známými webovými portály Cplusplus a Crefference, slouţícími jako online dokumentace pro programovací jazyk C a C++. Zároveň usilujeme o splnění kritéria (viz 3.2.4 Dostupná dokumentace), jeţ bylo pro námi provedenou analýzu vybraných knihoven pro práci s řetězci a znaky v kódování UTF-8 definováno. Jeho doporučení zní, ţe správná dokumentace obsahuje název funkce, její prototyp, vstupní parametry, návratové hodnoty, celkový popis a ukázkový příklad. Níţe je uvedena ukázka deskripce funkce u_strlen. int32_t u_strlen ( 1. 2.
25
const UChar * str ); /* Popis: zjistuje, kolik znaku typu UChar obsahuje vstupni retezec str ukonceny hodnotou NULL. Vstupni parametry: retezec str typu UChar ukonceny hodnotou NULL. Navratova hodnota: pocet znaku retezce str. Hodnota NULL se nepocita. */ #include <stdint.h> #include "unicode/ustring.h" int main() { /* uString obsahuje rezetec "Hello world!". */ UChar uString[] = { 0x0048, 0x0065, 0x006c, 0x006c, 0x006f, 0x0020, \ 0x0077, 0x006f, 0x0072, 0x006c, 0x0064, 0x0021, \ 0x0000 }; int32_t uSize; /* Ziskej delku uString. Hodnota promenne uSize je 12. */ size = u_strlen(uString); return 0; } Výčet jednotlivých hlavičkových souborů a jejich funkcí je uspořádán lexikograficky. Nejprve je tedy zdokumentován soubor uchar.h, poté ustring.h.
26
Kapitola 6. Závěr V rámci této bakalářské práce byly vyhledány volně dostupné knihovny jazyka C pro práci s řetězci a znaky v kódování UTF-8. Dle námi stanovených specifických kritérií (zajištění funkcionality dodávané standardní knihovnou jazyka C, další nabízená funkcionalita, portabilita, dostupná dokumentace, podpora, korektnost a ošetření výjimek a jiné) byl proveden výběr nejvhodnější, jeţ splňuje nejdůleţitější a nejširší spektrum našich poţadavků. Nejlépe hodnoceným kandidátem se stala knihovna ICU4C. Zajišťuje funkcionalitu, která nabízí vyuţití i v jiných oblastech práce, které se dotýkají odlišností spojených s internacionalizací. Pro tento účel není tedy nutné vyhledávat a testovat jiné knihovny. Značná rozsáhlost knihovny ICU4C můţe některým vývojářům při práci s ní činit potíţe. Z tohoto důvodu byl vytvořen krátký průvodce instalací tohoto balíčku. Pro demonstrační účely poslouţil systém Microsoft Windows verze Vista a vývojové prostředí Microsoft Visual Studio verze 2010, jehoţ pouţívání je sice placené, ale existuje jeho odlehčená verze Express, jejíţ pouţívání je bezplatné. Ta mimo jiné byla téţ pouţita v rámci aplikované analýzy a vygenerování příkladů pouţití vybraných funkcí knihovny ICU4C. Přiloţená referenční příručka byla vyhotovena za účelem provedení popisu vybraných funkcí, které se přímo týkají našich poţadavků pro práci s řetězci a znaky. Strategie vyhotovení byla pojata tak, aby bylo moţné přehledně vidět praktické vyuţití vybraných funkcí bez jakýchkoliv dalších komplexních částí kódu, které by mohli být matoucí. Další výhoda ICU4C je podpora více typů kódování (UTF-16, UTF-32). Jazyková varianta příručky existuje pro český i anglický jazyk. Po prohledání internetových zdrojů bylo zjištěno, ţe ţádná česká podpora pro tuto knihovnu není dodávána. Vytvoření referenční příručky tedy bude mít přínos minimálně pro ty, kteří neovládají cizí jazyky. Jelikoţ standardní knihovna stále neposkytuje uspokojivou funkcionalitu pro práci s řetězci a znaky v kódování UTF-8, jsme odkázáni na pouţívání externích knihoven. Jestliţe však jsou vyuţívány pouze základní funkce pro úpravu řetězců (kopírování, porovnávání či spojování bajtové sekvence řetězců), není třeba připojovat další knihovny. Tuto funkcionalitu lze jednoduše nahradit prostředky, které dodává GNU C Library (viz 3.2.1 Zajištění funkcionality dodávané standardní knihovnou) V souvislosti se standardizací programovacího jazyka C se často hovoří o připravovaném verzi C1X. V současné době je stále aktuální verze C99. Ten je podporován většinou pouţívaných kompilátorů pro jazyk C. Nicméně C1X by mohl vyřešit problém s kódováním UTF-8 uvnitř programu a odstranit nutnost vyuţívat externí knihovny. I přes jeho eventuální oficiální vydání stále má smysl ICU4C i nadále v aplikacích pouţívat, neboť dodává podporu nejen pro práci se znaky a řetězci, ale zároveň nabízí funkcionalitu pro formátování času, data, měny, uvozovek s ohledem na lokalizaci. Nicméně jedná se však pouze rozšiřující funkce, nikoliv nezbytné. Stejně jako kódování UTF-8 je dnes symbolem spojení všech států na úrovni informačních technologií, i knihovna ICU4C představuje nástroj, který pomáhá aplikacím psaným v jazyce C navzájem si rozumět. Věřím, ţe tato práce dobře poslouţí jako pomůcka pro české programátory, kteří chtějí psát aplikace přenositelné na stroje běţící pod různými operačními systémy po celém světě. V rámci dalšího rozšíření této práce by bylo vhodné obohatit referenční příručku o dokumentaci ostatních funkcí a maker z hlavičkových souborů, které nebyly v rozsahu této práce detailně popsány.
27
Příloha 1. Příloha Součástí bakalářské práce je přiloţené CD, kde je k dispozici: zdrojový kód této práce ve formátu XML tato práce ve formátu PDF tato práce ve formátu HTML tato práce ve formátu RTF zdrojový kód referenční příručky ve formátu HTML zdrojový kód knihovny ICU4C
28
Literatura [1] Brian Wilson Kernighan, Dennis MacAlistair Ritchie, The C Programming Language, Prentice-Hall, 1978, 0-13-110163-3, [2] C library, Cplusplus.com, 2011, http://www.cplusplus.com/reference/clibrary/, [3] Společnost pro výzkum a podporu open-source, OSS Alliance, 2008, http://www.oss.cz/, [4] Markus Kuhn, UTF-8 and Unicode FAQ for Unix/Linux, 2009, http://www.cl.cam.ac.uk/~mgk25/unicode.html, [5] Jukka Korpela, A tutorial on character code issues, 2009, http://www.cs.tut.fi/~jkorpela/chars.html,
29