Se há alguma coisa que é simples e causa dores de cabeça mas mesmo assim é negligenciada por todos os programadores/software engineers/javascript ninjas, acho que é a codificação de texto.
A norma mais comum para a representação e codificação de texto é o Unicode, em
que cada caratér é representado por um número. O conjunto de caratéres que
constituem a norma tem mais de 107 000 entradas, que vão desde letras latinas comuns
(a b c
…) a smiles com pinta (😒
), e cujo objetivo é ser universal e
suportar todos os alfabetos.
Uma das formas de representar caratéres Unicode é recorrendo ao UTF-32, UTF-16
ou UTF-8 (o mais comum). O número de cada um reflete o número mínimo de bits que
cada caratér usa em cada formato; por exemplo, o UTF-32 define todos como tendo
4 bytes (32 bits, o que possibilita representar 2^31 possibilidades), o UTF-16
entre 2 e 4 bytes e o UTF-8 pode ter só 1 byte. Por exemplo, para a letra a
(com o código Unicode correspondente ao decimal 65), as representações são:
- UTF-8:
0100 0001
- UTF-16:
0000 0000 0100 0001
- UTF-32:
0000 0000 0000 0000 0000 0000 0100 0001
Tanto o UTF-16 como o UTF-8, para conseguirem representar tantos caratéres como
o UTF-32, usam bits de continuação. Para caratéres fora do que é possível representar
com 1 byte (2^7 = 128), como por exemplo o क़
(representado por 0x0958
), seguimos as instruções:
- Começar pela representação em binário:
0000 1001 0101 1000
- Procurar o formato UTF-8 correspondente ao número de bits necessário (varia caso sejam
precisos 1, 2 ou 4 bytes). Neste caso são necessários 3 bytes, portanto segue o formato:
1110 xxxx 10xx xxxx 10xx xxxx
- Substituir no formato os bits destinados ao caratér pela sua representação em
binário. Para um binário imaginário
ABCD EFGH IJKL MNOP
seria1110 ABCD 10EF GHIJ 10KL MNOP
, para oक़
o resultado é:1110 0000 1010 0101 1001 1000
Mais importante do que saber como são feitas as várias codificações é saber as vantagens e desvantagens de cada uma. Como vimos antes, do UTF-8 ao UTF-32 o espaço de armazenamento na maior parte dos casos aumenta, sendo só igual para os caratéres de ordem mais elevada que realmente necessitem de 4 bytes em UTF-8. A vantagem em usar UTF-32 é que, no caso de se estar a fazer um qualquer processamento caratér a caratér, pode ser vantajoso ter a garantia que todos têm o mesmo tamanho em memória, não sendo necessário qualquer descodificação. Por outro lado, o UTF-8 mapeia diretamente na representação em ASCII ou latin-1 (ISO 8859-1). Finalmente, o UTF-16 oferece um meio-termo entre ambos os casos, o que é vantajoso quando o predominante no texto são caratéres que necessetariam de 3 bytes em UTF-8, mas apenas de 2 em UTF-16 (que consegue representá-los com menos espaço porque não precisa de tantos bits de continuação); apesar de, devido aos caratéres como o espaço, dígitos e newline serem representáveis num só byte em UTF-8, a vantagem prática em usar UTF-16 acaba por ser reduzida.