/*
  Copyright(C) 2007-2012 National Institute of Information and Communications Technology
*/

/*
  svmtools
  *.sv to *.fv converter
*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "exception.h"
#include "split.h"
#include "svm_common.h"
#include "svm_fv.h"


#define BUF_SIZE (32 * 1024)
#define MODE_EXAMPLE 0
#define MODE_MODEL 1


int main(int argc, char **argv) {
  int i;
  SVM_FT *ft;
  SVM_SV sv;
  SVM_FV fv;
  FILE *fp;
  int buf_size;
  char *buf;
  int nelem;
  char **elem;
  int sv_size;
  int mode;
  int line;
  char *s;
  int len;
  char *label;

  if (argc == 2) {
    mode = MODE_EXAMPLE;
  } else if (argc == 3 && strcmp(argv[1], "-model") == 0) {
    mode = MODE_MODEL;
  } else {
    fprintf(stderr, "usage: %s [-model] <*.ft> < <*.sv> > <*.fv>\n", argv[0]);
    return 1;
  }

  /* 初期化 */
  buf_size = BUF_SIZE;
  buf = smalloc(sizeof(char) * buf_size);
  elem = smalloc(sizeof(char *) * (buf_size / 2));
  sv_size = 0;
  sv.idx = NULL;
  sv.val = NULL;
  fv.ftr = NULL;
  fv.val = NULL;

  /* 素性テーブルの読み込み */
  fp = fopen(argv[argc - 1], "rt");
  exception(fp == NULL, "cannot open the *.ft file");
  ft = svm_fv_readft(fp);
  exception(ft == NULL, "cannot read the *.ft file");
  fclose(fp);

  /* 一行ずつ読んで変換 */
  for (line = 1; ; line++) {
    /* ベクトルの読み込み(メモリの動的確保) */
    if (fgets(buf, buf_size, stdin) == NULL) break;
    while (buf[(len = strlen(buf)) - 1] != '\n') {
      buf_size = 2 * buf_size + 1;
      buf = srealloc(buf, sizeof(char) * buf_size);
      elem = srealloc(elem, sizeof(char *) * (buf_size / 2));
      exception(fgets(buf + len, buf_size - len, stdin) == NULL, "unexpected EOF (line: %d)", line);
    }
    buf[--len] = '\0';
    if (len > 0 && buf[len - 1] == '\r') buf[--len] = '\0';
    if (len > 0 && buf[len - 1] == ' ') buf[--len] = '\0';

    /* モデルデータの場合 */
    if (mode == MODE_MODEL && line <= 9) {
      printf("%s\n", buf);
      continue;
    }

    /* コメント */
    if (buf[0] == '#') {
      printf("%s\n", buf);
      continue;
    }

    /* 分割 */
    nelem = split(buf, ' ', elem, buf_size / 2);

    /* ラベル */
    label = elem[0];

    /* ベクトル */
    while (nelem - 1 > sv_size) {
      sv_size = 2 * sv_size + 1;
      sv.idx = srealloc(sv.idx, sizeof(int) * sv_size);
      sv.val = srealloc(sv.val, sizeof(float) * sv_size);
      fv.ftr = srealloc(fv.ftr, sizeof(char *) * sv_size);
      fv.val = srealloc(fv.val, sizeof(float) * sv_size);
    }
    for (i = 1, sv.num = 0; i < nelem; i++) {
      if (elem[i][0] == '\0') continue;	/* 2つ以上スペースがある場合 */
      s = rindex(elem[i], ':');
      exception(s == NULL, "invalid data (no colon) (line: %d)\n", line);

      *(s++) = '\0';
      sv.idx[sv.num] = atoi(elem[i]);
      sv.val[sv.num] = (float)atof(s);
      if (sv.val[sv.num] == 0.0f) continue;
      sv.num++;
    }

    /* 変換 */
    svm_fv_sv2fv(ft, &sv, &fv);

    /* 出力 */
    printf("%s", label);
    for (i = 0; i < fv.num; i++) {
      printf(" %s:%.7g", fv.ftr[i], fv.val[i]);
    }
    printf("\n");
  }

  return 0;
}
