boost::crc かなりE感じですね。しかし・・・、bit演算が・・・。

boost::crcC言語用に移植しています。
もう、テンプレート使いまくりでパフォーマンスアップを計ろうと必死にコーディングされています。好印象^^

C言語に移植する際、やっぱりGenericな実装がしにくい。
CRC16の時とCRC32の時、テーブルのサイズが違うのでtemplateとかを駆使して型情報を変えられないので、私が考えられる限りのアプローチとして、

  • unsigned charのポインタにしてmemcpy
  • 各、型用のルーチンを書く(マクロとして定義すれば型をとっかえひっかえした定義を作る事は出来るが・・・、*1 )

の手段があるが・・・。
ウーム、どちらもキライ。boost::crc並のC言語CRCライブラリは出来そうに無い・・・。
この際、テーブルサイズは32bit固定にしてしまうとか!?ハッハッハ^^;

やっぱり両ルーチンを別々に定義してステート保存用の構造体の中に関数のポインタ作ってそれをいじる関数を作るのがイイかな?C++で言う、virtualみたいな。


typedef struct dkc_CRC{
///ロード関数へのポインタ
void (*mLoader)(struct dkc_CRC *,const BYTE *,size_t);
///テーブルへのポインタ
void *mTable;
///状態遷移変数
unsigned long mR;
///生成済みCRC保存変数
unsigned long mResult;
///生成するCRCのビット数
size_t mBits;
///生成多項式
ULONG mTruncPoly;
///初期値
ULONG mInitRem;
///最後にXORする値
ULONG mFinalXor;

dkctBOOL mReflectIn;

dkctBOOL mReflectRem;
}DKC_CRC;

でも、そんなに多種多様じゃないし、素直にif文で分岐する事にしました。
code patchってテクニックもあるらしいけど、良くわからない・・・。
多分、配列にコードをぶち込んでいじるのかな?と思ってみたりみなかったり・・・。*2





で、移植中に気づいたのですが、やっぱりCRCとかは私の苦手なビット演算がくるのですよ。
私の場合、大体は英単語だと思って覚える事にしているのですが、やっぱり経験が足りないみたいで・・・。

で、やっぱり思い浮かばないところが・・・。


unsigned long 型の変数に32となっていたらLSBからMSBまですべて32個が1になって
31となっていたらLSBから順に31個が1になって・・
以下略
1となっていたらLSBから順に1個が1になって・・
0だとLSBからMSBまですべて0になって・・・
って奴。


32 -> 0xFFFFFFFF
31 -> 0xFFFFFFFE


ちょっと、ノートに書き出して、チマチマ考えてみる事にします。m(_ _)m
もし、定石を知っている方がいらっしゃいましたら、コメントに書いていただけると非常にうれしいです。m(_ _)m

*1:boost::lambdaですか!?

*2:なんか、違うような・・・