2009/04/19(日)続・UOのジャーナル保存
久しぶりに C を書きたくなったので、ミソな部分+αを書いてみた。
-  シングルバイトな<LF> を取り除いて
	
- 諸悪の根源を除去
 
 - <CR> も邪魔なので取り除いて
 - ついでに <LF> が連続する場合も取り除いちゃう
 
後は
-  UTF-16-LE な文字コードを UTF-8 か Shift-JIS に変換
	
- マルチプラットフォームで文字コード変換できるライブラリってあるんかな
 
 -  処理結果をファイルに保存
	
- 10行くらいの追加でとりあえず OK
 
 
UO のジャーナルファイルは一度のゲームで数百KB 程度になるらしいので、一度に処理するバッファのサイズは 128KB くらいがちょうどいいのかなぁ。
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
int main(int argc, char **argv)
{
  char *file, *buf, *newbuf;
  int index, newindex, lfflag, lfappered, crflag;
  FILE *filep;
  size_t bufsize = 1024 * 128; /* 128KB でいいかな? */
  size_t gottenbuf;
  if (argc < 2) {
    fprintf(stderr, "Please indicate an UO\'s Journal.\n");
  }
  filep = fopen(argv[1], "r");
  if (!filep) {
    fprintf(stderr, "%s could not be opened.\n", argv[1]);
    exit(-1);
  }
  
  buf = malloc(sizeof(char) * bufsize);
  newbuf = malloc(sizeof(char) * bufsize);
  memset(newbuf, 0x00, bufsize);
  memset(buf, 0x00, bufsize);
  crflag = lfflag = 0;
  while (gottenbuf = fread(buf, sizeof(char), bufsize, filep)) {
    newindex = 0;
    for(index = 0; index < gottenbuf; index++) {
      if (buf[index] == 0x0d) {
	lfflag = 1;
      } else if (lfflag && buf[index] == 0x00) {
      /* 前のバイトが 0x0d かつ今見てるものが 0x00 なら 0x0d00 を挿入 */
	if(lfappered) {
        /* <LF> が連続している場合は読み飛ばす(何もしない) */
	  lfflag = 0;
	  lfappered = 0;
	} else {
	  newbuf[newindex] = 0x0d;
	  newindex++;
	  newbuf[newindex] = buf[index];
	  newindex++;
	  lfflag = 0;
          /* 一文字前は <LF> だったことを示すフラグを立てる */
	  lfappered = 1;
	}
      } else if (buf[index] == 0x0a) {
      /* <CR> は いらない子 */
	crflag = 1;
	lfappered = 0;
      } else if (crflag && buf[index] == 0x00) {
	crflag = 0;
	lfappered = 0; /* 実際はここでフラグ立ってることはないはず */
      } else {
      /* 改行文字以外の文字は普通に読み込む。かつ各フラグクリア */
	newbuf[newindex] = buf[index];
	newindex++;
	lfflag = 0;
	crflag = 0;
	lfappered = 0;
      }
    }
    fwrite(newbuf, sizeof(char), newindex, stdout);
    memset(newbuf, 0x00, bufsize);
    memset(buf, 0x00, bufsize);
  }
  close(filep);
  free(buf);
  free(newbuf);
}
自分でバッファを切り出して~とかバッファが変なところで切れた場合にどうするか~とか Perlだと考えないので面白かった。