yeah, switches are nothing new, and can sometimes if left unchecked get pretty big and ugly.
recently, in a piece of code of mine, this particularly glorious example has appeared:
ret=0; mode=0; nextmode=0;
while((cs<cse) && (ct<cte) && !ret)
{
i=*cs++;
switch(i&0xE0)
{
case 0x80:
n1=(i&31)+1;
ct+=n1*stride;
break;
case 0xE0:
switch(i)
{
case 0xE0:
if(mode)
{ mode=0; nextmode=0; }
else
{ ret=1; }
break;
case 0xE1:
cs+=3;
break;
case 0xE8:
bgbbtj_rpza_memcpy8(ct, ct-stride);
ct+=stride;
break;
case 0xE9:
j=(*cs++)+1;
while(j--)
{
bgbbtj_rpza_memcpy8(ct, ct-stride);
ct+=stride;
}
break;
case 0xEA:
j=(*cs++)+1;
if((ct-j*stride)<blks) { ret=-1; break; }
bgbbtj_rpza_memcpy8(ct, ct-j*stride);
ct+=stride;
break;
case 0xEB:
j=(cs[0]<<8)+cs[1]+1;
cs+=2;
if((ct-j*stride)<blks) { ret=-1; break; }
bgbbtj_rpza_memcpy8(ct, ct-j*stride);
ct+=stride;
break;
case 0xEC:
j=(*cs++)+1;
k=(*cs++)+1;
if((ct+j*stride)>cte) { ret=-1; break; }
if((ct-k*stride)<blks) { ret=-1; break; }
while(j--)
{
bgbbtj_rpza_memcpy8(ct, ct-k*stride);
ct+=stride;
}
break;
case 0xED:
j=(cs[0])+1;
k=(cs[1]<<8)+cs[2]+1;
cs+=3;
if((ct+j*stride)>cte) { ret=-1; break; }
if((ct-k*stride)<blks) { ret=-1; break; }
while(j--)
{
bgbbtj_rpza_memcpy8(ct, ct-k*stride);
ct+=stride;
}
break;
case 0xF0:
switch(cs[0])
{
case 0xF0: cs++; mode=0; nextmode=0; break;
case 0xF1: cs++; mode=1; nextmode=1; break;
case 0xF2: cs++; mode=2; nextmode=2; break;
case 0xF3: cs++; mode=3; nextmode=3; break;
default: nextmode=mode; mode=0; break;
}
break;
case 0xF1: nextmode=mode; mode=1; break;
case 0xF2: nextmode=mode; mode=2; break;
case 0xF3: nextmode=mode; mode=3; break;
case 0xF8:
switch(*cs++)
{
case 0x81:
for(j=0; j<256; j++)
{ ctx->pal256[j]=rpza_blkidxcolor[j]; }
for(j=0; j<16; j++)
{ ctx->pal16[j]=rpza_blkidxcolor[j]; }
for(j=0; j<256; j++)
{ ctx->pat256[j]=rpza_blkidx_pixpat[j]; }
break;
case 0x82:
j=*cs++;
k=(*cs++)+1;
for(; j<k; j++)
{
l=(cs[0]<<8)|cs[1];
cs+=2;
ctx->pal256[j]=l;
}
break;
case 0x83:
j=(cs[0]>>4)&15;
k=(cs[0]&15)+1;
for(; j<k; j++)
{ ctx->pal16[j]=ctx->pal256[*cs++]; }
break;
case 0x84:
j=(cs[0]>>4)&15;
k=(cs[0]&15)+1;
for(; j<k; j++)
{
l=(cs[0]<<8)|cs[1]; cs+=2;
ctx->pal16[j]=l;
}
break;
case 0x85:
j=*cs++;
k=(*cs++)+1;
for(; j<k; j++)
{
l=(cs[0]<<24)|(cs[1]<<16)|(cs[2]<<8)|cs[3];
cs+=4;
ctx->pat256[j]=l;
}
break;
}
default:
break;
}
break;
default:
switch(mode)
{
case 0:
switch(i&0xE0)
{
case 0xA0:
j=(cs[0]<<8)|cs[1];
cs+=2;
l=j;
j=((j&0x7FE0)<<1)|(j&0x1F);
if(l&0x8000)
{
ctb[0]=j&0xFF;
ctb[1]=(j>>8)&0xFF;
ctb[2]=j&0xFF;
ctb[3]=(j>>8)&0xFF;
ctb[4]=0xFF; ctb[5]=0xFF;
ctb[6]=0xFF; ctb[7]=0xFF;
}else
{
ctb[0]=j&0xFF;
ctb[1]=(j>>8)&0xFF;
ctb[2]=j&0xFF;
ctb[3]=(j>>8)&0xFF;
ctb[4]=0; ctb[5]=0;
ctb[6]=0; ctb[7]=0;
}
n1=(i&31)+1;
for(i=0; i<n1; i++)
{
bgbbtj_rpza_memcpy8(ct, ctb);
ct+=stride;
}
break;
case 0xC0:
j=(cs[0]<<8)|cs[1];
k=(cs[2]<<8)|cs[3];
cs+=4;
l=k;
j=((j&0x7FE0)<<1)|(j&0x1F);
k=((k&0x7FE0)<<1)|(k&0x1F);
if(l&0x8000)
{
if(j<=k)
{
ctb[0]=j&0xFF;
ctb[1]=(j>>8)&0xFF;
ctb[2]=k&0xFF;
ctb[3]=(k>>8)&0xFF;
csm=rpza_blkmap1;
}else
{
ctb[0]=k&0xFF;
ctb[1]=(k>>8)&0xFF;
ctb[2]=j&0xFF;
ctb[3]=(j>>8)&0xFF;
csm=rpza_blkmap2;
}
}else
{
if(j>k)
{
ctb[0]=j&0xFF;
ctb[1]=(j>>8)&0xFF;
ctb[2]=k&0xFF;
ctb[3]=(k>>8)&0xFF;
csm=rpza_blkmap1;
}else
{
ctb[0]=k&0xFF;
ctb[1]=(k>>8)&0xFF;
ctb[2]=j&0xFF;
ctb[3]=(j>>8)&0xFF;
csm=rpza_blkmap2;
}
}
n1=(i&31)+1;
for(i=0; i<n1; i++)
{
ctb[4]=csm[cs[0]]; ctb[5]=csm[cs[1]];
ctb[6]=csm[cs[2]]; ctb[7]=csm[cs[3]];
cs+=4;
bgbbtj_rpza_memcpy8(ct, ctb);
ct+=stride;
}
break;
default:
if(cs[1]&0x80)
{
cs--;
j=(cs[0]<<8)|cs[1];
k=(cs[2]<<8)|cs[3];
cs+=4;
j=((j&0x7FE0)<<1)|(j&0x1F);
k=((k&0x7FE0)<<1)|(k&0x1F);
if(j>k)
{
ctb[0]=j&0xFF;
ctb[1]=(j>>8)&0xFF;
ctb[2]=k&0xFF;
ctb[3]=(k>>8)&0xFF;
csm=rpza_blkmap1;
}else
{
ctb[0]=k&0xFF;
ctb[1]=(k>>8)&0xFF;
ctb[2]=j&0xFF;
ctb[3]=(j>>8)&0xFF;
csm=rpza_blkmap2;
}
ctb[4]=csm[cs[0]]; ctb[5]=csm[cs[1]];
ctb[6]=csm[cs[2]]; ctb[7]=csm[cs[3]];
cs+=4;
bgbbtj_rpza_memcpy8(ct, ctb);
ct+=stride;
}else
{
memset(ctb, 0, 8);
//dummy...
cs+=31;
bgbbtj_rpza_memcpy8(ct, ctb); ct+=stride;
}
break;
}
break;
case 1:
switch(i&0xE0)
{
case 0xA0:
j=ctx->pal256[*cs++];
j=((j&0x7FE0)<<1)|(j&0x1F);
ctb[0]=j&0xFF;
ctb[1]=(j>>8)&0xFF;
ctb[2]=j&0xFF;
ctb[3]=(j>>8)&0xFF;
ctb[4]=0; ctb[5]=0;
ctb[6]=0; ctb[7]=0;
n1=(i&31)+1;
for(i=0; i<n1; i++)
{
bgbbtj_rpza_memcpy8(ct, ctb);
ct+=stride;
}
break;
case 0xC0:
j=ctx->pal256[cs[0]];
k=ctx->pal256[cs[1]];
cs+=2;
j=((j&0x7FE0)<<1)|(j&0x1F);
k=((k&0x7FE0)<<1)|(k&0x1F);
ctb[0]=j&0xFF;
ctb[1]=(j>>8)&0xFF;
ctb[2]=k&0xFF;
ctb[3]=(k>>8)&0xFF;
csm=rpza_blkmap1;
n1=(i&31)+1;
for(i=0; i<n1; i++)
{
j=rpza_blkidxmap1[cs[0]];
k=rpza_blkidxmap1[cs[1]];
cs+=2;
ctb[4]=csm[(j>>8)&255]; ctb[5]=csm[j&255];
ctb[6]=csm[(k>>8)&255]; ctb[7]=csm[k&255];
bgbbtj_rpza_memcpy8(ct, ctb);
ct+=stride;
}
break;
default:
cs--;
j=ctx->pal256[cs[0]];
k=ctx->pal256[cs[1]];
cs+=2;
j=((j&0x7FE0)<<1)|(j&0x1F);
k=((k&0x7FE0)<<1)|(k&0x1F);
ctb[0]=j&0xFF;
ctb[1]=(j>>8)&0xFF;
ctb[2]=k&0xFF;
ctb[3]=(k>>8)&0xFF;
csm=rpza_blkmap1;
j=rpza_blkidxmap1[cs[0]];
k=rpza_blkidxmap1[cs[1]];
cs+=2;
ctb[4]=csm[(j>>8)&255]; ctb[5]=csm[j&255];
ctb[6]=csm[(k>>8)&255]; ctb[7]=csm[k&255];
bgbbtj_rpza_memcpy8(ct, ctb);
ct+=stride;
break;
}
break;
case 2:
switch(i&0xE0)
{
case 0xA0:
j=ctx->pal16[(*cs++)&15];
j=((j&0x7FE0)<<1)|(j&0x1F);
ctb[0]=j&0xFF;
ctb[1]=(j>>8)&0xFF;
ctb[2]=j&0xFF;
ctb[3]=(j>>8)&0xFF;
ctb[4]=0; ctb[5]=0;
ctb[6]=0; ctb[7]=0;
n1=(i&31)+1;
for(i=0; i<n1; i++)
{
bgbbtj_rpza_memcpy8(ct, ctb);
ct+=stride;
}
break;
case 0xC0:
j=ctx->pal16[(cs[0]>>4)&15];
k=ctx->pal16[(cs[0]>>0)&15];
cs++;
j=((j&0x7FE0)<<1)|(j&0x1F);
k=((k&0x7FE0)<<1)|(k&0x1F);
ctb[0]=j&0xFF;
ctb[1]=(j>>8)&0xFF;
ctb[2]=k&0xFF;
ctb[3]=(k>>8)&0xFF;
csm=rpza_blkmap1;
n1=(i&31)+1;
for(i=0; i<n1; i++)
{
j=ctx->pat256[*cs++];
ctb[4]=csm[(j>>24)&255]; ctb[5]=csm[(j>>16)&255];
ctb[6]=csm[(j>> 8)&255]; ctb[7]=csm[(j )&255];
bgbbtj_rpza_memcpy8(ct, ctb);
ct+=stride;
}
break;
default:
cs--;
j=ctx->pal16[(cs[0]>>4)&15];
k=ctx->pal16[(cs[0]>>0)&15];
cs++;
j=((j&0x7FE0)<<1)|(j&0x1F);
k=((k&0x7FE0)<<1)|(k&0x1F);
ctb[0]=j&0xFF;
ctb[1]=(j>>8)&0xFF;
ctb[2]=k&0xFF;
ctb[3]=(k>>8)&0xFF;
csm=rpza_blkmap1;
j=ctx->pat256[*cs++];
ctb[4]=csm[(j>>24)&255]; ctb[5]=csm[(j>>16)&255];
ctb[6]=csm[(j>> 8)&255]; ctb[7]=csm[(j )&255];
bgbbtj_rpza_memcpy8(ct, ctb);
ct+=stride;
break;
}
break;
case 3:
switch(i&0xE0)
{
case 0xA0:
j=ctx->pal256[*cs++];
j=((j&0x7FE0)<<1)|(j&0x1F);
ctb[0]=j&0xFF;
ctb[1]=(j>>8)&0xFF;
ctb[2]=j&0xFF;
ctb[3]=(j>>8)&0xFF;
ctb[4]=0; ctb[5]=0;
ctb[6]=0; ctb[7]=0;
n1=(i&31)+1;
for(i=0; i<n1; i++)
{
bgbbtj_rpza_memcpy8(ct, ctb);
ct+=stride;
}
break;
case 0xC0:
j=ctx->pal256[cs[0]];
k=ctx->pal256[cs[1]];
cs+=2;
j=((j&0x7FE0)<<1)|(j&0x1F);
k=((k&0x7FE0)<<1)|(k&0x1F);
ctb[0]=j&0xFF;
ctb[1]=(j>>8)&0xFF;
ctb[2]=k&0xFF;
ctb[3]=(k>>8)&0xFF;
csm=rpza_blkmap1;
n1=(i&31)+1;
for(i=0; i<n1; i++)
{
j=ctx->pat256[*cs++];
ctb[4]=csm[(j>>24)&255]; ctb[5]=csm[(j>>16)&255];
ctb[6]=csm[(j>> 8)&255]; ctb[7]=csm[(j )&255];
bgbbtj_rpza_memcpy8(ct, ctb);
ct+=stride;
}
break;
default:
cs--;
j=ctx->pal256[cs[0]];
k=ctx->pal256[cs[1]];
cs+=2;
j=((j&0x7FE0)<<1)|(j&0x1F);
k=((k&0x7FE0)<<1)|(k&0x1F);
ctb[0]=j&0xFF;
ctb[1]=(j>>8)&0xFF;
ctb[2]=k&0xFF;
ctb[3]=(k>>8)&0xFF;
csm=rpza_blkmap1;
j=ctx->pat256[*cs++];
ctb[4]=csm[(j>>24)&255]; ctb[5]=csm[(j>>16)&255];
ctb[6]=csm[(j>> 8)&255]; ctb[7]=csm[(j )&255];
bgbbtj_rpza_memcpy8(ct, ctb);
ct+=stride;
break;
}
break;
default:
break;
}
mode=nextmode;
break;
}
}
context:
this is the primary image decoding loop from one of my video codecs (BTIC1C).
it started out simpler (when the format had a few less features) but is getting a bit more hairy as time goes on.
part of the hair is due to the recent addition of modality in terms of the block-encoding (optional cheaper / lower-quality blocks).
side note: I actually have a small army of specialized codecs at this point, it is actually starting to get a bit silly...
each is slightly different though with different trade-offs.
OTOH, some big switches have appeared elsewhere, but have generally been big flat switches, rather than nested ones.