October 20, 2008
Porque usar UTF-8 - Codificando/Decodificando
Bom galera, como prometido venho hoje aqui demonstrar como o UTF-8 realmente funciona por debaixo dos panos, e vamos criar uma implementação do mesmo utilizando JavaScript.
Como eu já havia dito antes, o UTF-8 usa uma codificação de tamanho variável, onde cada caractere pode ocupar entre 1 e 4 bytes, para que isso seja possível, existem bits que são usados para verificar isso, vamos ver o primeiro caso:Eu falei para vocês anteriormente que para os valores ASCII padrão o UTF-8 mantém a compatibilidade, ou seja, não existe nenhum transformação para os caracteres entre 0 e 127, se você olhar o binário disso, vai perceber que isso varia entre:00000000
01111111
É importante notar que o primeiro bit do byte não é modificado, isso é importante porque ele é flag que indica se vamos precisar de mais bytes no caractere, então, a partir do valor 128 temos que utilizar algum tipo de transformação.Antes de proseguirmos com os detalhes vamos iniciar nosso script, comecem ele da seguinte forma:
Esse é um simples script que por hora não faz nada :P
10000000Mas para o UTF-8 a sequencia correta seria:
11000010 10000000Parece complicado, mas não é para tanto, quando passamos dos 128 caracteres iniciais temos alguns "moldes" onde devemos encaixar nossos bits, que no caso são os seguintes (por uso de bytes):
1 byte - 0xxxxxxx
2 bytes - 110xxxxx 10xxxxxx
3 bytes - 1110xxxx 10xxxxxx 10xxxxxx
4 bytes - 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
Esses moldes não são ao acaso, e como pode-se ver eles seguem um padrão, esses moldes são importantes para que o precesso de decodificação, notem que a partir dos primeiros bits do primeiro byte é possivel saber exatamente quantos bytes tem o caractere atual.Para criamos o processo de encoding, o primeiro passo é descobrir quantos bytes serão nescessários para criar nosso caractere no formato UTF-8, para saber isso é só contar os limites a partir do número de bits que podem ser alocados em cada nível. Mas como eu sou muito legal eu já vou disponibilar esses números para você, e são eles: 128, 2048, 65536Pra quem nunca executou operações bit a bit pode parecer um pouco complicado sair mexendo eles por ai, mas é facil, primeiro mantenha a calculadora do windows aberta (em modo científico, assim você pode converter entre decimal, hexadecimal e binario sempre que precisar, e você vai precisar), então vamos criar a função de encode:
Pra quem não está acostumado com manipulação de bits isso pode parecer coisa de louco, mas é simples, vou ilustrar como funcionam os operadores bit a bit utilizados nas operações:
00011000 >> 2
resulta em: 00000110
01101110 >> 3
resulta em: 00001101
ou seja, eh simplesmente mover bits a direita (se lembre, tudo isso é forma de representação, tudo são bits, desde numeros a caracteres, vc não vai digitar em formato binário nunca, pelo menos não em javascript)E binário (&): executa uma operação E entre binários, a idéia é simples, você coloca os bits que são comparados em uma listagem de 1 para 1, caso o valor seja 1 nos 2, o resultádo será 1, caso contrário será 0, exemplos:
00110111
& 01100010
----------
00100010
01111000
& 00111110
----------
00111000
esse operador é muito usado para mascarar bits, por exemplo, você quer apenas os 4 últimos bits de um dado binário, então você opera um E contendo 00001111 sobre esse binário, dessa forma você terá o resultado com os 4 últimos valores.OU binário (|): esse é parecido com o anterior, mas com uma diferença básica, esse retorn 1 exceto se os 2 operadores forem 0, exemplo:
00110101
| 11100001
----------
11110101
Isso são alguns operadores binários, caso não tenha ficado muito claro podem tirar suas dúvidas comigo por comentários ou e-mail.Dever de casa: pegue os números utilizados no algoritmo anterior em formato hexadecimal (que comecam com 0x) e veja suas formas em binário (use a calculadora do windows ou similar), e va executando o algoritmo como se fosse o computador, dessa forma você terá um melhor entendimento do algoritmo.O encode está pronto, agora precisamos pegar os códigos Unicode a partir disso que geramos, então vamos criar o decode: O processo inverso é exatamente a mesma coisa, é só pegar os bits que você jogou no formato e junta-los novamente. Para descobrir quantos bytes são usados eu utilizei a seguinte idéia:1 - se for menor que 128, então é padrão ASCII, jogar direto
2 - verificar bit zero dentro do primeiro byte, a partir disso é possível descobrir o número (se baseando nos formatos possíveis).O único operador novo é o left shift (<<) que simplesmente move os bits para esquerda ;)Bom galera, termino por aqui, qualquer dúvida entrem em contato comigo por e-mail ou comentários.Mudarei de assunto no próximo post (assunto indefinido até o momento ;).See yah!
Você pode conferir abaixo o resultado final:
Filed under //
algorithms
javascript
Geek guy that really like to be on the edge of web technologies, like music and guitar (but play really bad), also like to see all kind of non-sense things in internet.