Punycode
# Punycode

Punycode è un sistema di codifica definito nella RFC 3492 che serve a rappresentare univocamente una sequenza di caratteri unicode tramite una sequenza di caratteri ASCII, per rendere possibile l'uso di tali sequenze nei nomi di dominio, senza dover modificare infrastrutture e standard esistenti. In questo modo si possono gestire nomi di dominio internazionalizzati (IDNA) aggiungendo all'inizio della stringa punycode i caratteri 'xn--'.

La traduzione di sequenze Punycode nella codifica originaria è a carico dello user agent.

## Algoritmo di base

L'algoritmo non è semplicissimo, tuttavia può essere ricondotto a operazioni di base elementari, oltre ad essere facilmente implementabile e versatile. Gli elementi principali sono i seguenti:

* Dapprima vengono inseriti, così come compaiono, i caratteri ASCII standard.
* Tali caratteri sono seguiti da un trattino e da una serie di caratteri alfanumerici che rappresentano la trascodifica vera e propria dei simboli unicode non ASCII in punycode.

Un esempio può essere dato da totò trascodificato in tot-ena.

Per capire il cuore dell'algoritmo dovremo soffermarci sul terzo punto. La sequenza alfanumerica dopo quel trattino solitario in realtà rappresenta uno o più numeri, chiamati delta, ognuno associato alla presenza di un carattere Unicode all'interno della stringa. L'ordine dei delta inseriti segue quello dei codici Unicode e non quello della posizione dei caratteri nella stringa iniziale.

Nel caso in questione, ad esempio, la stringa ena rappresenta la presenza della ò in 4ª posizione, ma a causa dell'algoritmo usato (in cui entrano in gioco la lunghezza della stringa, i caratteri già inseriti, e altri parametri) potrebbe significare anche un altro codice unicode in un'altra posizione.

### Delta

Soffermandoci adesso sul singolo delta, esso:

* Rappresenta un numero in notazione 36esimale (lettere a-z e numeri 0-9) con talune particolarità. Le lettere dell'alfabetico (minuscole o maiuscole) rappresentano, in ordine alfabetico, i numeri da 0 a 25, mentre le cifre 0-9 rappresentano i numeri da 26 a 35.
* Il numero è little endian, ovverosia con la cifra meno significativa a sinistra.
* Vi sono alcuni caratteri che, oltre ad avere un proprio valore numerico, segnano allo stesso tempo la fine del delta (e l'eventuale inizio di un altro)
   * il numero dei caratteri che possono fungere da marcatori varia durante l'algoritmo ed in ogni caso comprendono tutti i caratteri con valore minore di uno dato.
   * la presenza di tali caratteri si riflette nel motivo per cui il peso di una data cifra non sarà data semplicemente dalla formula base^n, ma a volte alla base occorre sottrarre i cosiddetti threshold, ovverosia il numero di possibili marcatori di fine delta.

Inoltre, cosa più importante, il delta rappresenta contemporaneamente sia il codice Unicode da inserire all'interno della stringa ASCII che la sua posizione.

Inoltre, dato <n,i> un particolare stato dove n è il codice di un carattere da inserire (anzi, lo scostamento rispetto ad un valore base) e i è la posizione di inserimento, i è vincolato a crescere fino alla lunghezza complessiva della stringa, per poi tornare a 0 e incrementare n di 1; dato i=0, la sequenza degli stati sarà simile a questa: <n,i>,<n,i+1>....<n,L>,<n+1,i>,<n+1,i+1>..... Il valore numerico del delta è definito come numero di stati precedenti a uno stato di inserimento.

In pratica, dato un certo delta, dividendolo per la lunghezza della stringa base +1, si ottiene come resto la posizione in cui inserire il carattere unicode (posizione che varia da 0 (inizio) a L (fine)), e come quoziente lo scostamento del valore unicode rispetto a un valore base (fissato inizialmente, per comodità, a 128).

### Threshold

I threshold sono calcolati digit per digit e rappresentano all'interno di ognuno di questi il numero di possibili caratteri-segnalatori della fine del delta, a partire da quello con valore più basso, la 'a' appunto. In particolare per calcolare il threshold di un singolo digit si avrà la formula: t(j)=base*(j+1)-bias

dove j è il numero di digit considerato (a partire da 0), base è appunto 36, e bias è un valore che inizialmente è posto a 72, ma che successivamente viene variato al passaggio da un delta all'altro in base ad una particolare formula. t(j) inoltre viene vincolato a essere compreso tra un tmin=1 e un tmax=26. Per raggiungere tale scopo, se per qualche motivo t(j) scende sotto tmin, viene posto t(j)=tmin e se t(j) va sopra tmax verrà posto t(j)=tmax

Essendo inoltre i caratteri definiti dai threshold dei segnalatori, essi influenzano indirettamente anche il peso di ogni digit, calcolato con la seguente formula:

* w(0)=1 (peso del primo digit)
* w(j)=w(j-1)*(base-t(j-1)) (per j>0)

Detto in forma più comprensibile, il peso di ogni digit non sarà semplicemente la base^j bensì (base-t(0))*(base-t(1))....*(base-t(n))

### Iterazioni

Ogni codifica di un delta successivo occorre:

* Dividere il valore del delta per 2 (tranne la prima volta che si divide per 700).
* Aggiungere al delta, il valore di delta/numpoints, dove per numpoints si indicano il numero di delta già codificati.
* while delta > ((base - tmin) * tmax) div 2 do let delta = delta div (base - tmin)
* let bias = (base * the number of divisions performed in step 3) + (((base - tmin + 1) * delta) div (delta + skew))

### Esempi

Tornando al nostro totò (tot-ena) sarà facile adesso capire che per mettere la o accentata nella posizione precedente (toòt) basterà sottrarre al delta 1, e ricordando che esso è little-endian si deve modificare la sua prima lettera (e), ovverosia: (tot-dna).

Ponendo la ò accentata ancora prima tòot, la trascodifica sarà xn--tot-cna ('c'='e'-2) e nel caso di òtot, tot-bna ('b'='e'-3)

Ritornando ora a totò, con codifica tot-ena, se vogliamo aggiungere uno stato al delta, siccome abbiamo già raggiunto la fine della stringa, il carattere unicode assumerà il valore successivo (la o accentata al contrario ó) e l'indice i si azzererà come previsto, ponendosi all'inizio. ótot avrà insomma codifica tot-fna ('f'='e'+1)

