Диар ол..
у меня есть чудовищный код, доставшийся мне от индусов, который должен считать crc16. у меня есть класс, считающий crc и когда я увидел *это*, я заплакал..
я мало знаком с темплэйтами и прочим в vc++, поэтому я не понимаю совершенно как работает этот код.. помогите, пожалуйста разобраться:
WORD CBZXMessage::GetCRC(const CString &sFName, WORD nSerial,long newparameter)
{
USES_CONVERSION;
union
{
WORD uWholeWord;
struct
{
BYTE Low;
BYTE High;
}
ucByte;
}
uCRC;
deque<BYTE> byteQ;
BYTE bByte;
bool bRetVal = false;
WORD nFileCRC = 0;
uCRC.uWholeWord = nSerial;
ifstream ifs;
ifs.open(T2CA(sFName), ios_base::binary );
while ( ios::goodbit == ifs.rdstate())
{
char c;
ifs.get( c);
bByte = c;
byteQ.push_back( bByte);
if( byteQ.size() > newparameter) // 7 == magic number ( last char in file is read twice cos ios::eofbit
// is only set when a read fails + 4 for CRC + 0x0d + 0x0a)
{
uCRC.ucByte.Low ^= byteQ.front();
byteQ.pop_front();
for ( int j = 0; j < 8; j++) /* do 8 times */
{
WORD uFlag = uCRC.uWholeWord & 1; /* shift seed one bit to right */
uCRC.uWholeWord = uCRC.uWholeWord >> 1;
if (uFlag) /* if a 1 bit was shifted out */
{
uCRC.uWholeWord ^= 0xA001; /* exclusive or A001 to seed */
}
}
}
}
ifs.close();
return uCRC.uWholeWord;
}
newparameter = 7 всегда, nSerial = 0
где используются прочитаные из файла байты? для чего нужны ксоры ucByte.Low, если идет анализ только uWholeWord?.. Check для этой функции: BA04.
Please HELP!!!
29.03.08 21:46: Перенесено модератором из '.NET' — AndrewVK
Здравствуйте, alex2a, Вы писали:
A>у меня есть чудовищный код, доставшийся мне от индусов, который должен считать crc16. у меня есть класс, считающий crc и когда я увидел *это*, я заплакал..
Не проще ли взять в Гугле "C# crc16", выбрать пример получше и поставить вместо этого?..
Здравствуйте, nzeemin, Вы писали:
N>Не проще ли взять в Гугле "C# crc16", выбрать пример получше и поставить вместо этого?..
у меня есть уже класс, который считает Crc16 по всем правилам — можно задать полином, начальное значение, инверсию и тд, и тп..
но тот код, который я привел мне обязательно нужно перевести на C#, потому что 1) этот код считает CRC по индусскому специальному алгоритму какому-то и 2) удаленная система присылает файл и CRC, а моя система должна подсчитать CRC по тому же алгоритму и смэтчить.. на той стороне есссно, никто давно не знает как это работает и менять ничего не будет, и никаких тебе md5 и тп..
Здравствуйте, alex2a, Вы писали:
A>у меня есть чудовищный код, доставшийся мне от индусов, который должен считать crc16. у меня есть класс, считающий crc и когда я увидел *это*, я заплакал.. A>я мало знаком с темплэйтами и прочим в vc++, поэтому я не понимаю совершенно как работает этот код.. помогите, пожалуйста разобраться
При чём тут темплейты?
1. Последние шесть байт из потока (четырехбайтовая CRC и два байта на конец строки) в подсчёте CRC не учавствуют. Для этого организовано игрище с декой (которое можно заменить чем-нибудь более шустрым). Семь — потому что последний байт только на втором чтении вынесет ifs.rdstate().
2. Каждый байт ксорится с младшим байтом CRC.
3. CRC сдвигается вправо восемь раз — по разу на бит. Каждый сдвиг, когда вправо вылетает единичка, всё слово ксорится с 0xA001.
4. Всё.
Вроде ничего сложного, "индускоссти" немного, разве что вот этот замухрон с union-ом двух байтов в слово. Без него можно (и нужно) обойтись. А так нормально, и даже понятно комментировано. Всякий хлам, типа nFileCRC и bRetVal тоже нужно выкинуть.
Здравствуйте, Xander Zerge, Вы писали:
XZ>При чём тут темплейты?
deque вроде темплэйт? просто я не пользовался никогда
XZ>1. Последние шесть байт из потока (четырехбайтовая CRC и два байта на конец строки) в подсчёте CRC не учавствуют. Для этого организовано игрище с декой (которое можно заменить чем-нибудь более шустрым). Семь — потому что последний байт только на втором чтении вынесет ifs.rdstate().
попробую поиграться
XZ>2. Каждый байт ксорится с младшим байтом CRC.
хм.. а где? я вижу uCRC.ucByte.Low ^= byteQ.front(); — но это ведь, насколько я понимаю, ксор первого байта дека с младшим байтом crc?
а в цикле вообще byteQ не участвует..
XZ>Вроде ничего сложного, "индускоссти" немного, разве что вот этот замухрон с union-ом двух байтов в слово. Без него можно (и нужно) обойтись. А так нормально, и даже понятно комментировано. Всякий хлам, типа nFileCRC и bRetVal тоже нужно выкинуть.
вам, профессионалам от c++ легко
Спасибо Xander Zerge, с кодом я разобрался.
если кому интересно, реализация в C# следущая:
public ushort MercuryCRC(string strFileName)
{
ushort crc = 0x0000;
System.IO.FileInfo fi = new FileInfo(strFileName);
const int BlockSize = 1024; // block size for file read
int numberOfFullBlocks = (int)((fi.Length — 6) / BlockSize);
/* number of blocks of 256 to read
* 6 is magic hindu number.
* we skip last 6 bytes in file
* */
// bytes rest after all 256 blocks are read
int AuxBlockSize = (numberOfFullBlocks == 0) ? (int)(fi.Length — 6) : (int)((fi.Length — 6) % BlockSize);
BinaryReader bn = new BinaryReader(File.Open(strFileName, FileMode.Open), System.Text.Encoding.Default);
byte[] buf = new byte[BlockSize];
try
{
for (int i = 0; i < numberOfFullBlocks; i++)
{
buf = bn.ReadBytes(BlockSize);
foreach (byte by in buf)
{
crc ^= (ushort)by;
for (int j = 0; j < 8; j++)
{
bool flag = Convert.ToBoolean(crc & 1); // test high word of crc and 1
crc >>= 1;
if (flag)
crc ^= 0xa001;
}// for 8 times
}// foreach by in buf
}// for number of full blocks
// now read rest bytes
buf = bn.ReadBytes(AuxBlockSize); // read number of the rest bytes
foreach (byte by in buf) // for each
{
crc ^= (ushort)by;
for (int j = 0; j < 8; j++)
{
bool flag = Convert.ToBoolean(crc & 1); // test high word of crc and 1
crc >>= 1;
if (flag)
crc ^= 0xa001;
}// for 8 times
}// foreach of the rest bytes
return crc;
}//try
catch (Exception ex)
{
throw new Exception("Error calculation M-CRC for " + strFileName + "\n" + ex.Message);
return 0;
}
finally
{
bn.Close();
}
}