<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xml" href="/cjs/screen.xsl" media="screen"?>
<lecture>

<meta>
  <maintitle>Webové technologie</maintitle>
  <author>Jiří Znamenáček</author>
  <title>Kódování, Unicode</title>
  <date>2010-09-16</date>
  <link><!--a href="http://vyuka.ookami.cz" rel="external">http://vyuka.ookami.cz</a--></link>
  <style>
  
    #ascii { font-family: monospace; }
        td.blue { background-color: lightblue; }
        td.darkblue { background-color: dodgerblue; }
        td.green { background-color: lightgreen; }
        td.yellow { background-color: yellow; }
        td.orange { background-color: orange; }
        td.violet { background-color: violet; }
    #ascii td[title] { cursor: help; }
  
  </style>
</meta>


<slide title="ASCII">
  
  <p>
    „Prvním“ počítačům (nebo spíše anglicky hovořícím uživatelům necítícím potřebu psát slova s cizími písmeny :-) stačila tabulka znaků o 128 položkách, tzv. ASCII:
  </p>
  <!--img src="_files/ascii.png" alt="" title="ASCII"/-->
  <table id="ascii" class="center slim">
    <tr>
        <th/>
        <th>0</th><th>1</th><th>2</th><th>3</th><th>4</th><th>5</th><th>6</th><th>7</th><th>8</th><th>9</th><th>A</th><th>B</th><th>C</th><th>D</th><th>E</th><th>F</th>
    </tr>
    <tr>
        <th>0</th>
        <td class="blue" title="null">NUL</td><td class="green" title="start of header">SOH</td><td class="green" title="start of text">STX</td><td class="green" title="end of text">ETX</td><td class="green" title="end of transmission">EOT</td><td class="green" title="enquiry">ENQ</td><td class="green" title="acknowledgement">ACK</td><td class="yellow" title="bell&#10;Python: \a">BEL</td><td class="orange" title="backspace&#10;Python: \b">BS</td><td class="orange" title="horizontal tab&#10;Python: \t">HT</td><td class="orange" title="line feed&#10;Python: \n">LF</td><td class="orange" title="vertical feed&#10;Python: \v">VT</td><td class="orange" title="form feed&#10;Python: \f">FF</td><td class="orange" title="carriage return&#10;Python: \r">CR</td><td class="violet" title="shift out">SO</td><td class="violet" title="shift in">SI</td>
    </tr>
    <tr>
        <th>1</th>
        <td class="green" title="data link escape">DLE</td><td class="yellow" title="device control 1 (XON)">DC1</td><td class="yellow" title="device control 2">DC2</td><td class="yellow" title="device control 3 (XOFF)">DC3</td><td class="yellow" title="device control 4">DC4</td><td class="green" title="negative acknowledgement">NAK</td><td class="green" title="synchronous idle">SYN</td><td class="green" title="end of transmission block">ETB</td><td class="blue" title="cancel">CAN</td><td class="blue" title="end of medium">EM</td><td class="blue" title="substitue">SUB</td><td class="violet" title="escape">ESC</td><td class="darkblue" title="file separator">FS</td><td class="darkblue" title="group separator">GS</td><td class="darkblue" title="request to send/record separator">RS</td><td class="darkblue" title="unit separator">US</td>
    </tr>
    <tr>
        <th>2</th>
        <td title="space">&#160;</td><td>!</td><td>"</td><td>#</td><td>$</td><td>%</td><td>&amp;</td><td>'</td><td>(</td><td>)</td><td>*</td><td>+</td><td>,</td><td>-</td><td>.</td><td>/</td>
    </tr>
    <tr>
        <th>3</th>
        <td>0</td><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td><td>8</td><td>9</td><td>:</td><td>;</td><td>&lt;</td><td>=</td><td>&gt;</td><td>?</td>
    </tr>
    <tr>
        <th>4</th>
        <td>@</td><td>A</td><td>B</td><td>C</td><td>D</td><td>E</td><td>F</td><td>G</td><td>H</td><td>I</td><td>J</td><td>K</td><td>L</td><td>M</td><td>N</td><td>O</td>
    </tr>
    <tr>
        <th>5</th>
        <td>P</td><td>Q</td><td>R</td><td>S</td><td>T</td><td>U</td><td>V</td><td>W</td><td>X</td><td>Y</td><td>Z</td><td>[</td><td>\</td><td>]</td><td>^</td><td>_</td>
    </tr>
    <tr>
        <th>6</th>
        <td>`</td><td>a</td><td>b</td><td>c</td><td>d</td><td>e</td><td>f</td><td>g</td><td>h</td><td>i</td><td>j</td><td>k</td><td>l</td><td>m</td><td>n</td><td>o</td>
    </tr>
    <tr>
        <th>7</th>
        <td>p</td><td>q</td><td>r</td><td>s</td><td>t</td><td>u</td><td>v</td><td>w</td><td>x</td><td>y</td><td>z</td><td>{</td><td>|</td><td>}</td><td>~</td><td class="blue" title="delete">DEL</td>
    </tr>
  </table>
  <note>
    Po najetí myší nad řídící znaky se objeví jejich krátký popis, případně u existujících i jejich pythoní textový ekvivalent.
  </note>
  <handout>
    https://www.sciencebuddies.org/science-fair-projects/references/ascii-table
  </handout>
  <p>
    Jednotlivé prvky tabulky mají přiřazená čísla 0-127 decimálně (aneb 0-7F hexadecimálně nebo 0-177 osmičkově) – k jejich zachycení v počítači tudíž stačí pouhých 7 bitů z každého bajtu.
  </p>
  <note>
    Jelikož tato dekódovací tabulka je starší než počítače a používala se již u dálnopisů, část z těchto 128 znaků (konkrétně 33; jsou to ty barevné v obrázku) nepředstavuje nějaký konkrétní zobrazitelný znak, ale tzv. <strong>znak řídicí</strong>. Například kódy 10 (LF = <em>line feed</em>) a 13 (CR = <em>carriage return</em>) se používají pro označení konce textové řádky, 9 (HT = <em>horizontal tabulator</em>) je běžný tabulátor a třebas 7 (BEL = <em>bell</em>) je zvoneček – schválně si zkuste na svém počítači zavolat v Python'u <code>print('\x07')</code> (nebo ekvivalentně kódovým znakem <code>print('\a')</code>) ^_~
  </note>

</slide>
<slide title="Nadstavby ASCII">
  
  <p>
    Počítače však už standardně používaly <em>bajty</em>, tj. bitů 8. To dávalo k dispozici dalších 128 možných znaků. Není ale divu, že každý si do volného místa vymyslel něco úplně jiného, kupříkladu i grafické prvky:
  </p>
  <img src="_files/oem.png" alt="" title="OEM"/>

</slide>
<slide title="PS: Bajty a znaky">

    <p>
        Základní jednotkou paměti počítačů je <strong>jeden bajt</strong>. V rámci jednoho bajtu dokáží počítače uložit – a tím pádem i rozpoznat – právě 256 různých čísel.
    </p>
    <note>
        Konkrétně jde o čísla 0 až 255. To je důsledkem toho, že jeden bajt se skládá z <strong>osmi bitů</strong>, přičemž každý bit se může nacházet pouze ve dvou stavech – 0 nebo 1. To dává dohromady právě oněch 256 možností – od <code>00000000</code> (což je nula jak dvojkově, tak desítkově) přes <code>01111111</code> (desítkově 127) až po <code>11111111</code> (desítkově 255).
    </note>
    <p>
        Většinou jsou tato čísla příkazy pro procesor, co má vykonat za instrukci, případně číselná data těchto instrukcí. Pokud však daný úsek paměti představuje text, odpovídají uvedená čísla znakům tohoto textu. A jelikož téměř všechna <strong>jednobajtová kódování znaků</strong> používají celých osm bitů, umožňuje takovéto kódování přiřadit k těmto dvěma stům padesáti šesti číslům stejný počet různých znaků textu – prostě jaké číslo se v dané buňce paměti nachází, takový znak (podle příslušné dekódovací tabulky daného kódování) mu odpovídá.
    </p>
    <!--p>
        Přitom z historických a naštěstí i praktických důvodů se téměř všechna běžně používaná kódování shodla na prvních 128 znacích (tedy přiřazení znaků číslům 0 až 127). Důsledkem je, že text obsahující převážně písmena latinské abecedy bez diakritiky bývá zvětší části čitelný, i když je zobrazen ve špatném kódování (kdy se tedy znaky s čísly 128 až 255 nezobrazují všechny správně).
    </p-->

</slide>
<slide title="Kódové stránky">
  
  <p>
    Pro rozlišení mezi různými rozšířeními v osmém bitu se zavedly tzv. <em>kódové stránky</em> (CP = <em>code pages</em>). Příkladem budiž CP 852 (Latin 2), Windows 1250 (Central Europe) nebo ISO/IEC 8859-5 (Cyrillic).
  </p>
  <note>
    Kupříkladu české slovo <code>svět</code> se liší bajtem pro písmenko <code>ě</code> v různých jednobajtových kódováních následujícím způsobem (hodnoty jsou uvedeny v šestnáctkové soustavě):
    <table border="border">
        <tr>
            <th>ISO 8859-2</th>
            <th>CP1250</th>
            <th>CP852</th>
            <th>MacCE</th>
        </tr>
        <tr>
            <td>73 76 EC 74</td>
            <td>73 76 EC 74</td>
            <td>73 76 D8 74</td>
            <td>73 76 9E 74</td>
        </tr>
    </table>
    Ostatní písmenka mají stejné kódy jako v ASCII – <code>s = 73</code>, <code>v = 76</code>, <code>t = 74</code> (podívejte se do <a href="?slajd=1">tabulky na prvním slajdu</a>). Celkem jsou na čtyři znaky slova potřeba právě čtyři bajty, tedy co znak, to jeden bajt. Proto se takovýmto kódováním říká <em>jednobajtová</em>.
  </note>
  <p>
    Alespoň že se všichni shodli, že prvních 128 čísel (0-127) bude odpovídat znakům starého dobrého ASCII – důsledkem je, že text obsahující převážně písmena latinské abecedy bez diakritiky bývá zvětší části čitelný, i když je zobrazen ve špatném kódování (kdy se tedy znaky s čísly 128 až 255 nezobrazují všechny správně). <!--Ovšem všechno ostatní ... škoda mluvit.-->
  </p>

</slide>
<slide title="Intermezzo">
  
  <p>
    Mimochodem – nejen že co jazyk, to vlastní CP. Spíš co výrobce nebo program to vlastní CP *_* Pamětníkům dodnes vstávají vlasy hrůzou na hlavě, když si vzpomenou na různá kódování češtiny…
  </p>
  <note>
    A co teprve takový textový editor WordStar, který prý osmý bit používal pro označení posledního znaku slova *_*
  </note>
  <p>
    A nezapomeňme na východní jazyky, kterým pouhých 128/256 znaků na zaznamenání jejich obrázkových písem o desítkách tisíc znaků v žádném případě stačit nemohlo! Ty svůj problém vyřešily použitím tzv. DBCS-systému – něco se zapsalo bajtem jedním, něco (většina) dvěma.
  </p>
  <note>
    A co takhle zkusit vytvořit dokument s alespoň dvěma různými písmy najednou, co vy na to, he?
  </note>

</slide>
<slide title="Enter Unicode!">
  
  <p>
    Dlouho přehlížený problém, který se provalil na světlo s příchodem Internetu (a tedy do té doby nevídanou volnou výměnou dokumentů mezi různými počítači a systémy), naštěstí pár osvícenců<sup>*</sup> řešilo už v osmdesátých letech. Výsledkem jejich snažení byla univerzální množina znaků, tzv.
  </p>
  <blockquote style="font-weight: bold; font-size: xx-large;">
    <center>UNICODE</center>
  </blockquote>
  <note>
    <sup>*</sup> Konkrétně programátoři z Japonska a lidi z firmy Xerox (jak jinak; už chybí jenom někdo z Bellových laboratoří :-).
  </note>
  <p>
    PS: Kromě samotné tabulky znaků řeší Unicode ale i mnoho dalších věcí, zvláště pro implementátory – namátkou třebas řazení nebo vykreslování.
  </p>

</slide>
<slide title="Code Points">
  
  <p>
    V Unicode'u má každý znak (jehož přesná definice není ani trochu triviální!) přiřazeno jedinečné konkrétní číslo, tzv. <em>code point</em>. Tak kupříkladu latinské <em>A</em> má číslo U+0041 a řecká <em>α</em> zase U+03B1.
  </p>
  <p>
    Přiřazených znaků je v dané chvíli již přes sto tisíc, tudíž je jasné, že pro jejich zachycení si už dávno nevystačíme ani se dvěma bajty.
  </p>
  <note>
    Dva bajty odpovídají celkem <code>256^2=65536</code> (teoreticky) možným znakům.
  </note>

</slide>
<slide title="Kódování">
  
  <p>
    Nejjednodušším způsobem jak uložit text v Unicode'u bude asi prostě zapsat jeho <em>code point</em> přímo jako bajty (pro prvních 65536 znaků případ UTF-16). Číhá na nás ale několik zádrhelů:
  </p>
  <ul>
    <li>
      Ne všechny systémy ukládají vícebajtové hodnoty ve stejném pořadí (viz <em>big-endian</em> a <em>little-endian</em>)!
      <note>
        Pořadí <em>big-endian</em> je tak nějak lidsky přirozenější – číslo 256, které už se nevleze do jednoho bajtu a musíme ho tak zapsat bajty dvěma, se v něm zapíše jako <code
      >00000001 00000000</code> (tedy <code>1*256^1 + 0*256^0</code>), zatímco v <em>little-endian</em> je pořadí bajtů opačné, tj. <code>00000000 00000001</code> (neboli <code>0*256^0 + 1*256^1</code>).
      </note>
    </li>
    <li>
      Vidíte, kolik zbytečných nul bude obsahovat text, na který by bývalo stačilo ASCII?
    </li>
  </ul>
  
  <p>
    První problém (pořadí bajtů) byl nuceně vyřešen (téměř) povinným zápisem jisté sekvence bajtů na začátek každého unicodového řetězce, tzv. <em>BOM</em> (<em>byte order mark</em>). Podle jejich pořadí pak program (interpretující danou sekvenci bajtů jako text) pozná, o kterou z obou variant jde.
  </p>
  <note>
    Konkrétně je BOM sekvencí <code>FE FF</code> pro UTF-16 a <code>00 00 FE FF</code> pro UTF-32. V UTF-8 BOM (který pak je <code>EF BB BF</code>) spíše překáží – za prvé je tam zbytečný (UTF-8 je sekvence jednotlivých bajtů, takže žádné problémy s pořadím zápisu vícebajtových hodnot nemá) a za druhé s ním spousta programů nepočítá.
  </note>
  <p>
    Druhý problém si ovšem vyžádal hodně přemýšlení: Jak jednoznačně a výhodně zaznamenat oněch více jak sto tisíc znaků, aby se všechny vešly, ale přitom jsme nespotřebovávali zbytečně moc místa?
  </p>

</slide>
<slide title="Enter UTF-8!">
  
  <p>
    Naprosto geniálním řešením (i když východní Asie naše nadšení sdílet nemusí) je kódování UTF-8.
  </p>
  <ul>
    <li>Znaky s <em>code points</em> 0 až 127, tj. staré dobré ASCII, se vlezou do jednoho bajtu a jsou zaznamenány úplně stejně.</li>
    <li>Znaky s vyššími <em>code points</em> se zaznamenávají rozdílným počtem bajtů (dvěma až čtyřmi).</li>
  </ul>
  <p>
    Příklad: České slovo <code>svět</code> je v UTF-8 zakódováno do 5 bajtů, ačkoli má pouze 4 písmenka – <code>73 76 C4 9B 74</code> (hexadecimálně). Zvětšení jde na vrub písmenku <code>ě</code>, které potřebuje bajty dva (<code>C4 9B</code>), zatímco zbylá tři písmenka jsou zakódována stejně jako v ASCII (porovnejte s <a href="?slajd=4">příklady jednobajtových kódování</a>).
  </p>

</slide>
<slide title="UTF-8 algoritmus">
  
  <p>
    Konkrétně platí, že začíná-li bajt v UTF-8 zakódovaném textu na jedničku, jde o součást vícebajtové reprezentace jednoho konkrétního znaku s <em>codepoint</em>em v rozsahu 128+:
  </p>
  <table border="1" cellspacing="0" cellpadding="5" align="center">
    <tr>
        <th>oktet 1</th>
        <th>oktet 2</th>
        <th>oktet 3</th>
        <th>oktet 4</th>
        <th><em>code point</em></th>
        <th>znaků</th>
    </tr>
    <tr>
        <td>0xxxxxxx</td>
        <td/>
        <td/>
        <td/>
        <td align="right">0xxxxxxx</td>
        <td align="center">128</td>
    </tr>
    <tr>
        <td>110zzzyy</td>
        <td>10xxxxxx</td>
        <td/>
        <td/>
        <td align="right">00000zzz yyxxxxxx</td>
        <td align="center">?</td>
    </tr>
    <tr>
        <td>1110wwww</td>
        <td>10zzzzyy</td>
        <td>10xxxxxx</td>
        <td/>
        <td align="right">wwwwzzzz yyxxxxxx</td>
        <td align="center">?</td>
    </tr>
    <tr>
        <td>11110uuu</td>
        <td>10vvwwww</td>
        <td>10zzzzyy</td>
        <td>10xxxxxx</td>
        <td align="right">000uuuvv wwwwzzzz yyxxxxxx</td>
        <td align="center">?</td>
    </tr>
  </table>
  <notes>
    <note>
      Navíc vidíte, že bajty začínající na <code>10</code> jsou druhým (třetím, čtvrtým…) ve vícebajtovém záznamu, zatímco bajty začínající na <code>11</code> jsou počátkem příslušného vícebajtového záznamu znaku (a konkrétní tvar začátku tohoto bajtu pak i říká, z kolika dalších bajtů je třeba výsledný <em>codepoint</em> spočítat).
    </note>
    <note>
      Podle: "Unicode Explained" by Jukka K. Korpela (O'Reilly 2006), ISBN 0-596-10121-X &amp; <a class="external" href="http://en.wikipedia.org/wiki/UTF-8">http://en.wikipedia.org/wiki/UTF-8</a>
    </note>
  </notes>
  <p>
    PS: Otazníčky v posledním sloupečku jsou pochopitelně úkol na příslušné hodině ^_~ Nicméně přímý převod z bitů na počet znaků je pouze teoretické maximum, které sráží asi tak na polovinu výrazně komplikovanější struktura Unicode'u, než by člověk na první pohled čekal. (Ne všechny dostupné číselné rozsahy jsou totiž použity pro <em>codepoints</em>, tedy vlastní určení znaku. Navíc se také uplatňuje pravidlo, že je-li možné daný <em>codepoint</em> v bajtech zapsat vícero způsoby, vybírá se ten kratší, čímž se delší varianta vyřadí z množiny dostupných hodnot.)
  </p>

</slide>
<slide title="Příklad (čeština)">

    <p>
        Podívejme se na zoubek českému slovu <code>svět</code> v kódování UTF-8:
    </p>
    <example lang="python">
        >>> 'svět'.encode('utf-8')
        b'sv\xc4\x9bt'
    </example>
    <p>
        Písmenu <code>ě</code> tedy odpovídá sekvence bajtů <code>\xc4\x9b</code>, zatímco písmena <code>s</code>, <code>v</code> a <code>t</code> jakožto členy spodní části ASCII-tabulky jsou reprezentována sama sebou. V tomto případě můžeme toto rozdělení vykoukat snadno přímo (pouze jeden znak je zaznamenán dvoubajtově), ale správně ho zjistíme až z odpovídající binární podoby:
    </p>
    <example lang="python">
        # s (skutečně začíná na 0, zobrazeno je jenom 7 bitů)
        >>> bin(ord('s'))
        '0b1110011'
        
        # v (skutečně začíná na 0, zobrazeno je jenom 7 bitů)
        >>> bin(ord('v'))
        '0b1110110'

        # ě
        >>> bin(int('c4', 16))
        '0b11000100'
        >>> bin(int('9b', 16))
        '0b10011011'
        
        # t (skutečně začíná na 0, zobrazeno je jenom 7 bitů)
        >>> bin(ord('t'))
        '0b1110100'
    </example>
    <p>
        Podle algoritmu pro kódování UTF-8 získáme pro jednotlivé znaky odpovídající číslo do unicodové tabulky:
    </p>
    <example lang="python">
        # s = '0b01110011'
        >>> int('01110011', 2)
        115
        
        # v = '0b01110110'
        >>> int('01110110', 2)
        118
        
        # ě = '0b11000100' '0b10011011'
        >>> int('00000001', 2) * 256 + int('00011011', 2)
        283
        
        # t = '0b01110100'
        >>> int('01110100', 2)
        116
    </example>
    <p>
        Aniž bychom koukali do standardu, jaké znaky těmto unicodovým <em>codepointům</em> odpovídají, můžeme daná čísla přímo použít pro <a href="xML.encoding.xml?slajd=5">znakové HTML-entity</a> <code>&amp;#115; &amp;#118; &amp;#283; &amp;#116;</code>: „&#115;&#118;&#283;&#116;“
    </p>

</slide>
<slide title="Příklad (japonština)">

    <p>
        Podívejme se na zoubek japonskému znaku <code>狼</code> (<em>ookami</em> = vlk) v kódování UTF-8:
    </p>
    <example lang="python">
        >>> '狼'.encode('utf-8')
        b'\xe7\x8b\xbc'
    </example>
    <p>
        Jednotlivé bajty mají následující binární podobu:
    </p>
    <example lang="python">
        >>> bin(int('e7', 16))
        '0b11100111'
        >>> bin(int('8b', 16))
        '0b10001011'
        >>> bin(int('bc', 16))
        '0b10111100'
    </example>
    <p>
        Podle algoritmu pro kódování UTF-8 získáme odpovídající číslo do unicodové tabulky:
    </p>
    <example lang="python">
        >>> int('01110010', 2) * 256 + int('11111100', 2)
        29436
    </example>
    <p>
        A decimální <code>29436</code> je skutečně <em>codepoint</em> odpovídající v Unicode'u znaku <code>狼</code>.
    </p>
    <note>
        O čemž se i bez náhledu do standardu snadno přesvědčíme například použitím daného čísla pro <a href="xML.encoding.xml?slajd=5">znakovou HTML-entitu</a> <code>&amp;#29436;</code>: „&#29436;“
    </note>

</slide>
<!--slide title="Příklad (čeština)">

    <p>
        Podívejme se na zoubek českému slovu <code>řeč</code> v kódování UTF-8:
    </p>
    <example lang="python">
        >>> 'řeč'.encode('utf-8')
        b'\xc5\x99e\xc4\x8d'
    </example>
    <p>
        Písmenu <code>ř</code> odpovídá sekvence bajtů <code>\xc5\x99</code>, písmeno <code>e</code> jako člen spodní části ASCII-tabulky je reprezentováno samo sebou a písmeno <code>č</code> zabírá poslední dva bajty <code>\xc4\x8d</code>. Zde můžeme toto rozdělení vykoukat sice přímo, ale správně ho zjistíme až z odpovídající binární podoby:
    </p>
    <example lang="python">
        # ř
        >>> bin(int('c5', 16))
        '0b11000101'
        >>> bin(int('99', 16))
        '0b10011001'
        
        # e (skutečně začíná na 0, zobrazeno je jenom 7 bitů)
        >>> bin(ord('e'))
        '0b1100101'
        
        # č
        >>> bin(int('c4', 16))
        '0b11000100'
        >>> bin(int('8d', 16))
        '0b10001101'
    </example>
    <p>
        Podle algoritmu pro kódování UTF-8 získáme pro jednotlivé znaky odpovídající číslo do unicodové tabulky:
    </p>
    <example lang="python">
        # ř = '0b11000101' '0b10011001'
        >>> int('00000001', 2) * 256 + int('01011001', 2)
        345
        
        # e = '0b01100101'
        >>> int('01100101', 2)
        101
        
        # č = '0b11000100' '0b10001101'
        >>> int('00000001', 2) * 256 + int('00001101', 2)
        269
    </example>
    <p>
        Aniž bychom koukali do standardu, jaké znaky těmto unicodovým <em>codepointům</em> odpovídají, můžeme daná čísla přímo použít pro <a href="xML.encoding.xml?slajd=5">znakové HTML-entity</a> <code>&amp;#345; &amp;#101; &amp;#269;</code>: „&#345;&#101;&#269;“
    </p>

</slide-->
<slide title="Poznámka k UTF-8">
  
  <p>
    Zatímco české znaky s nabodeníčky v libovolném jednobajtovém (tedy osmibitovém) kódování zabírají samozřejmě právě jeden bajt, v kódování UTF-8 zabírají bajty dva.
  </p>
  <note>
    Unicodová tabulka byla sestavena tak, že po latince z ASCII-části následují nejdříve její jednoduché úpravy v podobě kupříkladu českých nabodeníček. Konkrétně se jedná o (desítkový) rozsah 192 až 382:
    <pre>
      192:  À  Á  Â  Ã  Ä  Å  Æ  Ç  È  É  Ê  Ë  Ì  Í  Î  Ï
      208:  Ð  Ñ  Ò  Ó  Ô  Õ  Ö  ×  Ø  Ù  Ú  Û  Ü  Ý  Þ  ß
      224:  à  á  â  ã  ä  å  æ  ç  è  é  ê  ë  ì  í  î  ï
      240:  ð  ñ  ò  ó  ô  õ  ö  ÷  ø  ù  ú  û  ü  ý  þ  ÿ
      256:  Ā  ā  Ă  ă  Ą  ą  Ć  ć  Ĉ  ĉ  Ċ  ċ  Č  č  Ď  ď
      272:  Đ  đ  Ē  ē  Ĕ  ĕ  Ė  ė  Ę  ę  Ě  ě  Ĝ  ĝ  Ğ  ğ
      288:  Ġ  ġ  Ģ  ģ  Ĥ  ĥ  Ħ  ħ  Ĩ  ĩ  Ī  ī  Ĭ  ĭ  Į  į
      304:  İ  ı  Ĳ  ĳ  Ĵ  ĵ  Ķ  ķ  ĸ  Ĺ  ĺ  Ļ  ļ  Ľ  ľ  Ŀ
      320:  ŀ  Ł  ł  Ń  ń  Ņ  ņ  Ň  ň  ŉ  Ŋ  ŋ  Ō  ō  Ŏ  ŏ
      336:  Ő  ő  Œ  œ  Ŕ  ŕ  Ŗ  ŗ  Ř  ř  Ś  ś  Ŝ  ŝ  Ş  ş
      352:  Š  š  Ţ  ţ  Ť  ť  Ŧ  ŧ  Ũ  ũ  Ū  ū  Ŭ  ŭ  Ů  ů
      368:  Ű  ű  Ų  ų  Ŵ  ŵ  Ŷ  ŷ  Ÿ  Ź  ź  Ż  ż  Ž  ž  ſ    </pre>
  </note>
  <p>
    Podobně asijská písma dříve typicky zapisovaná pomocí svých specifických dvoubajtových kódování zabírají v UTF-8 na každý znak bajty tři (což jejich záznam v tomto kódování pochopitelně značně prodlužuje).
  </p>
  <!--p>
    V reálných textech se ale ukazuje, že rozdíl je zanedbatelný.
  </p>
  <note>
    Ad Asie: Alespoň to tvrdí Wikipedie, neověřoval jsem to.
  </note-->

</slide>
<slide title="A co na to Python?">
  
  <p>
    Odpověď je dvojí a nehezká:
  </p>
  <ul>
    <li class="py3k">
      Python 3 – pokud není řečeno jinak, je vše pokládáno za UTF-8. <em>*nirvána*</em>
      <note>
        I když díky BOMu bohužel zdaleka ne tak úplná, jak by mohla být – viz <a href="/materialy/python/pitfalls.xml?slajd=6">rozdíl mezi kódováními <code>utf-8</code> a <code>utf-8-sig</code></a> 0_o
      </note>
    </li>
    <li class="py2k">
      Python 2 – vše je pokládáno za sekvence bajtů v případě potřeby interpretované jako řetězce v aktuálním kódování (to jako vážně!) a pokud vám to nestačí, připravte se na škrábání levou rukou za pravým uchem s nohama svázanýma do kozelce.
      <note>
        U Python'u 2 vás budou zajímat metody takovéhoto „řetězce“ <em>decode()</em> a <em>encode()</em> plus velmi často systémová knihovna <em>codecs</em>.
      </note>
    </li>
  </ul>

</slide>


</lecture>
