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.

È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top