バイナリテンプレート読み込み

バイナリテンプレートを読み込むプログラムを書いてみた。
できるのはプレーンテキストの読み込みと変数の置き換えのみ。
perlから読み出せるようにもなっていないし、
ハッシュでテンプレートの変数を渡すようにもなっていない。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/mman.h>

//----------------------------------------------------------------------------

#define TPL_PLAIN    1
#define TPL_REPLACE  2
#define TPL_LB       253
#define TPL_RB       254
#define TPL_END      255

#define O_ENCODE     1
#define O_HSCHRS     2
#define O_HL2BR      4

#define ushort       unsigned short
#define uint         unsigned int

typedef struct {
  uint type;
} TPL_DESC;

typedef struct {
  uint type;
  uint ofsText;
} TPL_DESC_PLAIN;

typedef struct {
  uint type;
  uint ofsKey;
  uint opt;
} TPL_DESC_REPLACE;

typedef struct {
  uint type;
} TPL_DESC_LB;

typedef struct {
  uint type;
} TPL_DESC_RB;

typedef struct {
  uint type;
} TPL_DESC_END;

typedef struct {
  char* key;
  char* value;
} REPLACE_MAP;

static REPLACE_MAP replace_map[] =
  {
    { "message1", "test1" },
    { "message2", "test2" },
    { 0,           NULL   },
  };

//----------------------------------------------------------------------------
char* template_insert(char file[]);
void template_process(char* svHtml, void* pLines, void* pString, void* ptr);
char* process_replace(TPL_DESC_REPLACE *pDesc, char *svHtml, char *pString);
char* read_text(char* dst, char* r_pos);
char* read_hash(char* svHtml, char* pStr, int len);
//----------------------------------------------------------------------------

char* template_insert(char file[]) {
  char *svHtml;
  void *pMem, *pLines;
  char *pString;
  int len;

  svHtml = (char*)malloc(sizeof(char)*1000);

  len = mmap_file(file, (char**) &pMem);
  if (len == 0) exit;

  // ポインタを進めるときに使う
  pLines = pMem + sizeof(int);

  // 文字列を読み込むときに使う
  pString = (char*) (pLines + *((int*) pMem));

  template_process(svHtml, pLines, pString, pLines);

  munmap(pMem, len);
  return(svHtml);
}

void template_process(char* svHtml, void* pLines, void* pString, void* ptr) {
  int lastCond;

  lastCond = 0;

  while (1) {
    switch( ((TPL_DESC*)ptr)->type ) {
    case TPL_PLAIN:
      svHtml = read_text(svHtml, pString + ((TPL_DESC_PLAIN*)ptr)->ofsText);
      ptr += sizeof(TPL_DESC_PLAIN);
      lastCond = 1;
      break;
    case TPL_REPLACE:
      svHtml = process_replace((TPL_DESC_REPLACE*)ptr, svHtml, pString);
      ptr += sizeof(TPL_DESC_REPLACE);
      lastCond = 1;
      break;
    case TPL_LB: ptr += sizeof(TPL_DESC_LB); break;
    case TPL_RB: ptr += sizeof(TPL_DESC_RB); break;
    case TPL_END: lastCond = 1; return;
    }
  }
}

char* process_replace(TPL_DESC_REPLACE *pDesc, char *svHtml, char *pString) {
  char *pStr;
  int len;

  pStr = pString + pDesc->ofsKey; len = strlen(pStr);
  pStr = read_hash(svHtml, pStr, len);
  svHtml = read_text(svHtml, pStr);
  return svHtml;
}

char* read_text(char* dst, char* r_pos) {
  while (*r_pos != '\0') {
    *(dst++) = *(r_pos++);
  }
  return dst;
}

char* read_hash(char* svHtml, char* pStr, int len) {
  REPLACE_MAP *p;
  char *key, *value;
  
  key = (char*)malloc(sizeof(char)*len);
  value = (char*)malloc(sizeof(char)*100);

  strcpy(key,pStr);

  for (p = replace_map; p->value != 0; p++) {
    if (strcmp(p->key,key)==0) {
      strcpy(value,p->value);
      break;
    }
  }
  return(value);
}

int mmap_file(char* file, char** buf) {
  int len;
  size_t l;
  FILE* fd;

  fd = fopen(file, "rb");
  if (fd == NULL) return(0);
  fseek(fd, 0, SEEK_END);
  len = ftell(fd);
  fseek(fd, 0, SEEK_SET);

  *buf = (char*) mmap(0, len, PROT_READ, MAP_SHARED, fileno(fd), 0);
  fclose(fd);
  return(len);
}

int main() {
  char* result;
  char file[] = "bin.html";

  result = template_insert(file);
  printf("%s",result);

  return 0;
}

以下のHTMLテンプレートをコンパイルしたものを読み込んでみる。

<html>
<head>
<title>test</title>
</head>
<body>
$=h:message1$
$=h:message2$
</body>
</html>

出力結果は、

<html>
<head>
<title>test</title>
</head>
<body>
test1
test2
</body>
</html>

とりあえず置き換えられた。