<commit_before>//----------------------------  mg_dof_handler.cc  ---------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 2005, 2006 by the deal.II authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//----------------------------  mg_dof_handler.cc  ---------------------------

/* Author: Ralf Hartmann, 2005, O. Kayser-Herold, simply modified
  the mg_dof_handler.cc test for the hp::DoFHandler. */

#include <base/logstream.h>
#include <grid/tria.h>
#include <grid/grid_generator.h>
#include <grid/tria_accessor.h>
#include <grid/grid_out.h>
#include <fe/fe_dgq.h>
#include <dofs/hp_dof_handler.h>

#include <fstream>

int main ()
{
  std::ofstream logfile("hp_dof_handler/output");
  logfile.precision(2);

  deallog.attach(logfile);
  deallog.depth_console(0);
  deallog.threshold_double(1.e-10);

  const unsigned int dim=2;
  Triangulation<dim> tria;
  GridGenerator::hyper_cube(tria);

  FECollection<dim> fe_collection;
  fe_collection.add_fe (FE_DGQ<dim> (1));

  hp::DoFHandler<dim> dof_handler(tria);

  tria.begin_active()->set_refine_flag();
  tria.execute_coarsening_and_refinement();

  Triangulation<dim>::active_cell_iterator
    cell=tria.begin_active(),
    endc=tria.end();
  for (; cell!=endc; ++cell)
    cell->set_coarsen_flag();
  tria.execute_coarsening_and_refinement();

  dof_handler.distribute_dofs(fe_collection);

  deallog << "OK" << std::endl;
}
<commit_msg>Use proper namespace.<commit_after>//----------------------------  mg_dof_handler.cc  ---------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 2005, 2006 by the deal.II authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//----------------------------  mg_dof_handler.cc  ---------------------------

/* Author: Ralf Hartmann, 2005, O. Kayser-Herold, simply modified
  the mg_dof_handler.cc test for the hp::DoFHandler. */

#include <base/logstream.h>
#include <grid/tria.h>
#include <grid/grid_generator.h>
#include <grid/tria_accessor.h>
#include <grid/grid_out.h>
#include <fe/fe_dgq.h>
#include <dofs/hp_dof_handler.h>

#include <fstream>

int main ()
{
  std::ofstream logfile("hp_dof_handler/output");
  logfile.precision(2);

  deallog.attach(logfile);
  deallog.depth_console(0);
  deallog.threshold_double(1.e-10);

  const unsigned int dim=2;
  Triangulation<dim> tria;
  GridGenerator::hyper_cube(tria);

  hp::FECollection<dim> fe_collection;
  fe_collection.add_fe (FE_DGQ<dim> (1));

  hp::DoFHandler<dim> dof_handler(tria);

  tria.begin_active()->set_refine_flag();
  tria.execute_coarsening_and_refinement();

  Triangulation<dim>::active_cell_iterator
    cell=tria.begin_active(),
    endc=tria.end();
  for (; cell!=endc; ++cell)
    cell->set_coarsen_flag();
  tria.execute_coarsening_and_refinement();

  dof_handler.distribute_dofs(fe_collection);

  deallog << "OK" << std::endl;
}
<|endoftext|>


<commit_before>#ifndef __UTILS2_HPP__
#define __UTILS2_HPP__

/* utils2.hpp is a collection of utility functions and types that sits below the IO layer.
The reason it is separate from utils.hpp is that the IO layer needs some of the things in
utils2.hpp, but utils.hpp needs some things in the IO layer. */

#include "config/args.hpp"
#include <stdint.h>
#include <time.h>
#include "errors.hpp"

typedef uint64_t cas_t;

int get_cpu_count();
long get_available_ram();
long get_total_ram();

// This may be surprising to some people.
typedef char byte;

// for safety  TODO: move this to a different file
struct repli_timestamp {
    uint32_t time;

    static const repli_timestamp invalid;
};

struct initialized_repli_timestamp {
    uint32_t time;
    explicit initialized_repli_timestamp(uint32_t _time) : time(_time) { }
    initialized_repli_timestamp(repli_timestamp timestamp) : time(timestamp.time) { }

    operator repli_timestamp() const {
        repli_timestamp ret = { time };
        return ret;
    }
};

struct charslice {
    char *beg, *end;
    charslice(char *beg_, char *end_) : beg(beg_), end(end_) { }
    charslice() : beg(NULL), end(NULL) { }
};

struct const_charslice {
    const char *beg, *end;
    const_charslice(const char *beg_, const char *end_) : beg(beg_), end(end_) { }
    const_charslice() : beg(NULL), end(NULL) { }
};

// Converts a time_t (in seconds) to a repli_timestamp, but avoids
// returning the invalid repli_timestamp value, which might matter
// once every 116 years.
repli_timestamp repli_time(time_t t);

// TODO: move this to a different file
repli_timestamp current_time();

typedef uint64_t microtime_t;

microtime_t current_microtime();

// This is not a transitive operation.  It compares times "locally."
// Imagine a comparison function that compares angles, in the range
// [0, 2*pi), that is invariant with respect to rotation.  How would
// you implement that?  This is a function that compares timestamps in
// [0, 2**32), that is invariant with respect to translation.
int repli_compare(repli_timestamp x, repli_timestamp y);

// Like std::max, except it's technically not associative because it
// uses repli_compare.
repli_timestamp repli_max(repli_timestamp x, repli_timestamp y);

void *malloc_aligned(size_t size, size_t alignment = 64);

template <class T1, class T2>
T1 ceil_aligned(T1 value, T2 alignment) {
    return value + alignment - (((value + alignment - 1) % alignment) + 1);
}

template <class T1, class T2>
T1 ceil_divide(T1 dividend, T2 alignment) {
    return (dividend + alignment - 1) / alignment;
}

template <class T1, class T2>
T1 floor_aligned(T1 value, T2 alignment) {
    return value - (value % alignment);
}

typedef unsigned long long ticks_t;
ticks_t secs_to_ticks(float secs);
ticks_t get_ticks();
long get_ticks_res();
float ticks_to_secs(ticks_t ticks);
float ticks_to_ms(ticks_t ticks);
float ticks_to_us(ticks_t ticks);

/* Functions to create random delays. These must be in utils2.hpp instead of in
utils.hpp because the mock IO layer uses random delays. Internally, they
secretly use the IO layer, but it is safe to include utils2.hpp from within the
IO layer. */

void random_delay(void (*)(void*), void*);

template<class cb_t>
void random_delay(cb_t *cb, void (cb_t::*method)());

template<class cb_t, class arg1_t>
void random_delay(cb_t *cb, void (cb_t::*method)(arg1_t), arg1_t arg);

template<class cb_t>
bool maybe_random_delay(cb_t *cb, void (cb_t::*method)());

template<class cb_t, class arg1_t>
bool maybe_random_delay(cb_t *cb, void (cb_t::*method)(arg1_t), arg1_t arg);

/* Debugging printing API (prints current thread in addition to message) */

void debugf(const char *msg, ...) __attribute__((format (printf, 1, 2)));

// Returns a random number in [0, n).  Is not perfectly uniform; the
// bias tends to get worse when RAND_MAX is far from a multiple of n.
int randint(int n);

// The existence of these functions does not constitute an endorsement
// for casts.  These constitute an endorsement for the use of
// reinterpret_cast, rather than C-style casts.  The latter can break
// const correctness.
template <class T>
inline const T* ptr_cast(const void *p) { return reinterpret_cast<const T*>(p); }

template <class T>
inline T* ptr_cast(void *p) { return reinterpret_cast<T*>(p); }

bool begins_with_minus(const char *string);
// strtoul() and strtoull() will for some reason not fail if the input begins with a minus
// sign. strtoul_strict() and strtoull_strict() do.
long strtol_strict(const char *string, char **end, int base);
unsigned long strtoul_strict(const char *string, char **end, int base);
unsigned long long strtoull_strict(const char *string, char **end, int base);
bool strtobool_strict(const char *string, char **end);

// Put this in a private: section.
#define DISABLE_COPYING(T)                      \
    T(const T&);                                \
    void operator=(const T&)

// This is inefficient, it calls vsnprintf twice and copies the
// arglist and output buffer excessively.
std::string strprintf(const char *format, ...) __attribute__ ((format (printf, 1, 2)));

// Pad a value to the size of a cache line to avoid false sharing.
// TODO: This is implemented as a struct with subtraction rather than a union
// so that it gives an error when trying to pad a value bigger than
// CACHE_LINE_SIZE. If that's needed, this may have to be done differently.
// TODO: Use this in the rest of the perfmons, if it turns out to make any
// difference.

template<typename value_t>
struct cache_line_padded_t {
    value_t value;
    byte padding[CACHE_LINE_SIZE - sizeof value];
};

#include "utils2.tcc"

#endif /* __UTILS2_HPP__ */
<commit_msg>Hopefully fix a compile bug :/.<commit_after>#ifndef __UTILS2_HPP__
#define __UTILS2_HPP__

/* utils2.hpp is a collection of utility functions and types that sits below the IO layer.
The reason it is separate from utils.hpp is that the IO layer needs some of the things in
utils2.hpp, but utils.hpp needs some things in the IO layer. */

#include "config/args.hpp"
#include <stdint.h>
#include <time.h>
#include "errors.hpp"

typedef uint64_t cas_t;

int get_cpu_count();
long get_available_ram();
long get_total_ram();

// This may be surprising to some people.
typedef char byte;

// for safety  TODO: move this to a different file
struct repli_timestamp {
    uint32_t time;

    static const repli_timestamp invalid;
};

struct initialized_repli_timestamp {
    uint32_t time;
    explicit initialized_repli_timestamp(uint32_t _time) : time(_time) { }
    initialized_repli_timestamp(repli_timestamp timestamp) : time(timestamp.time) { }

    operator repli_timestamp() const {
        repli_timestamp ret = { time };
        return ret;
    }
};

struct charslice {
    char *beg, *end;
    charslice(char *beg_, char *end_) : beg(beg_), end(end_) { }
    charslice() : beg(NULL), end(NULL) { }
};

struct const_charslice {
    const char *beg, *end;
    const_charslice(const char *beg_, const char *end_) : beg(beg_), end(end_) { }
    const_charslice() : beg(NULL), end(NULL) { }
};

// Converts a time_t (in seconds) to a repli_timestamp, but avoids
// returning the invalid repli_timestamp value, which might matter
// once every 116 years.
repli_timestamp repli_time(time_t t);

// TODO: move this to a different file
repli_timestamp current_time();

typedef uint64_t microtime_t;

microtime_t current_microtime();

// This is not a transitive operation.  It compares times "locally."
// Imagine a comparison function that compares angles, in the range
// [0, 2*pi), that is invariant with respect to rotation.  How would
// you implement that?  This is a function that compares timestamps in
// [0, 2**32), that is invariant with respect to translation.
int repli_compare(repli_timestamp x, repli_timestamp y);

// Like std::max, except it's technically not associative because it
// uses repli_compare.
repli_timestamp repli_max(repli_timestamp x, repli_timestamp y);

void *malloc_aligned(size_t size, size_t alignment = 64);

template <class T1, class T2>
T1 ceil_aligned(T1 value, T2 alignment) {
    return value + alignment - (((value + alignment - 1) % alignment) + 1);
}

template <class T1, class T2>
T1 ceil_divide(T1 dividend, T2 alignment) {
    return (dividend + alignment - 1) / alignment;
}

template <class T1, class T2>
T1 floor_aligned(T1 value, T2 alignment) {
    return value - (value % alignment);
}

typedef unsigned long long ticks_t;
ticks_t secs_to_ticks(float secs);
ticks_t get_ticks();
long get_ticks_res();
float ticks_to_secs(ticks_t ticks);
float ticks_to_ms(ticks_t ticks);
float ticks_to_us(ticks_t ticks);

/* Functions to create random delays. These must be in utils2.hpp instead of in
utils.hpp because the mock IO layer uses random delays. Internally, they
secretly use the IO layer, but it is safe to include utils2.hpp from within the
IO layer. */

void random_delay(void (*)(void*), void*);

template<class cb_t>
void random_delay(cb_t *cb, void (cb_t::*method)());

template<class cb_t, class arg1_t>
void random_delay(cb_t *cb, void (cb_t::*method)(arg1_t), arg1_t arg);

template<class cb_t>
bool maybe_random_delay(cb_t *cb, void (cb_t::*method)());

template<class cb_t, class arg1_t>
bool maybe_random_delay(cb_t *cb, void (cb_t::*method)(arg1_t), arg1_t arg);

/* Debugging printing API (prints current thread in addition to message) */

void debugf(const char *msg, ...) __attribute__((format (printf, 1, 2)));

// Returns a random number in [0, n).  Is not perfectly uniform; the
// bias tends to get worse when RAND_MAX is far from a multiple of n.
int randint(int n);

// The existence of these functions does not constitute an endorsement
// for casts.  These constitute an endorsement for the use of
// reinterpret_cast, rather than C-style casts.  The latter can break
// const correctness.
template <class T>
inline const T* ptr_cast(const void *p) { return reinterpret_cast<const T*>(p); }

template <class T>
inline T* ptr_cast(void *p) { return reinterpret_cast<T*>(p); }

bool begins_with_minus(const char *string);
// strtoul() and strtoull() will for some reason not fail if the input begins with a minus
// sign. strtoul_strict() and strtoull_strict() do.
long strtol_strict(const char *string, char **end, int base);
unsigned long strtoul_strict(const char *string, char **end, int base);
unsigned long long strtoull_strict(const char *string, char **end, int base);
bool strtobool_strict(const char *string, char **end);

// Put this in a private: section.
#define DISABLE_COPYING(T)                      \
    T(const T&);                                \
    void operator=(const T&)

// This is inefficient, it calls vsnprintf twice and copies the
// arglist and output buffer excessively.
std::string strprintf(const char *format, ...) __attribute__ ((format (printf, 1, 2)));

// Pad a value to the size of a cache line to avoid false sharing.
// TODO: This is implemented as a struct with subtraction rather than a union
// so that it gives an error when trying to pad a value bigger than
// CACHE_LINE_SIZE. If that's needed, this may have to be done differently.
// TODO: Use this in the rest of the perfmons, if it turns out to make any
// difference.

template<typename value_t>
struct cache_line_padded_t {
    value_t value;
    byte padding[CACHE_LINE_SIZE - sizeof value_t];
};

#include "utils2.tcc"

#endif /* __UTILS2_HPP__ */
<|endoftext|>


<commit_before>#include "json.h"

#include "cc/misc/strings.h"

namespace json {

Object::Object() {
    type_ = JOT_NULL;
    data_ = NULL;
}

Object::Object(int64_t n) {
    type_ = JOT_INT;
    auto data = new int(n);
    data_ = reinterpret_cast<void*>(data);
}

Object::Object(const string& s) {
    type_ = JOT_STR;
    auto data = new string(s);
    data_ = reinterpret_cast<void*>(data);
}

Object::Object(const vector<uint64_t>& vec) {
    vector<int64_t> v;
    v.reserve(vec.size());
    for (auto& it : vec) {
        auto n = static_cast<int64_t>(it);
        v.emplace_back(n);
    }
    InitFromInts(v);
}

Object::Object(const set<uint64_t>& set) {
    vector<int64_t> v;
    v.reserve(set.size());
    for (auto& it : set) {
        auto n = static_cast<int64_t>(it);
        v.emplace_back(n);
    }
    InitFromInts(v);
}

Object::Object(const unordered_set<uint64_t>& set) {
    vector<int64_t> v;
    v.reserve(set.size());
    for (auto& it : set) {
        auto n = static_cast<int64_t>(it);
        v.emplace_back(n);
    }
    InitFromInts(v);
}

Object::Object(const vector<uint32_t>& vec) {
    vector<int64_t> v;
    v.reserve(vec.size());
    for (auto& it : vec) {
        auto n = static_cast<int64_t>(it);
        v.emplace_back(n);
    }
    InitFromInts(v);
}

Object::Object(const set<uint32_t>& set) {
    vector<int64_t> v;
    v.reserve(set.size());
    for (auto& it : set) {
        auto n = static_cast<int64_t>(it);
        v.emplace_back(n);
    }
    InitFromInts(v);
}

Object::Object(const unordered_set<uint32_t>& set) {
    vector<int64_t> v;
    v.reserve(set.size());
    for (auto& it : set) {
        auto n = static_cast<int64_t>(it);
        v.emplace_back(n);
    }
    InitFromInts(v);
}

Object::Object(const vector<string>& v) {
    InitFromStrings(v);
}

Object::Object(const set<string>& set) {
    vector<string> v;
    v.reserve(set.size());
    for (auto& it : set) {
        v.emplace_back(it);
    }
    InitFromStrings(v);
}

Object::Object(const unordered_set<string>& set) {
    vector<string> v;
    v.reserve(set.size());
    for (auto& it : set) {
        v.emplace_back(it);
    }
    InitFromStrings(v);
}

Object::Object(const vector<Object*>& v) {
    type_ = JOT_ARRAY;
    auto data = new vector<Object*>(v);
    data_ = reinterpret_cast<void*>(data);
}

Object::Object(const map<string, Object*>& d) {
    type_ = JOT_OBJ;
    auto data = new map<string, Object*>();
    for (auto& it : d) {
        (*data)[it.first] = it.second;
    }
    data_ = reinterpret_cast<void*>(data);
}

Object::~Object() {
    switch (type_) {
    case JOT_NULL:
        break;
    case JOT_BOOL:
        delete reinterpret_cast<bool*>(data_);
        break;
    case JOT_INT:
        delete reinterpret_cast<int64_t*>(data_);
        break;
    case JOT_STR:
        delete reinterpret_cast<string*>(data_);
        break;
    case JOT_ARRAY:
        {
            auto* data = reinterpret_cast<vector<Object*>*>(data_);
            for (auto& obj : *data) {
                delete obj;
            }
            delete data;
            break;
        }
    case JOT_OBJ:
        {
            auto* data = reinterpret_cast<map<string, Object*>*>(data_);
            for (auto& it : *data) {
                delete it.second;
            }
            delete data;
            break;
        }
    }
}

static void Quote(const string& in, string* out) {
    out->clear();
    out->reserve(in.size() + 2);
    *out += "\"";
    for (auto& c : in) {
        if (c == '"') {
            *out += "\\\"";
        } else {
            *out += c;
        }
    }
    *out += "\"";
}

void Object::AppendToString(
        string* out, size_t spaces_per_indent, size_t offset_spaces,
        bool leading_indent) const {
    string indent0(offset_spaces, ' ');
    string indent1(offset_spaces + spaces_per_indent, ' ');

    if (leading_indent) {
        *out += indent0;
    }

    switch (type_) {
    case JOT_NULL: {
        *out += "null";
        break;
    }
    case JOT_BOOL: {
        auto& b = *reinterpret_cast<bool*>(data_);
        *out += (b ? "true" : "false");
        break;
    }
    case JOT_INT: {
        auto& n = *reinterpret_cast<int64_t*>(data_);
        *out += strings::StringPrintf("%ld", n);
        break;
    }
    case JOT_STR: {
        auto& orig_s = *reinterpret_cast<string*>(data_);
        string quoted_s;
        Quote(orig_s, &quoted_s);
        *out += quoted_s;
        break;
    }
    case JOT_ARRAY: {
        auto& v = *reinterpret_cast<vector<Object*>*>(data_);
        *out += "[";
        if (v.size()) {
            *out += "\n";
        }
        for (auto i = 0u; i < v.size(); ++i) {
            auto& obj = v[i];
            obj->AppendToString(
                out, spaces_per_indent, offset_spaces + spaces_per_indent,
                true);
            if (i != v.size() - 1) {
                *out += ",";
            }
            *out += "\n";
        }
        if (v.size()) {
            *out += indent0;
        }
        *out += "]";
        break;
    }
    case JOT_OBJ: {
        auto& d = *reinterpret_cast<map<string, Object*>*>(data_);
        *out += "{";
        if (d.size()) {
            *out += "\n";
        }
        size_t count = 0;
        for (auto& it : d) {
            auto& orig_s = it.first;
            string quoted_s;
            Quote(orig_s, &quoted_s);
            *out += indent1 + quoted_s + ": ";
            auto& obj = it.second;
            obj->AppendToString(
                out, spaces_per_indent, offset_spaces + spaces_per_indent,
                false);
            if (count != d.size() - 1) {
                *out += ",";
            }
            *out += "\n";
        }
        if (d.size()) {
            *out += indent0;
        }
        *out += "}";
        break;
    }
    }
}

void Object::InitFromInts(const vector<int64_t>& v) {
    type_ = JOT_ARRAY;
    auto data = new vector<Object*>();
    data->reserve(v.size());
    for (auto& n : v) {
        data->emplace_back(new Object(n));
    }
    data_ = reinterpret_cast<void*>(data);
}

void Object::InitFromStrings(const vector<string>& v) {
    type_ = JOT_ARRAY;
    auto data = new vector<Object*>();
    data->reserve(v.size());
    for (auto& s : v) {
        data->emplace_back(new Object(s));
    }
    data_ = reinterpret_cast<void*>(data);
}

}  // namespace json
<commit_msg>Fix int64 init.<commit_after>#include "json.h"

#include "cc/misc/strings.h"

namespace json {

Object::Object() {
    type_ = JOT_NULL;
    data_ = NULL;
}

Object::Object(int64_t n) {
    type_ = JOT_INT;
    auto data = new int64_t(n);
    data_ = reinterpret_cast<void*>(data);
}

Object::Object(const string& s) {
    type_ = JOT_STR;
    auto data = new string(s);
    data_ = reinterpret_cast<void*>(data);
}

Object::Object(const vector<uint64_t>& vec) {
    vector<int64_t> v;
    v.reserve(vec.size());
    for (auto& it : vec) {
        auto n = static_cast<int64_t>(it);
        v.emplace_back(n);
    }
    InitFromInts(v);
}

Object::Object(const set<uint64_t>& set) {
    vector<int64_t> v;
    v.reserve(set.size());
    for (auto& it : set) {
        auto n = static_cast<int64_t>(it);
        v.emplace_back(n);
    }
    InitFromInts(v);
}

Object::Object(const unordered_set<uint64_t>& set) {
    vector<int64_t> v;
    v.reserve(set.size());
    for (auto& it : set) {
        auto n = static_cast<int64_t>(it);
        v.emplace_back(n);
    }
    InitFromInts(v);
}

Object::Object(const vector<uint32_t>& vec) {
    vector<int64_t> v;
    v.reserve(vec.size());
    for (auto& it : vec) {
        auto n = static_cast<int64_t>(it);
        v.emplace_back(n);
    }
    InitFromInts(v);
}

Object::Object(const set<uint32_t>& set) {
    vector<int64_t> v;
    v.reserve(set.size());
    for (auto& it : set) {
        auto n = static_cast<int64_t>(it);
        v.emplace_back(n);
    }
    InitFromInts(v);
}

Object::Object(const unordered_set<uint32_t>& set) {
    vector<int64_t> v;
    v.reserve(set.size());
    for (auto& it : set) {
        auto n = static_cast<int64_t>(it);
        v.emplace_back(n);
    }
    InitFromInts(v);
}

Object::Object(const vector<string>& v) {
    InitFromStrings(v);
}

Object::Object(const set<string>& set) {
    vector<string> v;
    v.reserve(set.size());
    for (auto& it : set) {
        v.emplace_back(it);
    }
    InitFromStrings(v);
}

Object::Object(const unordered_set<string>& set) {
    vector<string> v;
    v.reserve(set.size());
    for (auto& it : set) {
        v.emplace_back(it);
    }
    InitFromStrings(v);
}

Object::Object(const vector<Object*>& v) {
    type_ = JOT_ARRAY;
    auto data = new vector<Object*>(v);
    data_ = reinterpret_cast<void*>(data);
}

Object::Object(const map<string, Object*>& d) {
    type_ = JOT_OBJ;
    auto data = new map<string, Object*>();
    for (auto& it : d) {
        (*data)[it.first] = it.second;
    }
    data_ = reinterpret_cast<void*>(data);
}

Object::~Object() {
    switch (type_) {
    case JOT_NULL:
        break;
    case JOT_BOOL:
        delete reinterpret_cast<bool*>(data_);
        break;
    case JOT_INT:
        delete reinterpret_cast<int64_t*>(data_);
        break;
    case JOT_STR:
        delete reinterpret_cast<string*>(data_);
        break;
    case JOT_ARRAY:
        {
            auto* data = reinterpret_cast<vector<Object*>*>(data_);
            for (auto& obj : *data) {
                delete obj;
            }
            delete data;
            break;
        }
    case JOT_OBJ:
        {
            auto* data = reinterpret_cast<map<string, Object*>*>(data_);
            for (auto& it : *data) {
                delete it.second;
            }
            delete data;
            break;
        }
    }
}

static void Quote(const string& in, string* out) {
    out->clear();
    out->reserve(in.size() + 2);
    *out += "\"";
    for (auto& c : in) {
        if (c == '"') {
            *out += "\\\"";
        } else {
            *out += c;
        }
    }
    *out += "\"";
}

void Object::AppendToString(
        string* out, size_t spaces_per_indent, size_t offset_spaces,
        bool leading_indent) const {
    string indent0(offset_spaces, ' ');
    string indent1(offset_spaces + spaces_per_indent, ' ');

    if (leading_indent) {
        *out += indent0;
    }

    switch (type_) {
    case JOT_NULL: {
        *out += "null";
        break;
    }
    case JOT_BOOL: {
        auto& b = *reinterpret_cast<bool*>(data_);
        *out += (b ? "true" : "false");
        break;
    }
    case JOT_INT: {
        auto& n = *reinterpret_cast<int64_t*>(data_);
        *out += strings::StringPrintf("%ld", n);
        break;
    }
    case JOT_STR: {
        auto& orig_s = *reinterpret_cast<string*>(data_);
        string quoted_s;
        Quote(orig_s, &quoted_s);
        *out += quoted_s;
        break;
    }
    case JOT_ARRAY: {
        auto& v = *reinterpret_cast<vector<Object*>*>(data_);
        *out += "[";
        if (v.size()) {
            *out += "\n";
        }
        for (auto i = 0u; i < v.size(); ++i) {
            auto& obj = v[i];
            obj->AppendToString(
                out, spaces_per_indent, offset_spaces + spaces_per_indent,
                true);
            if (i != v.size() - 1) {
                *out += ",";
            }
            *out += "\n";
        }
        if (v.size()) {
            *out += indent0;
        }
        *out += "]";
        break;
    }
    case JOT_OBJ: {
        auto& d = *reinterpret_cast<map<string, Object*>*>(data_);
        *out += "{";
        if (d.size()) {
            *out += "\n";
        }
        size_t count = 0;
        for (auto& it : d) {
            auto& orig_s = it.first;
            string quoted_s;
            Quote(orig_s, &quoted_s);
            *out += indent1 + quoted_s + ": ";
            auto& obj = it.second;
            obj->AppendToString(
                out, spaces_per_indent, offset_spaces + spaces_per_indent,
                false);
            if (count != d.size() - 1) {
                *out += ",";
            }
            *out += "\n";
        }
        if (d.size()) {
            *out += indent0;
        }
        *out += "}";
        break;
    }
    }
}

void Object::InitFromInts(const vector<int64_t>& v) {
    type_ = JOT_ARRAY;
    auto data = new vector<Object*>();
    data->reserve(v.size());
    for (auto& n : v) {
        data->emplace_back(new Object(n));
    }
    data_ = reinterpret_cast<void*>(data);
}

void Object::InitFromStrings(const vector<string>& v) {
    type_ = JOT_ARRAY;
    auto data = new vector<Object*>();
    data->reserve(v.size());
    for (auto& s : v) {
        data->emplace_back(new Object(s));
    }
    data_ = reinterpret_cast<void*>(data);
}

}  // namespace json
<|endoftext|>


<commit_before>//call this script like this to have live scores:
//while true; do git pull; make -j grades.html; sleep 15; done;
#include <dirent.h>
#include <fstream>
#include <iostream>
#include <map>
#include <set>
#include <string>

#include "../code/util.cpp"

using namespace std;

//grade one single test case
int gradeFile(ifstream& in, ifstream& ans) {
  //read input
  Input input;
  readInput(input, in);

  //read answer
  //TODO read answer

  //compute score
  //TODO compute score

  return -1;
}

//iterate over all test cases
int main() {
  //open data directory
  DIR* datadir = opendir("data");
  if(!datadir) {
    cerr << "can't find data directory" << endl;
    return 1;
  }
  //save result data
  set<string> algorithms, testcases;
  map<pair<string, string>, int> scores;
  map<string, int> maxscores;
  //iterate over all files
  struct dirent* file;
  ifstream in, ans;
  while(0 != (file = readdir(datadir))) {
    string ansname = file->d_name;
    if(ansname.size() > 4 && !ansname.compare(ansname.size() - 4, 4, ".ans")) {
      cerr << "solving file " << ansname << endl;
      string testcase = ansname.substr(ansname.find_first_of(".") + 1, ansname.find_last_of(".") - ansname.find_first_of(".") - 1);
      testcases.insert(testcase);
      string algorithm = ansname.substr(0, ansname.find_first_of("."));
      algorithms.insert(algorithm);
      in.open("data/" + testcase + ".in");
      ans.open("data/" + ansname);
      scores[make_pair(algorithm, testcase)] = gradeFile(in, ans);
      maxscores[testcase] = max(maxscores[testcase], scores[make_pair(algorithm, testcase)]);
      in.close();
      ans.close();
    }
  }
  //print header
  cout << "<meta http-equiv=\"refresh\" content=\"15\" >"
          "<link rel=\"stylesheet\" href=\"https://fonts.googleapis.com/icon?family=Material+Icons\">"
          "<link rel=\"stylesheet\" href=\"https://code.getmdl.io/1.3.0/material.indigo-pink.min.css\">"
          "" << endl;
  //print table
  cout << "
" << endl << "

algorithm	";
  for(string testcase: testcases) {
    cout << "" << testcase << "	";
  }
  cout << "sum

" << endl;
  for(string algorithm: algorithms) {
    int sum = 0;
    cout << "
" << algorithm << "	";
    for(string testcase: testcases) {
      if(scores.find(make_pair(algorithm, testcase)) != scores.end()) {
        cout << "<td" << (scores[make_pair(algorithm, testcase)] == maxscores[testcase] ? " style=\"font-weight: bold;\"" : "") << ">" << scores[make_pair(algorithm, testcase)] << "	";
        sum += scores[make_pair(algorithm, testcase)];
      }
      else {
        cout << "-	";
      }
    }
    cout << "" << sum << "
" << endl;
  }
  int sum = 0;
  cout << "
maximum	";
  for(string testcase: testcases) {
    cout << "" << maxscores[testcase] << "	";
    sum += maxscores[testcase];
  }
  cout << "" << sum << "
" << endl << "

" << endl;
  //print footer
  cout << "" << endl;
}
<commit_msg>grader<commit_after>//call this script like this to have live scores:
//while true; do git pull; make -j grades.html; sleep 15; done;
#include <dirent.h>
#include <fstream>
#include <iostream>
#include <map>
#include <set>
#include <string>

#include "../code/util.cpp"

using namespace std;

//grade one single test case
int gradeFile(ifstream& in, ifstream& ans) {
  //read input
  Input input;
  readInput(input, in);

  //read answer
  ll score;

  set<pair<ll, ll>> done;
  // collid, amount
  map<int, int> amount;

  ll pics;
  ans >> pics;
  for (int i = 0; i < pics; i++) {
    ll lat, lon, t, s;
    ans >> lat >> lon >> t >> s;

    // TODO: check if photo can be made by satelite s
    for (int c : input.objects[make_pair(lat, lon)].collection_ids) {
      Collection& coll = input.collections[c];

      // TODO: check if t is in one of the intervals of coll
      if (!(std::find(done.begin(), done.end(), make_pair(lat, lon)) == done.end())) {
        amount[c] += 1;
        if (amount[c] == coll.objects.size()) {
          score += coll.v;
        }
      }
    }
  }
  return score;
}

//iterate over all test cases
int main() {
  //open data directory
  DIR* datadir = opendir("data");
  if(!datadir) {
    cerr << "can't find data directory" << endl;
    return 1;
  }
  //save result data
  set<string> algorithms, testcases;
  map<pair<string, string>, int> scores;
  map<string, int> maxscores;
  //iterate over all files
  struct dirent* file;
  ifstream in, ans;
  while(0 != (file = readdir(datadir))) {
    string ansname = file->d_name;
    if(ansname.size() > 4 && !ansname.compare(ansname.size() - 4, 4, ".ans")) {
      cerr << "solving file " << ansname << endl;
      string testcase = ansname.substr(ansname.find_first_of(".") + 1, ansname.find_last_of(".") - ansname.find_first_of(".") - 1);
      testcases.insert(testcase);
      string algorithm = ansname.substr(0, ansname.find_first_of("."));
      algorithms.insert(algorithm);
      in.open("data/" + testcase + ".in");
      ans.open("data/" + ansname);
      scores[make_pair(algorithm, testcase)] = gradeFile(in, ans);
      maxscores[testcase] = max(maxscores[testcase], scores[make_pair(algorithm, testcase)]);
      in.close();
      ans.close();
    }
  }
  //print header
  cout << "<meta http-equiv=\"refresh\" content=\"15\" >"
          "<link rel=\"stylesheet\" href=\"https://fonts.googleapis.com/icon?family=Material+Icons\">"
          "<link rel=\"stylesheet\" href=\"https://code.getmdl.io/1.3.0/material.indigo-pink.min.css\">"
          "" << endl;
  //print table
  cout << "
" << endl << "

algorithm	";
  for(string testcase: testcases) {
    cout << "" << testcase << "	";
  }
  cout << "sum

" << endl;
  for(string algorithm: algorithms) {
    int sum = 0;
    cout << "
" << algorithm << "	";
    for(string testcase: testcases) {
      if(scores.find(make_pair(algorithm, testcase)) != scores.end()) {
        cout << "<td" << (scores[make_pair(algorithm, testcase)] == maxscores[testcase] ? " style=\"font-weight: bold;\"" : "") << ">" << scores[make_pair(algorithm, testcase)] << "	";
        sum += scores[make_pair(algorithm, testcase)];
      }
      else {
        cout << "-	";
      }
    }
    cout << "" << sum << "
" << endl;
  }
  int sum = 0;
  cout << "
maximum	";
  for(string testcase: testcases) {
    cout << "" << maxscores[testcase] << "	";
    sum += maxscores[testcase];
  }
  cout << "" << sum << "
" << endl << "

" << endl;
  //print footer
  cout << "" << endl;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017 Joyent Inc.
 * All rights reserved.
 *
 * Written by: Matthew Macy <matt.macy@joyent.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *   2. 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 AUTHOR 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 AUTHOR 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 <sys/types.h>
#include <stdio.h>

#include <net/ethernet.h>
#define NETMAP_WITH_LIBS
#include <net/netmap_user.h>
#include <sys/poll.h>

#include "uvxbridge.h"
#include "uvxlan.h"

#define AE_REQUEST		0x0100040600080100UL
#define AE_REPLY		0x0200040600080100UL
#define AE_REVREQUEST		0x0300040600080100UL
#define AE_REVREPLY		0x0400040600080100UL

#define AE_REQUEST_ALL		0x0A00040600080100UL
#define AE_REVREQUEST_ALL	0x0B00040600080100UL
#define AE_VM_VXLANID_REQUEST	0x0C00040600080100UL
#define AE_VM_VXLANID_REQUEST_ALL	0x0D00040600080100UL
#define AE_VM_VXLANID_REPLY	0x0E00040600080100UL
#define AE_VM_VLANID_REQUEST	0x0F00040600080100UL
#define AE_VM_VLANID_REQUEST_ALL	0x1000040600080100UL
#define AE_VM_VLANID_REPLY	0x1100040600080100UL

#define A(val) printf("got %s\n", #val)
extern int debug;

int
cmd_dispatch_arp(char *rxbuf, char *txbuf, path_state_t *ps, vxstate_t *state)
{
	struct arphdr_ether *sah, *dah;
	struct ether_header *eh;
	int op, len;
	uint32_t hostip, targetpa = 0;
	uint16_t *rmacp, *lmacp;
	uint64_t targetha = 0, reply = 0;
	l2tbl_t &tbl = state->vs_l2_phys;

	len = ps->ps_rx_len;
	if (len < ETHER_HDR_LEN + sizeof(struct arphdr_ether) && debug < 2)
		return 0;

	sah = (struct arphdr_ether *)(rxbuf + ETHER_HDR_LEN);
	dah = (struct arphdr_ether *)(txbuf + ETHER_HDR_LEN);
	op = ntohs(sah->ae_hdr.fields.ar_op);
	/* place holder */
	hostip = htobe32(0xDEADBEEF);

	switch (op) {
		case ARPOP_REQUEST: {
			A(ARPOP_REQUEST);
			auto it = tbl.l2t_v4.find(sah->ae_tpa);
			if (it != tbl.l2t_v4.end()) {
				reply = AE_REPLY;
				targetpa = sah->ae_tpa;
				targetha = it->second;
			}
			break;
		}
		case ARPOP_REPLY:
			A(ARPOP_REPLY);
			memcpy(&targetha, sah->ae_tha, ETHER_ADDR_LEN);
			tbl.l2t_v4.insert(pair<uint32_t, uint64_t>(sah->ae_tpa, targetha));
			break;
		case ARPOP_REVREQUEST:
			A(ARPOP_REVREQUEST);
			reply = AE_REVREPLY;
			break;
		case ARPOP_REVREPLY:
			A(ARPOP_REVREPLY);
			break;
		case ARPOP_REQUEST_ALL:
			A(ARPOP_REQUEST_ALL);
			break;
		case ARPOP_REVREQUEST_ALL:
			A(ARPOP_REVREQUEST_ALL);
			break;
		case ARPOP_VM_VXLANID_REQUEST:
			A(ARPOP_VM_VXLANID_REQUEST);
			reply = AE_VM_VXLANID_REPLY;
			break;
		case ARPOP_VM_VXLANID_REQUEST_ALL:
			A(ARPOP_VM_VXLANID_REQUEST_ALL);
			break;
		case ARPOP_VM_VXLANID_REPLY:
			A(ARPOP_VM_VXLANID_REPLY);
			break;
		case ARPOP_VM_VLANID_REQUEST:
			A(ARPOP_VM_VLANID_REQUEST);
			reply = AE_VM_VLANID_REPLY;
			break;
		case ARPOP_VM_VLANID_REQUEST_ALL:
			A(ARPOP_VM_VLANID_REQUEST);
			break;
		case ARPOP_VM_VLANID_REPLY:
			A(ARPOP_VM_VLANID_REPLY);
			break;
		default:
			printf("unrecognized value data: 0x%016lX op: 0x%02X\n", sah->ae_hdr.data, op);
	}
	/* save potential cache stall to the end */
	if (reply) {
		eh = (struct ether_header *)txbuf;
		lmacp = (uint16_t *)&eh->ether_dhost;
		rmacp =  (uint16_t *)&state->vs_prov_mac;
		lmacp[0] = rmacp[0];
		lmacp[1] = rmacp[1];
		lmacp[2] = rmacp[2];
		rmacp =  (uint16_t *)&state->vs_ctrl_mac;
		lmacp[3] = rmacp[0];
		lmacp[4] = rmacp[1];
		lmacp[5] = rmacp[2];
		/* [6] */
		eh->ether_type = ETHERTYPE_ARP;
		/* [7-10] */
		dah->ae_hdr.data = reply;
		/* [11-13] - ar_sha */
		lmacp[11] = rmacp[0];
		lmacp[12] = rmacp[1];
		lmacp[13] = rmacp[2];
		/* [14-15] - ae_spa */
		dah->ae_spa = hostip;

		rmacp = (uint16_t *)&targetha;
		/* [16-18] - ae_tha */
		lmacp[16] = rmacp[0];
		lmacp[17] = rmacp[1];
		lmacp[18] = rmacp[2];
		/* actual value of interest */
		dah->ae_tpa = targetpa;
		return (1);
	}
	return (0);
}

/*
 * If rxbuf contains a neighbor discovery request return true.
 * If it's an nd request we can handle, enqueue a response.
 *
 * dir = EGRESS => VX, dir = INGRESS => PHYS
 */
bool
nd_request(struct arphdr_ether *sae, arphdr_ether *dae, vxstate_t &state, l2tbl_t &tbl)
{
#if 0
//  XXX we assume prepopulated ARP table so ignore replies
//	if (ae->ae_req != arpopreq && ae->ae_req != arpopreply)
	if (sae->ae_req != arpopreq)
		return false;

	dae->ae_req = arpopreply;
#endif
	abort();
	return true;
}

/*
 * If valid, deencapsulate rxbuf in to txbuf
 *
 */
bool
vxlan_decap(char *rxbuf, char *txbuf, int len, vxstate_t &state __unused)
{

	nm_pkt_copy(rxbuf, txbuf, len);
	return true;
}

/*
 * If valid, encapsulate rxbuf in to txbuf
 *
 */
bool
vxlan_encap(char *rxbuf, char *txbuf, int len, vxstate_t &state __unused)
{
	struct ether_vlan_header *evh, *evhrsp;
	int hdrlen, etype;

	evh = (struct ether_vlan_header *)(rxbuf);
	if (evh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
		hdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
		etype = ntohs(evh->evl_proto);
	} else {
		hdrlen = ETHER_HDR_LEN;
		etype = ntohs(evh->evl_encap_proto);
	}
	if (etype != ETHERTYPE_IP && etype != ETHERTYPE_IPV6)
		return false;
	/* first map evh->evl_shost -> vxlanid / vlanid */
	/* ..... */
	/* next map evh->evl_dhost -> remote ip addr in the corresponding forwarding table */
	/* ..... */
	/* next check if remote ip is on our local subnet */
	/* .... */
	/* if yes - lookup MAC address for peer */
	/* .... */
	/* if no - lookup MAC address for corresponding router */
	/* .... */
	/* use source IP for said subnet */
	/* calculate source port */
	/* .... */

	evhrsp = (struct ether_vlan_header *)(txbuf);
    nm_pkt_copy(rxbuf, txbuf, len);
    return true;
}
<commit_msg>add forwarding table lookup / update<commit_after>/*
 * Copyright (C) 2017 Joyent Inc.
 * All rights reserved.
 *
 * Written by: Matthew Macy <matt.macy@joyent.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *   2. 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 AUTHOR 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 AUTHOR 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 <sys/types.h>
#include <stdio.h>

#include <net/ethernet.h>
#define NETMAP_WITH_LIBS
#include <net/netmap_user.h>
#include <sys/poll.h>

#include "uvxbridge.h"
#include "uvxlan.h"

#define AE_REQUEST		0x0100040600080100UL
#define AE_REPLY		0x0200040600080100UL
#define AE_REVREQUEST		0x0300040600080100UL
#define AE_REVREPLY		0x0400040600080100UL

#define AE_REQUEST_ALL		0x0A00040600080100UL
#define AE_REVREQUEST_ALL	0x0B00040600080100UL
#define AE_VM_VXLANID_REQUEST	0x0C00040600080100UL
#define AE_VM_VXLANID_REQUEST_ALL	0x0D00040600080100UL
#define AE_VM_VXLANID_REPLY	0x0E00040600080100UL
#define AE_VM_VLANID_REQUEST	0x0F00040600080100UL
#define AE_VM_VLANID_REQUEST_ALL	0x1000040600080100UL
#define AE_VM_VLANID_REPLY	0x1100040600080100UL

#define A(val) printf("got %s\n", #val)
extern int debug;

int
cmd_dispatch_arp(char *rxbuf, char *txbuf, path_state_t *ps, vxstate_t *state)
{
	struct arphdr_ether *sah, *dah;
	struct ether_header *eh;
	int op, len;
	uint32_t hostip, targetpa = 0;
	uint16_t *rmacp, *lmacp;
	uint64_t targetha = 0, reply = 0;
	l2tbl_t &l2tbl = state->vs_l2_phys;
	ftable_t &ftable = state->vs_ftable;

	len = ps->ps_rx_len;
	if (len < ETHER_HDR_LEN + sizeof(struct arphdr_ether) && debug < 2)
		return 0;

	sah = (struct arphdr_ether *)(rxbuf + ETHER_HDR_LEN);
	dah = (struct arphdr_ether *)(txbuf + ETHER_HDR_LEN);
	op = ntohs(sah->ae_hdr.fields.ar_op);
	/* place holder */
	hostip = htobe32(0xDEADBEEF);

	switch (op) {
		case ARPOP_REQUEST: {
			A(ARPOP_REQUEST);
			auto it = l2tbl.l2t_v4.find(sah->ae_tpa);
			if (it != l2tbl.l2t_v4.end()) {
				reply = AE_REPLY;
				targetpa = sah->ae_tpa;
				targetha = it->second;
			}
			break;
		}
		case ARPOP_REPLY:
			A(ARPOP_REPLY);
			memcpy(&targetha, sah->ae_tha, ETHER_ADDR_LEN);
			if (targetha == 0)
				l2tbl.l2t_v4.erase(sah->ae_tpa);
			else
				l2tbl.l2t_v4.insert(pair<uint32_t, uint64_t>(sah->ae_tpa, targetha));
			break;
		case ARPOP_REVREQUEST: {
			/* ipv4 forwarding table lookup */
			A(ARPOP_REVREQUEST);
			memcpy(&targetha, sah->ae_tha, ETHER_ADDR_LEN);
			auto it = ftable.find(targetha);
			if (it != ftable.end() && it->second.vfe_v6 == 0) {
				reply = AE_REVREPLY;
				targetpa = it->second.vfe_raddr.in4.s_addr;
			}
			break;
		}
		case ARPOP_REVREPLY: {
			A(ARPOP_REVREPLY);
			memcpy(&targetha, sah->ae_tha, ETHER_ADDR_LEN);
			if (sah->ae_tpa == 0)
				ftable.erase(targetha);
			else {
				vfe_t vfe;
				vfe.vfe_raddr.in4.s_addr = sah->ae_tpa;
				ftable.insert(fwdent(targetha, vfe));
			}
			break;
		}
		case ARPOP_REQUEST_ALL:
			A(ARPOP_REQUEST_ALL);
			break;
		case ARPOP_REVREQUEST_ALL:
			A(ARPOP_REVREQUEST_ALL);
			break;
		case ARPOP_VM_VXLANID_REQUEST:
			A(ARPOP_VM_VXLANID_REQUEST);
			reply = AE_VM_VXLANID_REPLY;
			break;
		case ARPOP_VM_VXLANID_REQUEST_ALL:
			A(ARPOP_VM_VXLANID_REQUEST_ALL);
			break;
		case ARPOP_VM_VXLANID_REPLY:
			A(ARPOP_VM_VXLANID_REPLY);
			break;
		case ARPOP_VM_VLANID_REQUEST:
			A(ARPOP_VM_VLANID_REQUEST);
			reply = AE_VM_VLANID_REPLY;
			break;
		case ARPOP_VM_VLANID_REQUEST_ALL:
			A(ARPOP_VM_VLANID_REQUEST);
			break;
		case ARPOP_VM_VLANID_REPLY:
			A(ARPOP_VM_VLANID_REPLY);
			break;
		default:
			printf("unrecognized value data: 0x%016lX op: 0x%02X\n", sah->ae_hdr.data, op);
	}
	/* save potential cache stall to the end */
	if (reply) {
		eh = (struct ether_header *)txbuf;
		lmacp = (uint16_t *)&eh->ether_dhost;
		rmacp =  (uint16_t *)&state->vs_prov_mac;
		lmacp[0] = rmacp[0];
		lmacp[1] = rmacp[1];
		lmacp[2] = rmacp[2];
		rmacp =  (uint16_t *)&state->vs_ctrl_mac;
		lmacp[3] = rmacp[0];
		lmacp[4] = rmacp[1];
		lmacp[5] = rmacp[2];
		/* [6] */
		eh->ether_type = ETHERTYPE_ARP;
		/* [7-10] */
		dah->ae_hdr.data = reply;
		/* [11-13] - ar_sha */
		lmacp[11] = rmacp[0];
		lmacp[12] = rmacp[1];
		lmacp[13] = rmacp[2];
		/* [14-15] - ae_spa */
		dah->ae_spa = hostip;

		rmacp = (uint16_t *)&targetha;
		/* [16-18] - ae_tha */
		lmacp[16] = rmacp[0];
		lmacp[17] = rmacp[1];
		lmacp[18] = rmacp[2];
		/* actual value of interest */
		dah->ae_tpa = targetpa;
		return (1);
	}
	return (0);
}

/*
 * If rxbuf contains a neighbor discovery request return true.
 * If it's an nd request we can handle, enqueue a response.
 *
 * dir = EGRESS => VX, dir = INGRESS => PHYS
 */
bool
nd_request(struct arphdr_ether *sae, arphdr_ether *dae, vxstate_t &state, l2tbl_t &tbl)
{
#if 0
//  XXX we assume prepopulated ARP table so ignore replies
//	if (ae->ae_req != arpopreq && ae->ae_req != arpopreply)
	if (sae->ae_req != arpopreq)
		return false;

	dae->ae_req = arpopreply;
#endif
	abort();
	return true;
}

/*
 * If valid, deencapsulate rxbuf in to txbuf
 *
 */
bool
vxlan_decap(char *rxbuf, char *txbuf, int len, vxstate_t &state __unused)
{

	nm_pkt_copy(rxbuf, txbuf, len);
	return true;
}

/*
 * If valid, encapsulate rxbuf in to txbuf
 *
 */
bool
vxlan_encap(char *rxbuf, char *txbuf, int len, vxstate_t &state __unused)
{
	struct ether_vlan_header *evh, *evhrsp;
	int hdrlen, etype;

	evh = (struct ether_vlan_header *)(rxbuf);
	if (evh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
		hdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
		etype = ntohs(evh->evl_proto);
	} else {
		hdrlen = ETHER_HDR_LEN;
		etype = ntohs(evh->evl_encap_proto);
	}
	if (etype != ETHERTYPE_IP && etype != ETHERTYPE_IPV6)
		return false;
	/* first map evh->evl_shost -> vxlanid / vlanid */
	/* ..... */
	/* next map evh->evl_dhost -> remote ip addr in the corresponding forwarding table */
	/* ..... */
	/* next check if remote ip is on our local subnet */
	/* .... */
	/* if yes - lookup MAC address for peer */
	/* .... */
	/* if no - lookup MAC address for corresponding router */
	/* .... */
	/* use source IP for said subnet */
	/* calculate source port */
	/* .... */

	evhrsp = (struct ether_vlan_header *)(txbuf);
    nm_pkt_copy(rxbuf, txbuf, len);
    return true;
}
<|endoftext|>


<commit_before>#include <stdio.h>
//#include <unistd.h>

#include <utility>
#include <iostream>

#include <boost/bind.hpp>
#include <boost/scoped_ptr.hpp>

#include <muduo/base/Logging.h>
#include <muduo/base/Thread.h>
#include <muduo/net/EventLoop.h>
#include <muduo/net/InetAddress.h>

#include <bfcp/client/base_client.h>

using namespace muduo;
using namespace muduo::net;
using namespace bfcp;
using namespace bfcp::client;

void controlFunc(EventLoop *loop);
void onClientStateChanged(BaseClient::State state);
void onReceivedResponse(BaseClient::Error error, bfcp_prim prim, void *data);

#define CHECK_CIN_RESULT(res) do {\
  if (!(res)) {\
  std::cin.clear(); \
  std::cin.ignore(); \
  break; \
  }\
} while (false)

int main(int argc, char* argv[])
{
  Logger::setLogLevel(Logger::kTRACE);
  LOG_INFO << "pid = " << getpid() << ", tid = " << CurrentThread::tid();

  EventLoop loop;
  Thread thread(boost::bind(&controlFunc, &loop));
  thread.start();

  loop.loop();
  thread.join();
}

void printMenu()
{
  printf(
    "\n--------PARTICIPANT LIST-----------------------------\n"
    " ?      - Show the menu\n"
    " c      - Create the Participant\n"
    " h      - Destroy the Participant\n"
    " s      - Show the information of the conference\n"
    "BFCP Messages:\n"
    " f      - Hello\n"
    " r      - FloorRequest\n"
    " l      - FloorRelease\n"
    " o      - FloorRequestQuery\n"
    " u      - UserQuery\n"
    " e      - FloorQuery\n"
    " a      - ChairAction\n"
    " q      - quit\n"
    "------------------------------------------------------\n\n");
}

void controlFunc(EventLoop *loop)
{
  boost::shared_ptr<BaseClient> client;
  printMenu();
  char ch;
  while (std::cin >> ch)
  {
    switch (ch)
    {
      case '?':
        printMenu(); break;
      case 'c':
        {
          if (client)
          {
            printf("Error: A participant already exist\n");
            break;
          }
          printf("Enter the conferenceID of the conference:\n");
          uint32_t conferenceID;
          CHECK_CIN_RESULT(std::cin >> conferenceID);
          printf("Enter the userID of the participant:\n");
          uint16_t userID;
          CHECK_CIN_RESULT(std::cin >> userID);
          InetAddress serverAddr(AF_INET, "127.0.0.1", 7890);
          printf("connect to hostport:%s\n", serverAddr.toIpPort().c_str());
          client.reset(new BaseClient(loop, serverAddr, conferenceID, userID));
          client->setStateChangedCallback(&onClientStateChanged);
          client->setResponseReceivedCallback(&onReceivedResponse);
          client->connect();
          printf("BFCP Participant created.\n");
        } break;
      case 'h':
        {
          if (!client)
          {
            printf("Error: No participant exist\n");
            break;
          }
          client->forceDisconnect();
          // client must destruct in event loop
          loop->runInLoop(boost::bind(&boost::shared_ptr<BaseClient>::reset, client));
          client = nullptr;
          printf("BFCP participant destroyed.\n");
        } break;
      case 'f':
        if (!client)
        {
          printf("Error: No participant exist\n");
          break;
        }
        client->sendHello();
        break;

      case 'r':
        {
          if (!client)
          {
            printf("Error: No participant exist\n");
            break;
          }
          FloorRequestParam param;
          printf("Request for beneficiary user?: 0=false, 1=true\n");
          CHECK_CIN_RESULT(std::cin >> param.hasBeneficiaryID);
          if (param.hasBeneficiaryID)
          {
            printf("Enter the BeneficiaryID of the new request:\n");
            CHECK_CIN_RESULT(std::cin >> param.beneficiaryID);
          }
          printf("Enter the priority for this request (0=lowest --> 4=highest):\n");
          int priority = 0;
          CHECK_CIN_RESULT(std::cin >> priority);
          param.priority = static_cast<bfcp_priority>(priority);
          printf("Enter the FloorID:\n");
          uint16_t floorID = 0;
          CHECK_CIN_RESULT(std::cin >> floorID);
          param.floorIDs.push_back(floorID);
          printf("Enter the rest floors count:\n");
          size_t restCount = 0;
          CHECK_CIN_RESULT(std::cin >> restCount);
          printf("Enter the rest floorIDs:\n");
          for (size_t i = 0; i < restCount; ++i)
          {
            CHECK_CIN_RESULT(std::cin >> floorID);
            param.floorIDs.push_back(floorID);
          }
          client->sendFloorRequest(param);
          printf("Message sent!\n");
        } break;

      case 'l':
        {
          if (!client)
          {
            printf("Error: No participant exist\n");
            break;
          }
          printf("Enter the FloorRequestID of the request you want to release:\n");
          uint16_t floorRequestID;
          CHECK_CIN_RESULT(std::cin >> floorRequestID);
          client->sendFloorRelease(floorRequestID);
          printf("Message send!\n");
        } break;

      case 'o':
        {
          if (!client)
          {
            printf("Error: No participant exist\n");
            break;
          }
          printf("Enter the FloorRequestID of the request you're interested in:\n");
          uint16_t floorRequestID = 0;
          CHECK_CIN_RESULT(std::cin >> floorRequestID);
          client->sendFloorRequestQuery(floorRequestID);
          printf("Message send!\n");
        } break;

      case 'u':
        {
          if (!client)
          {
            printf("Error: No participant exist\n");
            break;
          }
          UserQueryParam param;
          printf("Query the beneficiary user?: 0=false, 1=true\n");
          CHECK_CIN_RESULT(std::cin >> param.hasBeneficiaryID);
          if (param.hasBeneficiaryID)
          {
            printf("Enter the BeneficiaryID if you want information about a specific user:\n");
            CHECK_CIN_RESULT(std::cin >> param.beneficiaryID);
          }
          client->sendUserQuery(param);
          printf("Message send!\n");
        } break;

      case 'e':
        {
          if (!client)
          {
            printf("Error: No participant exist\n");
            break;
          }
          bfcp_floor_id_list floorIDs;
          printf("Enter the floorID count:\n");
          size_t floorIDCount = 0;
          CHECK_CIN_RESULT(std::cin >> floorIDCount);
          printf("Enter the FloorIDs:\n");
          uint16_t floorID = 0;
          for (size_t i = 0; i < floorIDCount; ++i)
          {
            CHECK_CIN_RESULT(std::cin >> floorID);
            floorIDs.push_back(floorID);
          }
          client->sendFloorQuery(floorIDs);
          printf("Message send!\n");
        } break;

      case 'a':
        {
          if (!client)
          {
            printf("Error: No participant exist\n");
            break;
          }
          FloorRequestInfoParam param;
          printf("Enter the FloorRequestID:\n");
          CHECK_CIN_RESULT(std::cin >> param.floorRequestID);

          param.valueType |= AttrValueType::kHasOverallRequestStatus;
          param.oRS.floorRequestID = param.floorRequestID;
          param.oRS.hasRequestStatus = true;
          printf("What to do with this request? (2=Accept / 4=Deny / 7=Revoke):\n");
          int status;
          CHECK_CIN_RESULT(std::cin >> status);
          param.oRS.requestStatus.status = static_cast<bfcp_reqstat>(status);

          printf("Enter the desired position in queue for this request (0 if you are not interested in that):\n");
          int pos = 0;
          CHECK_CIN_RESULT(std::cin >> pos);
          param.oRS.requestStatus.qpos = static_cast<uint8_t>(pos);

          FloorRequestStatusParam floorStatus;
          printf("Enter the FloorID:\n");
          CHECK_CIN_RESULT(std::cin >> floorStatus.floorID);
          param.fRS.push_back(floorStatus);

          printf("Enter the rest floors count:\n");
          size_t restCount = 0;
          CHECK_CIN_RESULT(std::cin >> restCount);
          printf("Enter the rest floorIDs:\n");
          for (size_t i = 0; i < restCount; ++i)
          {
            CHECK_CIN_RESULT(std::cin >> floorStatus.floorID);
            param.fRS.push_back(floorStatus);
          }

          client->sendChairAction(param);
          printf("Message send!\n");
        } break;

      case 's':
        // TODO:
        printf("TODO:\n");
        break;

      case 'q':
        printf("Quit\n");
        if (client)
        {
          client->forceDisconnect();
          client.reset();
        }
        loop->quit();
        return;

      default:
        printf("Invalid menu choice - try again\n");
        break;
    }
  }
}

void onClientStateChanged( BaseClient::State state )
{

}

void onReceivedResponse( BaseClient::Error error, bfcp_prim prim, void *data )
{

}
<commit_msg>fix bug in bfcp client<commit_after>#include <stdio.h>
//#include <unistd.h>

#include <utility>
#include <iostream>

#include <boost/bind.hpp>
#include <boost/scoped_ptr.hpp>

#include <muduo/base/Logging.h>
#include <muduo/base/Thread.h>
#include <muduo/net/EventLoop.h>
#include <muduo/net/InetAddress.h>

#include <bfcp/client/base_client.h>

using namespace muduo;
using namespace muduo::net;
using namespace bfcp;
using namespace bfcp::client;

void controlFunc(EventLoop *loop);
void onClientStateChanged(BaseClient::State state);
void onReceivedResponse(BaseClient::Error error, bfcp_prim prim, void *data);

#define CHECK_CIN_RESULT(res) do {\
  if (!(res)) {\
  std::cin.clear(); \
  std::cin.ignore(); \
  break; \
  }\
} while (false)

int main(int argc, char* argv[])
{
  Logger::setLogLevel(Logger::kTRACE);
  LOG_INFO << "pid = " << getpid() << ", tid = " << CurrentThread::tid();

  EventLoop loop;
  Thread thread(boost::bind(&controlFunc, &loop));
  thread.start();

  loop.loop();
  thread.join();
}

void printMenu()
{
  printf(
    "\n--------PARTICIPANT LIST-----------------------------\n"
    " ?      - Show the menu\n"
    " c      - Create the Participant\n"
    " h      - Destroy the Participant\n"
    " s      - Show the information of the conference\n"
    "BFCP Messages:\n"
    " f      - Hello\n"
    " r      - FloorRequest\n"
    " l      - FloorRelease\n"
    " o      - FloorRequestQuery\n"
    " u      - UserQuery\n"
    " e      - FloorQuery\n"
    " a      - ChairAction\n"
    " q      - quit\n"
    "------------------------------------------------------\n\n");
}

void controlFunc(EventLoop *loop)
{
  boost::shared_ptr<BaseClient> client;
  printMenu();
  char ch;
  while (std::cin >> ch)
  {
    switch (ch)
    {
      case '?':
        printMenu(); break;
      case 'c':
        {
          if (client)
          {
            printf("Error: A participant already exist\n");
            break;
          }
          printf("Enter the conferenceID of the conference:\n");
          uint32_t conferenceID;
          CHECK_CIN_RESULT(std::cin >> conferenceID);
          printf("Enter the userID of the participant:\n");
          uint16_t userID;
          CHECK_CIN_RESULT(std::cin >> userID);
          InetAddress serverAddr(AF_INET, "127.0.0.1", 7890);
          printf("connect to hostport:%s\n", serverAddr.toIpPort().c_str());
          client.reset(new BaseClient(loop, serverAddr, conferenceID, userID));
          client->setStateChangedCallback(&onClientStateChanged);
          client->setResponseReceivedCallback(&onReceivedResponse);
          client->connect();
          printf("BFCP Participant created.\n");
        } break;
      case 'h':
        {
          if (!client)
          {
            printf("Error: No participant exist\n");
            break;
          }
          client->forceDisconnect();
          // client must destruct in event loop
          loop->runInLoop(boost::bind(&boost::shared_ptr<BaseClient>::reset, client));
          client = nullptr;
          printf("BFCP participant destroyed.\n");
        } break;
      case 'f':
        if (!client)
        {
          printf("Error: No participant exist\n");
          break;
        }
        client->sendHello();
        break;

      case 'r':
        {
          if (!client)
          {
            printf("Error: No participant exist\n");
            break;
          }
          FloorRequestParam param;
          printf("Request for beneficiary user?: 0=false, 1=true\n");
          CHECK_CIN_RESULT(std::cin >> param.hasBeneficiaryID);
          if (param.hasBeneficiaryID)
          {
            printf("Enter the BeneficiaryID of the new request:\n");
            CHECK_CIN_RESULT(std::cin >> param.beneficiaryID);
          }
          printf("Enter the priority for this request (0=lowest --> 4=highest):\n");
          int priority = 0;
          CHECK_CIN_RESULT(std::cin >> priority);
          param.priority = static_cast<bfcp_priority>(priority);
          printf("Enter the FloorID:\n");
          uint16_t floorID = 0;
          CHECK_CIN_RESULT(std::cin >> floorID);
          param.floorIDs.push_back(floorID);
          printf("Enter the rest floors count:\n");
          size_t restCount = 0;
          CHECK_CIN_RESULT(std::cin >> restCount);
          printf("Enter the rest floorIDs:\n");
          for (size_t i = 0; i < restCount; ++i)
          {
            CHECK_CIN_RESULT(std::cin >> floorID);
            param.floorIDs.push_back(floorID);
          }
          client->sendFloorRequest(param);
          printf("Message sent!\n");
        } break;

      case 'l':
        {
          if (!client)
          {
            printf("Error: No participant exist\n");
            break;
          }
          printf("Enter the FloorRequestID of the request you want to release:\n");
          uint16_t floorRequestID;
          CHECK_CIN_RESULT(std::cin >> floorRequestID);
          client->sendFloorRelease(floorRequestID);
          printf("Message send!\n");
        } break;

      case 'o':
        {
          if (!client)
          {
            printf("Error: No participant exist\n");
            break;
          }
          printf("Enter the FloorRequestID of the request you're interested in:\n");
          uint16_t floorRequestID = 0;
          CHECK_CIN_RESULT(std::cin >> floorRequestID);
          client->sendFloorRequestQuery(floorRequestID);
          printf("Message send!\n");
        } break;

      case 'u':
        {
          if (!client)
          {
            printf("Error: No participant exist\n");
            break;
          }
          UserQueryParam param;
          printf("Query the beneficiary user?: 0=false, 1=true\n");
          CHECK_CIN_RESULT(std::cin >> param.hasBeneficiaryID);
          if (param.hasBeneficiaryID)
          {
            printf("Enter the BeneficiaryID if you want information about a specific user:\n");
            CHECK_CIN_RESULT(std::cin >> param.beneficiaryID);
          }
          client->sendUserQuery(param);
          printf("Message send!\n");
        } break;

      case 'e':
        {
          if (!client)
          {
            printf("Error: No participant exist\n");
            break;
          }
          bfcp_floor_id_list floorIDs;
          printf("Enter the floorID count:\n");
          size_t floorIDCount = 0;
          CHECK_CIN_RESULT(std::cin >> floorIDCount);
          printf("Enter the FloorIDs:\n");
          uint16_t floorID = 0;
          for (size_t i = 0; i < floorIDCount; ++i)
          {
            CHECK_CIN_RESULT(std::cin >> floorID);
            floorIDs.push_back(floorID);
          }
          client->sendFloorQuery(floorIDs);
          printf("Message send!\n");
        } break;

      case 'a':
        {
          if (!client)
          {
            printf("Error: No participant exist\n");
            break;
          }
          FloorRequestInfoParam param;
          printf("Enter the FloorRequestID:\n");
          CHECK_CIN_RESULT(std::cin >> param.floorRequestID);

          param.valueType |= AttrValueType::kHasOverallRequestStatus;
          param.oRS.floorRequestID = param.floorRequestID;
          param.oRS.hasRequestStatus = true;
          printf("What to do with this request? (2=Accept / 4=Deny / 7=Revoke):\n");
          int status;
          CHECK_CIN_RESULT(std::cin >> status);
          param.oRS.requestStatus.status = static_cast<bfcp_reqstat>(status);

          printf("Enter the desired position in queue for this request (0 if you are not interested in that):\n");
          int pos = 0;
          CHECK_CIN_RESULT(std::cin >> pos);
          param.oRS.requestStatus.qpos = static_cast<uint8_t>(pos);

          FloorRequestStatusParam floorStatus;
          printf("Enter the FloorID:\n");
          CHECK_CIN_RESULT(std::cin >> floorStatus.floorID);
          param.fRS.push_back(floorStatus);

          printf("Enter the rest floors count:\n");
          size_t restCount = 0;
          CHECK_CIN_RESULT(std::cin >> restCount);
          printf("Enter the rest floorIDs:\n");
          for (size_t i = 0; i < restCount; ++i)
          {
            CHECK_CIN_RESULT(std::cin >> floorStatus.floorID);
            param.fRS.push_back(floorStatus);
          }

          client->sendChairAction(param);
          printf("Message send!\n");
        } break;

      case 's':
        // TODO:
        printf("TODO:\n");
        break;

      case 'q':
        printf("Quit\n");
        if (client)
        {
          client->forceDisconnect();
          loop->runInLoop(boost::bind(&boost::shared_ptr<BaseClient>::reset, client));
          client = nullptr;
        }
        loop->quit();
        return;

      default:
        printf("Invalid menu choice - try again\n");
        break;
    }
  }
}

void onClientStateChanged( BaseClient::State state )
{

}

void onReceivedResponse( BaseClient::Error error, bfcp_prim prim, void *data )
{

}
<|endoftext|>


<commit_before>#include "Definitions.h"
#include "Simulator.h"
#include "util.h"

#include "cpplog/cpplog.hpp"

#include <numeric>

#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>
#include <boost/algorithm/string/predicate.hpp>

namespace po = boost::program_options;

void measureTimes(Logger const& logger, state const& state0, boost::filesystem::path const& path)
{
    const unsigned int start = 0;
    const unsigned int powers = 10;

    std::vector<const unsigned int> numNeurons;
    std::vector<const double> avgTimesCalculations;
    std::vector<const double> avgTimesFFTW;
    std::vector<const double> avgTimesClFFT;

    for(int i = start; i < powers; ++i)
    {
        auto neurons = static_cast<const unsigned int>(pow(2.f, i));
        numNeurons.push_back(neurons);

        Simulator sim = Simulator(
            neurons,
            500,
            1,
            1,
            0.1f,
            state0,
            Simulator::NO_PLOT,
            Simulator::MEASURE,
            Simulator::FFTW,
            Simulator::CLFFT,
            path,
            logger);

        sim.simulate();

        auto timesCalculations = sim.getTimesCalculations();
        auto timesFFTW = sim.getTimesFFTW();
        auto timesClFFT = sim.getTimesClFFT();

        avgTimesCalculations.push_back(
            std::accumulate(
                timesCalculations.begin(),
                timesCalculations.end(), 0.0)
            / timesCalculations.size());

        avgTimesFFTW.push_back(
            std::accumulate(
            timesFFTW.begin(),
            timesFFTW.end(), 0.0)
            / timesFFTW.size());

        avgTimesClFFT.push_back(
            std::accumulate(
            timesClFFT.begin(),
            timesClFFT.end(), 0.0)
            / timesClFFT.size());
    }

    for(int i = 0; i < powers - start; ++i)
    {
        std::cout << static_cast<const unsigned int>(pow(2.f, (int)(i + start))) << "\t" << avgTimesCalculations[i] << "\t" << avgTimesFFTW[i] << "\t" << avgTimesClFFT[i] << std::endl;
    }
}

int finish()
{
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__)
    _CrtDumpMemoryLeaks();
#endif

    return(0);
}

int main(int ac, char **av)
{
    float V0, h0, n0, z0, sAMPA0, sNMDA0, xNMDA0, sGABAA0, IApp0, dt;
    unsigned int nX, nY, nZ, timesteps;
    std::string plotStr, measureStr, fftwStr, clfftStr;

    po::options_description desc("Allowed options");
    desc.add_options()
        ("help", "produce help message")
        ("V", po::value<float>(&V0)->default_value(-70.0), "initial value for membrane potential")
        ("h", po::value<float>(&h0)->default_value(1.0), "initial value for h")
        ("n", po::value<float>(&n0)->default_value(0.0), "initial value for n")
        ("z", po::value<float>(&z0)->default_value(0.0), "initial value for z")
        ("sAMPA", po::value<float>(&sAMPA0)->default_value(0.0), "initial value for sAMPA")
        ("sNMDA", po::value<float>(&sNMDA0)->default_value(0.0), "initial value for sNMDA")
        ("xNMDA", po::value<float>(&xNMDA0)->default_value(0.0), "initial value for xNMDA")
        ("sGABAA", po::value<float>(&sGABAA0)->default_value(0.0), "initial value for xNMDA")
        ("IApp", po::value<float>(&IApp0)->default_value(1.0), "initial value for IApp")
        ("dt", po::value<float>(&dt)->default_value(0.1f), "length of one timestep")
        ("timesteps", po::value<unsigned int>(&timesteps)->default_value(500), "number of timesteps")
        ("nX", po::value<unsigned int>(&nX)->default_value(1024), "number of neurons in network (X axis)")
        ("nY", po::value<unsigned int>(&nY)->default_value(1), "number of neurons in network (Y axis)")
        ("nZ", po::value<unsigned int>(&nZ)->default_value(1), "number of neurons in network (Z axis)")
        ("plot", po::value<std::string>(&plotStr)->default_value("false"), "plot results (false | gnuplot | opengl)")
        ("measure", po::value<std::string>(&measureStr)->default_value("true"), "measure execution time")
        ("fftw", po::value<std::string>(&fftwStr)->default_value("false"), "compute synaptic fields using fftw")
        ("clfft", po::value<std::string>(&clfftStr)->default_value("true"), "compute synaptic fields using clFFT")
    ;

    po::variables_map vm;
    try {
        po::store(po::parse_command_line(ac, av, desc), vm);
    } catch (po::error& err) {
        std::cout << desc << std::endl;
        exit(1);
    }

    po::notify(vm);

    if (vm.count("help")) {
        std::cout << desc << std::endl;
        exit(1);
    }

    if(stringToBool(clfftStr) && !isPowerOfTwo(nX * nY * nZ))
    {
        std::cout << "Error: numNeurons (nX * nY * nZ) must be radix 2" << std::endl;
        exit(1);
    }

    auto logger = make_shared<cpplog::StdErrLogger>();
    state state0;
    state0.V = V0;
    state0.h = h0;
    state0.n = n0;
    state0.z = z0;
    state0.s_AMPA = sAMPA0;
    state0.s_NMDA = sNMDA0;
    state0.x_NMDA = xNMDA0;
    state0.s_GABAA = sGABAA0;
    state0.I_app = IApp0;

    auto path = boost::filesystem::path(CL_SOURCE_DIR);
    path /= "/kernels.cl";

    Simulator::Plot plot;
    if(boost::iequals(plotStr, "gnuplot"))
    {
        plot = Simulator::PLOT_GNUPLOT;
    } else if(boost::iequals(plotStr, "opengl"))
    {
        plot = Simulator::PLOT_OPENGL;
    } else
    {
        plot = Simulator::NO_PLOT;
    }

    Simulator sim = Simulator(
        nX,
        nY,
        nZ,
        timesteps,
        dt,
        state0,
        plot,
        stringToBool(measureStr) ? Simulator::MEASURE : Simulator::NO_MEASURE,
        stringToBool(fftwStr) ? Simulator::FFTW : Simulator::NO_FFTW,
        stringToBool(clfftStr) ? Simulator::CLFFT : Simulator::NO_CLFFT,
        path,
        logger);

    sim.simulate();

    ////measureTimes(logger, state0, path);

    return finish();
}<commit_msg>restore some changes that got lost while merging from master...<commit_after>#include "Definitions.h"
#include "Simulator.h"
#include "util.h"

#include "cpplog/cpplog.hpp"

#include <numeric>

#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>
#include <boost/algorithm/string/predicate.hpp>

namespace po = boost::program_options;

void measureTimes(Logger const& logger, state const& state0, const unsigned int timesteps, float dt, boost::filesystem::path const& path)
{
    const unsigned int start = 14;
    const unsigned int powers = 20;

    std::vector<const unsigned int> numNeurons;
    std::vector<const double> avgTimesCalculations;
    std::vector<const double> avgTimesFFTW;
    std::vector<const double> avgTimesClFFT;

    for(int i = start; i < powers; ++i)
    {
        auto neurons = static_cast<const unsigned int>(pow(2.f, i));
        numNeurons.push_back(neurons);

        Simulator sim = Simulator(
            neurons,
            1,
            1,
            timesteps,
            dt,
            state0,
            Simulator::NO_PLOT,
            Simulator::MEASURE,
            Simulator::FFTW,
            Simulator::CLFFT,
            path,
            logger);

        sim.simulate();

        auto timesCalculations = sim.getTimesCalculations();
        auto timesFFTW = sim.getTimesFFTW();
        auto timesClFFT = sim.getTimesClFFT();

        avgTimesCalculations.push_back(
            std::accumulate(
                timesCalculations.begin(),
                timesCalculations.end(), 0.0)
            / timesCalculations.size());

        avgTimesFFTW.push_back(
            std::accumulate(
            timesFFTW.begin(),
            timesFFTW.end(), 0.0)
            / timesFFTW.size());

        avgTimesClFFT.push_back(
            std::accumulate(
            timesClFFT.begin(),
            timesClFFT.end(), 0.0)
            / timesClFFT.size());
    }

    std::cout << std::endl << "Results" << std::endl << "=======" << std::endl;
    for (int i = 0; i < powers - start; ++i)
    {
        std::cout << static_cast<const unsigned int>(pow(2.f, (int)(i + start))) << "\t" << avgTimesCalculations[i] << "\t" << avgTimesFFTW[i] << "\t" << avgTimesClFFT[i] << std::endl;
    }

    {
        Gnuplot plot_performance;
        plot_performance.set_title("Performance measurements (NVIDIA NVS 4200M)");
        plot_performance.set_style("linespoints");
        plot_performance.set_xlogscale(2);
        plot_performance.set_xlabel("Neurons");
        plot_performance.set_ylabel("Average execution time (ms)");
        plot_performance.plot_xy(numNeurons, avgTimesCalculations, "Runge-kutta approximations");
        plot_performance.plot_xy(numNeurons, avgTimesFFTW, "Convolution using FFTW");
        plot_performance.plot_xy(numNeurons, avgTimesClFFT, "Convolution using ClFFT");
        getchar();
    }
}

int finish(const int rc)
{
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__)
    _CrtDumpMemoryLeaks();
#endif

    return(rc);
}

int main(int ac, char **av)
{
    float V0, h0, n0, z0, sAMPA0, sNMDA0, xNMDA0, sGABAA0, IApp0, dt;
    unsigned int nX, nY, nZ, timesteps;
    std::string plotStr, measureStr, fftwStr, clfftStr, perfplot;

    po::options_description desc("Allowed options");
    desc.add_options()
        ("help", "produce help message")
        ("V", po::value<float>(&V0)->default_value(-70.0), "initial value for membrane potential")
        ("h", po::value<float>(&h0)->default_value(1.0), "initial value for h")
        ("n", po::value<float>(&n0)->default_value(0.0), "initial value for n")
        ("z", po::value<float>(&z0)->default_value(0.0), "initial value for z")
        ("sAMPA", po::value<float>(&sAMPA0)->default_value(0.0), "initial value for sAMPA")
        ("sNMDA", po::value<float>(&sNMDA0)->default_value(0.0), "initial value for sNMDA")
        ("xNMDA", po::value<float>(&xNMDA0)->default_value(0.0), "initial value for xNMDA")
        ("sGABAA", po::value<float>(&sGABAA0)->default_value(0.0), "initial value for xNMDA")
        ("IApp", po::value<float>(&IApp0)->default_value(1.0), "initial value for IApp")
        ("dt", po::value<float>(&dt)->default_value(0.1f), "length of one timestep")
        ("timesteps", po::value<unsigned int>(&timesteps)->default_value(500), "number of timesteps")
        ("nX", po::value<unsigned int>(&nX)->default_value(1024), "number of neurons in network (X axis)")
        ("nY", po::value<unsigned int>(&nY)->default_value(1), "number of neurons in network (Y axis)")
        ("nZ", po::value<unsigned int>(&nZ)->default_value(1), "number of neurons in network (Z axis)")
        ("plot", po::value<std::string>(&plotStr)->default_value("false"), "plot results (false | gnuplot | opengl)")
        ("measure", po::value<std::string>(&measureStr)->default_value("true"), "measure execution time")
        ("fftw", po::value<std::string>(&fftwStr)->default_value("false"), "compute synaptic fields using fftw")
        ("clfft", po::value<std::string>(&clfftStr)->default_value("true"), "compute synaptic fields using clFFT")
        ("perfplot", po::value<std::string>(&perfplot)->default_value("false"), "measure and plot performance for various network sizes")
    ;

    po::variables_map vm;
    try {
        po::store(po::parse_command_line(ac, av, desc), vm);
    } catch (po::error&) {
        std::cout << desc << std::endl;
        return finish(1);
    }

    po::notify(vm);

    if (vm.count("help")) {
        std::cout << desc << std::endl;
        return finish(1);
    }

    if(stringToBool(clfftStr) && !isPowerOfTwo(nX * nY * nZ))
    {
        std::cout << "Error: numNeurons (nX * nY * nZ) must be radix 2" << std::endl;
        return finish(1);
    }

    auto logger = make_shared<cpplog::StdErrLogger>();
    state state0;
    state0.V = V0;
    state0.h = h0;
    state0.n = n0;
    state0.z = z0;
    state0.s_AMPA = sAMPA0;
    state0.s_NMDA = sNMDA0;
    state0.x_NMDA = xNMDA0;
    state0.s_GABAA = sGABAA0;
    state0.I_app = IApp0;

    auto path = boost::filesystem::path(CL_SOURCE_DIR);
    path /= "/kernels.cl";

    if (stringToBool(perfplot))
    {
        measureTimes(logger, state0, timesteps, dt, path);
    } else
    {
        Simulator::Plot plot;
        if(boost::iequals(plotStr, "gnuplot"))
        {
            plot = Simulator::PLOT_GNUPLOT;
        } else if(boost::iequals(plotStr, "opengl"))
        {
            plot = Simulator::PLOT_OPENGL;
        } else
        {
            plot = Simulator::NO_PLOT;
        }

        Simulator sim = Simulator(
            nX,
            nY,
            nZ,
            timesteps,
            dt,
            state0,
            plot,
            stringToBool(measureStr) ? Simulator::MEASURE : Simulator::NO_MEASURE,
            stringToBool(fftwStr) ? Simulator::FFTW : Simulator::NO_FFTW,
            stringToBool(clfftStr) ? Simulator::CLFFT : Simulator::NO_CLFFT,
            path,
            logger);

        sim.simulate();
    }

    return finish(0);
}<|endoftext|>


<commit_before>#ifndef CONFIG_HPP
#define CONFIG_HPP

#include <iostream>
#include <fstream>
#include <sstream>
//#include <cctype>
#include <iomanip>
#include <string>
#include <vector>
#include <array>
#include <map>
#include <set>
#include <algorithm>
//#include <locale>
#include <regex>

#define DEBUG

#ifdef DEBUG
#define DEBUG_MSG(str) std::cout << str << std::endl;
#else
#define DEBUG_MSG(str)
#endif

namespace yampt
{

struct CaseAwareCompare
{
    bool operator()(const char * left, const char * right) const
    {
        bool tied = true;
        bool tiebreaker = false;
        int i;

        for(i = 0; left[i] != 0; ++i)
        {
            if(right[i] == 0)
            {
                return false;
            }
            if(tolower(left[i]) != tolower(right[i]))
            {
                return tolower(left[i]) < tolower(right[i]);
            }
            if(tied && left[i] != right[i])
            {
                tied = false;
                tiebreaker = left[i] < right[i];
            }
        }
        return(right[i] != 0) || (!tied && tiebreaker);
    }

    bool operator()(const std::string & left, const std::string & right) const
    {
        return operator()(left.c_str(), right.c_str());
    }
};

enum rec_type { CELL, DIAL, INDX, RNAM, DESC, GMST, FNAM, INFO, TEXT, BNAM, SCTX,
                Wilderness, Region, PGRD, ANAM, SCVR, DNAM, CNDT, GMDT };
enum ins_mode { RAW, BASE, ALL, NOTFOUND, CHANGED };
typedef std::array<std::map<std::string, std::string>, 11> dict_t;
typedef std::map<std::string, std::string> inner_dict_t;
const std::vector<std::string> type_name { "CELL", "DIAL", "INDX", "RNAM", "DESC", "GMST", "FNAM", "INFO", "TEXT", "BNAM", "SCTX",
                                           "Wilderness", "Region", "PGRD", "ANAM", "SCVR", "DNAM", "CNDT", "GMDT" };
const std::array<std::string, 5> dialog_type = { "T", "V", "G", "P", "J" };
const std::vector<std::string> sep = { "^", "<_id>", "</_id>", "<key>", "</key>", "<val>", "</val>", "<rec name=\"", "\"/>" };
const std::vector<std::string> err = { "<err name=\"", "\"/>" };
const std::vector<std::string> keyword_list = { "messagebox", "choice", "say ", "say," };

}

class Tools
{
public:
    void writeDict(const yampt::dict_t &dict,
                   const std::string &name);
    void writeText(const std::string &text,
                   const std::string &name);
    void writeFile(const std::vector<std::string> &rec_coll,
                   const std::string &name);
    int getNumberOfElementsInDict(const yampt::dict_t &dict);
    unsigned int convertStringByteArrayToUInt(const std::string &str);
    std::string convertUIntToStringByteArray(const unsigned int x);
    bool caseInsensitiveStringCmp(std::string lhs, std::string rhs);
    std::string eraseNullChars(std::string &str);
    std::string eraseCarriageReturnChar(std::string &str);
    std::string replaceNonReadableCharsWithDot(const std::string &str);
};

#endif // CONFIG_HPP
<commit_msg>move DEBUG flag to qtcreator config<commit_after>#ifndef CONFIG_HPP
#define CONFIG_HPP

#include <iostream>
#include <fstream>
#include <sstream>
//#include <cctype>
#include <iomanip>
#include <string>
#include <vector>
#include <array>
#include <map>
#include <set>
#include <algorithm>
//#include <locale>
#include <regex>

#ifdef DEBUG
#define DEBUG_MSG(str) std::cout << str << std::endl;
#else
#define DEBUG_MSG(str)
#endif

namespace yampt
{

struct CaseAwareCompare
{
    bool operator()(const char * left, const char * right) const
    {
        bool tied = true;
        bool tiebreaker = false;
        int i;

        for(i = 0; left[i] != 0; ++i)
        {
            if(right[i] == 0)
            {
                return false;
            }
            if(tolower(left[i]) != tolower(right[i]))
            {
                return tolower(left[i]) < tolower(right[i]);
            }
            if(tied && left[i] != right[i])
            {
                tied = false;
                tiebreaker = left[i] < right[i];
            }
        }
        return(right[i] != 0) || (!tied && tiebreaker);
    }

    bool operator()(const std::string & left, const std::string & right) const
    {
        return operator()(left.c_str(), right.c_str());
    }
};

enum rec_type { CELL, DIAL, INDX, RNAM, DESC, GMST, FNAM, INFO, TEXT, BNAM, SCTX,
                Wilderness, Region, PGRD, ANAM, SCVR, DNAM, CNDT, GMDT };
enum ins_mode { RAW, BASE, ALL, NOTFOUND, CHANGED };
typedef std::array<std::map<std::string, std::string>, 11> dict_t;
typedef std::map<std::string, std::string> inner_dict_t;
const std::vector<std::string> type_name { "CELL", "DIAL", "INDX", "RNAM", "DESC", "GMST", "FNAM", "INFO", "TEXT", "BNAM", "SCTX",
                                           "Wilderness", "Region", "PGRD", "ANAM", "SCVR", "DNAM", "CNDT", "GMDT" };
const std::array<std::string, 5> dialog_type = { "T", "V", "G", "P", "J" };
const std::vector<std::string> sep = { "^", "<_id>", "</_id>", "<key>", "</key>", "<val>", "</val>", "<rec name=\"", "\"/>" };
const std::vector<std::string> err = { "<err name=\"", "\"/>" };
const std::vector<std::string> keyword_list = { "messagebox", "choice", "say ", "say," };

}

class Tools
{
public:
    void writeDict(const yampt::dict_t &dict,
                   const std::string &name);
    void writeText(const std::string &text,
                   const std::string &name);
    void writeFile(const std::vector<std::string> &rec_coll,
                   const std::string &name);
    int getNumberOfElementsInDict(const yampt::dict_t &dict);
    unsigned int convertStringByteArrayToUInt(const std::string &str);
    std::string convertUIntToStringByteArray(const unsigned int x);
    bool caseInsensitiveStringCmp(std::string lhs, std::string rhs);
    std::string eraseNullChars(std::string &str);
    std::string eraseCarriageReturnChar(std::string &str);
    std::string replaceNonReadableCharsWithDot(const std::string &str);
};

#endif // CONFIG_HPP
<|endoftext|>


<commit_before>#include <string>
#include <vector>

#include "settings.h"
#include "scan/ScanIO.h"

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

  Settings settings(argc, argv);

  auto input = ScanIO::read_from(settings.inputScan);

  input.transform()->crop(
      settings.min.at(0),
      settings.min.at(1),
      settings.min.at(2),
      settings.max.at(0),
      settings.max.at(1),
      settings.max.at(2)
      );

  ScanIO::write_to(settings.outputScan, input);

  return 0;

}
<commit_msg>adapted scan-crop to new image classes<commit_after>#include <string>
#include <vector>

#include "settings.h"
#include "image/Image.h"

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

  Settings settings(argc, argv);

  Image input;
  input.read().from(settings.inputScan);

  input.crop().to(
      settings.min.at(0),
      settings.min.at(1),
      settings.min.at(2),
      settings.max.at(0),
      settings.max.at(1),
      settings.max.at(2)
      );

  input.write().to(settings.outputScan);

  return 0;

}
<|endoftext|>


<commit_before>#include <lua.hpp>
#include "lua_state.h"
#include "halley/support/exception.h"
#include "halley/support/logger.h"
#include "halley/core/resources/resources.h"
#include "halley/file_formats/binary_file.h"

using namespace Halley;

LuaState::LuaState(Resources& resources)
	: lua(luaL_newstate())
	, resources(&resources)
{
	luaL_openlibs(lua);

	// TODO: convert this into an automatic table
	LuaStackUtils u(*this);
	u.pushTable();
	u.setField("print", LuaCallbackBind(this, &LuaState::print));
	u.setField("errorHandler", LuaCallbackBind(this, &LuaState::errorHandler));
	u.setField("packageLoader", LuaCallbackBind(this, &LuaState::packageLoader));
	u.makeGlobal("halleyAPI");

	lua_getglobal(lua, "halleyAPI");
	lua_getfield(lua, -1, "errorHandler");
	errorHandlerRef = std::make_unique<LuaReference>(*this);
	lua_pop(lua, 1);

	auto res = resources.get<BinaryFile>("lua/halley/halley.lua");
	loadModule("halley", res->getSpan());
}

LuaState::~LuaState()
{
	modules.clear();
	closures.clear();
	errorHandlerRef.reset();
	lua_close(lua);
}

const LuaReference* LuaState::tryGetModule(const String& moduleName) const
{
	auto iter = modules.find(moduleName);
	if (iter == modules.end()) {
		return nullptr;
	}
	return &iter->second;
}

const LuaReference& LuaState::getModule(const String& moduleName) const
{
	auto result = tryGetModule(moduleName);
	if (!result) {
		throw Exception("Module not found: " + moduleName);
	}
	return *result;
}

const LuaReference& LuaState::getOrLoadModule(const String& moduleName)
{
	auto result = tryGetModule(moduleName);
	if (!result) {
		auto res = resources->get<BinaryFile>("lua/" + moduleName + ".lua");
		return loadModule(moduleName, res->getSpan());
	}
	return *result;
}

const LuaReference& LuaState::loadModule(const String& moduleName, gsl::span<const gsl::byte> data)
{
	modules[moduleName] = loadScript(moduleName, data);
	return getModule(moduleName);
}

void LuaState::unloadModule(const String& moduleName)
{
	auto iter = modules.find(moduleName);
	if (iter == modules.end()) {
		throw Exception("Module not loaded: " + moduleName);
	}
	modules.erase(iter);
}

void LuaState::call(int nArgs, int nRets)
{
	int result = lua_pcall(lua, nArgs, nRets, errorHandlerStackPos.empty() ? 0 : errorHandlerStackPos.back());

	if (result != 0) {
		throw Exception("Lua exception:\n\t" + LuaStackOps(*this).popString());
	}
}

lua_State* LuaState::getRawState()
{
	return lua;
}

LuaReference LuaState::loadScript(const String& chunkName, gsl::span<const gsl::byte> data)
{
	int result = luaL_loadbuffer(lua, reinterpret_cast<const char*>(data.data()), data.size_bytes(), chunkName.c_str());
	if (result != 0) {
		throw Exception("Error loading Lua chunk:\n\t" + LuaStackOps(*this).popString());
	}
	call(0, 1);

	// Store chunk in registry
	auto ref = LuaReference(*this);
	return std::move(ref);
}

void LuaState::print(String string)
{
	Logger::logInfo(string);
}

static int luaClosureInvoker(lua_State* lua)
{
	LuaCallback* callback = reinterpret_cast<LuaCallback*>(lua_touserdata(lua, lua_upvalueindex(1)));
	LuaState* state = reinterpret_cast<LuaState*>(lua_touserdata(lua, lua_upvalueindex(2)));
	return (*callback)(*state);
}

void LuaState::pushCallback(LuaCallback&& callback)
{
	closures.push_back(std::make_unique<LuaCallback>(callback));

	lua_pushlightuserdata(lua, closures.back().get());
	lua_pushlightuserdata(lua, this);
	lua_pushcclosure(lua, luaClosureInvoker, 2);
}

void LuaState::pushErrorHandler()
{
	if (errorHandlerRef) {
		errorHandlerRef->pushToLuaStack();
		errorHandlerStackPos.push_back(lua_gettop(lua));
	}
}

void LuaState::popErrorHandler()
{
	if (errorHandlerRef) {
		if (errorHandlerStackPos.empty()) {
			throw Exception("Error handler not set.");
		}
		if (errorHandlerStackPos.back() != lua_gettop(lua)) {
			throw Exception("Stack corruption.");
		}
		lua_pop(lua, 1);
		errorHandlerStackPos.pop_back();
	}
}

String LuaState::errorHandler(String message)
{
	String result = message;

	lua_Debug stack;
	for (int i = 1; lua_getstack(lua, i, &stack); ++i) {
		lua_getinfo(lua, "nSlf", &stack);

		String name;
		if (stack.namewhat) {
			name = stack.namewhat + String(" ");
		}
		if (stack.name) {
			name += stack.name;
		} else {
			name += "unknown";
		}

		result += "\n\t" + toString(i) + ": " + name + " [" + stack.short_src + ":" + toString(stack.currentline) + "]";

		{
			const char* localName = nullptr;
			for (int j = 1; (localName = lua_getupvalue(lua, -1, j)) != nullptr; ++j) {
				result += "\n\t\tU " + String(localName) + " = " + printVariableAtTop();
			}
		}
		{
			const char* localName = nullptr;
			for (int j = 1; (localName = lua_getlocal(lua, &stack, j)) != nullptr; ++j) {
				result += "\n\t\tL " + String(localName) + " = " + printVariableAtTop();
			}
		}
	}

	return result;
}

const LuaReference& LuaState::packageLoader(String module)
{
	return getOrLoadModule(module);
}

String LuaState::printVariableAtTop()
{
	String result;

	if (lua_istable(lua, -1)) {
		result = toString("{...}");
	} else if (lua_isinteger(lua, -1)) {
		result = toString(lua_tointeger(lua, -1));
	} else if (lua_isstring(lua, -1)) {
		result = String("\"") + lua_tostring(lua, -1) + "\"";
	} else if (lua_isnumber(lua, -1)) {
		result = toString(lua_tonumber(lua, -1));
	} else if (lua_isnoneornil(lua, -1)) {
		result = "nil";
	} else if (lua_isfunction(lua, -1)) {
		result = "function";
	} else if (lua_isboolean(lua, -1)) {
		result = lua_toboolean(lua, -1) != 0? "true" : "false";
	} else if (lua_isthread(lua, -1)) {
		result = "thread";
	}

	lua_pop(lua, 1);
	return result;
}
<commit_msg>Improved Lua stack traces.<commit_after>#include <lua.hpp>
#include "lua_state.h"
#include "halley/support/exception.h"
#include "halley/support/logger.h"
#include "halley/core/resources/resources.h"
#include "halley/file_formats/binary_file.h"

using namespace Halley;

LuaState::LuaState(Resources& resources)
	: lua(luaL_newstate())
	, resources(&resources)
{
	luaL_openlibs(lua);

	// TODO: convert this into an automatic table
	LuaStackUtils u(*this);
	u.pushTable();
	u.setField("print", LuaCallbackBind(this, &LuaState::print));
	u.setField("errorHandler", LuaCallbackBind(this, &LuaState::errorHandler));
	u.setField("packageLoader", LuaCallbackBind(this, &LuaState::packageLoader));
	u.makeGlobal("halleyAPI");

	lua_getglobal(lua, "halleyAPI");
	lua_getfield(lua, -1, "errorHandler");
	errorHandlerRef = std::make_unique<LuaReference>(*this);
	lua_pop(lua, 1);

	auto res = resources.get<BinaryFile>("lua/halley/halley.lua");
	loadModule("halley", res->getSpan());
}

LuaState::~LuaState()
{
	modules.clear();
	closures.clear();
	errorHandlerRef.reset();
	lua_close(lua);
}

const LuaReference* LuaState::tryGetModule(const String& moduleName) const
{
	auto iter = modules.find(moduleName);
	if (iter == modules.end()) {
		return nullptr;
	}
	return &iter->second;
}

const LuaReference& LuaState::getModule(const String& moduleName) const
{
	auto result = tryGetModule(moduleName);
	if (!result) {
		throw Exception("Module not found: " + moduleName);
	}
	return *result;
}

const LuaReference& LuaState::getOrLoadModule(const String& moduleName)
{
	auto result = tryGetModule(moduleName);
	if (!result) {
		auto res = resources->get<BinaryFile>("lua/" + moduleName + ".lua");
		return loadModule(moduleName, res->getSpan());
	}
	return *result;
}

const LuaReference& LuaState::loadModule(const String& moduleName, gsl::span<const gsl::byte> data)
{
	modules[moduleName] = loadScript(moduleName, data);
	return getModule(moduleName);
}

void LuaState::unloadModule(const String& moduleName)
{
	auto iter = modules.find(moduleName);
	if (iter == modules.end()) {
		throw Exception("Module not loaded: " + moduleName);
	}
	modules.erase(iter);
}

void LuaState::call(int nArgs, int nRets)
{
	int result = lua_pcall(lua, nArgs, nRets, errorHandlerStackPos.empty() ? 0 : errorHandlerStackPos.back());

	if (result != 0) {
		throw Exception("Lua exception:\n\t" + LuaStackOps(*this).popString());
	}
}

lua_State* LuaState::getRawState()
{
	return lua;
}

LuaReference LuaState::loadScript(const String& chunkName, gsl::span<const gsl::byte> data)
{
	int result = luaL_loadbuffer(lua, reinterpret_cast<const char*>(data.data()), data.size_bytes(), chunkName.c_str());
	if (result != 0) {
		throw Exception("Error loading Lua chunk:\n\t" + LuaStackOps(*this).popString());
	}
	call(0, 1);

	// Store chunk in registry
	auto ref = LuaReference(*this);
	return std::move(ref);
}

void LuaState::print(String string)
{
	Logger::logInfo(string);
}

static int luaClosureInvoker(lua_State* lua)
{
	LuaCallback* callback = reinterpret_cast<LuaCallback*>(lua_touserdata(lua, lua_upvalueindex(1)));
	LuaState* state = reinterpret_cast<LuaState*>(lua_touserdata(lua, lua_upvalueindex(2)));
	return (*callback)(*state);
}

void LuaState::pushCallback(LuaCallback&& callback)
{
	closures.push_back(std::make_unique<LuaCallback>(callback));

	lua_pushlightuserdata(lua, closures.back().get());
	lua_pushlightuserdata(lua, this);
	lua_pushcclosure(lua, luaClosureInvoker, 2);
}

void LuaState::pushErrorHandler()
{
	if (errorHandlerRef) {
		errorHandlerRef->pushToLuaStack();
		errorHandlerStackPos.push_back(lua_gettop(lua));
	}
}

void LuaState::popErrorHandler()
{
	if (errorHandlerRef) {
		if (errorHandlerStackPos.empty()) {
			throw Exception("Error handler not set.");
		}
		if (errorHandlerStackPos.back() != lua_gettop(lua)) {
			throw Exception("Stack corruption.");
		}
		lua_pop(lua, 1);
		errorHandlerStackPos.pop_back();
	}
}

String LuaState::errorHandler(String message)
{
	String result = message;

	lua_Debug stack;
	for (int i = 1; lua_getstack(lua, i, &stack); ++i) {
		lua_getinfo(lua, "nSlf", &stack);

		String name;
		if (stack.namewhat && String(stack.namewhat) != "") {
			name = stack.namewhat + String(" ");
		}
		if (stack.name) {
			name += stack.name;
		} else {
			name += "<unknown>";
		}

		String args;
		{
			const char* argName = nullptr;
			for (int j = 1; (argName = lua_getlocal(lua, &stack, j)) != nullptr && j <= stack.nparams; ++j) {
				if (j > 1) {
					args += ", ";
				}
				args += String(argName) + " = " + printVariableAtTop();
			}
		}

		result += "\n\t" + toString(i) + ": " + name + " (" + args + ") [" + stack.source + ":" + toString(stack.currentline) + "]";

		{
			const char* localName = nullptr;
			for (int j = 1; (localName = lua_getupvalue(lua, -1, j)) != nullptr; ++j) {
				result += "\n\t\tU " + String(localName) + " = " + printVariableAtTop();
			}
		}
		{
			const char* localName = nullptr;
			for (int j = 1 + stack.nparams; (localName = lua_getlocal(lua, &stack, j)) != nullptr; ++j) {
				result += "\n\t\tL " + String(localName) + " = " + printVariableAtTop();
			}
		}
	}

	return result;
}

const LuaReference& LuaState::packageLoader(String module)
{
	return getOrLoadModule(module);
}

String LuaState::printVariableAtTop()
{
	String result;

	if (lua_istable(lua, -1)) {
		result = toString("{...}");
	} else if (lua_isinteger(lua, -1)) {
		result = toString(lua_tointeger(lua, -1));
	} else if (lua_isstring(lua, -1)) {
		result = String("\"") + lua_tostring(lua, -1) + "\"";
	} else if (lua_isnumber(lua, -1)) {
		result = toString(lua_tonumber(lua, -1));
	} else if (lua_isnoneornil(lua, -1)) {
		result = "nil";
	} else if (lua_isfunction(lua, -1)) {
		result = "function";
	} else if (lua_isboolean(lua, -1)) {
		result = lua_toboolean(lua, -1) != 0? "true" : "false";
	} else if (lua_isthread(lua, -1)) {
		result = "thread";
	}

	lua_pop(lua, 1);
	return result;
}
<|endoftext|>