Dal titolo si capisce che sono andato a vedere "yesterday"? il film che i Beatles non sono mai esistiti?
Io non ho 64 anni, ma il numerello mi ha girato per la testa, fino a farmi venire in mente un problemino che dovrò risolvere la prossima volta che metto mano al maggiordomo
La codifica base64
Brr che paura......
ho cercato e trovato una comoda libreria che codifica e de-codifica da e per base64, ma per come la vedo io fa "brutta cosa", lavora su array di byte già formati
e se devo lavorare su oggetti lunghi la memoria mi fa difetto, voi lo sapete che mi piace lavorare on the fly (libera traduzione: a cavallo della mosca, non credo che sia proprio proprio corretta...)
ecco quindi che ho pensato a una funzione che accetta in ingresso un singolo byte
e che restituisce un int, ogni volta che riceve 8 bit utili restituisce un byte corretto, altrimenti restituisce -1
e così posso de-codificare al volo una stringa in ingresso base64, senza dover stivare (a me stoccare non piace, sembra brutto)
senza dover stivare dicevo, sia l'intera stringa in ingresso che l'intera stringa di uscita
come funziona?
semplice: riceve un byte, lo converte, una variabile locale statica tiene conto dei bit utili ricevuti,
sulla base dei bit utili ricevuti calcolo i bitshift che servono per costruire la variabile da ritornare, se i bit ricevuti sono meno di 8 restituisce -1, se più di otto ne avanza per la prossima chiamata
eccola:
int base64decode(byte input)
{
// riceve in ingresso un byte di una stringa base64
// restituisce -1 se non ha nulla da decodificare
// restituisce da 0 a 255 se ha decodificato qualcosa
int ritorno = -1;
typedef union assemblato
{
byte a[2];
unsigned int b;
};
// restituisce un byte de-codificato da base 64
// oppure -1 se non ha ancora ricevuto abbastanza byte in ingresso
// per prima cosa de-codifico il byte in ingresso
char c = (char)input;
byte d = 0;
static assemblato h;
bool valido = 0;
static byte resto = 0;
// richiamata, ricevo un carattere
// lo decodifico
if (c >= 'A' and c <= 'Z')
{
d = c - 'A';
valido = 1;
}
if (c >= 'a' and c <= 'z')
{
d = c - 'a' + 26;
valido = 1;
}
if (c >= '0' and c <= '9')
{
d = c - '0' + 52;
valido = 1;
}
if (c == '+')
{
d = 62;
valido = 1;
}
if (c == '/')
{
d = 63;
valido = 1;
}
//se valido
if (valido)
{
valido = 0;
// metto il suo codice nel primo byte
h.a[0] = d;
h.a[0] <<= 2;
// lo spingo nel secondo byte (il secondo byte ha 0,2,4,6 byte)
byte posizioni = 8 - resto;
if (posizioni > 6)
{
posizioni = 6;
}
h.b <<= posizioni;
resto = resto + 6;
// se ho piu' di 7 bit;
if (resto > 7)
{
resto = resto - 8;
ritorno = h.a[1];
h.a[1] = 0;
h.b <<= resto;
}
}
return ritorno;
}
come vedete il grosso è una pura enumerazione di casi per la conversione
poi abbiamo il check che si tratti di un valore valido
poi il giochino di bitshift
col trucco che scrivo in una union, un array di due byte unito con un unsigned int
shifto prima di due bit il byte in ingresso e lo scrivo nel primo dei due byte dello array
poi calcolo lo shift dell'intero gruppo di bit (16)
poi se ne ho 8 utili leggo il "secondo" byte dello array , lo azzero e finisco lo shift
un bell'esempio di uso:
char prova[] = "V2hlbiBJIGdldCBvbGRlciBsb3NpbmcgbXkgaGFpcgpNYW55IHllYXJzIGZyb20gbm93CldpbGwgeW91IHN0aWxsIGJlIHNlbmRpbmcgbWUgYSB2YWxlbnRpbmUKQmlydGhkYXkgZ3JlZXRpbmdzLCBib3R0bGUgb2Ygd2luZT8KCklmIEnigJlkIGJlZW4gb3V0IHRpbGwgcXVhcnRlciB0byB0aHJlZQpXb3VsZCB5b3UgbG9jayB0aGUgZG9vcgpXaWxsIHlvdSBzdGlsbCBuZWVkIG1lLCB3aWxsIHlvdSBzdGlsbCBmZWVkIG1lCldoZW4gSeKAmW0gc2l4dHktZm91cj8=";
char * puntatore = prova;
void setup(void)
{
Serial.begin(9600);
while (*puntatore)
{
int i = base64decode(*puntatore++);
if (i > 0)
{
Serial.print((char)i);
}
}
Serial.println();
}
dove vi ho messo anche una stringa base64 che dimostra il buon funzionamento della cosa
come dicevo una volta?
sono graditi gli applausi