読者です 読者をやめる 読者になる 読者になる
月 の 上

C++でのバイナリファイルいじりについて

動画いじってて、C++バイナリのデータを操作したかったんだけど
C++のfstreamはなんか使いづらかったのでC文字列使って頑張った話

バイト一つ一つ弄るにはunsigned charにキャストしてやるのが一番楽っぽい

以下メモ

#include <iostream>
#include <stdlib.h>

typedef unsigned char BYTE;


void bitAnd(const BYTE *a, const BYTE *b, BYTE *dst, size_t size){
  for (int i=0; i<size; i++) {
    dst[i] = a[i] & b[i];    
  }
}


void str2byte(const char *src, BYTE *dst, size_t size){
  for (int i=0; i<size; i++) {
    dst[i] = (BYTE)src[i];
  }
}


const BYTE * memsearch(const BYTE *s, const BYTE *s_end, const BYTE *q, const BYTE *q_end){
  const BYTE *ss = s;
  const BYTE *s_end_1 = s_end + 1;
  
  register const BYTE *i, *j;
  
  while (ss != s_end_1) {
    i = ss;
    j = q;
    
    while (*i == *j) {
      if (j == q_end) return ss;
      i++; j++;
    }
    ss++;
  }
  return NULL;
}


int main(int argc, char **argv){

  BYTE *header = new BYTE[10];
  BYTE *mask = new BYTE[10];
  BYTE *dst = new BYTE[10];
  
  str2byte("\x21\x00\x01\x00\x01\x80\x00\x01\x00\x00", header, 10);
  str2byte("\xF1\x00\x01\x00\x01\x80\x00\x01\x00\x00", mask, 10);  

  bitAnd((BYTE *)header, (BYTE *)mask, dst, 10);

  for (int i = 0; i < 10; i++) {
    if (dst[i] != header[i]) {
      std::cout << "bitAnd error! " << i << std::endl;
      exit(1);
    }
  }

  BYTE *idx = (BYTE *)memsearch(header, header + 10, dst+3, dst + 10);
  if (idx == NULL) std::cout << "not found! (;_;)" << std::endl;
  std::cout << idx - header << std::endl;
  
  delete[] header;
  delete[] mask;
  delete[] dst;

  return 0;
}

実行結果

$ g++ bit.cpp
$ ./a.out 
3

memなんとか系の関数っぽいの作るとき、voidポインタ使うべきか迷ったけど、見た目ごちゃごちゃして間違えそうだったからやめた