Mentre all'interno di un blocco di commutazione
-
27-09-2019 - |
Domanda
ho visto il seguente codice, preso dal libb64 progetto . Sto cercando di capire che cosa è lo scopo del ciclo while all'interno del blocco interruttore -
switch (state_in->step)
{
while (1)
{
case step_a:
do {
if (codechar == code_in+length_in)
{
state_in->step = step_a;
state_in->plainchar = *plainchar;
return plainchar - plaintext_out;
}
fragment = (char)base64_decode_value(*codechar++);
} while (fragment < 0);
*plainchar = (fragment & 0x03f) << 2;
case step_b:
do {
if (codechar == code_in+length_in)
{
state_in->step = step_b;
state_in->plainchar = *plainchar;
return plainchar - plaintext_out;
}
fragment = (char)base64_decode_value(*codechar++);
} while (fragment < 0);
*plainchar++ |= (fragment & 0x030) >> 4;
*plainchar = (fragment & 0x00f) << 4;
case step_c:
do {
if (codechar == code_in+length_in)
{
state_in->step = step_c;
state_in->plainchar = *plainchar;
return plainchar - plaintext_out;
}
fragment = (char)base64_decode_value(*codechar++);
} while (fragment < 0);
*plainchar++ |= (fragment & 0x03c) >> 2;
*plainchar = (fragment & 0x003) << 6;
case step_d:
do {
if (codechar == code_in+length_in)
{
state_in->step = step_d;
state_in->plainchar = *plainchar;
return plainchar - plaintext_out;
}
fragment = (char)base64_decode_value(*codechar++);
} while (fragment < 0);
*plainchar++ |= (fragment & 0x03f);
}
}
Che cosa può dare il tempo? Sembra che in ogni caso, sempre lo switch eseguirà solo uno dei casi. Mi sono perso qualcosa?
Grazie.
Soluzione
Sebbene questa sia dispositivo di Duff, questa versione non è sull'implementazione un'ottimizzazione loop-unrolling ma piuttosto per implementare un iteratore su un flusso codificato Base64. Così si può fare qualcosa di simile:
Base64Stream stream; // the base64 data
char c;
while ((c == stream->NextChar ()) != 0)
{
// do something with c
}
Nel codice data, il primo interruttore noi utilizzato per saltare indietro dove il return
precedente usciva, e quindi il tempo (1) permette al ciclo di iterazione per continuare indefinitamente. Tuttavia, non c'è alcuna protezione contro un sovraccarico del buffer in questa funzione.
In C #, c'è una soluzione più ordinato a questo, la dichiarazione yield
.
Altri suggerimenti
Come Kenny dice, questo codice si presenta come il dispositivo di un Duff. Ecco è quello che dice Wikipedia su di esso.
Se si tratta di un tentativo di attuare il dispositivo di un Duff, allora è probabilmente fuori luogo.
Si noti che nel caso di un dispositivo di Duff, come descritto in Wikipedia, il ciclo è finito, mentre nel codice presentato sopra è un anello senza fine. L'unica possibilità per esso alla fine è la soddisfazione del (codechar == code_in + length_in) condizione (code_id e length_in sono immutabili nel frammento di codice, però).
Dubito che funziona anche come dispositivo di un Duff, cioè che il risultato sarà corretto espansione ciclo dal compilatore.