Unicode
Antes do aparecimento do Unicode a forma como os caracteres e símbolos das linguagens humanas eram codificados no computador não era realizada da mesma maneira. As linguagens latinas seguiam a regra de um byte por cada carácter cujo valor é atribuído por uma tabela de caracteres pré-definida como a ASCII ou a ISO-8859-1. Nas linguagens orientais devido ao elevado número de caracteres cada é codificado por múltiplos bytes de acordo com um standard. Para além da quantidade de bytes outra diferença impostas pelas linguagens é a sua orientação de escrita: os ocidentais seguem na sua maioria a orientação da esquerda para a direita enquanto outras linguagens impõe a orientação inversas ou mesmo a orientação de cima para baixo.
Estas diferenças dificultam o processamento informático de textos que têm de combinar diversas linguagens . Para solucionar este problema foi desenvolvido o Unicode por forma a definir uma tabela contendo os caracteres de todas as linguagens e algoritmos que permitem misturar pedaços de textos escritos em linguagens diferentes para definir um todo que seja tratável por um computador.
Tabela de caracteres
A tabela de caracteres do Unicode representa caracteres e não as suas representações gráficas (claro que na tabela de caracteres há uma representação gráfica do mesmo de forma a ser mais fácil a sua identificação). A representação gráfica de cada carácter Unicode é da responsabilidade do designer de fontes para computador. Além dos caracteres presentes nos alfabetos das linguagens mundiais como as latinas, as árabes, a cirilica, a grega, a chinesa, a japonesa, a coreana entre outras há outros caracteres provenientes de notações como a matemática, a música, musica bizantina, Braille, etc,.
Cada carácter no Unicode tem o nome de code element e é identificado por um valor numérico a que se dá o nome de codepoint. Também é caracterizado por um nome unívoco, uma abreviação e por várias propriedades, entre elas as mais importantes são:
- Categoria, isto é, se é número ou uma letra, ou um simbolo,
- O seu valor numérico se tal for aplicável,
- Indicação se é uma letra maiúscula, minúscula ou se só é maiúscula no inicio de uma palavra
- Tipo, isto é, se é um carácter base, um carácter de combinação, um carácter de formato – (por exemplo, indicação de mudança de linha ) ou um carácter de controle (por exemplo, permitem controlar a orientação do texto).
Dada a quantidade de informação associada a cada carácter ser muito grande o consorcium Unicode distribui essa informação em vários ficheiros de texto a que se dá o nome de Unicode Character Database (UCD).
Desde a versão 3 do Unicode, a mais recente é a 5, que cada carácter da tabela Unicode é representado por um conjunto de 32bits. A actual versão define 99089 caracteres pertencentes a alfabetos mundiais e a diversas notações. O intervalo de valores disponíveis para os codepoints é chamado de codespace, estando definido da seguinte forma: [0, D7FF] e [E000, 10FFFFF], existindo por isso 1 114 112 codepoints possíveis de serem atribuídos a code elements.
Numa tentativa de organizar os mais de 99 mil caracteres a especificação Unicode agrupa os caracteres de acordo com a linguagem ou notação a que pertencem, dividindo assim logicamente as secções do codespace. A cada divisão chama-se um Script.
Os actuais scripts do Unicode são (primeiro é apresentado o intervalo de codepoints e depois o nome do script):
0000..007F; Basic Latin
0080..00FF; Latin-1 Supplement
0100..017F; Latin Extended-A
0180..024F; Latin Extended-B
0250..02AF; IPA Extensions
02B0..02FF; Spacing Modifier Letters
0300..036F; Combining Diacritical Marks
0370..03FF; Greek and Coptic
0400..04FF; Cyrillic
0500..052F; Cyrillic Supplement
0530..058F; Armenian
0590..05FF; Hebrew
0600..06FF; Arabic
0700..074F; Syriac
0750..077F; Arabic Supplement
0780..07BF; Thaana
07C0..07FF; NKo
0900..097F; Devanagari
0980..09FF; Bengali
0A00..0A7F; Gurmukhi
0A80..0AFF; Gujarati
0B00..0B7F; Oriya
0B80..0BFF; Tamil
0C00..0C7F; Telugu
0C80..0CFF; Kannada
0D00..0D7F; Malayalam
0D80..0DFF; Sinhala
0E00..0E7F; Thai
0E80..0EFF; Lao
0F00..0FFF; Tibetan
1000..109F; Myanmar
10A0..10FF; Georgian
1100..11FF; Hangul Jamo
1200..137F; Ethiopic
1380..139F; Ethiopic Supplement
13A0..13FF; Cherokee
1400..167F; Unified Canadian Aboriginal Syllabics
1680..169F; Ogham
16A0..16FF; Runic
1700..171F; Tagalog
1720..173F; Hanunoo
1740..175F; Buhid
1760..177F; Tagbanwa
1780..17FF; Khmer
1800..18AF; Mongolian
1900..194F; Limbu
1950..197F; Tai Le
1980..19DF; New Tai Lue
19E0..19FF; Khmer Symbols
1A00..1A1F; Buginese
1B00..1B7F; Balinese
1D00..1D7F; Phonetic Extensions
1D80..1DBF; Phonetic Extensions Supplement
1DC0..1DFF; Combining Diacritical Marks Supplement
1E00..1EFF; Latin Extended Additional
1F00..1FFF; Greek Extended
2000..206F; General Punctuation
2070..209F; Superscripts and Subscripts
20A0..20CF; Currency Symbols
20D0..20FF; Combining Diacritical Marks for Symbols
2100..214F; Letterlike Symbols
2150..218F; Number Forms
2190..21FF; Arrows
2200..22FF; Mathematical Operators
2300..23FF; Miscellaneous Technical
2400..243F; Control Pictures
2440..245F; Optical Character Recognition
2460..24FF; Enclosed Alphanumerics
2500..257F; Box Drawing
2580..259F; Block Elements
25A0..25FF; Geometric Shapes
2600..26FF; Miscellaneous Symbols
2700..27BF; Dingbats
27C0..27EF; Miscellaneous Mathematical Symbols-A
27F0..27FF; Supplemental Arrows-A
2800..28FF; Braille Patterns
2900..297F; Supplemental Arrows-B
2980..29FF; Miscellaneous Mathematical Symbols-B
2A00..2AFF; Supplemental Mathematical Operators
2B00..2BFF; Miscellaneous Symbols and Arrows
2C00..2C5F; Glagolitic
2C60..2C7F; Latin Extended-C
2C80..2CFF; Coptic
2D00..2D2F; Georgian Supplement
2D30..2D7F; Tifinagh
2D80..2DDF; Ethiopic Extended
2E00..2E7F; Supplemental Punctuation
2E80..2EFF; CJK Radicals Supplement
2F00..2FDF; Kangxi Radicals
2FF0..2FFF; Ideographic Description Characters
3000..303F; CJK Symbols and Punctuation
3040..309F; Hiragana
30A0..30FF; Katakana
3100..312F; Bopomofo
3130..318F; Hangul Compatibility Jamo
3190..319F; Kanbun
31A0..31BF; Bopomofo Extended
31C0..31EF; CJK Strokes
31F0..31FF; Katakana Phonetic Extensions
3200..32FF; Enclosed CJK Letters and Months
3300..33FF; CJK Compatibility
3400..4DBF; CJK Unified Ideographs Extension A
4DC0..4DFF; Yijing Hexagram Symbols
4E00..9FFF; CJK Unified Ideographs
A000..A48F; Yi Syllables
A490..A4CF; Yi Radicals
A700..A71F; Modifier Tone Letters
A720..A7FF; Latin Extended-D
A800..A82F; Syloti Nagri
A840..A87F; Phags-pa
AC00..D7AF; Hangul Syllables
D800..DB7F; High Surrogates
DB80..DBFF; High Private Use Surrogates
DC00..DFFF; Low Surrogates
E000..F8FF; Private Use Area
F900..FAFF; CJK Compatibility Ideographs
FB00..FB4F; Alphabetic Presentation Forms
FB50..FDFF; Arabic Presentation Forms-A
FE00..FE0F; Variation Selectors
FE10..FE1F; Vertical Forms
FE20..FE2F; Combining Half Marks
FE30..FE4F; CJK Compatibility Forms
FE50..FE6F; Small Form Variants
FE70..FEFF; Arabic Presentation Forms-B
FF00..FFEF; Halfwidth and Fullwidth Forms
FFF0..FFFF; Specials
10000..1007F; Linear B Syllabary
10080..100FF; Linear B Ideograms
10100..1013F; Aegean Numbers
10140..1018F; Ancient Greek Numbers
10300..1032F; Old Italic
10330..1034F; Gothic
10380..1039F; Ugaritic
103A0..103DF; Old Persian
10400..1044F; Deseret
10450..1047F; Shavian
10480..104AF; Osmanya
10800..1083F; Cypriot Syllabary
10900..1091F; Phoenician
10A00..10A5F; Kharoshthi
12000..123FF; Cuneiform
12400..1247F; Cuneiform Numbers and Punctuation
1D000..1D0FF; Byzantine Musical Symbols
1D100..1D1FF; Musical Symbols
1D200..1D24F; Ancient Greek Musical Notation
1D300..1D35F; Tai Xuan Jing Symbols
1D360..1D37F; Counting Rod Numerals
1D400..1D7FF; Mathematical Alphanumeric Symbols
20000..2A6DF; CJK Unified Ideographs Extension B
2F800..2FA1F; CJK Compatibility Ideographs Supplement
E0000..E007F; Tags
E0100..E01EF; Variation Selectors Supplement
F0000..FFFFF; Supplementary Private Use Area-A
100000..10FFFF; Supplementary Private Use Area-B
Os caracteres cujo code point pode ser codificados por 16 bits (entre 0 e 65536) estão no plano Basic Multilingual Plane (BMP), correspondendo aos scripts da maioria das linguagens humanas.
O Unicode foi desenhado para ser compatível com algumas codificações já existentes como o código ASCII ou o ISO-8859-1, pelo que os primeiros 255 caracteres são idênticos a esses dois códigos, por exemplo a letra A tem o valor 65(dec) no Unicode, no ASCII e no ISO-8859-1.
Para além dos caracteres das linguagens humanas também estão definidos caracteres que permitem ao computador identificar onde começa uma palavra, uma linha ou um paragrafo, são os chamados caracteres de controlo. A seguir identifica-se alguns dos caracteres de controlo mais importantes:
Caracteres para mudança de linha e de paragrafo:
|
Acronym Name
|
Unicode
|
ASCII
|
O Unicode define dois caracteres para delimitar linhas e parágrafos. O seu uso não é obrigatório uma vez que também estão definidos os caracteres usados pelo código ASCII para separar linhas. Note-se que no mundo Windows a mudança de linha é identificada pelo par CRLF ao passo que no UNIX a mudança de linha é indicada apenas por LF.
Caracteres identificadores de espaço
Caracteres que permitem controlar a direcção do texto, isto é, se ele flui da esquerda para a direita ou vice-versa. São usados quando há uma combinação de texto bi-direccional, senão o seu uso não é obrigatório.
O carácter do euro € tem o codepoint U+20AC
Composição de caracteres
Uma diferença do Unicode para os códigos ASCII e ISO-8859-1 é que permite a composição dinâmica de caracteres, isto é, um conjunto de caracteres Unicode combinados entre si podem definir um novo carácter que não está presente na tabela de caracteres. Esta funcionalidade é útil para suportar as linguagens asiáticas. Contudo, do ponto de vista de programação a composição de caracteres elimina a regra “um carácter por cada unidade de codificação” que é valida desde os tempos do ASCII. Para programas pensados para serem executados apenas no Ocidente a regra continua a ser válida uma vez que não é necessário a composição de caracteres para estas linguagens.
Para combinar caracteres é necessário ter um carácter “base” e um ou mais caracteres “combinantes”. Os caracteres combinantes são aplicados sempre ao carácter base que se apresente à sua esquerda, por exemplo: A sequência de codepoints <U0041 U0307> resulta no caractere Ä, uma vez que o U0041 é o caracteres base A e U0307 é caracter combinante ¨.
Do exemplo anterior e de uma inspecção à tabela de códigos do Unicode chega-se à conclusão que já existe o carácter Ä com o codepoint 00C4. Tal facto, deve-se como já foi mencionado anteriormente, de o Unicode suportar standards já existentes como o ASCII ou o ISO-8859-1.
Quando um carácter com um codepoint atribuído é igual a um carácter obtidos através de combinação diz-se que ocorreu uma equivalência.
Encoding
Como os computadores só entendem conjuntos de bits que podem ter o tamanho de 8, 16, 32 e mais recentemente em 64 o standard Unicode definiu de uma forma clara como representar cada codepoint da tabela de caracteres nos diversos tamanhos. São as chamadas codificações (encodings). O standard especifica três:
- UTF-8: transforma um codepoint numa sequência de tamanho variável de bytes (conjunto de 8 bits).
- UTF-16: transforma um codepoint num ou em dois conjuntos de words (conjunto de 16 bits)
- UTF-32: transforma um codepoint num único conjunto de 32 bits.
Independente de cada forma de codificação, há a garantia de cada carácter Unicode ser codificado por uma sequência com no máximo 4 conjuntos (bytes).
A sigla UTF significa Unicode Transformation Format.
A seguinte tabela ilustra os valores das três codificações para quatro caracteres dispersos no codespace do Unicode (os valores estão em hexadecimal e o espaço delimita cada conjunto de bits).
.
|
Carácter
|
A
|
Ω
|
representação indisponível
|
representação indisponível
|
Como pode ser observado, em algumas situações os valores de UTF-16 e UTF-8 não são iguais ao valor do codepoint codificado. Tal facto está relacionado com as regras de cada codificação, que são:
Para a codificação UTF-32:
- os codepoints são codificados directamente em 32 bits sendo bem formado se estiver entre os valores do codespace Unicode: [0, D7FF] ou [E000 e 10FFFF]
Para a codificação UTF-16:
- os codepoints entre [0000 e FFFF] (hex), com um número menor que 16bits, são representados directamente numa única Word.
- os codepoints entre 10000(hex) e 10FFFF(hex) são representados através de duas words usando a seguinte regra:
- O valor binário de um codepoint na forma 000uuuuuxxxxxxxxxxxxxxxx é codificado em duas words: A primeira constituída por 110110wwwwxxxxxx e a segunda por 110111xxxxxxxxxx, onde wwww=uuuuu-1
Para o UTF-8 (<NU> = Não usado):
| Codepoint |
1º byte |
2ºbyte |
3ºbyte |
4ºbyte |
As codificações UTF-16 e UTF-32 tem variantes para acomodar o tipo de processador que codificou o texto, ou seja se ele é Big-Endien (onde o byte mais significativo é colocado primeiro) ou Litle-Endien (onde o byte menos significativo é colocado primeiro). As codificações para estes casos chamam-se UTF-16-LE, UTF-32-LE, UTF-16-BE, UTF-32-BE e seguem as regras de codificações descritas anteriormente para o UTF-16 e UTF-32. A única diferença é a ordem dos bytes obtidos como resultado da codificação. A codificação UTF-8 não tem variante BE ou LE porque os bits de um byte são processados pela mesma ordem em todas as arquitecturas.
As codificações UTF-16 e UTF-32 levantam um problema de interpretação porque não indicam qual a ordem de leitura dos bytes, ao contrario das codificações UTF-16-BE, UTF-16-LE, UTF-32-BE e UTF-32-LE que especificam claramente a sua ordem. Para resolver este problema, o Unicode definiu o carácter Byte Order Mark (BOM) com o codepoint UFEFF que permite identificar a ordem de leitura dos bytes das codificações UTF-16 e UTF-32.
A inclusão do BOM não é obrigatório, o que nesse caso deixa à consideração da aplicação leitora a interpretação da ordem de leitura dos bytes, embora haja a tendência de ser interpretada como big-endien.
O BOM quando usado para identificar a ordem deve surgir antes da informação codificada (deve ser o primeiro carácter) e dependendo da ordem de bytes usada na codificação o seu valor identifica o ardem de codificação, assim, se o seu valor é :
- U+FEFF identifica que a informação está codificada na ordem litle-endien
- U+FFFE indica a ordem big-enfien.
As codificações UTF-16BE, UTF-16LE, UTF-32BE e UTF-32LE não necessitam do BOM porque a ordem dos byte é explicitada pelos sufixos BE (Big-endien) e LE (little-endien).
A seguinte tabela demonstra a codificação de um único codepoint nas várias variantes da UTF-16
|
Codepoint
|
Codificação
|
Valor
|
Um efeito colateral interessante do uso do BOM é que permite implicitamente identificar que a informação seguinte são caracteres Unicode, embora tal detecção não seja fiável uma vez que o standard não obriga o seu uso. Na codificação UTF-8 o BOM é expresso pela sequência <EF BB BF>, não tendo qualquer significado a não ser que é provável que a informação a seguir seja texto Unicode.
Ordenação e pesquisa de caracteres
O critério de ordenação de caracteres não é uniforme entre as diversas linguagens. Cada uma tem as suas particularidades devido à posição a que atribui aos caracteres do seu alfabeto, como ordena os caracteres com acento ou como ordena os caracteres na forma maiúscula ou na forma minúscula.
Collation é o termo dado à forma como duas string são comparadas de forma a determinar qual a menor e a maior.
No Unicode não se podem comparar Strings de caracteres através da comparação directa do valor do codepoint de cada carácter.
Para comparar String Unicode deve-se usar o Algoritmo “Unicode Colaction Algorithm” que através de uma Collation Element Table consegue ordena as strings. O standard Unicode define a Default Unicode Collation Element Table, como sendo a tabela a usar com o algoritmo.
A tabela Collation Element Table também é usada na operação de pesquisa de caracteres.
Visualização de texto e a Bidireccionalidade
Quando é necessário misturar texto de linguagens com diferentes orientações tem de haver uma maneira de identificar onde começa e acaba cada orientação. Para tal, na tabela de caracteres Unicode há caracteres de controlo caracterizadores da orientação e que devem ser usados de acordo com o algoritmo “Bidireccional Algorithm”.
Os caracteres de controlo só tem influência para a operação de visualização do texto e tem um âmbito de acção somente no paragrafo em que estão presentes. Estes caracteres não têm importância para outros aspectos do texto. Cada paragrafo pode ser delimitado por um carácter de controlo que existe no Unicode.
De uma forma simplista o algoritmo da bidirecionalidade obriga a que o texto com uma determinada orientação começe com o carácter de controlo identificador da orientação, que pode ser o RLE para o sentido direita-esquerda ou o LRE o para o sentido esquerda-direita, seguido dos caracteres de texto a ser visualizados terminando com o carácter de controlo de fim de paragrafo ou com o carácter de controlo PDF (Pop Directional Format ) que anula a ultima orientação dada por RLE ou LRE.
Conclusão
O standard Unicode ao contrário do simples código ASCII ou ISO-8859-1 não é só uma simples tabela gigante com todos os caracteres usados pelas linguagens mundiais, também, apresenta algoritmos que permitem do ponto de vista linguístico processar o texto de acordo com a convenção de cada país e idioma. A título ilustrativo, para além dos já mencionados algoritmos de ordenação, visualização há outros que permitem identificar os limites de um carácter, de uma palavra, de uma frase ou mesmo de um paragrafo.
Referências: