<commit_before>// symbiosis: A framework for toy compilers
//
#include "symbiosis.hpp"
#include <sys/stat.h>

#include <iostream>

#include <vector>
#include <functional>

#include "cpu_defines.hpp"

using namespace std;

namespace symbiosis {

  void dump(uchar* start, size_t s) {
    for (size_t i = 0; i < s; i++) {
      printf("%02x ", start[i]);
    }
  }

#ifdef __x86_64__
  bool intel = true;
  bool arm = false;
#endif

#ifdef __arm__
  bool intel = false;
  bool arm = true;
#endif

  bool pic_mode;

  class exception : public std::exception {
    const char *what_;
  public:
    exception(const char *w) : what_(w) { }
    virtual ~exception() throw() { }
    virtual const char* what() const throw() { return what_; }
  };

  char *command_file = 0;;

  #define M10(v, b) #v #b
  #define M3(a,b) M10(a+1000, v),M10(a+2000, v), M10(a+3000, v),M10(a+4000, v)
  #define M2(a,b) M3(a+100, v) , M3(a+200, v) , M3(a+300, v) , M3(a+400, v)
  #define M1(a,b) M2(a+10, v) , M2(a+20, v) , M2(a+30, v) , M2(a+40, v)
  #define M(v) M1(1, v), M1(2, v), M1(3, v), M1(4, v), M1(5, v)

  uchar *virtual_code_start = 0;
  uchar *virtual_code_end = 0;

  uchar *out_code_start = 0;
  uchar *out_code_end = 0;
  uchar *out_c = 0;
  uchar *out_c0 = 0;

  uchar *virtual_strings_start = 0;
  uchar *virtual_strings_end = 0;
  uchar *out_strings_start = 0;
  uchar *out_strings_end = 0;
  uchar *out_s = 0;

  #define STRINGS_START "STRINGS_START"
  #define STRINGS_END "STRINGS_END"

  unsigned int _i32 = 0;

  const char* id::i32() {
    if (virtual_adr) { _i32 = (size_t)virtual_adr;
         //printf("virtual_adr: %x\n", _i32);
        return (const char*)&_i32; }
    if (type == T_UINT) return (const char*)&d.ui;
    return (const char*)&d.i;
  }
  const char* id::i64() {
    if (type == T_ULONG) return (const char*)&d.ul;
    return (const char*)&d.l;
  }
  vector<const char*> type_str = { "0:???", "int", "uint", "long", "ulong",
      "charp", "float", "double"};

  void id::describe() {
    if (type > type_str.size() - 1) {
      cout << "<id:" << type << ">";
    } else {
      cout << type_str[type];
    }
    cout << endl;
  }
  id  id::operator()(id i) { add_parameter(i); return i; }

  id_new::id_new(const char *p) : id(p) {
    virtual_adr = virtual_strings_start + (out_s - out_strings_start);
    virtual_size = strlen(p);
    if (out_s + virtual_size + 1 > out_strings_end)
        throw exception("Strings: Out of memory");
    memcpy(out_s, p, virtual_size + 1);
    out_s += virtual_size + 1;
  };

  const char *reserved_strings[] = { STRINGS_START,
  M(ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc)
  STRINGS_END };

#define FIND(v) { \
  pos = 0; \
  bool found = false; \
  for (size_t i = 0; !found && i < (input_size - v##_s); i++) { \
    for (int j = 0; j < v##_s; j++) { \
      if (buf[i + j] != v[j]) break; \
      if (j == v##_s - 1) { \
        pos = i; \
        found = true; \
      } \
    } \
  } }

  uchar buf[200 * 1024];
  FILE* input = 0;
  size_t input_size = 0;

  void find_space(uchar* start, size_t start_s,
      uchar* end, size_t end_s, uchar **out_start, uchar **out_end) {
    if (!input) {
      input = fopen(command_file, "r");
      if (!input) { fprintf(stderr, "Failed\n"); }
      input_size = fread(buf, 1, sizeof(buf), input);
    }
    size_t pos = 0, s = 0, e = 0;
    FIND(start); s = pos;
    FIND(end); e = pos;
    *out_start = &buf[s];
    *out_end = &buf[e];
    //printf("s: %zd, e:%zd, l:%zd\n", s, e, e - s);
  }

  void write() {
    FILE *out = fopen("a.out", "w");
    fwrite(buf, 1, input_size, out);
    fclose(out);
    printf("Writing a.out\n");
    chmod("a.out", 0777);
  }

  int __offset = 0;
  const char* call_offset(uchar *out_current_code_pos, void *__virt_f) {
    auto virt_f = (uchar*)__virt_f;
    ssize_t out_start_distance = out_current_code_pos - out_code_start;
    ssize_t virt_dist_from_code_start = virt_f - virtual_code_start;
    __offset = virt_dist_from_code_start - out_start_distance - 5;
    cout << "__virt_f: " << __virt_f << endl;
    //cout << "call_offset: " << __offset << " virt: " << virt_dist_from_code_start << " out: " << out_start_distance << endl;
    return (const char*)&__offset;
  }

  const char* rip_relative_offset(uchar *out_current_code_pos,
      uchar *virt_adr) {
    ssize_t distance = out_current_code_pos - out_code_start;
    ssize_t virt_dist_from_code_start = (size_t)virt_adr -
        (size_t)virtual_code_start - distance;
    __offset = virt_dist_from_code_start - 7;
    printf("virt_dist_from_code_start: %zx %x, string ofs: %zd\n",
        (size_t)virt_adr, __offset,
        (size_t)(out_s - out_strings_start));
    return (const char*)&__offset;
  }

  constexpr int parameters_max = 3;

  class Backend {
    vector<function<void()> > callbacks;
  public:
    int parameter_count = 0;
    Backend() { }
    virtual ~Backend() { }
    void callback(function<void()> f) { callbacks.push_back(f); }
    void perform_callbacks() {
        for (size_t i = 0; i < callbacks.size(); ++i) { callbacks[i]();  }}
    virtual void add_parameter(id p) = 0;
    virtual void jmp(void *f) = 0;
    virtual void __call(void *f) = 0;
    virtual void __vararg_call(void *f) = 0;
    virtual void emit_byte(uchar uc) = 0;
    virtual void emit(const char* _s, size_t _l = 0) {
      size_t l = _l > 0 ? _l : strlen(_s);
      uchar *s = (uchar *)_s; uchar *e = s + l;
      for (uchar * b  = s; b < e; b++)  emit_byte(*b);
      //dump(out_start, l);
    }
  };

  const char *register_parameters_intel_32[] = {
      "\xbf", /*edi*/ "\xbe", /*esi*/ "\xba" /*edx*/ };

  const char *register_rip_relative_parameters_intel_64[] = {
    "\x48\x8d\x3d", /* rdi */ "\x48\x8d\x35", /* rsi */
    "\x48\x8d\x15" /* rdx */ };

  const char *register_parameters_intel_64[] = {
      "\x48\xbf" /*rdi*/, "\x48\xbe" ,/*rsi*/ "\x48\xba" /*rdx*/ };

  class Intel : public Backend {
  public:
    Intel() : Backend() { }
    void emit_byte(uchar c) {
      if (out_c + 1 > out_code_end) throw exception("Code: Out of memory");
      *out_c = c;
      out_c++;
    }
    virtual void add_parameter(id p) {
      if (p.is_charp()) {
        if (!pic_mode) {
          emit(register_parameters_intel_32[parameter_count]);
          emit(p.i32(), 4);
        } else {
          uchar *out_current_code_pos = out_c;
          emit(register_rip_relative_parameters_intel_64[parameter_count]);
          emit(rip_relative_offset(out_current_code_pos, p.virtual_adr), 4);
        }
      } else if (p.is_integer()) {
        if (p.is_32()) {
          emit(register_parameters_intel_32[parameter_count]);
          emit(p.i32(), 4);
        } else if (p.is_64()) {
          emit(register_parameters_intel_64[parameter_count]);
          emit(p.i64(), 8);
        }
      }
    }
    virtual void jmp(void *f)  {
      uchar *out_current_code_pos = out_c;
      emit_byte(I_JMP_e9);
      emit(call_offset(out_current_code_pos, f), 4);
    }
    virtual void __call(void *f) {
      uchar *out_current_code_pos = out_c;
      emit_byte(I_CALL_e8);
      emit(call_offset(out_current_code_pos, f), 4);
    }
    virtual void __vararg_call(void *f) {
      emit_byte(I_XOR_30); emit_byte(0xc0); // xor    al,al
      __call(f);
    }
  };

  const char *register_parameters_arm_32[] = {
      "\xe5\x9f\x00", /*r0*/ "\xe5\x9f\x10", /*r1*/ "\xe5\x9f\x20" /*r2*/ };

  class Arm : public Backend {
    int ofs = 1;
  public:
    Arm() : Backend() { alloc_next_32_bits(); }
    void alloc_next_32_bits() {
      if (out_c + 4 > out_code_end) throw exception("Code: Out of memory");
      out_c += 4;
      ofs = 1;
    }
    void emit_byte(uchar c) {
      printf(".%02x", c);
      *(out_c - ofs) = c;
      ofs++;
      if (ofs == 5) {
        if (out_c > out_code_start) { printf("<<"); dump(out_c - 4, 4); printf(">>"); }
        alloc_next_32_bits();
      }
    }
    virtual void add_parameter(id p) {
      if (p.is_charp()) {
        if (!pic_mode) {
          emit(register_parameters_arm_32[parameter_count], 3);
          uchar *ldr_p = out_c - 1;
          emit("\x12");
          callback([=]() {
              cout << "Would set string ref for : " <<
              parameter_count << endl; });
        } else {
          throw exception("pic mode not supported yet!");
          //uchar *out_current_code_pos = out_c;
          //emit(register_rip_relative_parameters_intel_64[parameter_count]);
          //emit(rip_relative_offset(out_current_code_pos, p.virtual_adr), 4);
        }
      } else if (p.is_integer()) {
        if (p.is_32()) {
          emit(register_parameters_arm_32[parameter_count], 3);
          uchar *ldr_p = out_c - 1;
          emit("\x12");
          callback([=]() {
              cout << "Would set imm for : " << parameter_count << endl; });
        } else if (p.is_64()) {
          throw exception("64bit not supported yet!");
        }
      } else {
        //cout << "No integer not supported yet" << endl;
        throw exception("No integer not supported yet");
      }
    }
    virtual void jmp(void *f)  {
      uchar *out_current_code_pos = out_c;
      emit_byte(A_B_08);
      emit(call_offset(out_current_code_pos, f), 3);
    }
    virtual void __call(void *f) {
      uchar *out_current_code_pos = out_c;
      emit_byte(A_BL_eb);
      emit(call_offset(out_current_code_pos, f), 3);
      perform_callbacks();
    }
    virtual void __vararg_call(void *f) {
      throw exception("No arm support yet!");
    }
  };

  Backend* backend;

  id add_parameter(id p) {
    if (backend->parameter_count >= parameters_max) {
      fprintf(stderr, "Too many parameters!\n");
      return p;
    }
    backend->add_parameter(p);
    ++backend->parameter_count;
    return p;
  }

  void jmp(void *f) { backend->jmp(f); }
  void __call(void *f) { backend->__call(f); backend->parameter_count = 0; }
  void __vararg_call(void *f) { backend->__vararg_call(f); }

  void init(char *c, uchar *start, size_t ss, uchar *end, size_t es) {
    arm = true; intel = false; pic_mode = false;
    cout << "intel: " << intel << ", arm: " << arm <<
        ", pic_mode: " << pic_mode << endl;
    command_file = c;
    virtual_code_start = start;
    virtual_code_end = end;
    find_space(start, ss, end, es, &out_code_start,
        &out_code_end);
    virtual_strings_start = (uchar *)STRINGS_START;
    virtual_strings_end = (uchar *)STRINGS_END;
    out_c = out_code_start;
    find_space(virtual_strings_start, strlen(STRINGS_START),
        virtual_strings_end, strlen(STRINGS_END),
            &out_strings_start, &out_strings_end);
    out_s = out_strings_start;
    if (intel) { backend = new Intel(); }
    if (arm) { backend = new Arm(); }
  }

  void finish() {
    jmp(virtual_code_end);
    write();
  }

}
<commit_msg>Fixed callback invocation.<commit_after>// symbiosis: A framework for toy compilers
//
#include "symbiosis.hpp"
#include <sys/stat.h>

#include <iostream>

#include <vector>
#include <functional>

#include "cpu_defines.hpp"

using namespace std;

namespace symbiosis {

  void dump(uchar* start, size_t s) {
    for (size_t i = 0; i < s; i++) {
      printf("%02x ", start[i]);
    }
  }

#ifdef __x86_64__
  bool intel = true;
  bool arm = false;
#endif

#ifdef __arm__
  bool intel = false;
  bool arm = true;
#endif

  bool pic_mode;

  class exception : public std::exception {
    const char *what_;
  public:
    exception(const char *w) : what_(w) { }
    virtual ~exception() throw() { }
    virtual const char* what() const throw() { return what_; }
  };

  char *command_file = 0;;

  #define M10(v, b) #v #b
  #define M3(a,b) M10(a+1000, v),M10(a+2000, v), M10(a+3000, v),M10(a+4000, v)
  #define M2(a,b) M3(a+100, v) , M3(a+200, v) , M3(a+300, v) , M3(a+400, v)
  #define M1(a,b) M2(a+10, v) , M2(a+20, v) , M2(a+30, v) , M2(a+40, v)
  #define M(v) M1(1, v), M1(2, v), M1(3, v), M1(4, v), M1(5, v)

  uchar *virtual_code_start = 0;
  uchar *virtual_code_end = 0;

  uchar *out_code_start = 0;
  uchar *out_code_end = 0;
  uchar *out_c = 0;
  uchar *out_c0 = 0;

  uchar *virtual_strings_start = 0;
  uchar *virtual_strings_end = 0;
  uchar *out_strings_start = 0;
  uchar *out_strings_end = 0;
  uchar *out_s = 0;

  #define STRINGS_START "STRINGS_START"
  #define STRINGS_END "STRINGS_END"

  unsigned int _i32 = 0;

  const char* id::i32() {
    if (virtual_adr) { _i32 = (size_t)virtual_adr;
         //printf("virtual_adr: %x\n", _i32);
        return (const char*)&_i32; }
    if (type == T_UINT) return (const char*)&d.ui;
    return (const char*)&d.i;
  }
  const char* id::i64() {
    if (type == T_ULONG) return (const char*)&d.ul;
    return (const char*)&d.l;
  }
  vector<const char*> type_str = { "0:???", "int", "uint", "long", "ulong",
      "charp", "float", "double"};

  void id::describe() {
    if (type > type_str.size() - 1) {
      cout << "<id:" << type << ">";
    } else {
      cout << type_str[type];
    }
    cout << endl;
  }
  id  id::operator()(id i) { add_parameter(i); return i; }

  id_new::id_new(const char *p) : id(p) {
    virtual_adr = virtual_strings_start + (out_s - out_strings_start);
    virtual_size = strlen(p);
    if (out_s + virtual_size + 1 > out_strings_end)
        throw exception("Strings: Out of memory");
    memcpy(out_s, p, virtual_size + 1);
    out_s += virtual_size + 1;
  };

  const char *reserved_strings[] = { STRINGS_START,
  M(ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc)
  STRINGS_END };

#define FIND(v) { \
  pos = 0; \
  bool found = false; \
  for (size_t i = 0; !found && i < (input_size - v##_s); i++) { \
    for (int j = 0; j < v##_s; j++) { \
      if (buf[i + j] != v[j]) break; \
      if (j == v##_s - 1) { \
        pos = i; \
        found = true; \
      } \
    } \
  } }

  uchar buf[200 * 1024];
  FILE* input = 0;
  size_t input_size = 0;

  void find_space(uchar* start, size_t start_s,
      uchar* end, size_t end_s, uchar **out_start, uchar **out_end) {
    if (!input) {
      input = fopen(command_file, "r");
      if (!input) { fprintf(stderr, "Failed\n"); }
      input_size = fread(buf, 1, sizeof(buf), input);
    }
    size_t pos = 0, s = 0, e = 0;
    FIND(start); s = pos;
    FIND(end); e = pos;
    *out_start = &buf[s];
    *out_end = &buf[e];
    //printf("s: %zd, e:%zd, l:%zd\n", s, e, e - s);
  }

  void write() {
    FILE *out = fopen("a.out", "w");
    fwrite(buf, 1, input_size, out);
    fclose(out);
    printf("Writing a.out\n");
    chmod("a.out", 0777);
  }

  int __offset = 0;
  const char* call_offset(uchar *out_current_code_pos, void *__virt_f) {
    auto virt_f = (uchar*)__virt_f;
    ssize_t out_start_distance = out_current_code_pos - out_code_start;
    ssize_t virt_dist_from_code_start = virt_f - virtual_code_start;
    __offset = virt_dist_from_code_start - out_start_distance - 5;
    cout << "__virt_f: " << __virt_f << endl;
    //cout << "call_offset: " << __offset << " virt: " << virt_dist_from_code_start << " out: " << out_start_distance << endl;
    return (const char*)&__offset;
  }

  const char* rip_relative_offset(uchar *out_current_code_pos,
      uchar *virt_adr) {
    ssize_t distance = out_current_code_pos - out_code_start;
    ssize_t virt_dist_from_code_start = (size_t)virt_adr -
        (size_t)virtual_code_start - distance;
    __offset = virt_dist_from_code_start - 7;
    printf("virt_dist_from_code_start: %zx %x, string ofs: %zd\n",
        (size_t)virt_adr, __offset,
        (size_t)(out_s - out_strings_start));
    return (const char*)&__offset;
  }

  constexpr int parameters_max = 3;

  class Backend {
    vector<function<void()> > callbacks;
  public:
    int parameter_count = 0;
    Backend() { }
    virtual ~Backend() { }
    void callback(function<void()> f) { callbacks.push_back(f); }
    void perform_callbacks() {
      for (size_t i = 0; i < callbacks.size(); ++i) { callbacks[i]();  }
      callbacks.clear();
    }
    virtual void add_parameter(id p) = 0;
    virtual void jmp(void *f) = 0;
    virtual void __call(void *f) = 0;
    virtual void __vararg_call(void *f) = 0;
    virtual void emit_byte(uchar uc) = 0;
    virtual void emit(const char* _s, size_t _l = 0) {
      size_t l = _l > 0 ? _l : strlen(_s);
      uchar *s = (uchar *)_s; uchar *e = s + l;
      for (uchar * b  = s; b < e; b++)  emit_byte(*b);
      //dump(out_start, l);
    }
  };

  const char *register_parameters_intel_32[] = {
      "\xbf", /*edi*/ "\xbe", /*esi*/ "\xba" /*edx*/ };

  const char *register_rip_relative_parameters_intel_64[] = {
    "\x48\x8d\x3d", /* rdi */ "\x48\x8d\x35", /* rsi */
    "\x48\x8d\x15" /* rdx */ };

  const char *register_parameters_intel_64[] = {
      "\x48\xbf" /*rdi*/, "\x48\xbe" ,/*rsi*/ "\x48\xba" /*rdx*/ };

  class Intel : public Backend {
  public:
    Intel() : Backend() { }
    void emit_byte(uchar c) {
      if (out_c + 1 > out_code_end) throw exception("Code: Out of memory");
      *out_c = c;
      out_c++;
    }
    virtual void add_parameter(id p) {
      if (p.is_charp()) {
        if (!pic_mode) {
          emit(register_parameters_intel_32[parameter_count]);
          emit(p.i32(), 4);
        } else {
          uchar *out_current_code_pos = out_c;
          emit(register_rip_relative_parameters_intel_64[parameter_count]);
          emit(rip_relative_offset(out_current_code_pos, p.virtual_adr), 4);
        }
      } else if (p.is_integer()) {
        if (p.is_32()) {
          emit(register_parameters_intel_32[parameter_count]);
          emit(p.i32(), 4);
        } else if (p.is_64()) {
          emit(register_parameters_intel_64[parameter_count]);
          emit(p.i64(), 8);
        }
      }
    }
    virtual void jmp(void *f)  {
      uchar *out_current_code_pos = out_c;
      emit_byte(I_JMP_e9);
      emit(call_offset(out_current_code_pos, f), 4);
    }
    virtual void __call(void *f) {
      uchar *out_current_code_pos = out_c;
      emit_byte(I_CALL_e8);
      emit(call_offset(out_current_code_pos, f), 4);
    }
    virtual void __vararg_call(void *f) {
      emit_byte(I_XOR_30); emit_byte(0xc0); // xor    al,al
      __call(f);
    }
  };

  const char *register_parameters_arm_32[] = {
      "\xe5\x9f\x00", /*r0*/ "\xe5\x9f\x10", /*r1*/ "\xe5\x9f\x20" /*r2*/ };

  class Arm : public Backend {
    int ofs = 1;
  public:
    Arm() : Backend() { alloc_next_32_bits(); }
    void alloc_next_32_bits() {
      if (out_c + 4 > out_code_end) throw exception("Code: Out of memory");
      out_c += 4;
      ofs = 1;
    }
    void emit_byte(uchar c) {
      printf(".%02x", c);
      *(out_c - ofs) = c;
      ofs++;
      if (ofs == 5) {
        if (out_c > out_code_start) { printf("<<"); dump(out_c - 4, 4); printf(">>"); }
        alloc_next_32_bits();
      }
    }
    virtual void add_parameter(id p) {
      if (p.is_charp()) {
        if (!pic_mode) {
          emit(register_parameters_arm_32[parameter_count], 3);
          uchar *ldr_p = out_c - 1;
          emit("\x12");
          int pc = parameter_count;
          callback([pc]() {
              cout << "Would set string ref for : " <<
              pc << endl; });
        } else {
          throw exception("pic mode not supported yet!");
          //uchar *out_current_code_pos = out_c;
          //emit(register_rip_relative_parameters_intel_64[parameter_count]);
          //emit(rip_relative_offset(out_current_code_pos, p.virtual_adr), 4);
        }
      } else if (p.is_integer()) {
        if (p.is_32()) {
          emit(register_parameters_arm_32[parameter_count], 3);
          uchar *ldr_p = out_c - 1;
          emit("\x12");
          int pc = parameter_count;
          callback([pc]() {
              cout << "Would set imm for : " << pc << endl; });
        } else if (p.is_64()) {
          throw exception("64bit not supported yet!");
        }
      } else {
        //cout << "No integer not supported yet" << endl;
        throw exception("No integer not supported yet");
      }
    }
    virtual void jmp(void *f)  {
      uchar *out_current_code_pos = out_c;
      emit_byte(A_B_08);
      emit(call_offset(out_current_code_pos, f), 3);
    }
    virtual void __call(void *f) {
      uchar *out_current_code_pos = out_c;
      emit_byte(A_BL_eb);
      emit(call_offset(out_current_code_pos, f), 3);
      perform_callbacks();
    }
    virtual void __vararg_call(void *f) {
      throw exception("No arm support yet!");
    }
  };

  Backend* backend;

  id add_parameter(id p) {
    if (backend->parameter_count >= parameters_max) {
      fprintf(stderr, "Too many parameters!\n");
      return p;
    }
    backend->add_parameter(p);
    ++backend->parameter_count;
    return p;
  }

  void jmp(void *f) { backend->jmp(f); }
  void __call(void *f) { backend->__call(f); backend->parameter_count = 0; }
  void __vararg_call(void *f) { backend->__vararg_call(f); }

  void init(char *c, uchar *start, size_t ss, uchar *end, size_t es) {
    arm = true; intel = false; pic_mode = false;
    cout << "intel: " << intel << ", arm: " << arm <<
        ", pic_mode: " << pic_mode << endl;
    command_file = c;
    virtual_code_start = start;
    virtual_code_end = end;
    find_space(start, ss, end, es, &out_code_start,
        &out_code_end);
    virtual_strings_start = (uchar *)STRINGS_START;
    virtual_strings_end = (uchar *)STRINGS_END;
    out_c = out_code_start;
    find_space(virtual_strings_start, strlen(STRINGS_START),
        virtual_strings_end, strlen(STRINGS_END),
            &out_strings_start, &out_strings_end);
    out_s = out_strings_start;
    if (intel) { backend = new Intel(); }
    if (arm) { backend = new Arm(); }
  }

  void finish() {
    jmp(virtual_code_end);
    write();
  }

}
<|endoftext|>


<commit_before>/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */

/*
 *  Main authors:
 *     Guido Tack <guido.tack@monash.edu>
 */

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <minizinc/model.hh>
#include <minizinc/exception.hh>

namespace MiniZinc {

  Model::Model(void) : _parent(NULL) {
    GC::add(this);
  }

  Model::~Model(void) {
    for (unsigned int j=0; j<_items.size(); j++) {
      Item* i = _items[j];
      if (IncludeI* ii = i->dyn_cast<IncludeI>()) {
        if (ii->own() && ii->_m) {
          delete ii->_m;
          ii->_m = NULL;
        }
      }
    }
    GC::remove(this);
  }

  void
  Model::registerFn(FunctionI* fi) {
    Model* m = this;
    while (m->_parent)
      m = m->_parent;
    FnMap::iterator i_id = m->fnmap.find(fi->_id);
    if (i_id == m->fnmap.end()) {
      // new element
      std::vector<FunctionI*> v; v.push_back(fi);
      m->fnmap.insert(std::pair<ASTString,std::vector<FunctionI*> >(fi->_id,v));
    } else {
      // add to list of existing elements
      std::vector<FunctionI*>& v = i_id->second;
      for (unsigned int i=0; i<v.size(); i++) {
        if (v[i]->_params.size() == fi->_params.size()) {
          bool alleq=true;
          for (unsigned int j=0; j<fi->_params.size(); j++) {
            if (v[i]->_params[j]->_type != fi->_params[j]->_type) {
              alleq=false; break;
            }
          }
          if (alleq) {
            throw TypeError(fi->_loc,
              "function with the same type already defined in "
              +v[i]->_loc.toString());
          }
        }
      }
      v.push_back(fi);
    }
  }

  FunctionI*
  Model::matchFn(const ASTString& id,
                 const std::vector<Type>& t) {
    Model* m = this;
    while (m->_parent)
      m = m->_parent;
    FnMap::iterator i_id = m->fnmap.find(id);
    if (i_id == m->fnmap.end()) {
      assert(false);
      return NULL; // builtin not defined. TODO: should this be an error?
    }
    std::vector<FunctionI*>& v = i_id->second;
    for (unsigned int i=0; i<v.size(); i++) {
      FunctionI* fi = v[i];
      if (fi->_params.size() == t.size()) {
        bool match=true;
        for (unsigned int j=0; j<t.size(); j++) {
          if (!t[j].isSubtypeOf(fi->_params[j]->_type)) {
            match=false;
            break;
          }
        }
        if (match) {
          return fi;
        }
      }
    }
    assert(false);
    return NULL;
  }

  namespace {
    class FunSort {
    public:
      bool operator()(FunctionI* x, FunctionI* y) const {
        if (x->_params.size() < y->_params.size())
          return true;
        if (x->_params.size() == y->_params.size()) {
          for (unsigned int i=0; i<x->_params.size(); i++) {
            switch (x->_params[i]->_type.cmp(y->_params[i]->_type)) {
            case -1: return true;
            case 1: return false;
            }
          }
        }
        return false;
      }
    };
  }

  void
  Model::sortFn(void) {
    Model* m = this;
    while (m->_parent)
      m = m->_parent;
    FunSort funsort;
    for (FnMap::iterator it=m->fnmap.begin(); it!=m->fnmap.end(); ++it) {
      std::sort(it->second.begin(),it->second.end(),funsort);
    }
  }

  FunctionI*
  Model::matchFn(const ASTString& id,
                 const std::vector<Expression*>& args) const {
    const Model* m = this;
    while (m->_parent)
      m = m->_parent;
    FnMap::const_iterator it = m->fnmap.find(id);
    if (it == m->fnmap.end()) {
      return NULL;
    }
    const std::vector<FunctionI*>& v = it->second;
    for (unsigned int i=0; i<v.size(); i++) {
      FunctionI* fi = v[i];
      if (fi->_params.size() == args.size()) {
        bool match=true;
        for (unsigned int j=0; j<args.size(); j++) {
          if (!args[j]->_type.isSubtypeOf(fi->_params[j]->_type)) {
            match=false;
            break;
          }
        }
        if (match) {
          return fi;
        }
      }
    }
    return NULL;
  }

  FunctionI*
  Model::matchFn(Call* c) const {
    const Model* m = this;
    while (m->_parent)
      m = m->_parent;
    FnMap::const_iterator it = m->fnmap.find(c->_id.str());
    if (it == m->fnmap.end()) {
      return NULL;
    }
    const std::vector<FunctionI*>& v = it->second;
    for (unsigned int i=0; i<v.size(); i++) {
      FunctionI* fi = v[i];
      if (fi->_params.size() == c->_args.size()) {
        bool match=true;
        for (unsigned int j=0; j<c->_args.size(); j++) {
          if (!c->_args[j]->_type.isSubtypeOf(fi->_params[j]->_type)) {
            match=false;
            break;
          }
        }
        if (match) {
          return fi;
        }
      }
    }
    return NULL;
  }

  Item*&
  Model::operator[] (int i) { return _items[i]; }
  const Item*
  Model::operator[] (int i) const { return _items[i]; }
  unsigned int
  Model::size(void) const { return _items.size(); }

  void
  Model::compact(void) {
    struct { bool operator() (const Item* i) {
      return i->removed();
    }} isremoved;
    _items.erase(remove_if(_items.begin(),_items.end(),isremoved),
                 _items.end());
  }
}
<commit_msg>Don't allocate new string<commit_after>/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */

/*
 *  Main authors:
 *     Guido Tack <guido.tack@monash.edu>
 */

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <minizinc/model.hh>
#include <minizinc/exception.hh>

namespace MiniZinc {

  Model::Model(void) : _parent(NULL) {
    GC::add(this);
  }

  Model::~Model(void) {
    for (unsigned int j=0; j<_items.size(); j++) {
      Item* i = _items[j];
      if (IncludeI* ii = i->dyn_cast<IncludeI>()) {
        if (ii->own() && ii->_m) {
          delete ii->_m;
          ii->_m = NULL;
        }
      }
    }
    GC::remove(this);
  }

  void
  Model::registerFn(FunctionI* fi) {
    Model* m = this;
    while (m->_parent)
      m = m->_parent;
    FnMap::iterator i_id = m->fnmap.find(fi->_id);
    if (i_id == m->fnmap.end()) {
      // new element
      std::vector<FunctionI*> v; v.push_back(fi);
      m->fnmap.insert(std::pair<ASTString,std::vector<FunctionI*> >(fi->_id,v));
    } else {
      // add to list of existing elements
      std::vector<FunctionI*>& v = i_id->second;
      for (unsigned int i=0; i<v.size(); i++) {
        if (v[i]->_params.size() == fi->_params.size()) {
          bool alleq=true;
          for (unsigned int j=0; j<fi->_params.size(); j++) {
            if (v[i]->_params[j]->_type != fi->_params[j]->_type) {
              alleq=false; break;
            }
          }
          if (alleq) {
            throw TypeError(fi->_loc,
              "function with the same type already defined in "
              +v[i]->_loc.toString());
          }
        }
      }
      v.push_back(fi);
    }
  }

  FunctionI*
  Model::matchFn(const ASTString& id,
                 const std::vector<Type>& t) {
    Model* m = this;
    while (m->_parent)
      m = m->_parent;
    FnMap::iterator i_id = m->fnmap.find(id);
    if (i_id == m->fnmap.end()) {
      assert(false);
      return NULL; // builtin not defined. TODO: should this be an error?
    }
    std::vector<FunctionI*>& v = i_id->second;
    for (unsigned int i=0; i<v.size(); i++) {
      FunctionI* fi = v[i];
      if (fi->_params.size() == t.size()) {
        bool match=true;
        for (unsigned int j=0; j<t.size(); j++) {
          if (!t[j].isSubtypeOf(fi->_params[j]->_type)) {
            match=false;
            break;
          }
        }
        if (match) {
          return fi;
        }
      }
    }
    assert(false);
    return NULL;
  }

  namespace {
    class FunSort {
    public:
      bool operator()(FunctionI* x, FunctionI* y) const {
        if (x->_params.size() < y->_params.size())
          return true;
        if (x->_params.size() == y->_params.size()) {
          for (unsigned int i=0; i<x->_params.size(); i++) {
            switch (x->_params[i]->_type.cmp(y->_params[i]->_type)) {
            case -1: return true;
            case 1: return false;
            }
          }
        }
        return false;
      }
    };
  }

  void
  Model::sortFn(void) {
    Model* m = this;
    while (m->_parent)
      m = m->_parent;
    FunSort funsort;
    for (FnMap::iterator it=m->fnmap.begin(); it!=m->fnmap.end(); ++it) {
      std::sort(it->second.begin(),it->second.end(),funsort);
    }
  }

  FunctionI*
  Model::matchFn(const ASTString& id,
                 const std::vector<Expression*>& args) const {
    const Model* m = this;
    while (m->_parent)
      m = m->_parent;
    FnMap::const_iterator it = m->fnmap.find(id);
    if (it == m->fnmap.end()) {
      return NULL;
    }
    const std::vector<FunctionI*>& v = it->second;
    for (unsigned int i=0; i<v.size(); i++) {
      FunctionI* fi = v[i];
      if (fi->_params.size() == args.size()) {
        bool match=true;
        for (unsigned int j=0; j<args.size(); j++) {
          if (!args[j]->_type.isSubtypeOf(fi->_params[j]->_type)) {
            match=false;
            break;
          }
        }
        if (match) {
          return fi;
        }
      }
    }
    return NULL;
  }

  FunctionI*
  Model::matchFn(Call* c) const {
    const Model* m = this;
    while (m->_parent)
      m = m->_parent;
    FnMap::const_iterator it = m->fnmap.find(c->_id);
    if (it == m->fnmap.end()) {
      return NULL;
    }
    const std::vector<FunctionI*>& v = it->second;
    for (unsigned int i=0; i<v.size(); i++) {
      FunctionI* fi = v[i];
      if (fi->_params.size() == c->_args.size()) {
        bool match=true;
        for (unsigned int j=0; j<c->_args.size(); j++) {
          if (!c->_args[j]->_type.isSubtypeOf(fi->_params[j]->_type)) {
            match=false;
            break;
          }
        }
        if (match) {
          return fi;
        }
      }
    }
    return NULL;
  }

  Item*&
  Model::operator[] (int i) { return _items[i]; }
  const Item*
  Model::operator[] (int i) const { return _items[i]; }
  unsigned int
  Model::size(void) const { return _items.size(); }

  void
  Model::compact(void) {
    struct { bool operator() (const Item* i) {
      return i->removed();
    }} isremoved;
    _items.erase(remove_if(_items.begin(),_items.end(),isremoved),
                 _items.end());
  }
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "fakevimhandler.h"

#include <QApplication>
#include <QFontMetrics>
#include <QMainWindow>
#include <QMessageBox>
#include <QPainter>
#include <QPlainTextEdit>
#include <QStatusBar>
#include <QTextEdit>

#define EDITOR(editor, call) \
    if (QPlainTextEdit *ed = qobject_cast<QPlainTextEdit *>(editor)) { \
        (ed->call); \
    } else if (QTextEdit *ed = qobject_cast<QTextEdit *>(editor)) { \
        (ed->call); \
    }

using namespace FakeVim::Internal;

typedef QLatin1String _;

/**
 * Simple editor widget.
 * @tparam TextEdit QTextEdit or QPlainTextEdit as base class
 */
template <typename TextEdit>
class Editor : public TextEdit
{
public:
    Editor(QWidget *parent = 0) : TextEdit(parent)
    {
        TextEdit::setCursorWidth(0);
    }

    void paintEvent(QPaintEvent *e)
    {
        TextEdit::paintEvent(e);

        // Draw text cursor.
        QRect rect = TextEdit::cursorRect();
        if ( e->rect().contains(rect) ) {
            QPainter painter(TextEdit::viewport());

            if ( TextEdit::overwriteMode() ) {
                QFontMetrics fm(TextEdit::font());
                rect.setWidth(fm.width(QLatin1Char('m')));
                painter.setPen(Qt::NoPen);
                painter.setBrush(TextEdit::palette().color(QPalette::Base));
                painter.setCompositionMode(QPainter::CompositionMode_Difference);
            } else {
                rect.setWidth(TextEdit::cursorWidth());
                painter.setPen(TextEdit::palette().color(QPalette::Text));
            }
            painter.drawRect(rect);
        }
    }
};

class Proxy : public QObject
{
    Q_OBJECT

public:
    Proxy(QWidget *widget, QMainWindow *mw, QObject *parent = 0)
      : QObject(parent), m_widget(widget), m_mainWindow(mw)
    {}

public slots:
    void changeSelection(const QList<QTextEdit::ExtraSelection> &s)
    {
        EDITOR(m_widget, setExtraSelections(s));
    }

    void changeStatusData(const QString &info)
    {
        m_statusData = info;
        updateStatusBar();
    }

    void highlightMatches(const QString &pattern)
    {
        QTextEdit *ed = qobject_cast<QTextEdit *>(m_widget);
        if (!ed)
            return;

        // Clear previous highlights.
        ed->selectAll();
        QTextCursor cur = ed->textCursor();

        QTextEdit::ExtraSelection selection;
        selection.format.setBackground(Qt::yellow);

        // Highlight matches.
        QTextDocument *doc = ed->document();
        QRegExp re(pattern);
        cur = doc->find(re);

        QList<QTextEdit::ExtraSelection> selections;

        int a = cur.position();
        while ( !cur.isNull() ) {
            if ( cur.hasSelection() ) {
                selection.cursor = cur;
                selections.append(selection);
            } else {
                cur.movePosition(QTextCursor::NextCharacter);
            }
            cur = doc->find(re, cur);
            int b = cur.position();
            if (a == b) {
                cur.movePosition(QTextCursor::NextCharacter);
                cur = doc->find(re, cur);
                b = cur.position();
                if (a == b) break;
            }
            a = b;
        }

        ed->setExtraSelections(selections);
    }

    void changeStatusMessage(const QString &contents, int cursorPos)
    {
        m_statusMessage = cursorPos == -1 ? contents
            : contents.left(cursorPos) + QChar(10073) + contents.mid(cursorPos);
        updateStatusBar();
    }

    void changeExtraInformation(const QString &info)
    {
        QMessageBox::information(m_widget, tr("Information"), info);
    }

    void updateStatusBar()
    {
        int slack = 80 - m_statusMessage.size() - m_statusData.size();
        QString msg = m_statusMessage + QString(slack, QLatin1Char(' ')) + m_statusData;
        m_mainWindow->statusBar()->showMessage(msg);
    }

    void handleExCommand(bool *handled, const ExCommand &cmd)
    {
        if (cmd.matches(_("q"), _("quit")) || cmd.matches(_("qa"), _("qall"))) {
            QApplication::quit();
        } else {
            *handled = false;
            return;
        }

        *handled = true;
    }

private:
    QWidget *m_widget;
    QMainWindow *m_mainWindow;
    QString m_statusMessage;
    QString m_statusData;
};

QWidget *createEditorWidget(bool usePlainTextEdit)
{
    QWidget *editor = 0;
    if (usePlainTextEdit) {
        Editor<QPlainTextEdit> *w = new Editor<QPlainTextEdit>;
        w->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        editor = w;
    } else {
        Editor<QTextEdit> *w = new Editor<QTextEdit>;
        w->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        editor = w;
    }
    editor->setObjectName(_("Editor"));
    editor->setFocus();

    return editor;
}

void initHandler(FakeVimHandler &handler)
{
    // Set some Vim options.
    handler.handleCommand(_("set expandtab"));
    handler.handleCommand(_("set shiftwidth=8"));
    handler.handleCommand(_("set tabstop=16"));
    handler.handleCommand(_("set autoindent"));

    // Try to source file "fakevimrc" from current directory.
    handler.handleCommand(_("source fakevimrc"));

    handler.installEventFilter();
    handler.setupWidget();
}

void initMainWindow(QMainWindow &mainWindow, QWidget *centralWidget, const QString &title)
{
    mainWindow.setWindowTitle(QString(_("FakeVim (%1)")).arg(title));
    mainWindow.setCentralWidget(centralWidget);
    mainWindow.resize(600, 650);
    mainWindow.move(0, 0);
    mainWindow.show();

    // Set monospace font for editor and status bar.
    QFont font = QApplication::font();
    font.setFamily(_("Monospace"));
    centralWidget->setFont(font);
    mainWindow.statusBar()->setFont(font);
}

void readFile(FakeVimHandler &handler, const QString &editFileName)
{
    handler.handleCommand(QString(_("r %1")).arg(editFileName));
}

void clearUndoRedo(QWidget *editor)
{
    EDITOR(editor, setUndoRedoEnabled(false));
    EDITOR(editor, setUndoRedoEnabled(true));
}

void connectSignals(FakeVimHandler &handler, Proxy &proxy)
{
    QObject::connect(&handler, SIGNAL(commandBufferChanged(QString,int,int,int,QObject*)),
        &proxy, SLOT(changeStatusMessage(QString,int)));
    QObject::connect(&handler,
        SIGNAL(selectionChanged(QList<QTextEdit::ExtraSelection>)),
        &proxy, SLOT(changeSelection(QList<QTextEdit::ExtraSelection>)));
    QObject::connect(&handler, SIGNAL(extraInformationChanged(QString)),
        &proxy, SLOT(changeExtraInformation(QString)));
    QObject::connect(&handler, SIGNAL(statusDataChanged(QString)),
        &proxy, SLOT(changeStatusData(QString)));
    QObject::connect(&handler, SIGNAL(highlightMatches(QString)),
        &proxy, SLOT(highlightMatches(QString)));
    QObject::connect(&handler, SIGNAL(handleExCommandRequested(bool*,ExCommand)),
        &proxy, SLOT(handleExCommand(bool*,ExCommand)));
}

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QStringList args = app.arguments();

    // If first argument is present use QPlainTextEdit instead on QTextEdit;
    bool usePlainTextEdit = args.size() > 1;
    // Second argument is path to file to edit.
    const QString editFileName = args.value(2, QString(_("/usr/share/vim/vim73/tutor/tutor")));

    // Create editor widget.
    QWidget *editor = createEditorWidget(usePlainTextEdit);

    // Create FakeVimHandler instance which will emulate Vim behavior in editor widget.
    FakeVimHandler handler(editor, 0);

    // Create main window.
    QMainWindow mainWindow;
    initMainWindow(mainWindow, editor, usePlainTextEdit ? _("QPlainTextEdit") : _("QTextEdit"));

    // Connect slots to FakeVimHandler signals.
    Proxy proxy(editor, &mainWindow);
    connectSignals(handler, proxy);

    // Initialize FakeVimHandler.
    initHandler(handler);

    // Read file content to editor.
    readFile(handler, editFileName);

    // Clear undo and redo queues.
    clearUndoRedo(editor);

    return app.exec();
}

#include "main.moc"
<commit_msg>Redraw cursor correctly with width of current character<commit_after>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "fakevimhandler.h"

#include <QApplication>
#include <QFontMetrics>
#include <QMainWindow>
#include <QMessageBox>
#include <QPainter>
#include <QPlainTextEdit>
#include <QStatusBar>
#include <QTextEdit>

#define EDITOR(editor, call) \
    if (QPlainTextEdit *ed = qobject_cast<QPlainTextEdit *>(editor)) { \
        (ed->call); \
    } else if (QTextEdit *ed = qobject_cast<QTextEdit *>(editor)) { \
        (ed->call); \
    }

using namespace FakeVim::Internal;

typedef QLatin1String _;

/**
 * Simple editor widget.
 * @tparam TextEdit QTextEdit or QPlainTextEdit as base class
 */
template <typename TextEdit>
class Editor : public TextEdit
{
public:
    Editor(QWidget *parent = 0) : TextEdit(parent)
    {
        TextEdit::setCursorWidth(0);
    }

    void paintEvent(QPaintEvent *e)
    {
        TextEdit::paintEvent(e);

        if ( !m_cursorRect.isNull() && e->rect().intersects(m_cursorRect) ) {
            QRect rect = m_cursorRect;
            m_cursorRect = QRect();
            TextEdit::update(rect);
        }

        // Draw text cursor.
        QRect rect = TextEdit::cursorRect();
        if ( e->rect().intersects(rect) ) {
            QPainter painter(TextEdit::viewport());

            if ( TextEdit::overwriteMode() ) {
                QFontMetrics fm(TextEdit::font());
                const int position = TextEdit::textCursor().position();
                const QChar c = TextEdit::document()->characterAt(position);
                rect.setWidth(fm.width(c));
                painter.setPen(Qt::NoPen);
                painter.setBrush(TextEdit::palette().color(QPalette::Base));
                painter.setCompositionMode(QPainter::CompositionMode_Difference);
            } else {
                rect.setWidth(TextEdit::cursorWidth());
                painter.setPen(TextEdit::palette().color(QPalette::Text));
            }

            painter.drawRect(rect);
            m_cursorRect = rect;
        }
    }

private:
    QRect m_cursorRect;
};

class Proxy : public QObject
{
    Q_OBJECT

public:
    Proxy(QWidget *widget, QMainWindow *mw, QObject *parent = 0)
      : QObject(parent), m_widget(widget), m_mainWindow(mw)
    {}

public slots:
    void changeSelection(const QList<QTextEdit::ExtraSelection> &s)
    {
        EDITOR(m_widget, setExtraSelections(s));
    }

    void changeStatusData(const QString &info)
    {
        m_statusData = info;
        updateStatusBar();
    }

    void highlightMatches(const QString &pattern)
    {
        QTextEdit *ed = qobject_cast<QTextEdit *>(m_widget);
        if (!ed)
            return;

        // Clear previous highlights.
        ed->selectAll();
        QTextCursor cur = ed->textCursor();

        QTextEdit::ExtraSelection selection;
        selection.format.setBackground(Qt::yellow);

        // Highlight matches.
        QTextDocument *doc = ed->document();
        QRegExp re(pattern);
        cur = doc->find(re);

        QList<QTextEdit::ExtraSelection> selections;

        int a = cur.position();
        while ( !cur.isNull() ) {
            if ( cur.hasSelection() ) {
                selection.cursor = cur;
                selections.append(selection);
            } else {
                cur.movePosition(QTextCursor::NextCharacter);
            }
            cur = doc->find(re, cur);
            int b = cur.position();
            if (a == b) {
                cur.movePosition(QTextCursor::NextCharacter);
                cur = doc->find(re, cur);
                b = cur.position();
                if (a == b) break;
            }
            a = b;
        }

        ed->setExtraSelections(selections);
    }

    void changeStatusMessage(const QString &contents, int cursorPos)
    {
        m_statusMessage = cursorPos == -1 ? contents
            : contents.left(cursorPos) + QChar(10073) + contents.mid(cursorPos);
        updateStatusBar();
    }

    void changeExtraInformation(const QString &info)
    {
        QMessageBox::information(m_widget, tr("Information"), info);
    }

    void updateStatusBar()
    {
        int slack = 80 - m_statusMessage.size() - m_statusData.size();
        QString msg = m_statusMessage + QString(slack, QLatin1Char(' ')) + m_statusData;
        m_mainWindow->statusBar()->showMessage(msg);
    }

    void handleExCommand(bool *handled, const ExCommand &cmd)
    {
        if (cmd.matches(_("q"), _("quit")) || cmd.matches(_("qa"), _("qall"))) {
            QApplication::quit();
        } else {
            *handled = false;
            return;
        }

        *handled = true;
    }

private:
    QWidget *m_widget;
    QMainWindow *m_mainWindow;
    QString m_statusMessage;
    QString m_statusData;
};

QWidget *createEditorWidget(bool usePlainTextEdit)
{
    QWidget *editor = 0;
    if (usePlainTextEdit) {
        Editor<QPlainTextEdit> *w = new Editor<QPlainTextEdit>;
        w->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        editor = w;
    } else {
        Editor<QTextEdit> *w = new Editor<QTextEdit>;
        w->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        editor = w;
    }
    editor->setObjectName(_("Editor"));
    editor->setFocus();

    return editor;
}

void initHandler(FakeVimHandler &handler)
{
    // Set some Vim options.
    handler.handleCommand(_("set expandtab"));
    handler.handleCommand(_("set shiftwidth=8"));
    handler.handleCommand(_("set tabstop=16"));
    handler.handleCommand(_("set autoindent"));

    // Try to source file "fakevimrc" from current directory.
    handler.handleCommand(_("source fakevimrc"));

    handler.installEventFilter();
    handler.setupWidget();
}

void initMainWindow(QMainWindow &mainWindow, QWidget *centralWidget, const QString &title)
{
    mainWindow.setWindowTitle(QString(_("FakeVim (%1)")).arg(title));
    mainWindow.setCentralWidget(centralWidget);
    mainWindow.resize(600, 650);
    mainWindow.move(0, 0);
    mainWindow.show();

    // Set monospace font for editor and status bar.
    QFont font = QApplication::font();
    font.setFamily(_("Monospace"));
    centralWidget->setFont(font);
    mainWindow.statusBar()->setFont(font);
}

void readFile(FakeVimHandler &handler, const QString &editFileName)
{
    handler.handleCommand(QString(_("r %1")).arg(editFileName));
}

void clearUndoRedo(QWidget *editor)
{
    EDITOR(editor, setUndoRedoEnabled(false));
    EDITOR(editor, setUndoRedoEnabled(true));
}

void connectSignals(FakeVimHandler &handler, Proxy &proxy)
{
    QObject::connect(&handler, SIGNAL(commandBufferChanged(QString,int,int,int,QObject*)),
        &proxy, SLOT(changeStatusMessage(QString,int)));
    QObject::connect(&handler,
        SIGNAL(selectionChanged(QList<QTextEdit::ExtraSelection>)),
        &proxy, SLOT(changeSelection(QList<QTextEdit::ExtraSelection>)));
    QObject::connect(&handler, SIGNAL(extraInformationChanged(QString)),
        &proxy, SLOT(changeExtraInformation(QString)));
    QObject::connect(&handler, SIGNAL(statusDataChanged(QString)),
        &proxy, SLOT(changeStatusData(QString)));
    QObject::connect(&handler, SIGNAL(highlightMatches(QString)),
        &proxy, SLOT(highlightMatches(QString)));
    QObject::connect(&handler, SIGNAL(handleExCommandRequested(bool*,ExCommand)),
        &proxy, SLOT(handleExCommand(bool*,ExCommand)));
}

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QStringList args = app.arguments();

    // If first argument is present use QPlainTextEdit instead on QTextEdit;
    bool usePlainTextEdit = args.size() > 1;
    // Second argument is path to file to edit.
    const QString editFileName = args.value(2, QString(_("/usr/share/vim/vim74/tutor/tutor")));

    // Create editor widget.
    QWidget *editor = createEditorWidget(usePlainTextEdit);

    // Create FakeVimHandler instance which will emulate Vim behavior in editor widget.
    FakeVimHandler handler(editor, 0);

    // Create main window.
    QMainWindow mainWindow;
    initMainWindow(mainWindow, editor, usePlainTextEdit ? _("QPlainTextEdit") : _("QTextEdit"));

    // Connect slots to FakeVimHandler signals.
    Proxy proxy(editor, &mainWindow);
    connectSignals(handler, proxy);

    // Initialize FakeVimHandler.
    initHandler(handler);

    // Read file content to editor.
    readFile(handler, editFileName);

    // Clear undo and redo queues.
    clearUndoRedo(editor);

    return app.exec();
}

#include "main.moc"
<|endoftext|>


<commit_before>/* Copyright (c) 2016 Tobias Koelsch
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <catch_with_main.hpp>
<commit_msg>Adapt to new version of Catch<commit_after>/* Copyright (c) 2016 Tobias Koelsch
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#define CATCH_CONFIG_MAIN
#include <catch.hpp>
<|endoftext|>


<commit_before>#include "catch.hpp"

#include "etl/fast_vector.hpp"
#include "etl/fast_matrix.hpp"
#include "etl/dyn_vector.hpp"
#include "etl/dyn_matrix.hpp"
#include "etl/stop.hpp"

TEST_CASE( "stop/fast_vector_1", "stop<unary<fast_vec>>" ) {
    using mat_type = etl::fast_vector<double, 4>;
    mat_type test_vector(3.3);

    auto r = s(log(test_vector));

    using type = remove_reference_t<remove_cv_t<decltype(r)>>;

    REQUIRE(r.size() == 4);
    REQUIRE(etl_traits<type>::size(r) == 4);
    REQUIRE(size(r) == 4);
    REQUIRE(etl_traits<type>::is_vector);
    REQUIRE(etl_traits<type>::is_value);
    REQUIRE(etl_traits<type>::is_fast);
    REQUIRE(!etl_traits<type>::is_matrix);

    constexpr const auto size_1 = etl_traits<type>::size();
    REQUIRE(size_1 == 4);

    constexpr const auto size_2 = size(r);
    REQUIRE(size_2 == 4);

    for(std::size_t i = 0; i < r.size(); ++i){
        REQUIRE(r[i] == log(3.3));
    }
}

TEST_CASE( "stop/fast_matrix_1", "stop<unary<fast_mat>>" ) {
    using mat_type = etl::fast_matrix<double, 3, 2>;
    mat_type test_matrix(3.3);

    auto r = s(log(test_matrix));

    using type = remove_reference_t<remove_cv_t<decltype(r)>>;

    REQUIRE(r.size() == 6);
    REQUIRE(etl_traits<type>::size(r) == 6);
    REQUIRE(size(r) == 6);
    REQUIRE(etl_traits<type>::rows(r) == 3);
    REQUIRE(rows(r) == 3);
    REQUIRE(etl_traits<type>::columns(r) == 2);
    REQUIRE(columns(r) == 2);
    REQUIRE(etl_traits<type>::is_matrix);
    REQUIRE(etl_traits<type>::is_value);
    REQUIRE(etl_traits<type>::is_fast);
    REQUIRE(!etl_traits<type>::is_vector);

    constexpr const auto size_1 = etl_traits<type>::size();
    constexpr const auto rows_1 = etl_traits<type>::rows();
    constexpr const auto columns_1 = etl_traits<type>::columns();

    REQUIRE(size_1 == 6);
    REQUIRE(rows_1 == 3);
    REQUIRE(columns_1 == 2);

    constexpr const auto size_2 = size(r);
    constexpr const auto rows_2 = rows(r);
    constexpr const auto columns_2 = columns(r);

    REQUIRE(size_2 == 6);
    REQUIRE(rows_2 == 3);
    REQUIRE(columns_2 == 2);

    for(std::size_t i = 0; i < r.size(); ++i){
        REQUIRE(r[i] == log(3.3));
    }
}

TEST_CASE( "stop/fast_matrix_2", "stop<binary<fast_mat>>" ) {
    using mat_type = etl::fast_matrix<double, 3, 2>;
    mat_type test_matrix(3.3);

    auto r = s(test_matrix + test_matrix);

    using type = remove_reference_t<remove_cv_t<decltype(r)>>;

    REQUIRE(r.size() == 6);
    REQUIRE(etl_traits<type>::size(r) == 6);
    REQUIRE(size(r) == 6);
    REQUIRE(etl_traits<type>::rows(r) == 3);
    REQUIRE(rows(r) == 3);
    REQUIRE(etl_traits<type>::columns(r) == 2);
    REQUIRE(columns(r) == 2);
    REQUIRE(etl_traits<type>::is_matrix);
    REQUIRE(etl_traits<type>::is_value);
    REQUIRE(etl_traits<type>::is_fast);
    REQUIRE(!etl_traits<type>::is_vector);

    constexpr const auto size_1 = etl_traits<type>::size();
    constexpr const auto rows_1 = etl_traits<type>::rows();
    constexpr const auto columns_1 = etl_traits<type>::columns();

    REQUIRE(size_1 == 6);
    REQUIRE(rows_1 == 3);
    REQUIRE(columns_1 == 2);

    constexpr const auto size_2 = size(r);
    constexpr const auto rows_2 = rows(r);
    constexpr const auto columns_2 = columns(r);

    REQUIRE(size_2 == 6);
    REQUIRE(rows_2 == 3);
    REQUIRE(columns_2 == 2);

    for(std::size_t i = 0; i < r.size(); ++i){
        REQUIRE(r[i] == 6.6);
    }
}<commit_msg>More tests<commit_after>#include "catch.hpp"

#include "etl/fast_vector.hpp"
#include "etl/fast_matrix.hpp"
#include "etl/dyn_vector.hpp"
#include "etl/dyn_matrix.hpp"
#include "etl/stop.hpp"

TEST_CASE( "stop/fast_vector_1", "stop<unary<fast_vec>>" ) {
    using mat_type = etl::fast_vector<double, 4>;
    mat_type test_vector(3.3);

    auto r = s(log(test_vector));

    using type = remove_reference_t<remove_cv_t<decltype(r)>>;

    REQUIRE(r.size() == 4);
    REQUIRE(etl_traits<type>::size(r) == 4);
    REQUIRE(size(r) == 4);
    REQUIRE(etl_traits<type>::is_vector);
    REQUIRE(etl_traits<type>::is_value);
    REQUIRE(etl_traits<type>::is_fast);
    REQUIRE(!etl_traits<type>::is_matrix);

    constexpr const auto size_1 = etl_traits<type>::size();
    REQUIRE(size_1 == 4);

    constexpr const auto size_2 = size(r);
    REQUIRE(size_2 == 4);

    for(std::size_t i = 0; i < r.size(); ++i){
        REQUIRE(r[i] == log(3.3));
    }
}

TEST_CASE( "stop/fast_matrix_1", "stop<unary<fast_mat>>" ) {
    using mat_type = etl::fast_matrix<double, 3, 2>;
    mat_type test_matrix(3.3);

    auto r = s(log(test_matrix));

    using type = remove_reference_t<remove_cv_t<decltype(r)>>;

    REQUIRE(r.size() == 6);
    REQUIRE(etl_traits<type>::size(r) == 6);
    REQUIRE(size(r) == 6);
    REQUIRE(etl_traits<type>::rows(r) == 3);
    REQUIRE(rows(r) == 3);
    REQUIRE(etl_traits<type>::columns(r) == 2);
    REQUIRE(columns(r) == 2);
    REQUIRE(etl_traits<type>::is_matrix);
    REQUIRE(etl_traits<type>::is_value);
    REQUIRE(etl_traits<type>::is_fast);
    REQUIRE(!etl_traits<type>::is_vector);

    constexpr const auto size_1 = etl_traits<type>::size();
    constexpr const auto rows_1 = etl_traits<type>::rows();
    constexpr const auto columns_1 = etl_traits<type>::columns();

    REQUIRE(size_1 == 6);
    REQUIRE(rows_1 == 3);
    REQUIRE(columns_1 == 2);

    constexpr const auto size_2 = size(r);
    constexpr const auto rows_2 = rows(r);
    constexpr const auto columns_2 = columns(r);

    REQUIRE(size_2 == 6);
    REQUIRE(rows_2 == 3);
    REQUIRE(columns_2 == 2);

    for(std::size_t i = 0; i < r.size(); ++i){
        REQUIRE(r[i] == log(3.3));
    }
}

TEST_CASE( "stop/fast_matrix_2", "stop<binary<fast_mat>>" ) {
    using mat_type = etl::fast_matrix<double, 3, 2>;
    mat_type test_matrix(3.3);

    auto r = s(test_matrix + test_matrix);

    using type = remove_reference_t<remove_cv_t<decltype(r)>>;

    REQUIRE(r.size() == 6);
    REQUIRE(etl_traits<type>::size(r) == 6);
    REQUIRE(size(r) == 6);
    REQUIRE(etl_traits<type>::rows(r) == 3);
    REQUIRE(rows(r) == 3);
    REQUIRE(etl_traits<type>::columns(r) == 2);
    REQUIRE(columns(r) == 2);
    REQUIRE(etl_traits<type>::is_matrix);
    REQUIRE(etl_traits<type>::is_value);
    REQUIRE(etl_traits<type>::is_fast);
    REQUIRE(!etl_traits<type>::is_vector);

    constexpr const auto size_1 = etl_traits<type>::size();
    constexpr const auto rows_1 = etl_traits<type>::rows();
    constexpr const auto columns_1 = etl_traits<type>::columns();

    REQUIRE(size_1 == 6);
    REQUIRE(rows_1 == 3);
    REQUIRE(columns_1 == 2);

    constexpr const auto size_2 = size(r);
    constexpr const auto rows_2 = rows(r);
    constexpr const auto columns_2 = columns(r);

    REQUIRE(size_2 == 6);
    REQUIRE(rows_2 == 3);
    REQUIRE(columns_2 == 2);

    for(std::size_t i = 0; i < r.size(); ++i){
        REQUIRE(r[i] == 6.6);
    }
}

TEST_CASE( "stop/dyn_vector_1", "stop<unary<dyn_vec>>" ) {
    using mat_type = etl::dyn_vector<double>;
    mat_type test_vector(4, 3.3);

    auto r = s(log(test_vector));

    using type = remove_reference_t<remove_cv_t<decltype(r)>>;

    REQUIRE(r.size() == 4);
    REQUIRE(etl_traits<type>::size(r) == 4);
    REQUIRE(size(r) == 4);
    REQUIRE(etl_traits<type>::is_vector);
    REQUIRE(etl_traits<type>::is_value);
    REQUIRE(!etl_traits<type>::is_fast);
    REQUIRE(!etl_traits<type>::is_matrix);

    for(std::size_t i = 0; i < r.size(); ++i){
        REQUIRE(r[i] == log(3.3));
    }
}

TEST_CASE( "stop/dyn_matrix_1", "stop<unary<dyn_mat>>" ) {
    using mat_type = etl::dyn_matrix<double>;
    mat_type test_matrix(3, 2, 3.3);

    auto r = s(log(test_matrix));

    using type = remove_reference_t<remove_cv_t<decltype(r)>>;

    REQUIRE(r.size() == 6);
    REQUIRE(etl_traits<type>::size(r) == 6);
    REQUIRE(size(r) == 6);
    REQUIRE(etl_traits<type>::rows(r) == 3);
    REQUIRE(rows(r) == 3);
    REQUIRE(etl_traits<type>::columns(r) == 2);
    REQUIRE(columns(r) == 2);
    REQUIRE(etl_traits<type>::is_matrix);
    REQUIRE(etl_traits<type>::is_value);
    REQUIRE(!etl_traits<type>::is_fast);
    REQUIRE(!etl_traits<type>::is_vector);

    for(std::size_t i = 0; i < r.size(); ++i){
        REQUIRE(r[i] == log(3.3));
    }
}

TEST_CASE( "stop/dyn_matrix_2", "stop<binary<dyn_mat>>" ) {
    using mat_type = etl::dyn_matrix<double>;
    mat_type test_matrix(3, 2, 3.3);

    auto r = s(test_matrix + test_matrix);

    using type = remove_reference_t<remove_cv_t<decltype(r)>>;

    REQUIRE(r.size() == 6);
    REQUIRE(etl_traits<type>::size(r) == 6);
    REQUIRE(size(r) == 6);
    REQUIRE(etl_traits<type>::rows(r) == 3);
    REQUIRE(rows(r) == 3);
    REQUIRE(etl_traits<type>::columns(r) == 2);
    REQUIRE(columns(r) == 2);
    REQUIRE(etl_traits<type>::is_matrix);
    REQUIRE(etl_traits<type>::is_value);
    REQUIRE(!etl_traits<type>::is_fast);
    REQUIRE(!etl_traits<type>::is_vector);

    for(std::size_t i = 0; i < r.size(); ++i){
        REQUIRE(r[i] == 6.6);
    }
}<|endoftext|>


<commit_before>#include <iostream>
#include <sstream>
#include <string>
#include "encoding/enum.hpp"
#include "encoding/integer.hpp"
#include "encoding/float.hpp"
#include "encoding/input.hpp"
#include "encoding/output.hpp"

using namespace std;

int main(void)
{
  encoding::UnsignedIntegerCodec c1(16);
  cout << c1.encode(1024) <<endl;

  encoding::EnumCodec<string> c2({"hola","adios"}, "hola");
  cout << c2.encode("hola") << endl;
  cout << c2.decode(encoding::Bitset(1, 1)) << endl;

  encoding::FloatCodec c3;
  cout << c3.decode(c3.encode(1.5f)) << endl;

  encoding::FixedPointFloatCodec<4,28> c4;
  cout << "bits: " << c4.sizeInBits << endl;
  cout << c4.decode(c4.encode(1.5f)) << endl;

  std::istringstream in({0x01,0x25,0x23,0x53});
  encoding::InputStream input(in);
  cout << "paco: " << input.read(c1) << endl;
  cout << "paco: " << input.read(c1) << endl;

  encoding::UnsignedIntegerCodec c5(8);
  encoding::UnsignedIntegerCodec c6(4);
  std::stringstream out;
  encoding::OutputStream output(out);
  output.write(c5, 97U);
  output.write(c5, 98U);
  output.write(c5, 99U);
  output.write(c6, 6U);
  output.write(c6, 4U);
  output.close();
  cout << "miau: " << out.str() << endl;
  return 0;
}
<commit_msg>Add some tests<commit_after>// Copyright (c) 2013, Noe Casas (noe.casas@gmail.com).
// Distributed under New BSD License.
// (see accompanying file COPYING)

#include <iostream>
#include <sstream>
#include <string>
#include <ctime>
#include <cstdlib>

#include "encoding/enum.hpp"
#include "encoding/integer.hpp"
#include "encoding/float.hpp"
#include "encoding/input.hpp"
#include "encoding/output.hpp"

using namespace std;
using namespace encoding;

/*****************************************************************************/
template<typename Type>
void testEncode(const Codec<Type>& codec,
                Type value,
                const std::string& bits)
{
  encoding::Bitset obtainedBits = codec.encode(value);
  if (obtainedBits == Bitset(bits))
  {
    cout << "[PASS] Encoded " << value
         << " and obtained " << bits
         << endl;
  }
  else
  {
    cout << "[FAIL] Encoded " << value
         << " and obtained " << obtainedBits
         << " but expected " << bits
         << endl;
  }
}

/*****************************************************************************/
template<typename Type>
void testDecode(const Codec<Type>& codec,
                Type value,
                const std::string& bits)
{
  Type obtainedValue = codec.decode(Bitset(bits));
  if (obtainedValue == value)
  {
    cout << "[PASS] Decoded " << bits
         << " and obtained " << value
         << endl;
  }
  else
  {
    cout << "[FAIL] Decoded " << bits
         << " and obtained " << obtainedValue
         << " but expected " << value
         << endl;
  }
}

/*****************************************************************************/
template<typename Type>
void testRoundtripValue(const Codec<Type>& codec, Type value)
{
  Type roundtripValue = codec.decode(codec.encode(value));

  if (roundtripValue == value)
  {
    cout << "[PASS] Rountrip converted " << value
         << endl;
  }
  else
  {
    cout << "[FAIL] Roundtrip converted " << value
         << " and obtained " << roundtripValue
         << endl;
  }
}

/*****************************************************************************/
template<typename Type>
void testEncodeAndDecode(const Codec<Type>& codec,
                         Type value,
                         const std::string& bits)
{
  testEncode (codec, value, bits);
  testDecode (codec, value, bits);
}

/*****************************************************************************/
void testUnsignedIntegerRandomRoundtrip()
{
  srand (time(0));
  for (std::size_t i = 0; i < 5; ++i)
  {
    std::size_t numBits = rand() % 65;

    for (std::size_t k = 0; k < 20; ++k)
    {
      uint32_t randomNumber = rand() % (1 << numBits);
      testRoundtripValue (UnsignedIntegerCodec(numBits), randomNumber);
    }
  }
}

/*****************************************************************************/
void testUnsignedIntegerEncodePerformance()
{
  const std::size_t performanceSamples = 10000000;
  UnsignedIntegerCodec codec(32);
  clock_t begin = clock();
  for (uint32_t x = 0; x < performanceSamples ; ++x)
  {
    Bitset result = codec.encode(x);
  }
  clock_t end = clock();
  double elapsedmsecs = 1000.0 * double(end - begin) / CLOCKS_PER_SEC;
  cout << "Unsigned integer encode time: "
       << (1000 * elapsedmsecs / performanceSamples) << "usecs "
       << "( " << performanceSamples << " samples )"
       << endl;
}

/*****************************************************************************/
void testUnsigned ()
{
  testEncodeAndDecode (UnsignedIntegerCodec(1), uint32_t(0), "0");
  testEncodeAndDecode (UnsignedIntegerCodec(1), uint32_t(1), "1");
  testEncodeAndDecode (UnsignedIntegerCodec(11), uint32_t(1024), "10000000000");
  testEncodeAndDecode (UnsignedIntegerCodec(16), uint32_t(1024), "0000010000000000");

  testUnsignedIntegerRandomRoundtrip();

  testUnsignedIntegerEncodePerformance();
}

/*****************************************************************************/
/*****************************************************************************/
/*****************************************************************************/

int main(void)
{
  testUnsigned();
/*
  encoding::EnumCodec<string> c2({"hola","adios"}, "hola");
  cout << c2.encode("hola") << endl;
  cout << c2.decode(encoding::Bitset(1, 1)) << endl;

  encoding::FloatCodec c3;
  cout << c3.decode(c3.encode(1.5f)) << endl;

  encoding::FixedPointFloatCodec<4,28> c4;
  cout << "bits: " << c4.sizeInBits << endl;
  cout << c4.decode(c4.encode(1.5f)) << endl;

  std::istringstream in({0x01,0x25,0x23,0x53});
  encoding::InputStream input(in);
  cout << "paco: " << input.read(c1) << endl;
  cout << "paco: " << input.read(c1) << endl;

  encoding::UnsignedIntegerCodec c5(8);
  encoding::UnsignedIntegerCodec c6(4);
  std::stringstream out;
  encoding::OutputStream output(out);
  output.write(c5, 97U);
  output.write(c5, 98U);
  output.write(c5, 99U);
  output.write(c6, 6U);
  output.write(c6, 4U);
  output.close();
  cout << "miau: " << out.str() << endl;
*/
  return 0;
}
<|endoftext|>


<commit_before>#include "../src/util.h"

#include "test.h"

using namespace Helium;

void test_factorial()
{
  COMPARE(1, factorial(0));
  COMPARE(1, factorial(1));
  COMPARE(2, factorial(2));
  COMPARE(6, factorial(3));
  COMPARE(24, factorial(4));
}

void test_num_combinations()
{
  COMPARE(8, num_combinations(8, 1));
  COMPARE(28, num_combinations(8, 2));
  COMPARE(56, num_combinations(8, 3));
}

void test_combinations()
{
  std::string s = "ABCDEFGH";

  // 1 element
  int count = 0;
  do {
    ++count;
  } while (next_combination(s.begin(), s.begin() + 1, s.end()));

  COMPARE(8, count);

  // 2 elements
  count = 0;
  do {
    ++count;
  } while (next_combination(s.begin(), s.begin() + 2, s.end()));

  COMPARE(28, count);

  // 3 elements
  count = 0;
  do {
    ++count;
  } while (next_combination(s.begin(), s.begin() + 3, s.end()));

  COMPARE(56, count);
}

int main()
{
  test_factorial();
  test_num_combinations();
  test_combinations();
}
<commit_msg>Fix include path<commit_after>#include <Helium/util.h>

#include "test.h"

using namespace Helium;

void test_factorial()
{
  COMPARE(1, factorial(0));
  COMPARE(1, factorial(1));
  COMPARE(2, factorial(2));
  COMPARE(6, factorial(3));
  COMPARE(24, factorial(4));
}

void test_num_combinations()
{
  COMPARE(8, num_combinations(8, 1));
  COMPARE(28, num_combinations(8, 2));
  COMPARE(56, num_combinations(8, 3));
}

void test_combinations()
{
  std::string s = "ABCDEFGH";

  // 1 element
  int count = 0;
  do {
    ++count;
  } while (next_combination(s.begin(), s.begin() + 1, s.end()));

  COMPARE(8, count);

  // 2 elements
  count = 0;
  do {
    ++count;
  } while (next_combination(s.begin(), s.begin() + 2, s.end()));

  COMPARE(28, count);

  // 3 elements
  count = 0;
  do {
    ++count;
  } while (next_combination(s.begin(), s.begin() + 3, s.end()));

  COMPARE(56, count);
}

int main()
{
  test_factorial();
  test_num_combinations();
  test_combinations();
}
<|endoftext|>


<commit_before>#include <bitcoin/network/network.hpp>
#include <bitcoin/util/logger.hpp>

#include <atomic>
#include <functional>
#include <iostream>

using std::placeholders::_1;
using std::placeholders::_2;
using namespace libbitcoin;

void error_exit(const std::string& message, int status=1)
{
    log_error() << "net: " << message;
    exit(status);
}

std::mutex mutex;
std::condition_variable condition;
size_t inv_count = 0;

void receive_inv(network_ptr net, channel_handle chandle,
    const message::inv& packet)
{
    log_info() << "Received:";
    for (const message::inv_vect& ivv: packet.invs)
    {
        if (ivv.type != message::inv_type::block)
            log_info() << "  --";
        else
            log_info() << "  " << pretty_hex(ivv.hash);
    }
    net->subscribe_inv(chandle, std::bind(&receive_inv, net, chandle, _1));
    std::unique_lock<std::mutex> lock(mutex);
    inv_count += packet.invs.size();
    condition.notify_one();
}

void handle_send_getblock(const std::error_code& ec)
{
    if (ec)
        error_exit(ec.message());
}

message::getblocks create_getblocks_message()
{
    message::getblocks packet;
    hash_digest genesis{0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xd6, 0x68,
                        0x9c, 0x08, 0x5a, 0xe1, 0x65, 0x83, 0x1e, 0x93,
                        0x4f, 0xf7, 0x63, 0xae, 0x46, 0xa2, 0xa6, 0xc1,
                        0x72, 0xb3, 0xf1, 0xb6, 0x0a, 0x8c, 0xe2, 0x6f};
    packet.locator_start_hashes.push_back(genesis);
    packet.hash_stop = hash_digest{0, 0, 0, 0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0, 0, 0, 0};
    return packet;
}

void handle_handshake(const std::error_code& ec, channel_handle chandle,
    network_ptr net)
{
    net->subscribe_inv(chandle, std::bind(&receive_inv, net, chandle, _1));
    net->send(chandle, create_getblocks_message(),
        std::bind(&handle_send_getblock, _1));
}

int main()
{
    network_ptr net(new network_impl);
    handshake_connect(net, "localhost", 8333,
        std::bind(&handle_handshake, _1, _2, net));

    std::unique_lock<std::mutex> lock(mutex);
    condition.wait(lock, []{ return inv_count >= 500; });
    return 0;
}

<commit_msg>use std::array.fill(0) instead of {0, 0, 0, ...<commit_after>#include <bitcoin/network/network.hpp>
#include <bitcoin/util/logger.hpp>

#include <atomic>
#include <functional>
#include <iostream>

using std::placeholders::_1;
using std::placeholders::_2;
using namespace libbitcoin;

void error_exit(const std::string& message, int status=1)
{
    log_error() << "net: " << message;
    exit(status);
}

std::mutex mutex;
std::condition_variable condition;
size_t inv_count = 0;

void receive_inv(network_ptr net, channel_handle chandle,
    const message::inv& packet)
{
    log_info() << "Received:";
    for (const message::inv_vect& ivv: packet.invs)
    {
        if (ivv.type != message::inv_type::block)
            log_info() << "  --";
        else
            log_info() << "  " << pretty_hex(ivv.hash);
    }
    net->subscribe_inv(chandle, std::bind(&receive_inv, net, chandle, _1));
    std::unique_lock<std::mutex> lock(mutex);
    inv_count += packet.invs.size();
    condition.notify_one();
}

void handle_send_getblock(const std::error_code& ec)
{
    if (ec)
        error_exit(ec.message());
}

message::getblocks create_getblocks_message()
{
    message::getblocks packet;
    hash_digest genesis{0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xd6, 0x68,
                        0x9c, 0x08, 0x5a, 0xe1, 0x65, 0x83, 0x1e, 0x93,
                        0x4f, 0xf7, 0x63, 0xae, 0x46, 0xa2, 0xa6, 0xc1,
                        0x72, 0xb3, 0xf1, 0xb6, 0x0a, 0x8c, 0xe2, 0x6f};
    packet.locator_start_hashes.push_back(genesis);
    packet.hash_stop.fill(0);
    return packet;
}

void handle_handshake(const std::error_code& ec, channel_handle chandle,
    network_ptr net)
{
    net->subscribe_inv(chandle, std::bind(&receive_inv, net, chandle, _1));
    net->send(chandle, create_getblocks_message(),
        std::bind(&handle_send_getblock, _1));
}

int main()
{
    network_ptr net(new network_impl);
    handshake_connect(net, "localhost", 8333,
        std::bind(&handle_handshake, _1, _2, net));

    std::unique_lock<std::mutex> lock(mutex);
    condition.wait(lock, []{ return inv_count >= 500; });
    return 0;
}

<|endoftext|>


<commit_before>/*
Copyright (c) 2016, Vlad Meșco
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <string>
#include <sstream>
#include <vector>
#include <functional>

#include <parser.h>
#include <parser_types.h>

#define TEOF (0)

int tokenizer_lineno = 1;

struct Token
{
    typedef int Type;
    Type type;
    std::string value;
    Token(Type type_, std::string value_ = "")
        : type(type_), value(value_)
    {}
};

struct Tokenizer
{
    FILE* f;
    char c;

    Tokenizer(FILE* f_)
        : f(f_)
    {
        if(feof(f)) c = EOF;
        else c = fgetc(f);
    }

    Token operator()()
    {
        while(isspace(c) || c == 13 || c == 10)
        {
            c = fgetc(f);
            if(feof(f)) return {TEOF};
            if(c == 10) tokenizer_lineno++;
        }
        if(c == '[') { c = fgetc(f); return {LSQUARE}; }
        if(c == ']') { c = fgetc(f); return {RSQUARE}; }
        if(c == '(') { c = fgetc(f); return {LPAREN}; }
        if(c == ')') { c = fgetc(f); return {RPAREN}; }
        if(c == '=') { c = fgetc(f); return {EQUALS}; }

        std::stringstream ss;
        std::function<bool(char)> conditions[] = {
            [](char c) -> bool {
                return !(isspace(c)
                        || c == 13
                        || c == 10
                        || c == '['
                        || c == ']'
                        || c == '('
                        || c == ')'
                        || c == '='
                        );
            },
            [](char c) -> bool {
                return c != '"';
            },
        };
        bool quoted = (c == '"');
        auto condition = conditions[quoted];
        if(quoted) c = fgetc(f);
        while(condition(c))
        {
            ss << c;
            c = fgetc(f);
            if(feof(f)) break;
        }
        if(quoted) c = fgetc(f);
        return {STRING, ss.str()};
    }
};

int main(int argc, char* argv[])
{
    for(int i = 1; i < argc; ++i) {
        if(strcmp(argv[i], "-v") == 0) {
            printf("jakbeat v%d\nCopyright Vlad Mesco 2016\n\n", VERSION);
            exit(0);
        }
    }

    extern void* ParseAlloc(void* (*)(size_t));
    extern void Parse(void*, int, char*, File*);
    extern void ParseFree(void*, void (*)(void*));
    extern void Render(File, std::string);

    File f;
    Tokenizer tok(stdin);
    auto pParser = ParseAlloc(malloc);
    do {
        auto t = tok();
        printf("%d %s\n", t.type, (t.type == STRING) ? t.value.c_str() : "");
        char* s = strdup(t.value.c_str());
        Parse(pParser, t.type, s, &f);
        if(t.type == TEOF) break;
    } while(1);
    ParseFree(pParser, free);

    Render(f, "test.wav");

    return 0;
}
<commit_msg>fix compiler crash (!) on 18.00.21005.1<commit_after>/*
Copyright (c) 2016, Vlad Meșco
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <string>
#include <sstream>
#include <vector>
#include <functional>

#include <parser.h>
#include <parser_types.h>

#define TEOF (0)

int tokenizer_lineno = 1;

struct Token
{
    typedef int Type;
    Type type;
    std::string value;
    Token(Type type_, std::string value_ = "")
        : type(type_), value(value_)
    {}
};

struct Tokenizer
{
    FILE* f;
    char c;

    Tokenizer(FILE* f_)
        : f(f_)
    {
        if(feof(f)) c = EOF;
        else c = fgetc(f);
    }

    Token operator()()
    {
        while(isspace(c) || c == 13 || c == 10)
        {
            c = fgetc(f);
            if(feof(f)) return {TEOF};
            if(c == 10) tokenizer_lineno++;
        }
        if(c == '[') { c = fgetc(f); return {LSQUARE}; }
        if(c == ']') { c = fgetc(f); return {RSQUARE}; }
        if(c == '(') { c = fgetc(f); return {LPAREN}; }
        if(c == ')') { c = fgetc(f); return {RPAREN}; }
        if(c == '=') { c = fgetc(f); return {EQUALS}; }

        std::stringstream ss;
        std::function<bool(char)> conditions[] = {
            [](char c) -> bool {
                return !(isspace(c)
                        || c == 13
                        || c == 10
                        || c == '['
                        || c == ']'
                        || c == '('
                        || c == ')'
                        || c == '='
                        );
            },
            [](char c) -> bool {
                return c != '"';
            },
        };
        bool quoted = (c == '"');
        auto condition = conditions[quoted];
        if(quoted) c = fgetc(f);
        while(condition(c))
        {
            ss << c;
            c = fgetc(f);
            if(feof(f)) break;
        }
        if(quoted) c = fgetc(f);
        //return {STRING, ss.str()}; // curly bracket form crashes msvc 18.00.21005.1
        return Token(STRING, ss.str());
    }
};

int main(int argc, char* argv[])
{
    for(int i = 1; i < argc; ++i) {
        if(strcmp(argv[i], "-v") == 0) {
            printf("jakbeat v%d\nCopyright Vlad Mesco 2016\n\n", VERSION);
            exit(0);
        }
    }

    extern void* ParseAlloc(void* (*)(size_t));
    extern void Parse(void*, int, char*, File*);
    extern void ParseFree(void*, void (*)(void*));
    extern void Render(File, std::string);

    File f;
    Tokenizer tok(stdin);
    auto pParser = ParseAlloc(malloc);
    do {
        auto t = tok();
        printf("%d %s\n", t.type, (t.type == STRING) ? t.value.c_str() : "");
        char* s = strdup(t.value.c_str());
        Parse(pParser, t.type, s, &f);
        if(t.type == TEOF) break;
    } while(1);
    ParseFree(pParser, free);

    Render(f, "test.wav");

    return 0;
}
<|endoftext|>