diff options
author | theuni <theuni-nospam-@xbmc.org> | 2011-01-24 16:05:21 -0500 |
---|---|---|
committer | theuni <theuni-nospam-@xbmc.org> | 2011-01-24 16:05:21 -0500 |
commit | c51b1189e3d5353e842991f5859ddcea0f73e426 (patch) | |
tree | ef2cb8a6184699aa614f3655dca4ce661cdc108e /lib/UnrarXLib/rs.cpp | |
parent | be61ebdc9e897fe40c6f371111724de79ddee8d5 (diff) |
Merged cptspiff's code-reshuffle branch.
Squashed commit due to build breakage during code-reshuffle history.
Conflicts:
xbmc/Util.cpp
xbmc/cdrip/CDDARipper.cpp
xbmc/filesystem/Directory.cpp
xbmc/filesystem/File.cpp
Diffstat (limited to 'lib/UnrarXLib/rs.cpp')
-rw-r--r-- | lib/UnrarXLib/rs.cpp | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/lib/UnrarXLib/rs.cpp b/lib/UnrarXLib/rs.cpp new file mode 100644 index 0000000000..9eed7a28f4 --- /dev/null +++ b/lib/UnrarXLib/rs.cpp @@ -0,0 +1,143 @@ +#include "rar.hpp" + +#define Clean(D,S) {for (int I=0;I<(S);I++) (D)[I]=0;} + +RSCoder::RSCoder(int ParSize) +{ + RSCoder::ParSize=ParSize; + FirstBlockDone=false; + gfInit(); + pnInit(); +} + + +void RSCoder::gfInit() +{ + for (int I=0,J=1;I<MAXPAR;I++) + { + gfLog[J]=I; + gfExp[I]=J; + if ((J<<=1)&256) + J^=285; + } + for (int I=MAXPAR;I<MAXPOL;I++) + gfExp[I]=gfExp[I-MAXPAR]; +} + + +inline int RSCoder::gfMult(int a,int b) +{ + return(a==0 || b == 0 ? 0:gfExp[gfLog[a]+gfLog[b]]); +} + + +void RSCoder::pnInit() +{ + int p1[MAXPAR+1],p2[MAXPAR+1]; + + Clean(p2,ParSize); + p2[0]=1; + for (int I=1;I<=ParSize;I++) + { + Clean(p1,ParSize); + p1[0]=gfExp[I]; + p1[1]=1; + pnMult(p1,p2,GXPol); + for (int J=0;J<ParSize;J++) + p2[J]=GXPol[J]; + } +} + + +void RSCoder::pnMult(int *p1,int *p2,int *r) +{ + Clean(r,ParSize); + for (int I=0;I<ParSize;I++) + if (p1[I]!=0) + for(int J=0;J<ParSize-I;J++) + r[I+J]^=gfMult(p1[I],p2[J]); +} + + +void RSCoder::Encode(byte *Data,int DataSize,byte *DestData) +{ + int ShiftReg[MAXPAR+1]; + + Clean(ShiftReg,ParSize+1); + for (int I=0;I<DataSize;I++) + { + int D=Data[I]^ShiftReg[ParSize-1]; + for (int J=ParSize-1;J>0;J--) + ShiftReg[J]=ShiftReg[J-1]^gfMult(GXPol[J],D); + ShiftReg[0]=gfMult(GXPol[0],D); + } + for (int I=0;I<ParSize;I++) + DestData[I]=ShiftReg[ParSize-I-1]; +} + + +bool RSCoder::Decode(byte *Data,int DataSize,int *EraLoc,int EraSize) +{ + int SynData[MAXPOL]; + bool AllZeroes=true; + for (int I=0;I<ParSize;I++) + { + int Sum=Data[0],J=1,Exp=gfExp[I+1]; + for (;J+8<=DataSize;J+=8) + { + Sum=Data[J]^gfMult(Exp,Sum); + Sum=Data[J+1]^gfMult(Exp,Sum); + Sum=Data[J+2]^gfMult(Exp,Sum); + Sum=Data[J+3]^gfMult(Exp,Sum); + Sum=Data[J+4]^gfMult(Exp,Sum); + Sum=Data[J+5]^gfMult(Exp,Sum); + Sum=Data[J+6]^gfMult(Exp,Sum); + Sum=Data[J+7]^gfMult(Exp,Sum); + } + for (;J<DataSize;J++) + Sum=Data[J]^gfMult(Exp,Sum); + if ((SynData[I]=Sum)!=0) + AllZeroes=false; + } + if (AllZeroes) + return(true); + + if (!FirstBlockDone) + { + FirstBlockDone=true; + Clean(PolB,ParSize+1); + PolB[0]=1; + for (int EraPos=0;EraPos<EraSize;EraPos++) + for (int I=ParSize,M=gfExp[DataSize-EraLoc[EraPos]-1];I>0;I--) + PolB[I]^=gfMult(M,PolB[I-1]); + + ErrCount=0; + for (int Root=MAXPAR-DataSize;Root<MAXPAR+1;Root++) + { + int Sum=0; + for (int B=0;B<ParSize+1;B++) + Sum^=gfMult(gfExp[(B*Root)%MAXPAR],PolB[B]); + if (Sum==0) + { + Dn[ErrCount]=0; + for (int I=1;I<ParSize+1;I+=2) + Dn[ErrCount]^= gfMult(PolB[I],gfExp[Root*(I-1)%MAXPAR]); + ErrorLocs[ErrCount++]=MAXPAR-Root; + } + } + } + + int PolD[MAXPOL]; + pnMult(PolB,SynData,PolD); + if ((ErrCount<=ParSize) && ErrCount>0) + for (int I=0;I<ErrCount;I++) + { + int Loc=ErrorLocs[I],DLoc=MAXPAR-Loc,N=0; + for (int J=0;J<ParSize;J++) + N^=gfMult(PolD[J],gfExp[DLoc*J%MAXPAR]); + int DataPos=DataSize-Loc-1; + if (DataPos>=0 && DataPos<DataSize) + Data[DataPos]^=gfMult(N,gfExp[MAXPAR-gfLog[Dn[I]]]); + } + return(ErrCount<=ParSize); +} |