<commit_before>#include "sexpr.hpp"

#include "../parse.hpp"

namespace {

  template<char ... c>
  static int matches(int x) {
    static const char data[] = {c..., 0};

    for(const char* i = data; *i; ++i) {
      if(*i == x) return true;
    }

    return false;
  }

}

sexpr parse(std::istream& in) {
  using namespace parser;

  static const auto true_parser =
    token("true") >> [](const char*) { return pure(true); };

  static const auto false_parser =
    token("false") >> [](const char*) { return pure(false); };

  static const auto boolean_parser = true_parser | false_parser;

  static const auto separator_parser = // parser::debug("sep") |=
    noskip(chr<std::isspace>());

  static const auto real_parser = // parser::debug("real") |=
    value<double>();

  static const auto number_parser = // parser::debug("num") |=
    real_parser >> [](real num) {
    const long cast = num;
    const sexpr value = num == real(cast) ? sexpr(cast) : sexpr(num);
    return pure(value);
  };

  static const auto initial_parser = chr<std::isalpha>();

  static const auto rest_parser = parser::chr<std::isalnum>();

  static const auto symbol_parser = initial_parser >> [](char c) {
    return noskip(*rest_parser >> [c](std::deque<char>&& rest) {
        const std::string tmp = c + std::string(rest.begin(), rest.end());
        return pure(symbol(tmp));
      });
  };

  static const auto op_parser =
    parser::chr<matches<'+', '-', '*', '/', '='>>() >> [](char c) {
    return pure(symbol(std::string(1, c)));
  };

  static const auto attr_parser = parser::chr<matches<'@'>>() >> [](char c) {
    return symbol_parser >> [c](symbol s) {
      return pure(symbol(c + std::string(s.get())));
    };
  };

  static const auto as_expr = parser::cast<sexpr>();

  static auto expr_parser = parser::any<sexpr>();

  static const auto lparen = // parser::debug("lparen") |=
    parser::token("(");

  static const auto rparen = // parser::debug("rparen") |=
    parser::token(")");

  static const auto exprs_parser = // parser::debug("exprs") |=
    parser::ref(expr_parser) % separator_parser;

  static const auto list_parser = // parser::debug("list") |=
    lparen >>= exprs_parser >> drop(rparen)
           >> [](std::deque<sexpr>&& es) {
    return pure(make_list(es.begin(), es.end()));
  };

  static const auto once =
    (expr_parser
     = (boolean_parser >> as_expr)
     | (symbol_parser >> as_expr)
     | (attr_parser >> as_expr)
     | (op_parser >> as_expr)
     | number_parser
     | (list_parser >> as_expr)
     , 0); (void) once;

  parser::debug::stream = &std::clog;

  if(auto value = expr_parser(in)) {
    return value.get();
  }

  throw parse_error("parse error");
}
<commit_msg>tokens<commit_after>#include "sexpr.hpp"

#include "../parse.hpp"

namespace {

  template<char ... c>
  static int matches(int x) {
    static const char data[] = {c..., 0};

    for(const char* i = data; *i; ++i) {
      if(*i == x) return true;
    }

    return false;
  }

}

sexpr parse(std::istream& in) {
  using namespace parser;

  static const auto true_parser =
    token("true") >> [](const char*) { return pure(true); };

  static const auto false_parser =
    token("false") >> [](const char*) { return pure(false); };

  static const auto boolean_parser = true_parser | false_parser;

  static const auto separator_parser = // parser::debug("sep") |=
    noskip(chr<std::isspace>());

  static const auto real_parser = // parser::debug("real") |=
    value<double>();

  static const auto number_parser = // parser::debug("num") |=
    real_parser >> [](real num) {
    const long cast = num;
    const sexpr value = num == real(cast) ? sexpr(cast) : sexpr(num);
    return pure(value);
  };

  static const auto initial_parser = chr<std::isalpha>();

  static const auto rest_parser = parser::chr<std::isalnum>();

  static const auto symbol_parser = initial_parser >> [](char c) {
    return noskip(*rest_parser >> [c](std::deque<char>&& rest) {
        const std::string tmp = c + std::string(rest.begin(), rest.end());
        return pure(symbol(tmp));
      });
  };

  static const auto op_parser =
    parser::chr<matches<'+', '-', '*', '/', '=', '<', '>', '%' >>() >> [](char c) {
    return pure(symbol(std::string(1, c)));
  }
    | (token("!=") | token("<=") | token(">=")) >> [](const char* s) {
                                                     return pure(symbol(s));
                                                   };

  static const auto attr_parser = parser::chr<matches<'@'>>() >> [](char c) {
    return symbol_parser >> [c](symbol s) {
      return pure(symbol(c + std::string(s.get())));
    };
  };

  static const auto as_expr = parser::cast<sexpr>();

  static auto expr_parser = parser::any<sexpr>();

  static const auto lparen = // parser::debug("lparen") |=
    parser::token("(");

  static const auto rparen = // parser::debug("rparen") |=
    parser::token(")");

  static const auto exprs_parser = // parser::debug("exprs") |=
    parser::ref(expr_parser) % separator_parser;

  static const auto list_parser = // parser::debug("list") |=
    lparen >>= exprs_parser >> drop(rparen)
           >> [](std::deque<sexpr>&& es) {
    return pure(make_list(es.begin(), es.end()));
  };

  static const auto once =
    (expr_parser
     = (boolean_parser >> as_expr)
     | (symbol_parser >> as_expr)
     | (attr_parser >> as_expr)
     | (op_parser >> as_expr)
     | number_parser
     | (list_parser >> as_expr)
     , 0); (void) once;

  parser::debug::stream = &std::clog;

  if(auto value = expr_parser(in)) {
    return value.get();
  }

  throw parse_error("parse error");
}
<|endoftext|>


<commit_before>char copyright[] = "Developed by Bulat Ziganshin\n"
                   "The code is placed in public domain\n";

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

#define kb 1024
#define mb (kb*kb)
typedef unsigned char byte;

class Smoker
{
public:
  virtual const char* name() = 0;
  virtual void smoke (void *buf, size_t bufsize, double *entropy) = 0;
  virtual ~Smoker() {}
};

/**********************************************************************/
/* Byte smoker: calculate compression ratio with the order-0 model    */
/**********************************************************************/

class ByteSmoker : public Smoker
{
public:
  virtual const char* name()  {return "ByteSmoker";};
  virtual void smoke (void *buf, size_t bufsize, double *entropy);
};

void ByteSmoker::smoke (void *buf, size_t bufsize, double *entropy)
{
  size_t count1[256] = {0};
  size_t count2[256] = {0};
  size_t count3[256] = {0};
  size_t count4[256] = {0};

  byte *p = (byte*) buf;  int i;
  for (i=0; i<bufsize-3; i+=4)
    count1[ p[i]   ]++,
    count2[ p[i+1] ]++,
    count3[ p[i+2] ]++,
    count4[ p[i+3] ]++;
  for (; i<bufsize; i++)
    count1[ p[i]   ]++;

  double order0 = 0;
  for (int i=0; i<256; i++)
  {
    size_t count  =  count1[i] + count2[i] + count3[i] + count4[i];
    if (count)
      order0 += count * log(double(bufsize/count))/log(double(2)) / 8;
  }

  *entropy  =  order0 / bufsize;
}

/**********************************************************************/
/* DWord smoker                                                       */
/**********************************************************************/

uint32_t hash_function (uint32_t x)
{
  uint64_t hash  =  x * uint64_t(123456791u);
  return uint32_t(hash>>32) ^ uint32_t(hash);
}

const size_t HASHSIZE = 128*kb;

class DWordSmoker : public Smoker
{
  size_t bits[256];
  byte table[HASHSIZE];
public:
  DWordSmoker();
  virtual const char* name()  {return "DWordSmoker";};
  virtual void smoke (void *buf, size_t bufsize, double *entropy);
  virtual ~DWordSmoker() {}
};

DWordSmoker::DWordSmoker()
{
  bits[0] = 0;
  for (int i=0; i<256; i++)
    bits[i]  =  bits[i/2] + (i%2);
}

void DWordSmoker::smoke (void *buf, size_t bufsize, double *entropy)
{
  const size_t   STEP = 4;                                          // Check only every n'th position
  const uint32_t FILTER = 16;                                       // Of those checked, count only every n'th hash
  const uint32_t FILTER_MAX_HASH = (1u<<31) / (FILTER/2);           // Count only hashes smaller than this value
  const uint32_t FILTER_HASH_DIVIDER = FILTER_MAX_HASH / CHAR_BIT;  // Dividing filtered hashes by this value will leave only 3 highest bits required to address bit in the byte

  memset(table,0,HASHSIZE);
  byte *p = (byte*) buf;
  for (size_t i=0; i<bufsize-STEP+1; i+=STEP)
  {
    uint32_t hash = hash_function(*(uint32_t*)(p+i));
    if (hash < FILTER_MAX_HASH)
      table[hash % HASHSIZE]  |=  1 << (hash/FILTER_HASH_DIVIDER);
  }

  size_t count = 0;
  for (size_t i=0; i<HASHSIZE; i++)
    count += bits[table[i]];

  // We have checked bufsize/(STEP*FILTER) hashes and found `count` original values among them
  *entropy  =  count / (double(bufsize)/(STEP*FILTER));
}

/**********************************************************************/
/* Supplementary code                                                 */
/**********************************************************************/

static char* show3 (uint64_t n, char *buf, const char *prepend="")
{
    char *p = buf + 27+strlen(prepend);
    int i = 4;

    *p = '\0';
    do {
        if (!--i) *--p = ',', i = 3;
        *--p = '0' + (n % 10);
    } while (n /= 10);

    memcpy (p-strlen(prepend), prepend, strlen(prepend));
    return p-strlen(prepend);
}

int main (int argc, char **argv)
{
  fprintf(stderr, "DataSmoker 0.1. ");

  if (argc==1)
  {
    fprintf(stderr, "\n\nUsage: smoke infile\n\n%s", copyright);
    return EXIT_FAILURE;
  }

  FILE *infile  = fopen (argv[1], "rb");  if (infile==NULL)  {fprintf (stderr, "Can't open input file %s!\n",    argv[1]); return EXIT_FAILURE;}

  ByteSmoker  ByteS;
  DWordSmoker DWordS;
  Smoker *smokers[] = {&ByteS, &DWordS};
  const int NumSmokers = sizeof(smokers)/sizeof(*smokers);
  double entropy,  min_entropy[NumSmokers],  avg_entropy[NumSmokers] = {0};
  for (int i=0; i<NumSmokers; ++i)  min_entropy[i] = 1;

  uint64_t origsize = 0;
  for(;;)
  {
    int buf_bytes;
    const int BUFSIZE = 4*mb;
    static char buf[BUFSIZE];

    buf_bytes = fread(buf, 1, BUFSIZE, infile);
    if (buf_bytes==0) break;

    for (int i=0; i<NumSmokers; i++)
    {
      smokers[i]->smoke(buf, buf_bytes, &entropy);
      if (entropy < min_entropy[i])
        min_entropy[i] = entropy;
      avg_entropy[i] += entropy*buf_bytes;
  }

    origsize += buf_bytes;
  }

  char temp1[100];  fprintf(stderr, "Processed %s bytes\n", show3(origsize,temp1));
  for (int i=0; i<NumSmokers; i++)
    fprintf(stderr, "%s entropy: minimum %.2lf%%, average %.2lf%%\n", smokers[i]->name(), min_entropy[i]*100, avg_entropy[i]/origsize*100);
  return EXIT_SUCCESS;
}
<commit_msg>DWord smoker modified to support even STEP==FILTER==1 values<commit_after>char copyright[] = "Developed by Bulat Ziganshin\n"
                   "The code is placed in public domain\n";

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <limits.h>

#define kb 1024
#define mb (kb*kb)
typedef unsigned char byte;

class Smoker
{
public:
  virtual const char* name() = 0;
  virtual void smoke (void *buf, size_t bufsize, double *entropy) = 0;
  virtual ~Smoker() {}
};

/**********************************************************************/
/* Byte smoker: calculate compression ratio with the order-0 model    */
/**********************************************************************/

class ByteSmoker : public Smoker
{
public:
  virtual const char* name()  {return "ByteSmoker";};
  virtual void smoke (void *buf, size_t bufsize, double *entropy);
};

void ByteSmoker::smoke (void *buf, size_t bufsize, double *entropy)
{
  size_t count1[256] = {0};
  size_t count2[256] = {0};
  size_t count3[256] = {0};
  size_t count4[256] = {0};

  byte *p = (byte*) buf;  int i;
  for (i=0; i<bufsize-3; i+=4)
    count1[ p[i]   ]++,
    count2[ p[i+1] ]++,
    count3[ p[i+2] ]++,
    count4[ p[i+3] ]++;
  for (; i<bufsize; i++)
    count1[ p[i]   ]++;

  double order0 = 0;
  for (int i=0; i<256; i++)
  {
    size_t count  =  count1[i] + count2[i] + count3[i] + count4[i];
    if (count)
      order0 += count * log(double(bufsize/count))/log(double(2)) / 8;
  }

  *entropy  =  order0 / bufsize;
}

/**********************************************************************/
/* DWord smoker                                                       */
/**********************************************************************/

uint32_t hash_function (uint32_t x)
{
  uint64_t hash  =  x * uint64_t(123456791u);
  return uint32_t(hash>>32) ^ uint32_t(hash);
}

const size_t HASHSIZE = 128*kb;

class DWordSmoker : public Smoker
{
  size_t bits[256];
  byte table[HASHSIZE];
public:
  DWordSmoker();
  virtual const char* name()  {return "DWordSmoker";};
  virtual void smoke (void *buf, size_t bufsize, double *entropy);
  virtual ~DWordSmoker() {}
};

DWordSmoker::DWordSmoker()
{
  bits[0] = 0;
  for (int i=0; i<256; i++)
    bits[i]  =  bits[i/2] + (i%2);
}

void DWordSmoker::smoke (void *buf, size_t bufsize, double *entropy)
{
  const size_t   STEP = 4;        // Check only every n'th position
  const uint32_t FILTER = 16;     // Of those checked, count only every n'th hash
  const uint32_t FILTER_MAX_HASH  =  uint32_t(-1) / FILTER;   // Count only hashes smaller or equal to this value
  const uint32_t FILTER_HASH_DIVIDER  =  (FILTER_MAX_HASH / CHAR_BIT) + 1;  // Dividing filtered hashes by this value will leave only 3 highest bits required to address bit in the byte

  memset(table,0,HASHSIZE);
  byte *p = (byte*) buf;
  for (size_t i=0; i<bufsize-STEP+1; i+=STEP)
  {
    uint32_t hash = hash_function(*(uint32_t*)(p+i));
    if (hash <= FILTER_MAX_HASH)
      table[hash % HASHSIZE]  |=  1 << (hash/FILTER_HASH_DIVIDER);
  }

  size_t count = 0;
  for (size_t i=0; i<HASHSIZE; i++)
    count += bits[table[i]];

  // We have checked bufsize/(STEP*FILTER) hashes and found `count` original values among them
  *entropy  =  count / (double(bufsize)/(STEP*FILTER));
}

/**********************************************************************/
/* Supplementary code                                                 */
/**********************************************************************/

static char* show3 (uint64_t n, char *buf, const char *prepend="")
{
    char *p = buf + 27+strlen(prepend);
    int i = 4;

    *p = '\0';
    do {
        if (!--i) *--p = ',', i = 3;
        *--p = '0' + (n % 10);
    } while (n /= 10);

    memcpy (p-strlen(prepend), prepend, strlen(prepend));
    return p-strlen(prepend);
}

int main (int argc, char **argv)
{
  fprintf(stderr, "DataSmoker 0.1. ");

  if (argc==1)
  {
    fprintf(stderr, "\n\nUsage: smoke infile\n\n%s", copyright);
    return EXIT_FAILURE;
  }

  FILE *infile  = fopen (argv[1], "rb");  if (infile==NULL)  {fprintf (stderr, "Can't open input file %s!\n",    argv[1]); return EXIT_FAILURE;}

  ByteSmoker  ByteS;
  DWordSmoker DWordS;
  Smoker *smokers[] = {&ByteS, &DWordS};
  const int NumSmokers = sizeof(smokers)/sizeof(*smokers);
  double entropy,  min_entropy[NumSmokers],  avg_entropy[NumSmokers] = {0};
  for (int i=0; i<NumSmokers; ++i)  min_entropy[i] = 1;

  uint64_t origsize = 0;
  for(;;)
  {
    int buf_bytes;
    const int BUFSIZE = 4*mb;
    static char buf[BUFSIZE];

    buf_bytes = fread(buf, 1, BUFSIZE, infile);
    if (buf_bytes==0) break;

    for (int i=0; i<NumSmokers; i++)
    {
      smokers[i]->smoke(buf, buf_bytes, &entropy);
      if (entropy < min_entropy[i])
        min_entropy[i] = entropy;
      avg_entropy[i] += entropy*buf_bytes;
  }

    origsize += buf_bytes;
  }

  char temp1[100];  fprintf(stderr, "Processed %s bytes\n", show3(origsize,temp1));
  for (int i=0; i<NumSmokers; i++)
    fprintf(stderr, "%s entropy: minimum %.2lf%%, average %.2lf%%\n", smokers[i]->name(), min_entropy[i]*100, avg_entropy[i]/origsize*100);
  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include <v8.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <common.h>
#include <dirent.h>
#include <string.h>
#include <unistd.h>

v8::Handle<v8::Value> _directory(const v8::Arguments& args) {
    v8::HandleScope handle_scope;
    if (args.Length() < 1 || args.This()->InternalFieldCount() == 0) {
	return v8::ThrowException(v8::String::New("Invalid call format. Use 'new Directory(name)'"));
    }

    args.This()->SetInternalField(0, args[0]);
    return args.This();
}

v8::Handle<v8::Value> _create(const v8::Arguments& args) {
    v8::HandleScope handle_scope;

    v8::String::Utf8Value name(args.This()->GetInternalField(0));
    int mode;
    if (args.Length() == 0) {
	mode = 0777;
    } else {
	mode = args[0]->Int32Value();
    }

    int result = mkdir(*name, mode);
    if (result != 0) {
	return v8::ThrowException(v8::String::New("Cannot create directory'"));
    }

    return args.This();
}

v8::Handle<v8::Value> _listfiles(const v8::Arguments& args) {
    v8::HandleScope handle_scope;
    v8::String::Utf8Value name(args.This()->GetInternalField(0));

    DIR * dp;
    struct dirent * ep;

    v8::Handle<v8::Array> result = v8::Array::New();

    dp = opendir(*name);
    if (dp == NULL) { return v8::ThrowException(v8::String::New("Directory cannot be opened")); }
    int cnt = 0;
    while ((ep = readdir(dp))) {
	if (ep->d_type == DT_REG) {
	    result->Set(v8::Integer::New(cnt++), v8::String::New(ep->d_name));
	}
    }
    closedir(dp);
    return result;
}

v8::Handle<v8::Value> _listdirectories(const v8::Arguments& args) {
    v8::HandleScope handle_scope;
    v8::String::Utf8Value name(args.This()->GetInternalField(0));

    DIR * dp;
    struct dirent * ep;

    v8::Handle<v8::Array> result = v8::Array::New();

    dp = opendir(*name);
    if (dp == NULL) { return v8::ThrowException(v8::String::New("Directory cannot be opened")); }
    int cnt = 0;
    while ((ep = readdir(dp))) {
	if (ep->d_type == DT_DIR) {
	    if (strcmp(ep->d_name, ".") != 0 && strcmp(ep->d_name, "..") != 0) {
		result->Set(v8::Integer::New(cnt++), v8::String::New(ep->d_name));
	    }
	}
    }
    closedir(dp);
    return result;
}

v8::Handle<v8::Value> _file(const v8::Arguments& args) {
    v8::HandleScope handle_scope;
    if (args.Length() < 1 || args.This()->InternalFieldCount() == 0) {
	return v8::ThrowException(v8::String::New("Invalid call format. Use 'new File(name)'"));
    }

    args.This()->SetInternalField(0, args[0]);
    args.This()->SetInternalField(1, v8::Boolean::New(false));
    return args.This();
}

v8::Handle<v8::Value> _open(const v8::Arguments& args) {
    v8::HandleScope handle_scope;
    if (args.Length() < 1) {
	return v8::ThrowException(v8::String::New("Bad argument count. Use 'file.open(mode)'"));
    }
    v8::String::Utf8Value mode(args[0]);
    v8::String::Utf8Value name(args.This()->GetInternalField(0));
    v8::Handle<v8::Value> file = args.This()->GetInternalField(1);
    if (!file->IsFalse()) {
	return v8::ThrowException(v8::String::New("File already opened"));
    }

    FILE * f;
    f = fopen(*name, *mode);

    if (!f) {
	return v8::ThrowException(v8::String::New("Cannot open file"));
    }

    struct stat st;
    if (stat(*name, &st) == 0) {
	args.This()->SetInternalField(2, v8::Integer::New(st.st_size));
    }
    args.This()->SetInternalField(1, v8::External::New((void *)f));
    args.This()->SetInternalField(3, v8::Integer::New(0));

    return args.This();
}

v8::Handle<v8::Value> _close(const v8::Arguments& args) {
    v8::HandleScope handle_scope;
    v8::Handle<v8::Value> file = args.This()->GetInternalField(1);

    if (file->IsFalse()) {
	return v8::ThrowException(v8::String::New("Cannot close non-opened file"));
    }

    FILE * f = reinterpret_cast<FILE *>(v8::Handle<v8::External>::Cast(file)->Value());
    fclose(f);
    args.This()->SetInternalField(1, v8::Boolean::New(false));
    return args.This();
}

v8::Handle<v8::Value> _read(const v8::Arguments& args) {
    v8::HandleScope handle_scope;
    v8::Handle<v8::Value> file = args.This()->GetInternalField(1);

    if (file->IsFalse()) {
	return v8::ThrowException(v8::String::New("File must be opened before reading"));
    }

    long size = args.This()->GetInternalField(2)->IntegerValue();
    long pos = args.This()->GetInternalField(3)->IntegerValue();

    FILE * f = reinterpret_cast<FILE *>(v8::Handle<v8::External>::Cast(file)->Value());

    long avail = size-pos;
    if (!avail) { return v8::Boolean::New(false); }

    if (args.Length() && args[0]->IsNumber()) {
        int len = args[0]->IntegerValue();
	if (len < avail) { avail = len; }
    }
    char buf[avail];
    fread(buf, sizeof(char), avail, f);
    pos += avail;

    args.This()->SetInternalField(3, v8::Integer::New(pos));

   if (args.Length() > 1 && args[1]->IsTrue()) {
       return char2array(buf, avail);
   } else {
       return char2string(buf, avail);
    }
}

v8::Handle<v8::Value> _rewind(const v8::Arguments& args) {
    v8::HandleScope handle_scope;
    v8::Handle<v8::Value> file = args.This()->GetInternalField(1);
    if (file->IsFalse()) {
	return v8::ThrowException(v8::String::New("File must be opened before rewinding"));
    }

    FILE * f = reinterpret_cast<FILE *>(v8::Handle<v8::External>::Cast(file)->Value());
    rewind(f);

    args.This()->SetInternalField(3, v8::Integer::New(0));
    return args.This();
}

v8::Handle<v8::Value> _write(const v8::Arguments& args) {
    v8::HandleScope handle_scope;
    v8::Handle<v8::Value> file = args.This()->GetInternalField(1);

    if (file->IsFalse()) {
	return v8::ThrowException(v8::String::New("File must be opened before writing"));
    }

    FILE * f = reinterpret_cast<FILE *>(v8::Handle<v8::External>::Cast(file)->Value());

    if (args[0]->IsArray()) {
	v8::Handle<v8::Array> arr = v8::Handle<v8::Array>::Cast(args[0]);
	int len = arr->Length();

	int max = 4096;
	int current = 0;
	char buf[max];
	for (int i=0;i<len;i++) {
    	    v8::Handle<v8::Integer> a = v8::Integer::New(arr->Get(v8::Integer::New(i))->IntegerValue());
	    buf[current++] = (char) a->Int32Value();
	    if (current == max) {
    		fwrite(buf, sizeof(char), current, f);
		current = 0;
	    }
	}
	if (current) { fwrite(buf, sizeof(char), current, f); }

    } else {
	v8::String::Utf8Value data(args[0]);

	fwrite(*data, sizeof(char), args[0]->ToString()->Utf8Length(), f);
    }

    return args.This();
}

v8::Handle<v8::Value> _remove(const v8::Arguments& args) {
    v8::HandleScope handle_scope;
    v8::String::Utf8Value name(args.This()->GetInternalField(0));

    if (remove(*name) != 0) {
	return v8::ThrowException(v8::String::New("Cannot remove file/dir"));
    }

    return args.This();
}

v8::Handle<v8::Value> _getsize(const v8::Arguments& args) {
    v8::HandleScope handle_scope;

    v8::String::Utf8Value name(args.This()->GetInternalField(0));
    struct stat st;
    if (stat(*name, &st) == 0) {
	return v8::Integer::New(st.st_size);
    } else {
	return v8::Boolean::New(false);
    }
}

v8::Handle<v8::Value> _copy(char * name1, char * name2) {
    int len = 1024;
    char buf[len];

    FILE * f1 = fopen(name1, "rb");
    FILE * f2 = fopen(name2, "wb");

    if (f1 == NULL) { return v8::ThrowException(v8::String::New("Cannot open source file")); }
    if (f2 == NULL) { return v8::ThrowException(v8::String::New("Cannot open target file")); }

    int size = 0;

    while ((size = fread(buf, sizeof(char), len, f1))) {
	fwrite(buf, sizeof(char), size, f2);
    }

    fclose(f1);
    fclose(f2);
    return v8::Boolean::New(true);
}
v8::Handle<v8::Value> _movefile(const v8::Arguments& args) {
    v8::HandleScope handle_scope;

    if (args.Length() < 1) {
	return v8::ThrowException(v8::String::New("Bad argument count. Use 'file.rename(newname)'"));
    }

    v8::String::Utf8Value name(args.This()->GetInternalField(0));
    v8::String::Utf8Value newname(args[0]);

    int renres = rename(*name, *newname);

    if (renres != 0) {
	v8::Handle<v8::Value> result = _copy(*name, *newname);
	if (result->IsTrue()) {
	    remove(*name);
	} else {
	    return result;
	}
    }

    args.This()->SetInternalField(0, args[0]);
    return args.This();
}

v8::Handle<v8::Value> _copyfile(const v8::Arguments & args) {
    v8::HandleScope handle_scope;
    if (args.Length() < 1) {
	return v8::ThrowException(v8::String::New("Bad argument count. Use 'file.copy(newname)'"));
    }

    v8::String::Utf8Value name(args.This()->GetInternalField(0));
    v8::String::Utf8Value newname(args[0]);

    v8::Handle<v8::Value> result = _copy(*name, *newname);
    if (result->IsTrue()) {
	return _file(args);
    } else {
	return result;
    }
}

v8::Handle<v8::Value> _tostring(const v8::Arguments& args) {
    v8::HandleScope handle_scope;
    return args.This()->GetInternalField(0);
}

v8::Handle<v8::Value> _exists(const v8::Arguments& args) {
    v8::HandleScope handle_scope;
    v8::String::Utf8Value name(args.This()->GetInternalField(0));
    int result = access(*name, F_OK);
    return v8::Boolean::New(result == 0);
}

void SetupIo(v8::Handle<v8::Object> target) {
  v8::HandleScope handle_scope;

  v8::Handle<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(_file);
  ft->SetClassName(v8::String::New("File"));
  v8::Handle<v8::ObjectTemplate> ot = ft->InstanceTemplate();
  ot->SetInternalFieldCount(4); /* filename, handle, size, position */

  v8::Handle<v8::ObjectTemplate> pt = ft->PrototypeTemplate();
  pt->Set("open", v8::FunctionTemplate::New(_open));
  pt->Set("read", v8::FunctionTemplate::New(_read));
  pt->Set("rewind", v8::FunctionTemplate::New(_rewind));
  pt->Set("close", v8::FunctionTemplate::New(_close));
  pt->Set("write", v8::FunctionTemplate::New(_write));
  pt->Set("remove", v8::FunctionTemplate::New(_remove));
  pt->Set("getSize", v8::FunctionTemplate::New(_getsize));
  pt->Set("toString", v8::FunctionTemplate::New(_tostring));
  pt->Set("exists", v8::FunctionTemplate::New(_exists));
  pt->Set("move", v8::FunctionTemplate::New(_movefile));
  pt->Set("copy", v8::FunctionTemplate::New(_copyfile));

  target->Set(v8::String::New("File"), ft->GetFunction());

  ft = v8::FunctionTemplate::New(_directory);
  ft->SetClassName(v8::String::New("Directory"));
  ot = ft->InstanceTemplate();
  ot->SetInternalFieldCount(1); /* dirname */

  pt = ft->PrototypeTemplate();
  pt->Set("create", v8::FunctionTemplate::New(_create));
  pt->Set("listFiles", v8::FunctionTemplate::New(_listfiles));
  pt->Set("listDirectories", v8::FunctionTemplate::New(_listdirectories));
  pt->Set("toString", v8::FunctionTemplate::New(_tostring));
  pt->Set("exists", v8::FunctionTemplate::New(_exists));
  pt->Set("remove", v8::FunctionTemplate::New(_remove));

  target->Set(v8::String::New("Directory"), ft->GetFunction());

}
<commit_msg>Bugfix in file copy behavior<commit_after>#include <v8.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <common.h>
#include <dirent.h>
#include <string.h>
#include <unistd.h>

v8::Handle<v8::FunctionTemplate> ft;

v8::Handle<v8::Value> _directory(const v8::Arguments& args) {
    v8::HandleScope handle_scope;
    if (args.Length() < 1 || args.This()->InternalFieldCount() == 0) {
	return v8::ThrowException(v8::String::New("Invalid call format. Use 'new Directory(name)'"));
    }

    args.This()->SetInternalField(0, args[0]);
    return args.This();
}

v8::Handle<v8::Value> _create(const v8::Arguments& args) {
    v8::HandleScope handle_scope;

    v8::String::Utf8Value name(args.This()->GetInternalField(0));
    int mode;
    if (args.Length() == 0) {
	mode = 0777;
    } else {
	mode = args[0]->Int32Value();
    }

    int result = mkdir(*name, mode);
    if (result != 0) {
	return v8::ThrowException(v8::String::New("Cannot create directory'"));
    }

    return args.This();
}

v8::Handle<v8::Value> _listfiles(const v8::Arguments& args) {
    v8::HandleScope handle_scope;
    v8::String::Utf8Value name(args.This()->GetInternalField(0));

    DIR * dp;
    struct dirent * ep;

    v8::Handle<v8::Array> result = v8::Array::New();

    dp = opendir(*name);
    if (dp == NULL) { return v8::ThrowException(v8::String::New("Directory cannot be opened")); }
    int cnt = 0;
    while ((ep = readdir(dp))) {
	if (ep->d_type == DT_REG) {
	    result->Set(v8::Integer::New(cnt++), v8::String::New(ep->d_name));
	}
    }
    closedir(dp);
    return result;
}

v8::Handle<v8::Value> _listdirectories(const v8::Arguments& args) {
    v8::HandleScope handle_scope;
    v8::String::Utf8Value name(args.This()->GetInternalField(0));

    DIR * dp;
    struct dirent * ep;

    v8::Handle<v8::Array> result = v8::Array::New();

    dp = opendir(*name);
    if (dp == NULL) { return v8::ThrowException(v8::String::New("Directory cannot be opened")); }
    int cnt = 0;
    while ((ep = readdir(dp))) {
	if (ep->d_type == DT_DIR) {
	    if (strcmp(ep->d_name, ".") != 0 && strcmp(ep->d_name, "..") != 0) {
		result->Set(v8::Integer::New(cnt++), v8::String::New(ep->d_name));
	    }
	}
    }
    closedir(dp);
    return result;
}

v8::Handle<v8::Value> _file(const v8::Arguments& args) {
    v8::HandleScope handle_scope;
    if (args.Length() < 1 || args.This()->InternalFieldCount() == 0) {
	return v8::ThrowException(v8::String::New("Invalid call format. Use 'new File(name)'"));
    }

    args.This()->SetInternalField(0, args[0]);
    args.This()->SetInternalField(1, v8::Boolean::New(false));
    return args.This();
}

v8::Handle<v8::Value> _open(const v8::Arguments& args) {
    v8::HandleScope handle_scope;
    if (args.Length() < 1) {
	return v8::ThrowException(v8::String::New("Bad argument count. Use 'file.open(mode)'"));
    }
    v8::String::Utf8Value mode(args[0]);
    v8::String::Utf8Value name(args.This()->GetInternalField(0));
    v8::Handle<v8::Value> file = args.This()->GetInternalField(1);
    if (!file->IsFalse()) {
	return v8::ThrowException(v8::String::New("File already opened"));
    }

    FILE * f;
    f = fopen(*name, *mode);

    if (!f) {
	return v8::ThrowException(v8::String::New("Cannot open file"));
    }

    struct stat st;
    if (stat(*name, &st) == 0) {
	args.This()->SetInternalField(2, v8::Integer::New(st.st_size));
    }
    args.This()->SetInternalField(1, v8::External::New((void *)f));
    args.This()->SetInternalField(3, v8::Integer::New(0));

    return args.This();
}

v8::Handle<v8::Value> _close(const v8::Arguments& args) {
    v8::HandleScope handle_scope;
    v8::Handle<v8::Value> file = args.This()->GetInternalField(1);

    if (file->IsFalse()) {
	return v8::ThrowException(v8::String::New("Cannot close non-opened file"));
    }

    FILE * f = reinterpret_cast<FILE *>(v8::Handle<v8::External>::Cast(file)->Value());
    fclose(f);
    args.This()->SetInternalField(1, v8::Boolean::New(false));
    return args.This();
}

v8::Handle<v8::Value> _read(const v8::Arguments& args) {
    v8::HandleScope handle_scope;
    v8::Handle<v8::Value> file = args.This()->GetInternalField(1);

    if (file->IsFalse()) {
	return v8::ThrowException(v8::String::New("File must be opened before reading"));
    }

    long size = args.This()->GetInternalField(2)->IntegerValue();
    long pos = args.This()->GetInternalField(3)->IntegerValue();

    FILE * f = reinterpret_cast<FILE *>(v8::Handle<v8::External>::Cast(file)->Value());

    long avail = size-pos;
    if (!avail) { return v8::Boolean::New(false); }

    if (args.Length() && args[0]->IsNumber()) {
        int len = args[0]->IntegerValue();
	if (len < avail) { avail = len; }
    }
    char buf[avail];
    fread(buf, sizeof(char), avail, f);
    pos += avail;

    args.This()->SetInternalField(3, v8::Integer::New(pos));

   if (args.Length() > 1 && args[1]->IsTrue()) {
       return char2array(buf, avail);
   } else {
       return char2string(buf, avail);
    }
}

v8::Handle<v8::Value> _rewind(const v8::Arguments& args) {
    v8::HandleScope handle_scope;
    v8::Handle<v8::Value> file = args.This()->GetInternalField(1);
    if (file->IsFalse()) {
	return v8::ThrowException(v8::String::New("File must be opened before rewinding"));
    }

    FILE * f = reinterpret_cast<FILE *>(v8::Handle<v8::External>::Cast(file)->Value());
    rewind(f);

    args.This()->SetInternalField(3, v8::Integer::New(0));
    return args.This();
}

v8::Handle<v8::Value> _write(const v8::Arguments& args) {
    v8::HandleScope handle_scope;
    v8::Handle<v8::Value> file = args.This()->GetInternalField(1);

    if (file->IsFalse()) {
	return v8::ThrowException(v8::String::New("File must be opened before writing"));
    }

    FILE * f = reinterpret_cast<FILE *>(v8::Handle<v8::External>::Cast(file)->Value());

    if (args[0]->IsArray()) {
	v8::Handle<v8::Array> arr = v8::Handle<v8::Array>::Cast(args[0]);
	int len = arr->Length();

	int max = 4096;
	int current = 0;
	char buf[max];
	for (int i=0;i<len;i++) {
    	    v8::Handle<v8::Integer> a = v8::Integer::New(arr->Get(v8::Integer::New(i))->IntegerValue());
	    buf[current++] = (char) a->Int32Value();
	    if (current == max) {
    		fwrite(buf, sizeof(char), current, f);
		current = 0;
	    }
	}
	if (current) { fwrite(buf, sizeof(char), current, f); }

    } else {
	v8::String::Utf8Value data(args[0]);

	fwrite(*data, sizeof(char), args[0]->ToString()->Utf8Length(), f);
    }

    return args.This();
}

v8::Handle<v8::Value> _remove(const v8::Arguments& args) {
    v8::HandleScope handle_scope;
    v8::String::Utf8Value name(args.This()->GetInternalField(0));

    if (remove(*name) != 0) {
	return v8::ThrowException(v8::String::New("Cannot remove file/dir"));
    }

    return args.This();
}

v8::Handle<v8::Value> _getsize(const v8::Arguments& args) {
    v8::HandleScope handle_scope;

    v8::String::Utf8Value name(args.This()->GetInternalField(0));
    struct stat st;
    if (stat(*name, &st) == 0) {
	return v8::Integer::New(st.st_size);
    } else {
	return v8::Boolean::New(false);
    }
}

v8::Handle<v8::Value> _copy(char * name1, char * name2) {
    int len = 1024;
    char buf[len];

    FILE * f1 = fopen(name1, "rb");
    FILE * f2 = fopen(name2, "wb");

    if (f1 == NULL) { return v8::ThrowException(v8::String::New("Cannot open source file")); }
    if (f2 == NULL) { return v8::ThrowException(v8::String::New("Cannot open target file")); }

    int size = 0;

    while ((size = fread(buf, sizeof(char), len, f1))) {
	fwrite(buf, sizeof(char), size, f2);
    }

    fclose(f1);
    fclose(f2);
    return v8::Boolean::New(true);
}
v8::Handle<v8::Value> _movefile(const v8::Arguments& args) {
    v8::HandleScope handle_scope;

    if (args.Length() < 1) {
	return v8::ThrowException(v8::String::New("Bad argument count. Use 'file.rename(newname)'"));
    }

    v8::String::Utf8Value name(args.This()->GetInternalField(0));
    v8::String::Utf8Value newname(args[0]);

    int renres = rename(*name, *newname);

    if (renres != 0) {
	v8::Handle<v8::Value> result = _copy(*name, *newname);
	if (result->IsTrue()) {
	    remove(*name);
	} else {
	    return result;
	}
    }

    args.This()->SetInternalField(0, args[0]);
    return args.This();
}

v8::Handle<v8::Value> _copyfile(const v8::Arguments & args) {
    v8::HandleScope handle_scope;
    if (args.Length() < 1) {
	return v8::ThrowException(v8::String::New("Bad argument count. Use 'file.copy(newname)'"));
    }

    v8::String::Utf8Value name(args.This()->GetInternalField(0));
    v8::String::Utf8Value newname(args[0]);

    v8::Handle<v8::Value> result = _copy(*name, *newname);
    if (result->IsTrue()) {
	v8::Handle<v8::Value> fargs[] = { args[0] };
    	return ft->GetFunction()->NewInstance(1, fargs);
    } else {
	return result;
    }
}

v8::Handle<v8::Value> _tostring(const v8::Arguments& args) {
    v8::HandleScope handle_scope;
    return args.This()->GetInternalField(0);
}

v8::Handle<v8::Value> _exists(const v8::Arguments& args) {
    v8::HandleScope handle_scope;
    v8::String::Utf8Value name(args.This()->GetInternalField(0));
    int result = access(*name, F_OK);
    return v8::Boolean::New(result == 0);
}

void SetupIo(v8::Handle<v8::Object> target) {

  ft = v8::FunctionTemplate::New(_file);
  ft->SetClassName(v8::String::New("File"));
  v8::Handle<v8::ObjectTemplate> ot = ft->InstanceTemplate();
  ot->SetInternalFieldCount(4); /* filename, handle, size, position */

  v8::Handle<v8::ObjectTemplate> pt = ft->PrototypeTemplate();
  pt->Set("open", v8::FunctionTemplate::New(_open));
  pt->Set("read", v8::FunctionTemplate::New(_read));
  pt->Set("rewind", v8::FunctionTemplate::New(_rewind));
  pt->Set("close", v8::FunctionTemplate::New(_close));
  pt->Set("write", v8::FunctionTemplate::New(_write));
  pt->Set("remove", v8::FunctionTemplate::New(_remove));
  pt->Set("getSize", v8::FunctionTemplate::New(_getsize));
  pt->Set("toString", v8::FunctionTemplate::New(_tostring));
  pt->Set("exists", v8::FunctionTemplate::New(_exists));
  pt->Set("move", v8::FunctionTemplate::New(_movefile));
  pt->Set("copy", v8::FunctionTemplate::New(_copyfile));

  target->Set(v8::String::New("File"), ft->GetFunction());

  ft = v8::FunctionTemplate::New(_directory);
  ft->SetClassName(v8::String::New("Directory"));
  ot = ft->InstanceTemplate();
  ot->SetInternalFieldCount(1); /* dirname */

  pt = ft->PrototypeTemplate();
  pt->Set("create", v8::FunctionTemplate::New(_create));
  pt->Set("listFiles", v8::FunctionTemplate::New(_listfiles));
  pt->Set("listDirectories", v8::FunctionTemplate::New(_listdirectories));
  pt->Set("toString", v8::FunctionTemplate::New(_tostring));
  pt->Set("exists", v8::FunctionTemplate::New(_exists));
  pt->Set("remove", v8::FunctionTemplate::New(_remove));

  target->Set(v8::String::New("Directory"), ft->GetFunction());

}
<|endoftext|>


<commit_before>#include "style.h"
#include "document.h"
#include "element.h"
#include "composite_element.h"
#include "helpers.h"
#include "attribute.h"
#include <iostream>
#include <sstream>
#include <map>
#include <string>
#include <vector>
#include <algorithm>

#define XSL_NS "xsl"
#define XSL_TEMPLATES "template"
#define XSL_APPLY_TEMPLATES "apply-templates"
#define XSL_MATCH "match"
#define XSL_ROOT_MATCH "/"

namespace Xsl
{
  typedef ::Document XMLDocument;

  bool is_element(Element const &, std::string const & = "");

  class Document
  {
    public:
      Document(XMLDocument const &);

      void apply_style_to(XMLDocument const &, std::ostream &) const;

    private:
      void handle_e(Element const &, Element const &, std::ostream &) const;
      void handle_ce(CompositeElement const &, Element const &, std::ostream &) const;
      void handle_xsl(Element const &, Element const &, std::ostream &) const;

      std::multimap<std::string, Element const *> _absolute_path_templates;
      std::multimap<std::string, Element const *> _relative_path_templates;
  };

  // Implementation

  bool is_element(Element const & element, std::string const & tag)
  {
    auto ns_split = element.ns_split();

    // F**king lower() method
    std::transform(ns_split.first.begin(), ns_split.first.end(),
        ns_split.first.begin(), ::tolower);
    std::transform(ns_split.second.begin(), ns_split.second.end(),
        ns_split.second.begin(), ::tolower);

    // Only xsl namespace
    return ns_split.first == XSL_NS && (tag.empty() || ns_split.second == tag);
  }

  Document::Document(XMLDocument const & doc):
    _absolute_path_templates(),
    _relative_path_templates()
  {
    for (auto child : doc.root()->children())
    {
      Element * element = dynamic_cast<Element *>(child);
      if (element != nullptr && is_element(*element, XSL_TEMPLATES))
      {
        for (auto attr : element->attributes())
        {
          if (attr->name() == XSL_MATCH && !attr->value().empty())
          {
            ((Helpers::trim(Helpers::split(attr->value(), '/')[0]).empty())
              ? _absolute_path_templates
              : _relative_path_templates
            ).insert({ attr->value(), { element } });

            break; // because f**k you that's why !
          }
        }
      }
    }
  }

  void Document::apply_style_to(XMLDocument const & xml, std::ostream & os) const
  {
    auto range = _absolute_path_templates.equal_range("/");
    for (auto it = range.first; it != range.second; it++)
    {
      if (it != _absolute_path_templates.end())
      {
        auto ce = dynamic_cast<CompositeElement const *>(it->second);
        handle_ce(*ce, *xml.root(), os);
      }
      else
      {
        // TODO handle when to "/" template is given
      }
    }
  }

  void Document::handle_e(Element const & template_element,
      Element const & root_element, std::ostream & os) const
  {
    if (is_element(template_element))
    {
      handle_xsl(template_element, root_element, os);
    }
    else
    {
      auto ce = dynamic_cast<CompositeElement const *>(&template_element);
      if (ce == nullptr)
      {
        os << template_element.str() << std::endl;
      }
      else
      {
        os << ce->begin_str() << std::endl;
        handle_ce(*ce, root_element, os);
        os << ce->end_str() << std::endl;
      }
    }
  }

  void Document::handle_ce(CompositeElement const & template_element,
      Element const & root_element, std::ostream & os) const
  {
    for (auto child : template_element.children())
    {
      auto child_element = dynamic_cast<Element const *>(child);
      if (child_element == nullptr)
      {
        os << child->str() << std::endl;
      }
      else
      {
        handle_e(*child_element, root_element, os);
      }
    }
  }

  void Document::handle_xsl(Element const & template_element,
      Element const & element, std::ostream & os) const
  {
    os << template_element.str()<< std::endl;
  }
}

void xml_apply_style(Document const & xml, Document const & xsl, std::ostream & os)
{
  Xsl::Document xsl_doc(xsl); // FIXME check for xsl:stylesheet root element
  xsl_doc.apply_style_to(xml, os);
}

// vim:ft=cpp et sw=2 sts=2:
<commit_msg>Remove multimap<commit_after>#include "style.h"
#include "document.h"
#include "element.h"
#include "composite_element.h"
#include "helpers.h"
#include "attribute.h"
#include <iostream>
#include <sstream>
#include <map>
#include <string>
#include <vector>
#include <algorithm>

#define XSL_NS "xsl"
#define XSL_TEMPLATES "template"
#define XSL_APPLY_TEMPLATES "apply-templates"
#define XSL_MATCH "match"
#define XSL_ROOT_MATCH "/"

namespace Xsl
{
  typedef ::Document XMLDocument;

  bool is_element(Element const &, std::string const & = "");

  class Document
  {
    public:
      Document(XMLDocument const &);

      void apply_style_to(XMLDocument const &, std::ostream &) const;

    private:
      void handle_e(Element const &, Element const &, std::ostream &) const;
      void handle_ce(CompositeElement const &, Element const &, std::ostream &) const;
      void handle_xsl(Element const &, Element const &, std::ostream &) const;

      std::map<std::string, Element const *> _absolute_path_templates;
      std::map<std::string, Element const *> _relative_path_templates;
  };

  // Implementation

  bool is_element(Element const & element, std::string const & tag)
  {
    auto ns_split = element.ns_split();

    // F**king lower() method
    std::transform(ns_split.first.begin(), ns_split.first.end(),
        ns_split.first.begin(), ::tolower);
    std::transform(ns_split.second.begin(), ns_split.second.end(),
        ns_split.second.begin(), ::tolower);

    // Only xsl namespace
    return ns_split.first == XSL_NS && (tag.empty() || ns_split.second == tag);
  }

  Document::Document(XMLDocument const & doc):
    _absolute_path_templates(),
    _relative_path_templates()
  {
    for (auto child : doc.root()->children())
    {
      Element * element = dynamic_cast<Element *>(child);
      if (element != nullptr && is_element(*element, XSL_TEMPLATES))
      {
        for (auto attr : element->attributes())
        {
          if (attr->name() == XSL_MATCH && !attr->value().empty())
          {
            ((Helpers::trim(Helpers::split(attr->value(), '/')[0]).empty())
              ? _absolute_path_templates
              : _relative_path_templates
            )[attr->value()] = { element };

            break; // because f**k you that's why !
          }
        }
      }
    }
  }

  void Document::apply_style_to(XMLDocument const & xml, std::ostream & os) const
  {
    auto it = _absolute_path_templates.find("/");
    if (it != _absolute_path_templates.end())
    {
      auto ce = dynamic_cast<CompositeElement const *>(it->second);
      handle_ce(*ce, *xml.root(), os);
    }
    else
    {
      // TODO handle when no "/" template is given
    }
  }

  void Document::handle_e(Element const & template_element,
      Element const & root_element, std::ostream & os) const
  {
    if (is_element(template_element))
    {
      handle_xsl(template_element, root_element, os);
    }
    else
    {
      auto ce = dynamic_cast<CompositeElement const *>(&template_element);
      if (ce == nullptr)
      {
        os << template_element.str() << std::endl;
      }
      else
      {
        os << ce->begin_str() << std::endl;
        handle_ce(*ce, root_element, os);
        os << ce->end_str() << std::endl;
      }
    }
  }

  void Document::handle_ce(CompositeElement const & template_element,
      Element const & root_element, std::ostream & os) const
  {
    for (auto child : template_element.children())
    {
      auto child_element = dynamic_cast<Element const *>(child);
      if (child_element == nullptr)
      {
        os << child->str() << std::endl;
      }
      else
      {
        handle_e(*child_element, root_element, os);
      }
    }
  }

  void Document::handle_xsl(Element const & template_element,
      Element const & element, std::ostream & os) const
  {
    os << template_element.str()<< std::endl;
  }
}

void xml_apply_style(Document const & xml, Document const & xsl, std::ostream & os)
{
  Xsl::Document xsl_doc(xsl); // FIXME check for xsl:stylesheet root element
  xsl_doc.apply_style_to(xml, os);
}

// vim:ft=cpp et sw=2 sts=2:
<|endoftext|>


<commit_before>// Copyright (c) 2018 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#include "gtest/gtest.h"
#include <Utils/ResponseUtils.h>
#include <Utils/TestUtils.h>

#include <hspp/Tasks/BasicTasks/CombatTask.h>
#include <hspp/Tasks/BasicTasks/InitAttackCountTask.h>

using namespace Hearthstonepp;

class CombatTester
{
 public:
    CombatTester()
        : m_gen(CardClass::DRUID, CardClass::ROGUE),
          m_agent(std::move(m_gen.player1), std::move(m_gen.player2)),
          m_resp(m_agent),
          m_combat(m_agent.GetTaskAgent())
    {
        // Do Nothing
    }

    std::tuple<Player&, Player&> GetPlayer()
    {
        return { m_agent.GetPlayer1(), m_agent.GetPlayer2() };
    }

    void Attack(size_t src, size_t dst, MetaData expected, bool init = false)
    {
        if (init)
        {
            m_init.Run(m_agent.GetPlayer1(), m_agent.GetPlayer2());
            m_init.Run(m_agent.GetPlayer2(), m_agent.GetPlayer1());
        }
        auto target = m_resp.Target(src, dst);
        MetaData result =
            m_combat.Run(m_agent.GetPlayer1(), m_agent.GetPlayer2());
        EXPECT_EQ(result, expected);

        TaskMeta meta = target.get();
        EXPECT_EQ(meta.id, +TaskID::REQUIRE);
    }

 private:
    TestUtils::PlayerGenerator m_gen;

    GameAgent m_agent;
    TestUtils::AutoResponder m_resp;

    BasicTasks::CombatTask m_combat;
    BasicTasks::InitAttackCountTask m_init;
};

TEST(CombatTask, GetTaskID)
{
    TaskAgent agent;
    BasicTasks::CombatTask combat(agent);
    EXPECT_EQ(combat.GetTaskID(), +TaskID::COMBAT);
}

TEST(CombatTask, Default)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();

    auto card1 = TestUtils::GenerateMinionCard("minion1", 3, 6);
    auto card2 = TestUtils::GenerateMinionCard("minion2", 5, 4);

    player1.field.emplace_back(new Minion(card1));
    player2.field.emplace_back(new Minion(card2));

    tester.Attack(1, 0, MetaData::COMBAT_SUCCESS, true);
    EXPECT_EQ(player1.field[0]->health, player1.field[0]->maxHealth);
    EXPECT_EQ(player2.hero->health,
              player2.hero->maxHealth - player1.field[0]->attack);

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    EXPECT_EQ(player1.field[0]->health, static_cast<size_t>(1));
    EXPECT_EQ(player2.field[0]->health, static_cast<size_t>(1));

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    EXPECT_EQ(player1.field.size(), static_cast<size_t>(0));
    EXPECT_EQ(player2.field.size(), static_cast<size_t>(0));

    auto card3 = TestUtils::GenerateMinionCard("minion3", 5, 6);
    auto card4 = TestUtils::GenerateMinionCard("minion4", 5, 4);

    player1.field.emplace_back(new Minion(card3));
    player2.field.emplace_back(new Minion(card4));

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    EXPECT_EQ(player1.field[0]->health, static_cast<size_t>(1));
    EXPECT_EQ(player2.field.size(), static_cast<size_t>(0));

    auto card5 = TestUtils::GenerateMinionCard("minion5", 5, 4);

    player1.field[0]->attack = 1;
    player2.field.emplace_back(new Minion(card5));

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    EXPECT_EQ(player1.field.size(), static_cast<size_t>(0));
    EXPECT_EQ(player2.field[0]->health, static_cast<size_t>(3));
}

TEST(CombatTask, IndexOutOfRange)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion1", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    tester.Attack(1, 2, MetaData::COMBAT_DST_IDX_OUT_OF_RANGE, true);
    tester.Attack(2, 1, MetaData::COMBAT_SRC_IDX_OUT_OF_RANGE, true);
}

TEST(CombatTask, Charge)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion1", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    player1.field[0]->SetAbility(GameTag::CHARGE, true);
    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, false);

    player1.field[0]->SetAbility(GameTag::CHARGE, false);
    tester.Attack(1, 1, MetaData::COMBAT_ALREADY_ATTACKED, false);
}

TEST(CombatTask, Taunt)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion1", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    player2.field[1]->SetAbility(GameTag::TAUNT, true);
    tester.Attack(1, 1, MetaData::COMBAT_FIELD_HAVE_TAUNT, true);

    player2.field[1]->SetAbility(GameTag::TAUNT, false);
    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
}

TEST(CombatTask, Stealth)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    player2.field[0]->SetAbility(GameTag::STEALTH, true);

    tester.Attack(1, 1, MetaData::COMBAT_TARGET_STEALTH, true);

    player1.field[0]->SetAbility(GameTag::STEALTH, true);
    player2.field[0]->SetAbility(GameTag::STEALTH, false);

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    EXPECT_EQ(player1.field[0]->gameTags[+GameTag::STEALTH], 0);
}

TEST(CombatTask, Immune)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    player2.field[0]->SetAbility(GameTag::IMMUNE, true);

    tester.Attack(1, 1, MetaData::COMBAT_TARGET_IMMUNE, true);
}

TEST(CombatTask, Windfury)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    tester.Attack(1, 1, MetaData::COMBAT_ALREADY_ATTACKED);

    player1.field[0]->SetAbility(GameTag::WINDFURY, true);

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS);
    tester.Attack(1, 1, MetaData::COMBAT_ALREADY_ATTACKED);
}

TEST(CombatTask, DivineShield)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    player1.field[0]->SetAbility(GameTag::DIVINE_SHIELD, true);
    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);

    EXPECT_EQ(player1.field[0]->health, player1.field[0]->maxHealth);
    EXPECT_EQ(player2.field[0]->health, static_cast<size_t>(9));

    player2.field[0]->SetAbility(GameTag::DIVINE_SHIELD, true);
    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);

    EXPECT_EQ(player1.field[0]->health, static_cast<size_t>(9));
    EXPECT_EQ(player2.field[0]->health, static_cast<size_t>(9));
}

TEST(CombatTask, Poisonous)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    player1.field[0]->SetAbility(GameTag::POISONOUS, true);
    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);

    EXPECT_EQ(player1.field[0]->health, static_cast<size_t>(9));
    EXPECT_EQ(player2.field.size(), static_cast<size_t>(0));

    player2.field.emplace_back(new Minion(card));

    player1.field[0]->SetAbility(GameTag::POISONOUS, false);
    player2.field[0]->SetAbility(GameTag::POISONOUS, true);

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    EXPECT_EQ(player1.field.size(), static_cast<size_t>(0));
    EXPECT_EQ(player2.field[0]->health, static_cast<size_t>(9));
}
<commit_msg>test: Add unit test to freeze ability<commit_after>// Copyright (c) 2018 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#include "gtest/gtest.h"
#include <Utils/ResponseUtils.h>
#include <Utils/TestUtils.h>

#include <hspp/Tasks/BasicTasks/CombatTask.h>
#include <hspp/Tasks/BasicTasks/InitAttackCountTask.h>

using namespace Hearthstonepp;

class CombatTester
{
 public:
    CombatTester()
        : m_gen(CardClass::DRUID, CardClass::ROGUE),
          m_agent(std::move(m_gen.player1), std::move(m_gen.player2)),
          m_resp(m_agent),
          m_combat(m_agent.GetTaskAgent())
    {
        // Do Nothing
    }

    std::tuple<Player&, Player&> GetPlayer()
    {
        return { m_agent.GetPlayer1(), m_agent.GetPlayer2() };
    }

    void Attack(size_t src, size_t dst, MetaData expected, bool init = false)
    {
        if (init)
        {
            m_init.Run(m_agent.GetPlayer1(), m_agent.GetPlayer2());
            m_init.Run(m_agent.GetPlayer2(), m_agent.GetPlayer1());
        }
        auto target = m_resp.Target(src, dst);
        MetaData result =
            m_combat.Run(m_agent.GetPlayer1(), m_agent.GetPlayer2());
        EXPECT_EQ(result, expected);

        TaskMeta meta = target.get();
        EXPECT_EQ(meta.id, +TaskID::REQUIRE);
    }

    void ReverseAttack(size_t src, size_t dst, MetaData expected,
                       bool init = false)
    {
        if (init)
        {
            m_init.Run(m_agent.GetPlayer2(), m_agent.GetPlayer1());
            m_init.Run(m_agent.GetPlayer1(), m_agent.GetPlayer2());
        }
        auto target = m_resp.Target(src, dst);
        MetaData result =
            m_combat.Run(m_agent.GetPlayer2(), m_agent.GetPlayer1());
        EXPECT_EQ(result, expected);

        TaskMeta meta = target.get();
        EXPECT_EQ(meta.id, +TaskID::REQUIRE);
    }

 private:
    TestUtils::PlayerGenerator m_gen;

    GameAgent m_agent;
    TestUtils::AutoResponder m_resp;

    BasicTasks::CombatTask m_combat;
    BasicTasks::InitAttackCountTask m_init;
};

TEST(CombatTask, GetTaskID)
{
    TaskAgent agent;
    BasicTasks::CombatTask combat(agent);
    EXPECT_EQ(combat.GetTaskID(), +TaskID::COMBAT);
}

TEST(CombatTask, Default)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();

    auto card1 = TestUtils::GenerateMinionCard("minion1", 3, 6);
    auto card2 = TestUtils::GenerateMinionCard("minion2", 5, 4);

    player1.field.emplace_back(new Minion(card1));
    player2.field.emplace_back(new Minion(card2));

    tester.Attack(1, 0, MetaData::COMBAT_SUCCESS, true);
    EXPECT_EQ(player1.field[0]->health, player1.field[0]->maxHealth);
    EXPECT_EQ(player2.hero->health,
              player2.hero->maxHealth - player1.field[0]->attack);

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    EXPECT_EQ(player1.field[0]->health, static_cast<size_t>(1));
    EXPECT_EQ(player2.field[0]->health, static_cast<size_t>(1));

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    EXPECT_EQ(player1.field.size(), static_cast<size_t>(0));
    EXPECT_EQ(player2.field.size(), static_cast<size_t>(0));

    auto card3 = TestUtils::GenerateMinionCard("minion3", 5, 6);
    auto card4 = TestUtils::GenerateMinionCard("minion4", 5, 4);

    player1.field.emplace_back(new Minion(card3));
    player2.field.emplace_back(new Minion(card4));

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    EXPECT_EQ(player1.field[0]->health, static_cast<size_t>(1));
    EXPECT_EQ(player2.field.size(), static_cast<size_t>(0));

    auto card5 = TestUtils::GenerateMinionCard("minion5", 5, 4);

    player1.field[0]->attack = 1;
    player2.field.emplace_back(new Minion(card5));

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    EXPECT_EQ(player1.field.size(), static_cast<size_t>(0));
    EXPECT_EQ(player2.field[0]->health, static_cast<size_t>(3));
}

TEST(CombatTask, IndexOutOfRange)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion1", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    tester.Attack(1, 2, MetaData::COMBAT_DST_IDX_OUT_OF_RANGE, true);
    tester.Attack(2, 1, MetaData::COMBAT_SRC_IDX_OUT_OF_RANGE, true);
}

TEST(CombatTask, Charge)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion1", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    player1.field[0]->SetAbility(GameTag::CHARGE, true);
    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, false);

    player1.field[0]->SetAbility(GameTag::CHARGE, false);
    tester.Attack(1, 1, MetaData::COMBAT_ALREADY_ATTACKED, false);
}

TEST(CombatTask, Taunt)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion1", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    player2.field[1]->SetAbility(GameTag::TAUNT, true);
    tester.Attack(1, 1, MetaData::COMBAT_FIELD_HAVE_TAUNT, true);

    player2.field[1]->SetAbility(GameTag::TAUNT, false);
    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
}

TEST(CombatTask, Stealth)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    player2.field[0]->SetAbility(GameTag::STEALTH, true);

    tester.Attack(1, 1, MetaData::COMBAT_TARGET_STEALTH, true);

    player1.field[0]->SetAbility(GameTag::STEALTH, true);
    player2.field[0]->SetAbility(GameTag::STEALTH, false);

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    EXPECT_EQ(player1.field[0]->gameTags[+GameTag::STEALTH], 0);
}

TEST(CombatTask, Immune)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    player2.field[0]->SetAbility(GameTag::IMMUNE, true);

    tester.Attack(1, 1, MetaData::COMBAT_TARGET_IMMUNE, true);
}

TEST(CombatTask, Windfury)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    tester.Attack(1, 1, MetaData::COMBAT_ALREADY_ATTACKED);

    player1.field[0]->SetAbility(GameTag::WINDFURY, true);

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS);
    tester.Attack(1, 1, MetaData::COMBAT_ALREADY_ATTACKED);
}

TEST(CombatTask, DivineShield)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    player1.field[0]->SetAbility(GameTag::DIVINE_SHIELD, true);
    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);

    EXPECT_EQ(player1.field[0]->health, player1.field[0]->maxHealth);
    EXPECT_EQ(player2.field[0]->health, static_cast<size_t>(9));

    player2.field[0]->SetAbility(GameTag::DIVINE_SHIELD, true);
    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);

    EXPECT_EQ(player1.field[0]->health, static_cast<size_t>(9));
    EXPECT_EQ(player2.field[0]->health, static_cast<size_t>(9));
}

TEST(CombatTask, Poisonous)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    player1.field[0]->SetAbility(GameTag::POISONOUS, true);
    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);

    EXPECT_EQ(player1.field[0]->health, static_cast<size_t>(9));
    EXPECT_EQ(player2.field.size(), static_cast<size_t>(0));

    player2.field.emplace_back(new Minion(card));

    player1.field[0]->SetAbility(GameTag::POISONOUS, false);
    player2.field[0]->SetAbility(GameTag::POISONOUS, true);

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    EXPECT_EQ(player1.field.size(), static_cast<size_t>(0));
    EXPECT_EQ(player2.field[0]->health, static_cast<size_t>(9));
}

TEST(CombatTask, Freeze)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    player1.field[0]->SetAbility(GameTag::FREEZE, true);
    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    EXPECT_EQ(player2.field[0]->HasAbility(GameTag::FROZEN), true);
    tester.ReverseAttack(1, 1, MetaData::COMBAT_SOURCE_FROZEN, false);

    EXPECT_EQ(player1.field[0]->health, static_cast<size_t>(9));
    EXPECT_EQ(player2.field[0]->health, static_cast<size_t>(9));
}<|endoftext|>


<commit_before>#include "stdafx.h"
#include "OkvisSLAMSystem.h"

namespace ark {

    OkvisSLAMSystem::OkvisSLAMSystem(const std::string & strVocFile, const std::string & strSettingsFile) :
        start_(0.0), t_imu_(0.0), deltaT_(1.0), num_frames_(0), kill(false),
        sparse_map_vector(), active_map_index(-1), new_map_checker(false){

        okvis::VioParametersReader vio_parameters_reader;
        try {
            vio_parameters_reader.readConfigFile(strSettingsFile);
        }
        catch (okvis::VioParametersReader::Exception ex) {
            std::cerr << ex.what() << "\n";
            return;
        }

        //okvis::VioParameters parameters;
        vio_parameters_reader.getParameters(parameters_);

        createNewMap();
        getActiveMap()->setEnableLoopClosure(parameters_.loopClosureParameters.enabled,strVocFile,true, new brisk::BruteForceMatcher());

        //initialize Visual odometry
        okvis_estimator_ = std::make_shared<okvis::ThreadedKFVio>(parameters_);
        okvis_estimator_->setBlocking(true);

        //Okvis's outframe is our inframe
        auto frame_callback = [this](const okvis::Time& timestamp, okvis::OutFrameData::Ptr frame_data) {
            frame_data_queue_.enqueue({ frame_data,timestamp });
        };

        okvis_estimator_->setFrameCallback(frame_callback);

        //at thread to pull from queue and call our own callbacks
        frameConsumerThread_ = std::thread(&OkvisSLAMSystem::FrameConsumerLoop, this);

        frame_data_queue_.clear();
        frame_queue_.clear();
        std::cout << "SLAM Initialized\n";
    }

    void OkvisSLAMSystem::Start() {
        //Do nothing, starts automatically
    }

    void OkvisSLAMSystem::FrameConsumerLoop() {
        while (!kill) {

            //Get processed frame data from OKVIS
            StampedFrameData frame_data;
            while (!frame_data_queue_.try_dequeue(&frame_data)) {
                if (okvis_estimator_->isReset()) {
                    frame_data_queue_.clear();
                    frame_queue_.clear();
                }
                if(okvis_estimator_->isReset() && !new_map_checker)
                {
                    cout<<"Created new map"<<endl;
                    new_map_checker = true;
                    createNewMap();
                }
                else if(!okvis_estimator_->isReset())
                    new_map_checker = false;
                if(kill)
                    return;
                std::this_thread::sleep_for(std::chrono::milliseconds(10));
            }
            //Get the corresponding frame from queue
            WrappedMultiCameraFrame wrapped_frame;
            bool frame_found = false;
            do {
                if (!(frame_found = frame_queue_.try_dequeue(&wrapped_frame))) {
                    break;
                }
            } while (okvis::Time(wrapped_frame.frame->timestamp_) < frame_data.timestamp);
            if (!frame_found){
                std::cout << "ERROR, FRAME NOT FOUND, THIS SHOULDN'T HAPPEN\n";
                continue;
            }

            //construct output frame
            MultiCameraFrame::Ptr out_frame = wrapped_frame.frame;
            out_frame->frameId_ = frame_data.data->id;
            out_frame->T_KS_ = frame_data.data->T_KS.T();
            out_frame->keyframeId_ = frame_data.data->keyframe_id;

            //add sensor transforms
            //Note: this could potentially just be done once for the system
            //Including here for now in case we switch to optimized results
            for (size_t i = 0; i <  wrapped_frame.frame->images_.size(); i++) {
                okvis::kinematics::Transformation T_SC;
                if (i < parameters_.nCameraSystem.numCameras()) {
                    T_SC = (*parameters_.nCameraSystem.T_SC(i));
                }
                else if (i - parameters_.nCameraSystem.numCameras() < parameters_.secondaryCameraSystem.numCameras()) {
                    T_SC = (*parameters_.secondaryCameraSystem.T_SC(i - parameters_.nCameraSystem.numCameras()));
                } else {
                    //no relationship data to imu
                    //TODO: throw errror
                    T_SC = okvis::kinematics::Transformation::Identity();
                }
                out_frame->T_SC_.push_back(T_SC.T());
            }

            //check if keyframe
            if(frame_data.data->is_keyframe){
                if(out_frame->keyframeId_!=out_frame->frameId_){
                    std::cout << "ERROR, KEYFRAME ID INCORRECT, THIS SHOULDN'T HAPPEN\n";
                    continue;
                }
                MapKeyFrame::Ptr keyframe = MapKeyFrame::Ptr(new MapKeyFrame);
                keyframe->frameId_=out_frame->frameId_;
                keyframe->T_WS_ = frame_data.data->T_WS.T();
                keyframe->T_SC_ = out_frame->T_SC_;
                keyframe->timestamp_ = out_frame->timestamp_;
                //copy keypoints and descriptors to output
                keyframe->keypoints_.resize(frame_data.data->keypoints.size());
                keyframe->keypoints3dh_C.resize(frame_data.data->keypoints.size());
                keyframe->descriptors_.resize(frame_data.data->descriptors.size());
                for(size_t cam_idx=0 ; cam_idx<frame_data.data->keypoints.size() ; cam_idx++){
                    keyframe->keypoints_[cam_idx].resize(frame_data.data->keypoints[cam_idx].size());

                    keyframe->keypoints3dh_C[cam_idx].resize(frame_data.data->keypoints[cam_idx].size());
                    //get transform of the camera
                    for(int i=0; i<frame_data.data->keypoints[cam_idx].size(); i++){
                        //copy keypoint
                        keyframe->keypoints_[cam_idx][i] = frame_data.data->keypoints[cam_idx][i];
                        //get estimated 3d position of keypoint in current camera frame
                        cv::Vec3f pt3d = out_frame->images_[2].at<cv::Vec3f>(
                            std::round(keyframe->keypoints_[cam_idx][i].pt.y),
                            std::round(keyframe->keypoints_[cam_idx][i].pt.x));
                        if(pt3d[2] >0)
                            keyframe->keypoints3dh_C[cam_idx][i] = Eigen::Vector4d(pt3d[0],pt3d[1],pt3d[2],1);
                        else
                            keyframe->keypoints3dh_C[cam_idx][i] = Eigen::Vector4d(0,0,0,0);
                    }
                    keyframe->descriptors_[cam_idx]=frame_data.data->descriptors[cam_idx];
                }

                // if(sparseMap_->detectLoopClosure(keyframe))
                // {
                //     cout<<"Found loop with my function"<<endl;
                // }
                // push to map
                for (int i = 0; i < sparse_map_vector.size(); i++) {
                    const auto sparseMap = sparse_map_vector[i];
                    if (sparseMap->detectLoopClosure(keyframe)) {
                        active_map_index = i;
                    }
                }

                if(getActiveMap()->addKeyframe(keyframe)){ //add keyframe returns true if a loop closure was detected
                    for (MapLoopClosureDetectedHandler::const_iterator callback_iter = mMapLoopClosureHandler.begin();
                        callback_iter != mMapLoopClosureHandler.end(); ++callback_iter) {
                        const MapLoopClosureDetectedHandler::value_type& pair = *callback_iter;
                            pair.second();
                    }
                }
            }

            out_frame->keyframe_ = getActiveMap()->getKeyframe(out_frame->keyframeId_);

            //Notify callbacks
            if(frame_data.data->is_keyframe){
                for (MapKeyFrameAvailableHandler::const_iterator callback_iter = mMapKeyFrameAvailableHandler.begin();
                    callback_iter != mMapKeyFrameAvailableHandler.end(); ++callback_iter) {
                    const MapKeyFrameAvailableHandler::value_type& pair = *callback_iter;
                    pair.second(out_frame);
                }
            }

            for (MapFrameAvailableHandler::const_iterator callback_iter = mMapFrameAvailableHandler.begin();
                callback_iter != mMapFrameAvailableHandler.end(); ++callback_iter) {
                const MapFrameAvailableHandler::value_type& pair = *callback_iter;
                pair.second(out_frame);
            }
        }
    }

    /*void OkvisSLAMSystem::PushFrame(const std::vector<cv::Mat>& images, const double &timestamp) {
        if (okvis_estimator_ == nullptr)
            return;
        okvis::Time t_image(timestamp / 1e9);
        if (start_ == okvis::Time(0.0)) {
            start_ = t_image;
        }

        if (t_image - start_ > deltaT_) {
            if(mMapFrameAvailableHandler.size()>0){
                frame_queue_.enqueue({ images,t_image,num_frames_ });
            }
            num_frames_++;
            for (size_t i = 0; i < images.size(); i++) {
                if (i < parameters_.nCameraSystem.numCameras()){
                    //printf("add image: %i\n", i);
                    okvis_estimator_->addImage(t_image, i, images[i]);
                }
            }
        }
    }

    void OkvisSLAMSystem::PushFrame(const cv::Mat image, const double &timestamp) {
        if (okvis_estimator_ == nullptr)
            return;
        okvis::Time t_image(timestamp / 1e9);
        if (start_ == okvis::Time(0.0)) {
            start_ = t_image;
        }

        if (t_image - start_ > deltaT_) {
            std::vector<cv::Mat> images;
            images.push_back(image);
            if(mMapFrameAvailableHandler.size()>0){
                frame_queue_.enqueue({ images,t_image,num_frames_ });
            }
            num_frames_++;
            okvis_estimator_->addImage(t_image, 0, image);
        }
    }*/

    void OkvisSLAMSystem::PushFrame(MultiCameraFrame::Ptr frame){
        if (okvis_estimator_ == nullptr)
            return;
        okvis::Time t_image(frame->timestamp_ / 1e9);
        if (start_ == okvis::Time(0.0)) {
            start_ = t_image;
        }

        if (t_image - start_ > deltaT_) {
            if(mMapFrameAvailableHandler.size()>0){
                frame_queue_.enqueue({ frame});
            }
            num_frames_++;
            for (size_t i = 0; i < frame->images_.size(); i++) {
                if (i < parameters_.nCameraSystem.numCameras()){
                    //printf("add image: %i\n", i);
                    okvis_estimator_->addImage(t_image, i, frame->images_[i]);
                }
            }
        }
    }

    void OkvisSLAMSystem::PushIMU(const std::vector<ImuPair>& imu) {
        if (okvis_estimator_ == nullptr) return;
        for (size_t i = 0; i < imu.size(); i++) {
            PushIMU(imu[i]);
        }
    }

    void OkvisSLAMSystem::PushIMU(const ImuPair& imu) {
        if (okvis_estimator_ == nullptr) return;
        t_imu_ = okvis::Time(imu.timestamp / 1e9);
        if (t_imu_ - start_ + okvis::Duration(1.0) > deltaT_) {
            //std::cout << imu.timestamp / 1e9 << " , " << imu.accel.transpose() << " , " << imu.gyro.transpose() << std::endl;
            okvis_estimator_->addImuMeasurement(t_imu_, imu.accel, imu.gyro);
        }
    }

    void OkvisSLAMSystem::PushIMU(double timestamp, const Eigen::Vector3d& accel, const Eigen::Vector3d gyro) {
        if (okvis_estimator_ == nullptr) return;
        t_imu_ = okvis::Time(timestamp / 1e9);
        if (t_imu_ - start_ + okvis::Duration(1.0) > deltaT_) {
            okvis_estimator_->addImuMeasurement(t_imu_, accel, gyro);
        }
    }

    void OkvisSLAMSystem::createNewMap() {
        sparse_map_vector.push_back(std::make_shared<SparseMap<DBoW2::FBRISK::TDescriptor, DBoW2::FBRISK>>());
        // set it to the latest one
        active_map_index = static_cast<int>(sparse_map_vector.size())-1;
    }

    void OkvisSLAMSystem::display() {
        if (okvis_estimator_ == nullptr)
            return;
        okvis_estimator_->display();
    }

    void OkvisSLAMSystem::ShutDown()
    {
        frame_queue_.clear();
        frame_data_queue_.clear();
        kill=true;
        frameConsumerThread_.join();
        okvis_estimator_.reset();
    }

    OkvisSLAMSystem::~OkvisSLAMSystem() {
        frame_queue_.clear();
        frame_data_queue_.clear();
        kill=true;
    }

    void OkvisSLAMSystem::RequestStop()
    {
        okvis_estimator_ = nullptr;
    }

    bool OkvisSLAMSystem::IsRunning()
    {
        return okvis_estimator_ == nullptr;
    }

    void OkvisSLAMSystem::getTrajectory(std::vector<Eigen::Matrix4d>& trajOut){
        getActiveMap()->getTrajectory(trajOut);
    }

    std::shared_ptr<SparseMap<DBoW2::FBRISK::TDescriptor, DBoW2::FBRISK>> OkvisSLAMSystem:: getActiveMap() {
        if (0 <= active_map_index && active_map_index < sparse_map_vector.size()) {
            return sparse_map_vector[active_map_index];
        } else {
            return nullptr;
        }
    }

} //ark<commit_msg>Refactor remove latency<commit_after>#include "stdafx.h"
#include "OkvisSLAMSystem.h"

namespace ark {

    OkvisSLAMSystem::OkvisSLAMSystem(const std::string & strVocFile, const std::string & strSettingsFile) :
        start_(0.0), t_imu_(0.0), deltaT_(1.0), num_frames_(0), kill(false),
        sparse_map_vector(), active_map_index(-1), new_map_checker(false){

        okvis::VioParametersReader vio_parameters_reader;
        try {
            vio_parameters_reader.readConfigFile(strSettingsFile);
        }
        catch (okvis::VioParametersReader::Exception ex) {
            std::cerr << ex.what() << "\n";
            return;
        }

        //okvis::VioParameters parameters;
        vio_parameters_reader.getParameters(parameters_);

        createNewMap();
        getActiveMap()->setEnableLoopClosure(parameters_.loopClosureParameters.enabled,strVocFile,true, new brisk::BruteForceMatcher());

        //initialize Visual odometry
        okvis_estimator_ = std::make_shared<okvis::ThreadedKFVio>(parameters_);
        okvis_estimator_->setBlocking(true);

        //Okvis's outframe is our inframe
        auto frame_callback = [this](const okvis::Time& timestamp, okvis::OutFrameData::Ptr frame_data) {
            frame_data_queue_.enqueue({ frame_data,timestamp });
        };

        okvis_estimator_->setFrameCallback(frame_callback);

        //at thread to pull from queue and call our own callbacks
        frameConsumerThread_ = std::thread(&OkvisSLAMSystem::FrameConsumerLoop, this);

        frame_data_queue_.clear();
        frame_queue_.clear();
        std::cout << "SLAM Initialized\n";
    }

    void OkvisSLAMSystem::Start() {
        //Do nothing, starts automatically
    }

    void OkvisSLAMSystem::FrameConsumerLoop() {
        while (!kill) {

            //Get processed frame data from OKVIS
            StampedFrameData frame_data;
            while (!frame_data_queue_.try_dequeue(&frame_data)) {
                if (okvis_estimator_->isReset() && !new_map_checker) {
                    cout<<"Created new map"<<endl;
                    new_map_checker = true;
                    createNewMap();
                } else if (!okvis_estimator_->isReset() && new_map_checker) {
                    frame_queue_.clear();
                    new_map_checker = false;
                }
                if(kill)
                    return;
                std::this_thread::sleep_for(std::chrono::milliseconds(10));
            }
            //Get the corresponding frame from queue
            WrappedMultiCameraFrame wrapped_frame;
            bool frame_found = false;
            do {
                if (!(frame_found = frame_queue_.try_dequeue(&wrapped_frame))) {
                    break;
                }
            } while (okvis::Time(wrapped_frame.frame->timestamp_) < frame_data.timestamp);
            if (!frame_found){
                std::cout << "ERROR, FRAME NOT FOUND, THIS SHOULDN'T HAPPEN\n";
                continue;
            }

            //construct output frame
            MultiCameraFrame::Ptr out_frame = wrapped_frame.frame;
            out_frame->frameId_ = frame_data.data->id;
            out_frame->T_KS_ = frame_data.data->T_KS.T();
            out_frame->keyframeId_ = frame_data.data->keyframe_id;

            //add sensor transforms
            //Note: this could potentially just be done once for the system
            //Including here for now in case we switch to optimized results
            for (size_t i = 0; i <  wrapped_frame.frame->images_.size(); i++) {
                okvis::kinematics::Transformation T_SC;
                if (i < parameters_.nCameraSystem.numCameras()) {
                    T_SC = (*parameters_.nCameraSystem.T_SC(i));
                }
                else if (i - parameters_.nCameraSystem.numCameras() < parameters_.secondaryCameraSystem.numCameras()) {
                    T_SC = (*parameters_.secondaryCameraSystem.T_SC(i - parameters_.nCameraSystem.numCameras()));
                } else {
                    //no relationship data to imu
                    //TODO: throw errror
                    T_SC = okvis::kinematics::Transformation::Identity();
                }
                out_frame->T_SC_.push_back(T_SC.T());
            }

            //check if keyframe
            if(frame_data.data->is_keyframe){
                if(out_frame->keyframeId_!=out_frame->frameId_){
                    std::cout << "ERROR, KEYFRAME ID INCORRECT, THIS SHOULDN'T HAPPEN\n";
                    continue;
                }
                MapKeyFrame::Ptr keyframe = MapKeyFrame::Ptr(new MapKeyFrame);
                keyframe->frameId_=out_frame->frameId_;
                keyframe->T_WS_ = frame_data.data->T_WS.T();
                keyframe->T_SC_ = out_frame->T_SC_;
                keyframe->timestamp_ = out_frame->timestamp_;
                //copy keypoints and descriptors to output
                keyframe->keypoints_.resize(frame_data.data->keypoints.size());
                keyframe->keypoints3dh_C.resize(frame_data.data->keypoints.size());
                keyframe->descriptors_.resize(frame_data.data->descriptors.size());
                for(size_t cam_idx=0 ; cam_idx<frame_data.data->keypoints.size() ; cam_idx++){
                    keyframe->keypoints_[cam_idx].resize(frame_data.data->keypoints[cam_idx].size());

                    keyframe->keypoints3dh_C[cam_idx].resize(frame_data.data->keypoints[cam_idx].size());
                    //get transform of the camera
                    for(int i=0; i<frame_data.data->keypoints[cam_idx].size(); i++){
                        //copy keypoint
                        keyframe->keypoints_[cam_idx][i] = frame_data.data->keypoints[cam_idx][i];
                        //get estimated 3d position of keypoint in current camera frame
                        cv::Vec3f pt3d = out_frame->images_[2].at<cv::Vec3f>(
                            std::round(keyframe->keypoints_[cam_idx][i].pt.y),
                            std::round(keyframe->keypoints_[cam_idx][i].pt.x));
                        if(pt3d[2] >0)
                            keyframe->keypoints3dh_C[cam_idx][i] = Eigen::Vector4d(pt3d[0],pt3d[1],pt3d[2],1);
                        else
                            keyframe->keypoints3dh_C[cam_idx][i] = Eigen::Vector4d(0,0,0,0);
                    }
                    keyframe->descriptors_[cam_idx]=frame_data.data->descriptors[cam_idx];
                }

                // if(sparseMap_->detectLoopClosure(keyframe))
                // {
                //     cout<<"Found loop with my function"<<endl;
                // }
                // push to map
                for (int i = 0; i < sparse_map_vector.size(); i++) {
                    const auto sparseMap = sparse_map_vector[i];
                    if (sparseMap->detectLoopClosure(keyframe)) {
                        active_map_index = i;
                    }
                }

                if(getActiveMap()->addKeyframe(keyframe)){ //add keyframe returns true if a loop closure was detected
                    for (MapLoopClosureDetectedHandler::const_iterator callback_iter = mMapLoopClosureHandler.begin();
                        callback_iter != mMapLoopClosureHandler.end(); ++callback_iter) {
                        const MapLoopClosureDetectedHandler::value_type& pair = *callback_iter;
                            pair.second();
                    }
                }
            }

            out_frame->keyframe_ = getActiveMap()->getKeyframe(out_frame->keyframeId_);

            //Notify callbacks
            if(frame_data.data->is_keyframe){
                for (MapKeyFrameAvailableHandler::const_iterator callback_iter = mMapKeyFrameAvailableHandler.begin();
                    callback_iter != mMapKeyFrameAvailableHandler.end(); ++callback_iter) {
                    const MapKeyFrameAvailableHandler::value_type& pair = *callback_iter;
                    pair.second(out_frame);
                }
            }

            for (MapFrameAvailableHandler::const_iterator callback_iter = mMapFrameAvailableHandler.begin();
                callback_iter != mMapFrameAvailableHandler.end(); ++callback_iter) {
                const MapFrameAvailableHandler::value_type& pair = *callback_iter;
                pair.second(out_frame);
            }
        }
    }

    /*void OkvisSLAMSystem::PushFrame(const std::vector<cv::Mat>& images, const double &timestamp) {
        if (okvis_estimator_ == nullptr)
            return;
        okvis::Time t_image(timestamp / 1e9);
        if (start_ == okvis::Time(0.0)) {
            start_ = t_image;
        }

        if (t_image - start_ > deltaT_) {
            if(mMapFrameAvailableHandler.size()>0){
                frame_queue_.enqueue({ images,t_image,num_frames_ });
            }
            num_frames_++;
            for (size_t i = 0; i < images.size(); i++) {
                if (i < parameters_.nCameraSystem.numCameras()){
                    //printf("add image: %i\n", i);
                    okvis_estimator_->addImage(t_image, i, images[i]);
                }
            }
        }
    }

    void OkvisSLAMSystem::PushFrame(const cv::Mat image, const double &timestamp) {
        if (okvis_estimator_ == nullptr)
            return;
        okvis::Time t_image(timestamp / 1e9);
        if (start_ == okvis::Time(0.0)) {
            start_ = t_image;
        }

        if (t_image - start_ > deltaT_) {
            std::vector<cv::Mat> images;
            images.push_back(image);
            if(mMapFrameAvailableHandler.size()>0){
                frame_queue_.enqueue({ images,t_image,num_frames_ });
            }
            num_frames_++;
            okvis_estimator_->addImage(t_image, 0, image);
        }
    }*/

    void OkvisSLAMSystem::PushFrame(MultiCameraFrame::Ptr frame){
        if (okvis_estimator_ == nullptr)
            return;
        okvis::Time t_image(frame->timestamp_ / 1e9);
        if (start_ == okvis::Time(0.0)) {
            start_ = t_image;
        }

        if (t_image - start_ > deltaT_) {
            if(mMapFrameAvailableHandler.size()>0){
                frame_queue_.enqueue({ frame});
            }
            num_frames_++;
            for (size_t i = 0; i < frame->images_.size(); i++) {
                if (i < parameters_.nCameraSystem.numCameras()){
                    //printf("add image: %i\n", i);
                    okvis_estimator_->addImage(t_image, i, frame->images_[i]);
                }
            }
        }
    }

    void OkvisSLAMSystem::PushIMU(const std::vector<ImuPair>& imu) {
        if (okvis_estimator_ == nullptr) return;
        for (size_t i = 0; i < imu.size(); i++) {
            PushIMU(imu[i]);
        }
    }

    void OkvisSLAMSystem::PushIMU(const ImuPair& imu) {
        if (okvis_estimator_ == nullptr) return;
        t_imu_ = okvis::Time(imu.timestamp / 1e9);
        if (t_imu_ - start_ + okvis::Duration(1.0) > deltaT_) {
            //std::cout << imu.timestamp / 1e9 << " , " << imu.accel.transpose() << " , " << imu.gyro.transpose() << std::endl;
            okvis_estimator_->addImuMeasurement(t_imu_, imu.accel, imu.gyro);
        }
    }

    void OkvisSLAMSystem::PushIMU(double timestamp, const Eigen::Vector3d& accel, const Eigen::Vector3d gyro) {
        if (okvis_estimator_ == nullptr) return;
        t_imu_ = okvis::Time(timestamp / 1e9);
        if (t_imu_ - start_ + okvis::Duration(1.0) > deltaT_) {
            okvis_estimator_->addImuMeasurement(t_imu_, accel, gyro);
        }
    }

    void OkvisSLAMSystem::createNewMap() {
        sparse_map_vector.push_back(std::make_shared<SparseMap<DBoW2::FBRISK::TDescriptor, DBoW2::FBRISK>>());
        // set it to the latest one
        active_map_index = static_cast<int>(sparse_map_vector.size())-1;
    }

    void OkvisSLAMSystem::display() {
        if (okvis_estimator_ == nullptr)
            return;
        okvis_estimator_->display();
    }

    void OkvisSLAMSystem::ShutDown()
    {
        frame_queue_.clear();
        frame_data_queue_.clear();
        kill=true;
        frameConsumerThread_.join();
        okvis_estimator_.reset();
    }

    OkvisSLAMSystem::~OkvisSLAMSystem() {
        frame_queue_.clear();
        frame_data_queue_.clear();
        kill=true;
    }

    void OkvisSLAMSystem::RequestStop()
    {
        okvis_estimator_ = nullptr;
    }

    bool OkvisSLAMSystem::IsRunning()
    {
        return okvis_estimator_ == nullptr;
    }

    void OkvisSLAMSystem::getTrajectory(std::vector<Eigen::Matrix4d>& trajOut){
        getActiveMap()->getTrajectory(trajOut);
    }

    std::shared_ptr<SparseMap<DBoW2::FBRISK::TDescriptor, DBoW2::FBRISK>> OkvisSLAMSystem:: getActiveMap() {
        if (0 <= active_map_index && active_map_index < sparse_map_vector.size()) {
            return sparse_map_vector[active_map_index];
        } else {
            std::cout << "Null map returned \n";
            return nullptr;
        }
    }

} //ark<|endoftext|>


<commit_before>#include "options.h"
#include <string>
#include <vector>
#include <map>
/**
 * @brief Stores a vector of parameters comming from command line
 * @param args vector of strings
 */
void Options::registerArgs(std::vector<std::string> args){
    std::map<std::string, std::string> parts;
    for(std::vector<Param>::iterator param_ite = this->internal_params.begin(); param_ite != this->internal_params.end(); param_ite++) {
        for (std::vector<std::string>::iterator args_ite = args.begin(); args_ite != args.end(); args_ite++) {
            parts = this->getParts( (*args_ite));
            if (this->isCommand(parts.begin()->first)) {
                this->commands[parts.begin()->first] = true; //parts.begin()->second;
            } else {
                // The Param ignores invalid assignments
                (*param_ite).setValue(parts.begin()->first, parts.begin()->second);
            }
        }
    }

}

bool Options::isCommand(std::string value) {
    bool is_command = false;
    if (value.find("help") != std::string::npos) {
        is_command = true;
    }
    return is_command;
}

void Options::runCommands() {
    std::cout << "Options::runCommands()" << ENDL;
    for(std::map<std::string, bool>::iterator command_ite = this->commands.begin(); command_ite != this->commands.end(); command_ite++) {
        std::cout << "Options::runCommands() -> Running command " << (*command_ite).first << ENDL;
        if ((*command_ite).first == "help") {
            this->cmdHelp();
        }
    }

    // this->printVector(command);
}

bool Options::hasCommands() {
    return this->commands.size() > 0;
}

void Options::cmdHelp() {
    std::cout << "[ This is the cmd_help ]" << ENDL;
    for(std::vector<Param>::iterator param_ite = this->internal_params.begin(); param_ite != this->internal_params.end(); param_ite++) {
        std::cout << "-" << (*param_ite).getShortForm() << ENDL;
        std::cout << "  --" << (*param_ite).getLongForm() << "\t\t" << (*param_ite).getDescription() << ENDL;
    }
}

/**
 * @brief Splits cli arguments
 * @details from "--name=value" to [name] = value
 * or "--something" to [something] = ""
 *
 * @param value A cli argument in the form "-s", "--long" or "--short=val"
 * @return [description]
 */
std::map<std::string, std::string> Options::getParts(std::string value) {
    std::map <std::string, std::string> out;
    // Remove leading dashes
    do {
        value = value.substr(1);
    } while ( value.substr(0,1) == "-");

    // Split by =
    int pos_eq = value.find('=');
    if (pos_eq != std::string::npos) {
        std::string name = value.substr(0, pos_eq);
        value = value.substr(pos_eq + 1);
        out[name] = value;
    } else {
        // Or just store an empty right hand value
        out[value] = "";
    }

    return out;
}

void Options::addParam(Param orig){
    this->internal_params.push_back(orig);
}

void Options::printVector(std::vector<std::string> original) {
    for (std::vector<std::string>::iterator i = original.begin(); i != original.end(); i++) {
        std::cout << *i << ENDL;
    }
}
void Options::printVector(std::vector<Param> original) {
    for (std::vector<Param>::iterator i = original.begin(); i != original.end(); i++) {
        std::cout << (*i).getLongForm() << " = " << (*i).getValue() << ENDL;
    }
}

void Options::printVector(std::map<std::string, std::string> original) {
    for (std::map<std::string, std::string>::iterator i = original.begin(); i != original.end(); i++) {
        std::cout << (*i).first << " = " << (*i).second << ENDL;
    }
}

bool Options::areParamsOk() {
    // 1. Check that there are params to check
    // 2.0 Check if any of the params has a dependency
    // 2.1 Check if they fulfill the dependency

    std::cout << "internal_params:" << ENDL;
    this->printVector(this->internal_params);
    return true;
}<commit_msg>Refactor: Remove debug and write to cerr if command is invalid<commit_after>#include "options.h"
#include <string>
#include <vector>
#include <map>
/**
 * @brief Stores a vector of parameters comming from command line
 * @param args vector of strings
 */
void Options::registerArgs(std::vector<std::string> args){
    std::map<std::string, std::string> parts;
    for(std::vector<Param>::iterator param_ite = this->internal_params.begin(); param_ite != this->internal_params.end(); param_ite++) {
        for (std::vector<std::string>::iterator args_ite = args.begin(); args_ite != args.end(); args_ite++) {
            parts = this->getParts( (*args_ite));
            if (this->isCommand(parts.begin()->first)) {
                this->commands[parts.begin()->first] = true; //parts.begin()->second;
            } else {
                // The Param ignores invalid assignments
                (*param_ite).setValue(parts.begin()->first, parts.begin()->second);
            }
        }
    }

}

bool Options::isCommand(std::string value) {
    bool is_command = false;
    if (value.find("help") != std::string::npos) {
        is_command = true;
    }
    return is_command;
}

void Options::runCommands() {
    for(std::map<std::string, bool>::iterator command_ite = this->commands.begin(); command_ite != this->commands.end(); command_ite++) {
        if ((*command_ite).first == "help") {
            this->cmdHelp();
        } else {
            std::cerr << "This command is invalid: " << (*command_ite).first << ENDL;
        }
    }

    // this->printVector(command);
}

bool Options::hasCommands() {
    return this->commands.size() > 0;
}

void Options::cmdHelp() {
    std::cout << "[ This is the cmd_help ]" << ENDL;
    for(std::vector<Param>::iterator param_ite = this->internal_params.begin(); param_ite != this->internal_params.end(); param_ite++) {
        std::cout << "-" << (*param_ite).getShortForm() << ENDL;
        std::cout << "  --" << (*param_ite).getLongForm() << "\t\t" << (*param_ite).getDescription() << ENDL;
    }
}

/**
 * @brief Splits cli arguments
 * @details from "--name=value" to [name] = value
 * or "--something" to [something] = ""
 *
 * @param value A cli argument in the form "-s", "--long" or "--short=val"
 * @return [description]
 */
std::map<std::string, std::string> Options::getParts(std::string value) {
    std::map <std::string, std::string> out;
    // Remove leading dashes
    do {
        value = value.substr(1);
    } while ( value.substr(0,1) == "-");

    // Split by =
    int pos_eq = value.find('=');
    if (pos_eq != std::string::npos) {
        std::string name = value.substr(0, pos_eq);
        value = value.substr(pos_eq + 1);
        out[name] = value;
    } else {
        // Or just store an empty right hand value
        out[value] = "";
    }

    return out;
}

void Options::addParam(Param orig){
    this->internal_params.push_back(orig);
}

void Options::printVector(std::vector<std::string> original) {
    for (std::vector<std::string>::iterator i = original.begin(); i != original.end(); i++) {
        std::cout << *i << ENDL;
    }
}
void Options::printVector(std::vector<Param> original) {
    for (std::vector<Param>::iterator i = original.begin(); i != original.end(); i++) {
        std::cout << (*i).getLongForm() << " = " << (*i).getValue() << ENDL;
    }
}

void Options::printVector(std::map<std::string, std::string> original) {
    for (std::map<std::string, std::string>::iterator i = original.begin(); i != original.end(); i++) {
        std::cout << (*i).first << " = " << (*i).second << ENDL;
    }
}

bool Options::areParamsOk() {
    // 1. Check that there are params to check
    // 2.0 Check if any of the params has a dependency
    // 2.1 Check if they fulfill the dependency

    std::cout << "internal_params:" << ENDL;
    this->printVector(this->internal_params);
    return true;
}<|endoftext|>