Executando verificação de segurança...
6

Unicode. O essencial que todo programador deveria saber - UTF-8, ASCII e Emojis

Motivação

Passando algum tempo no facebook é possível ver que algumas pessoas têm a capacidade de mudar os estilos das fontes nos seus posts - algo que me surpreendeu totalmente - mas por alguma razão, não é possível fazer o mesmo copiando um texto de um processador de texto(Word, Writer, Google Docs) com fontes estilizadas e tamanhos específicos de um lado para outro; o que me levou a uma procura de 5h de estudo sobre o funcionamento dos textos nos computadores.

O princípio

Bem lá a atrás quando o homem escrevia nas pedras ele teve a necessidade... Ok, talvez eu tenha ido muito atrás. Lá no início do desenvolvimento dos computadores e com a sua evolução passou a ser possível armazenar dados que por sua vez precisavam ser representados numa forma que era legível para humanos, e para isso foram criados padrões de textos que representavam certos valores com um código numérico, sendo o ASCII que se tornou o padrão Americano( nem preciso dizer que era em inglês).

ASCII

ASCI, traduzido como Padrão Americano para Intercâmbio de Informação é um sistema de representação de letras, algarismos e sinais de pontuação e de controle, através de um sinal codificado em forma de código binário (cadeias de bits formada por vários 0 e 1), desenvolvido a partir de 1960, que representa um conjunto de 128 sinais: 95 sinais gráficos (letras do alfabeto latino, algarismos arábicos, sinais de pontuação e sinais matemáticos) e 33 sinais de controle, utilizando 7 bits para representar todos os seus símbolos.
Este padrão serviu perfeitamente por muito tempo já que os que maior mercado de computadores estava lá nos EUA, e era presente em linguagens de programação muito fortes na época como a linguagem C. Na época os computadores eram na maioria 8 bits o que significa que era possível chegar até 256 combinações par códigos, mas já que o padrão ASCII usava 128 códigos, sobravam ainda outros 128 códigos possíveis.

O problema

Como já dito, ainda existia a possibilidade de usar 128 códigos livremente de acordo a vontade do fabricamente. Com o tempo computadores passaram a ser vendidos fora da América, e os códigos restantes passaram a ser adequados para fazer a representação de carácteres conforme o seu país que com o tempo foram chamados de code pages. Tudo isso era uma maravilha, já que cada país tinha seus próprios caractéres e contando que ninguém enviasse um texto para alguém de outro país tudo ficaria bem... até que a internet veio :) - o que significa literalmente fogo no parquinho.

Para exemplificar imaginemos que os caractéres acima de 127 representem letras do portugês:

á, é, í, ó. O que faria elas correspondentes a: 128,129,130 e 131 respectivamente.

Mas num outro país os números 128,129,130 e 131 fossem:

ぁ あ さ と ぺ respectivamente.

O computador era obrigado a mandar estes dados em binário e ao decodificar o destinatário recebia uma mensagem totalmente diferente da enviada, o que geraria uma confusão e tanto.

Unicode - a luz no fim do tunel

O unicode foi uma iniciativa inteligente de tentar criar um sistema global para a representação de carácteres. Ele representa os carácteres como uma versão ideal deles que podem ser mapeados para diferentes tipos de fontes como Times New Roman, Arial,etc e ainda assim continuarem a ser as mesmas letras de maneira individual, sem acréscimos de memória.
O unicode é representado por 'U+' e 4 valores em Hexadecimal. Por exemplo, a representação de "Hello" em unicode seria:

U+0048 U+0065 U+006C U+006C U+006F.

Apesar do total de bits ser 16 o que resulta em 65,356 carateres, este não é o limite do unicode, na verdade ele não tem limites porque ele pode se expandir( e diminuir) conforme a necessidade.

Codificação

Um dos problemas que se teve na codificação era o Endianess - a forma como os bytes são lidos podendo ser little endian ou big endian - mas foi resolvido com a colocação de prefixos FE FF que definiam a forma como os bytes deveriam ser lidos de acordo a máquina.

Outro problema era o uso de memória já que para aqueles que falam inglês apenas 8 bits eram necessários já que os primeiros caracteres do unicode são os mesmos que o do ASCII então seria desnecessário reservar 16 bits disperdiçando memória. Daí surgiu a necessidade do UTF-8 onde o 8 representa o número de bits por caracter unicode. Então, na realidade o unicode não é um tipo de codificação e sim um mapeamento para carateres sendo as codificações UTF-8, UTF-16, UCS-2, etc.

A resposta ao questionamento

Então porquê que eu não consigo colocar as fontes que quero no facebook mas posso estilizar textos como esses:

𝕰𝖝𝖊𝖒𝖕𝖑𝖔

ℰ𝓍ℯ𝓂𝓅𝓁ℴ

𝔈𝔵𝔢𝔪𝔭𝔩𝔬

𝔢𝔵𝔢𝔪𝔭𝔩𝔬

E agora as suas representações em unicode, respectivamente:

U+1D570 U+1D59D U+1D58A U+1D592 U+1D595 U+1D591 U+1D594

U+2130 U+1D4CD U+212F U+1D4C2 U+1D4C5 U+1D4C1 U+2134

U+1D508 U+1D535 U+1D522 U+1D52A U+1D52D U+1D529 U+1D52C

U+1D522 U+1D535 U+1D522 U+1D52A U+1D52D U+1D529 U+1D52C

A verdade é que estes textos não são "fontes de verdade" e sim representações unicode que estão presentes internamente em todos os dispositivos, razão pela qual é possível que elas são facilmente representadas. A forma mais fácil de pensar nelas é como se fossem emojis, que não passam de pictographs que todo mundo tem internamente armazenado nos seus smartphones.
Fontes de textos são arquivos que contêm um conjunto de caracteres mapeados pelo unicode, razão pela qual em programação é preciso linkar uma fonte externa

'https://fonts.googleapis.com/css?family=Sofia' 
          rel='stylesheet' />

para que o navegador consiga entendá-la, porque naquele escopo do arquivo html retornado a fonte que você quer colocar não existe.

Conclusão

Na verdade não existe tal coisa como "plain text" tudo são arquivos binários, mas os textos particularmente são interpretados de primeira como arquivos a serem visualizados de forma amigável.
O unicode é a razão pela qual você pode estar aí sentado no seu smartphone e comentar neste artigo: fino senhores 🗿 🍷

Sugestões

Se você gostou do artigo considere seguir as minhas redes sociais:
Youtube:CgSnakeDev
Linkedin:Cristino Canga

https://r12a.github.io/app-conversion/
https://cryptii.com/pipes/text-decimal
https://onlineunicodetools.com/convert-unicode-to-code-points
https://www.unicodetextconverter.net

Fontes

https://pt.wikipedia.org/wiki/Unicode

https://nedbatchelder.com/text/unipain.html

https://www.babelstone.co.uk/Unicode/text.html

https://www.utf8-chartable.de

https://pt.wikipedia.org/wiki/Unicode

https://nedbatchelder.com/text/unipain.html

https://www.babelstone.co.uk/Unicode/text.html

https://pt.wikipedia.org/wiki/ASCII

https://en.wikipedia.org/wiki/ANSI_escape_code

https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-developer-absolutely-positively-must-know-about-unicode-and-character-sets-no-excuses/

Carregando publicação patrocinada...
3

Parabéns pelo artigo, achei muito legal.

Há 2 pontos que eu queria destacar:

Primeiro que vc disse que um caracter Unicode é representado pelo "U+" seguido por 4 digitos, mas na verdade é por até 6 digitos porque o code space do Unicode vai até U+10FFFF.

O segundo ponto é que vc diz que o Unicode não tem limites e que pode se expandir conforme a necessidade.

Acontece que há um limite que é 1.114.112! E destes mais de 1 milhão de code points, apenas 149.186 são usados atualmente na vesão 15.0 do Unicode.

Fonte: https://www.unicode.org/versions/Unicode15.0.0/ch01.pdf

1
1

Respondendo a isso, o primeiro ponto sobre os 6 dígitos,sim realmente de acordo ao materia podem se extender até aí.
Mas quanto a questão do limite, é exactamente isso. Os caracteres mais comuns cobrem 2^16 = 65536, e no seu exemplo com mais dois dígitos hexadecimais o temos 2^24 =16777216(possíveis), ou seja, existem 149.186 caracteres unicode ACTUALMENTE, mas se hipoteticamente fossem criados mais caracteres ele poderia cobrir o resto conforme a necessidade, daí a expressão "não tem limites".

1

Vc entendeu errado a informação desta fonte que vc linkou.

Lá diz que o UTF-8 tem bits o bastante para codificar até o code point 0x1FFFFF, ou seja, tem limite. É um limite maior do que o UTF-16, mas tem limite.

Só que a RFC 3629 limitou o UTF-8 para ele combinar com o limite do UTF-16. Assim, tanto o UTF-8 quanto o UTF-16 só podem codificar até o code point 0x10FFFF.

Mesmo que vc pense que a RFC 3629 possa ser derrubada caso precise algum dia, vc estaria errado, pois ela não poderia ser simplesmente ignorada, pois isto permitiria que alguns code points fossem codificados em UTF-8, mas não em UTF-16.

Percebe que vc não pode dizer "que pode se estender até onde quiser"? Não pode porque tem limite e o limite é 0x10FFFF.


O outro ponto vc também entendeu errado. Eu disse que são 6 digitos hexadecimais, mas isso não quer dizer que vai até 2^24 porque os code points do Unicode não vão até 0xFFFFFF, eles vão até 0x10FFFF que é o máximo que o UTF-16 consegue codificar (e o máximo que aquela RFC permite que o UTF-8 vá também).

Mesmo que não houvesse a limitação dos seus irmãos (UTF-8 e UTF-16), nem o UTF-32 consegue se estender indefinidamente, pois ele só iria até 0xFFFFFFFF e isso nem faria sentido já que extrapola em muito o máximo de code points do Unicode.

A informação que eu te passei no primeiro comentário não saiu do nada, saiu da própria especificação. Não sei se vc chegou a ler, mas o paragrafo que eu queria te mostrar é o último do capitulo Introdução. Ele diz:

The Unicode Standard contains 1,114,112 code points, most of which are available for
encoding of characters...

O trecho acima é a própria especificação estabelecendo limites.

Como o Unicode esta devidamente especificado, não tem como ele crescer indefinidamente, pois os sistemas que o implementam devem ser previsíveis. Só que o limite dele não é um problema para nós, pois em mais de 30 anos de Unicode, não conseguimos atingir nem 20% dele.


Claro que no futuro o padrão pode mudar e uma nova especificação ser criada com um limite maior e até indefinido.

Para vc ter uma ideia, no inicio o Unicode era baseado em apenas 16 bits, ou seja, só podia codificar até 65536.

Só que indo por esta linha de raciocinio estariamos apenas especulando e o ponto é:

A versão atual do Unicode, a versão 15.0, tem limite que é 1.114.112, ou 0x10FFFF. Da mesma forma, seus modos de codificação, UTF-8, UTF-16 e UTF-32, também acompanham este limite.

2
2

Muito bom o post, deu pra entender legal o conceito de baixo nivel, sendo programador front-end, acabei de ter uma pespectiva melhor sobre as importações e como os navegadores interpretam e interagem com o sistema para renderização, muito obrigado pelo post!

2
2

Muito bom post, sempre uso a tabela Ascii em projetos de baixo nivel, mas o unicode é algo universal nos dias de hoje. Inclusive tinha lido em algum lugar que o criador original tava aprendendo git, pra subir o código original no github.

1
1
1

Felizmente eu não nasci nessa época hhhh
Estudei C porque estudo na 11ª classe de electrónica aqui em Angola, é obrigatório então foi algo necessário

1

Acho que me expressei mal...
não foi por exigência do curso que que eu decorei alguns caracteres ASC,
mas foi por necessidade durante o desenvolvimento de softwares; era necessário consultar muitas vezes à tabela ASCII.

1

Poxa, entrei achando que teria alguma menção ao emojipedia hahah. Mas bacana o post, é sempre interessante e importante esse tipo de conteúdo, hoje ainda utilizo algumas coisas com o código unicode para ter certeza que o navegador irá interpretar o que eu

1
1

Cara muito bacana o post.

Isso da muito bem para "puxar um gancho" sobre attacks usando unicode (code points inject).

Em resumo o ataque se é feito em ambientes onde determinados caracteres sofrem alterações ao passar por filtros 😅

1
2