<commit_before>#include "model/Map.h"
#include "util/util.h"

using std::vector;
using std::string;
using std::list;

Map::Map(const SizeType rowCnt_, const SizeType colCnt_) //Draw a wall
    : content(rowCnt_, vector<Point>(colCnt_)) {
    size = (rowCnt_ - 2) * (colCnt_ - 2);
    // Add boundary walls
    SizeType row = getRowCount();
	SizeType col = getColCount();
    for (SizeType i = 0; i < row; ++i) {
        if (i == 0 || i == row - 1) {  // The first and last row
            for (SizeType j = 0; j < col; ++j) {
                content[i][j].setType(Point::Type::WALL);
            }
        } else {  // Rows in the middle
            content[i][0].setType(Point::Type::WALL);
            content[i][col - 1].setType(Point::Type::WALL);
        }
    }
}

Map::~Map() {}

Point& Map::getPoint(const Pos &p) {
    return content[p.getX()][p.getY()];
}

const Point& Map::getPoint(const Pos &p) const {
    return content[p.getX()][p.getY()];
}

Map::SizeType Map::getRowCount() const {
    return content.size();
}

Map::SizeType Map::getColCount() const {
    return content[0].size();
}

Map::SizeType Map::getSize() const {
    return size;
}

void Map::setTestEnabled(const bool e) {
    testEnabled = e;
}

bool Map::isTestEnabled() const {
    return testEnabled;
}

bool Map::isInside(const Pos &p) const {
    return p.getX() > 0 && p.getY() > 0
        && p.getX() < getRowCount() - 1
        && p.getY() < getColCount() - 1;
}

bool Map::isEmpty(const Pos &p) const {
    return isInside(p) && getPoint(p).getType() == Point::Type::EMPTY;
}

bool Map::isEmptyNotVisit(const Pos &p) const {
    return isEmpty(p) && !getPoint(p).isVisit();
}

bool Map::isSafe(const Pos &p) const {
    const Point &point = getPoint(p);
    return isInside(p) && (point.getType() == Point::Type::EMPTY
                           || point.getType() == Point::Type::FOOD);
}

bool Map::isAllBody() const {
    SizeType row = getRowCount();
	SizeType col = getColCount();
    for (SizeType i = 1; i < row - 1; ++i) {
        for (SizeType j = 1; j < col - 1; ++j) {
            Point::Type type = content[i][j].getType();
            if (!(type == Point::Type::SNAKE_HEAD
                || type == Point::Type::SNAKE_BODY
                || type == Point::Type::SNAKE_TAIL)) {
                return false;
            }
        }
    }
    return true;
}

void Map::createRandFood() {
    auto random = util::Random<>::getInstance();
    vector<Pos> emptyPoints = getEmptyPoints();
    if (!emptyPoints.empty()) {
        SizeType i = random->nextInt((SizeType)0, emptyPoints.size() - 1);
        createFood(emptyPoints[i]);
    }
}

void Map::createFood(const Pos &pos) {
    food = pos;
    content[food.getX()][food.getY()].setType(Point::Type::FOOD);
}

void Map::removeFood() {
    if (hasFood()) {
        content[food.getX()][food.getY()].setType(Point::Type::EMPTY);
    }
}

bool Map::hasFood() const {
    return isInside(food) && getPoint(food).getType() == Point::Type::FOOD;
}

const Pos& Map::getFood() const {
    return food;
}

Map::SizeType Map::distance(const Pos &from, const Pos &to) {
    SizeType fromX = from.getX();
	SizeType toX = to.getX();
    SizeType fromY = from.getY();
	SizeType toY = to.getY();
    SizeType dx = fromX > toX ? fromX - toX : toX - fromX;
    SizeType dy = fromY > toY ? fromY - toY : toY - fromY;
    return dx + dy;
}

void Map::testPos(const Pos &p, const Point::Type type) {
    getPoint(p).setType(type);
    util::sleep(TEST_INTERVAL);
}

void Map::showPos(const Pos &p) {
    if (testEnabled) {
        testPos(p, Point::Type::TEST_VISIT);
    }
}

void Map::showPath(const Pos &start, const list<Direction> &path) {
    if (testEnabled) {
        Pos tmp = start;
        for (const Direction &d : path) {
            testPos(tmp, Point::Type::TEST_PATH);
            tmp = tmp.getAdj(d);
        }
        testPos(tmp, Point::Type::TEST_PATH);
    }
}

vector<Pos> Map::getEmptyPoints() const {
    vector<Pos> points;
    SizeType row = getRowCount();
	SizeTYPE col = getColCount();
    for (SizeType i = 1; i < row - 1; ++i) {
        for (SizeType j = 1; j < col - 1; ++j) {
            if (content[i][j].getType() == Point::Type::EMPTY) {
                points.push_back(Pos(i, j));
            }
        }
    }
    return points;
}
<commit_msg>Make clear statement in clde #17<commit_after>#include "model/Map.h"
#include "util/util.h"

using std::vector;
using std::string;
using std::list;

Map::Map(const SizeType rowCnt_, const SizeType colCnt_) //Draw a wall
    : content(rowCnt_, vector<Point>(colCnt_)) {
    size = (rowCnt_ - 2) * (colCnt_ - 2);
    // Add boundary walls
    SizeType row = getRowCount();
	SizeType col = getColCount();
    for (SizeType i = 0; i < row; ++i) {
        if (i == 0 || i == row - 1) {  // The first and last row
            for (SizeType j = 0; j < col; ++j) {
                content[i][j].setType(Point::Type::WALL);
            }
        } else {  // Rows in the middle
            content[i][0].setType(Point::Type::WALL);
            content[i][col - 1].setType(Point::Type::WALL);
        }
    }
}

Map::~Map() {}

Point& Map::getPoint(const Pos &p) {
    return content[p.getX()][p.getY()];
}

const Point& Map::getPoint(const Pos &p) const {
    return content[p.getX()][p.getY()];
}

Map::SizeType Map::getRowCount() const {
    return content.size();
}

Map::SizeType Map::getColCount() const {
    return content[0].size();
}

Map::SizeType Map::getSize() const {
    return size;
}

void Map::setTestEnabled(const bool e) {
    testEnabled = e;
}

bool Map::isTestEnabled() const {
    return testEnabled;
}

bool Map::isInside(const Pos &p) const {
    return p.getX() > 0 && p.getY() > 0
        && p.getX() < getRowCount() - 1
        && p.getY() < getColCount() - 1;
}

bool Map::isEmpty(const Pos &p) const {
    return isInside(p) && getPoint(p).getType() == Point::Type::EMPTY;
}

bool Map::isEmptyNotVisit(const Pos &p) const {
    return isEmpty(p) && !getPoint(p).isVisit();
}

bool Map::isSafe(const Pos &p) const {
    const Point &point = getPoint(p);
    return isInside(p) && (point.getType() == Point::Type::EMPTY
                           || point.getType() == Point::Type::FOOD);
}

bool Map::isAllBody() const {
    SizeType row = getRowCount();
	SizeType col = getColCount();
    for (SizeType i = 1; i < row - 1; ++i) {
        for (SizeType j = 1; j < col - 1; ++j) {
            Point::Type type = content[i][j].getType();
            if (!(type == Point::Type::SNAKE_HEAD
                || type == Point::Type::SNAKE_BODY
                || type == Point::Type::SNAKE_TAIL)) {
                return false;
            }
        }
    }
    return true;
}

void Map::createRandFood() {
    auto random = util::Random<>::getInstance();
    vector<Pos> emptyPoints = getEmptyPoints();
    if (!emptyPoints.empty()) {
        SizeType i = random->nextInt((SizeType)0, emptyPoints.size() - 1);
        createFood(emptyPoints[i]);
    }
}

void Map::createFood(const Pos &pos) {
    food = pos;
    content[food.getX()][food.getY()].setType(Point::Type::FOOD);
}

void Map::removeFood() {
    if (hasFood()) {
        content[food.getX()][food.getY()].setType(Point::Type::EMPTY);
    }
}

bool Map::hasFood() const {
    return isInside(food) && getPoint(food).getType() == Point::Type::FOOD;
}

const Pos& Map::getFood() const {
    return food;
}

Map::SizeType Map::distance(const Pos &from, const Pos &to) {
    SizeType fromX = from.getX();
	SizeType toX = to.getX();
    SizeType fromY = from.getY();
	SizeType toY = to.getY();
    SizeType dx = fromX > toX ? fromX - toX : toX - fromX;
    SizeType dy = fromY > toY ? fromY - toY : toY - fromY;
    return dx + dy;
}

void Map::testPos(const Pos &p, const Point::Type type) {
    getPoint(p).setType(type);
    util::sleep(TEST_INTERVAL);
}

void Map::showPos(const Pos &p) {
    if (testEnabled) {
        testPos(p, Point::Type::TEST_VISIT);
    }
}

void Map::showPath(const Pos &start, const list<Direction> &path) {
    if (testEnabled) {
        Pos tmp = start;
        for (const Direction &d : path) {
            testPos(tmp, Point::Type::TEST_PATH);
            tmp = tmp.getAdj(d);
        }
        testPos(tmp, Point::Type::TEST_PATH);
    }
}

vector<Pos> Map::getEmptyPoints() const {
    vector<Pos> points;
    SizeType row = getRowCount();
	SizeType col = getColCount();
    for (SizeType i = 1; i < row - 1; ++i) {
        for (SizeType j = 1; j < col - 1; ++j) {
            if (content[i][j].getType() == Point::Type::EMPTY) {
                points.push_back(Pos(i, j));
            }
        }
    }
    return points;
}
<|endoftext|>


<commit_before>#ifndef MUDI_JSON_HPP
#define MUDI_JSON_HPP

#include <unordered_map>
#include <vector>
#include <string>
#include <utility>  // make_pair

#include <memory>
#include <exception>

#define MUDI_NS_BEGIN namespace mudi {
#define MUDI_NS_END   }

#define MUDI_N_NS_BEGIN namespace mudi { namespace detail {
#define MUDI_N_NS_END   }}

// base value

MUDI_N_NS_BEGIN

class json_base_value: public json_value
{
public:
  json_base_value(unsigned int pos, unsigned int len, buffer_ptr buf): pos{ pos }, len{ len }, buffer{ buf }
  {}

  json_base_value(const json_string& rhs): pos{ rhs.pos }, len{ rhs.len }, buffer{ rhs.buffer }
  {}

  json_base_value& operator=(const json_string& rhs)
  {
    if (&rhs == this) {
      return *this;
    }

    auto tmp = rhs;
    std::swap(*this, tmp);
    return *this;
  }

  json_base_value(json_string&& rhs): pos{ rhs.pos }, len{ rhs.len }
  {
    buffer = std::move(rhs.buffer);
  }

  json_base_value& operator=(json_string&& rhs)
  {
    pos = rhs.pos;
    len = rhs.len;
    buffer = std::move(rhs.buffer);
  }

protected:
  unsigned int pos;
  unsigned int len;
  buffer_ptr buffer;
}

MUDI_N_NS_END

// string

MUDI_N_NS_BEGIN

class json_value;

typedef std::shared_ptr<std::string> buffer_ptr;

enum class value_type
{
  array,
  object,
  string,
  number,
  boolean,
  null,
};

class json_string: public json_value
{
public:
  json_string(unsigned int pos, unsigned int len, buffer_ptr buf): pos{ pos }, len{ len }, buffer{ buf }
  {}

  json_string(const json_string& rhs): pos{ rhs.pos }, len{ rhs.len }, buffer{ rhs.buffer }
  {}

  json_string& operator=(const json_string& rhs)
  {
    if (&rhs == this) {
      return *this;
    }

    auto tmp = rhs;
    std::swap(*this, tmp);
    return *this;
  }

  json_string(json_string&& rhs): pos{ rhs.pos }, len{ rhs.len }
  {
    buffer = std::move(rhs.buffer);
  }

  json_string& operator=(json_string&& rhs)
  {
    pos = rhs.pos;
    len = rhs.len;
    buffer = std::move(rhs.buffer);
  }

  std::string string_value() noexcept const override
  {
      return buffer.substr(pos, len);
  }

protected:
  value_type type() noexcept const override
  {
    return value_type::string;
  }

private:
  unsigned int pos;
  unsigned int len;
  buffer_ptr buffer;
};

MUDI_N_NS_END

// array

MUDI_N_NS_BEGIN

class json_array: public json_value
{
public:
  json_array() = default;

  json_array(const json_array& rhs): data{ rhs.data }
  {}

  json_array& operator=(const json_array& rhs)
  {
    if (&rhs == this) {
      return *this;
    }

    auto tmp = rhs;
    std::swap(*this, tmp);
    return *this;
  }

  json_array(json_array&& rhs)
  {
    data = std::move(rhs.data);
  }

  json_array& operator=(json_array&& rhs)
  {
    data = std::move(rhs.data);
    return *this;
  }

  json_value& operator[](unsigned int index) const override
  {
    return data.at(index);
  }

protected:
  value_type type() noexcept const override
  {
    return value_type::array;
  }

private:
  void append(json_value val) noexcept
  {
    data.push_back(val);
  }

private:
  std::vector<json_value> data;
};

MUDI_N_NS_END

// object

MUDI_N_NS_BEGIN

class json_object: public json_value
{
public:
  json_object() = default;

  json_object(const json_object& rhs): data{ rhs.data }
  {}

  json_object& operator=(const json_object& rhs)
  {
    data = rhs.data;
    return *this;
  }

  json_object(json_object&& rhs)
  {
    data = std::move(rhs.data);
  }

  json_object& operator=(json_object&& rhs)
  {
    data = std::move(rhs.data);
    return *this;
  }

  json_value& operator[](const std::string& key) noexcept const override
  {
    auto found = data.find(key);
    if (found == data.end()) {
      return json_null{};
    } else {
      return *found;
    }
  }

  bool append(const std::string& key, const json_value& value) noexcept
  {
    auto ret = data.insert(std::make_pair(key, value));
    return ret.second;
  }

  void remove(const std::string& key)
  {
    auto found = data.find(key);
    if (found != data.end())
      data.erase(found);
  }

protected:
  value_type type() noexcept const override
  {
    return value_type::object;
  }

private:
  std::unordered_map<std::string, json_value> data;
};

MUDI_N_NS_END

// number

MUDI_N_NS_BEGIN

class json_number: public json_value
{
public:
  json_number(unsigned int pos, unsigned int len, buffer_ptr buf): pos{ pos }, len{ len }, buffer{ buf }
  {}

  json_number(const json_number& rhs): pos{ rhs.pos }, len{ rhs.len }, buffer{ rhs.buffer }
  {}

  json_number& operator=(const json_number& rhs)
  {
    if (&rhs == this) {
      reutrn *this;
    }

    pos = rhs.pos;
    len = rhs.len;
    buffer = rhs.buffer;

    return *this;
  }

  json_number(json_number&& rhs): pos{ rhs.pos }, len{ rhs.len }
  {
    buffer = std::move(rhs.buffer);
  }

  json_number& operator=(json_number&& rhs)
  {
    pos = rhs.pos;
    len = rhs.len;
    buffer = std::move(rhs.buffer);

    return *this;
  }

  int int_value() noexcept const override
  {
    return 0;
  }

  double double_value() noexcept const override
  {
    return 0;
  }

protected:
  value_type type() noexcept const override
  {
    return value_type::number;
  }

private:
  unsigned int pos;
  unsigned int len;
  buffer_ptr buffer;
};

MUDI_N_NS_END

// boolean

MUDI_N_NS_BEGIN

class json_boolean: public json_value
{

};

MUDI_N_NS_END

// null

MUDI_N_NS_BEGIN

class json_null: public json_value
{
// public:
//   json_null(const json_null&) = delete;
//   json_null& operator=(const json_null&) = delete;

protected:
  value_type type() noexcept const override
  {
    return value_type::null;
  }
};

MUDI_N_NS_END

// interface

MUDI_NS_BEGIN

class json_value
{
public:
  virtual ~json_value() noexcept;

  virtual json_value& operator[](const std::string& key) noexcept const
  {
    return json_null{};
  }

  virtual json_value& operator[](unsigned int index) const
  {
    return json_null{};
  }

  virtual bool boolean_value() noexcept const
  {
    return false;
  }

  virtual std::string string_value() noexcept const
  {
    return "null";
  }

  virtual int int_value() noexcept const
  {
    return 0;
  }

  virtual double double_value() noexcept const
  {
    return 0;
  }

  bool is_bool() noexcept const
  {
    return type() == value_type::boolean;
  }

  bool is_array() noexcept const
  {
    return type() == value_type::array;
  }

  bool is_string() noexcept const
  {
    return type() == value_type::string;
  }

  bool is_number() noexcept const
  {
    return type() == value_type::number;
  }

  bool is_object() noexcept const
  {
    return type() == value_type::object;
  }

  bool is_null() noexcept const
  {
    return type() == value_type::null;
  }

protected:
  virtual value_type type() = 0;
};

std::unique_ptr<json_value> parse_string(const std::string& str);
std::unique_ptr<json_value> parse_cstring(const char* cstr, unsigned int len);

MUDI_NS_END

#endif
<commit_msg>base json value<commit_after>#ifndef MUDI_JSON_HPP
#define MUDI_JSON_HPP

#include <unordered_map>
#include <vector>
#include <string>

#include <utility>  // make_pair
#include <memory>   // share_ptr
#include <exception>

#define MUDI_NS_BEGIN namespace mundi {
#define MUDI_NS_END   }

#define MUDI_N_NS_BEGIN namespace mundi { namespace {
#define MUDI_N_NS_END   }}

MUDI_N_NS_BEGIN
enum class value_type
{
  array,
  object,
  string,
  number,
  boolean,
  null,
};

MUDI_N_NS_END

// exception

MUDI_NS_BEGIN

class not_supported: public std::exception
{
public:
  const char* what() const noexcept override
  {
    return "Not supported operation";
  }
};

class key_not_found: public std::exception
{
public:
  const char* what() const noexcept override
  {
    return "Key not found";
  }
};

MUDI_NS_END

// interface

MUDI_NS_BEGIN

class json_value
{
public:
  virtual ~json_value() noexcept;

  virtual const json_value& operator[](const std::string& key) const
  {
    throw not_supported();
  }

  virtual const json_value& operator[](unsigned int index) const
  {
    throw not_supported();
  }

  virtual bool boolean_value() const noexcept
  {
    return false;
  }

  virtual std::string string_value() const noexcept
  {
    return "null";
  }

  virtual int int_value() const noexcept
  {
    return 0;
  }

  virtual double double_value() const noexcept
  {
    return 0;
  }

  bool is_bool() const noexcept
  {
    return type() == value_type::boolean;
  }

  bool is_array() const noexcept
  {
    return type() == value_type::array;
  }

  bool is_string() const noexcept
  {
    return type() == value_type::string;
  }

  bool is_number() const noexcept
  {
    return type() == value_type::number;
  }

  bool is_object() const noexcept
  {
    return type() == value_type::object;
  }

  bool is_null() const noexcept
  {
    return type() == value_type::null;
  }

protected:
  virtual value_type type() const noexcept
  {
    return value_type::null;
  }
};

std::unique_ptr<json_value> parse_string(const std::string& str);
std::unique_ptr<json_value> parse_cstring(const char* cstr, unsigned int len);

MUDI_NS_END

// string

MUDI_N_NS_BEGIN

typedef std::shared_ptr<std::string> buffer_ptr;

class json_string: public json_value
{
public:
  json_string(unsigned int pos, unsigned int len, buffer_ptr buf): pos{ pos }, len{ len }, buffer{ buf }
  {}

  json_string(const json_string& rhs): pos{ rhs.pos }, len{ rhs.len }, buffer{ rhs.buffer }
  {}

  json_string& operator=(const json_string& rhs)
  {
    if (&rhs == this) {
      return *this;
    }

    auto tmp = rhs;
    std::swap(*this, tmp);
    return *this;
  }

  json_string(json_string&& rhs): pos{ rhs.pos }, len{ rhs.len }
  {
    buffer = std::move(rhs.buffer);
  }

  json_string& operator=(json_string&& rhs)
  {
    pos = rhs.pos;
    len = rhs.len;
    buffer = std::move(rhs.buffer);

    return *this;
  }

  std::string string_value() const noexcept override
  {
    return buffer->substr(pos, len);
  }

protected:
  value_type type() const noexcept override
  {
    return value_type::string;
  }

private:
  unsigned int pos;
  unsigned int len;
  buffer_ptr buffer;
};

MUDI_N_NS_END

// array

MUDI_N_NS_BEGIN

class json_array: public json_value
{
public:
  json_array() = default;

  json_array(const json_array& rhs): data{ rhs.data }
  {}

  json_array& operator=(const json_array& rhs)
  {
    if (&rhs == this) {
      return *this;
    }

    auto tmp = rhs;
    std::swap(*this, tmp);
    return *this;
  }

  json_array(json_array&& rhs)
  {
    data = std::move(rhs.data);
  }

  json_array& operator=(json_array&& rhs)
  {
    data = std::move(rhs.data);
    return *this;
  }

  ~json_array()
  {
    for (auto& v : data) {
      delete v;
    }
    data.clear();
  }

  const json_value& operator[](unsigned int index) const override
  {
    return *data.at(index);
  }

protected:
  value_type type() const noexcept override
  {
    return value_type::array;
  }

private:
  void append(json_value* val) noexcept
  {
    data.push_back(val);
  }

private:
  std::vector<json_value*> data;
};

MUDI_N_NS_END

// object

MUDI_N_NS_BEGIN

class json_object: public json_value
{
public:
  json_object() = default;

  json_object(const json_object& rhs): data{ rhs.data }
  {}

  json_object& operator=(const json_object& rhs)
  {
    data = rhs.data;
    return *this;
  }

  json_object(json_object&& rhs)
  {
    data = std::move(rhs.data);
  }

  json_object& operator=(json_object&& rhs)
  {
    data = std::move(rhs.data);
    return *this;
  }

  const json_value& operator[](const std::string& key) const override
  {
    auto found = data.find(key);
    if (found == data.cend()) {
      throw key_not_found();
    } else {
      return *(found->second);
    }
  }

  ~json_object()
  {
    for (auto& o : data) {
      delete o.second;
    }
    data.clear();
  }

  bool append(const std::string& key, json_value* value) noexcept
  {
    auto ret = data.insert(std::make_pair(key, value));
    return ret.second;
  }

  void remove(const std::string& key)
  {
    auto found = data.find(key);
    if (found != data.end())
      data.erase(found);
  }

protected:
  value_type type() const noexcept override
  {
    return value_type::object;
  }

private:
  std::unordered_map<std::string, json_value*> data;
};

MUDI_N_NS_END

// number

MUDI_N_NS_BEGIN

class json_number: public json_value
{
public:
  json_number(unsigned int pos, unsigned int len, buffer_ptr buf): pos{ pos }, len{ len }, buffer{ buf }
  {}

  json_number(const json_number& rhs): pos{ rhs.pos }, len{ rhs.len }, buffer{ rhs.buffer }
  {}

  json_number& operator=(const json_number& rhs)
  {
    if (&rhs == this) {
      return *this;
    }

    pos = rhs.pos;
    len = rhs.len;
    buffer = rhs.buffer;

    return *this;
  }

  json_number(json_number&& rhs): pos{ rhs.pos }, len{ rhs.len }
  {
    buffer = std::move(rhs.buffer);
  }

  json_number& operator=(json_number&& rhs)
  {
    pos = rhs.pos;
    len = rhs.len;
    buffer = std::move(rhs.buffer);

    return *this;
  }

  int int_value() const noexcept override
  {
    return 0;
  }

  double double_value() const noexcept override
  {
    return 0;
  }

protected:
  value_type type() const noexcept override
  {
    return value_type::number;
  }

private:
  unsigned int pos;
  unsigned int len;
  buffer_ptr buffer;
};

MUDI_N_NS_END

// boolean

MUDI_N_NS_BEGIN

class json_boolean: public json_value
{
public:
  json_boolean(unsigned int pos, unsigned int len, buffer_ptr buf): pos{ pos }, len{ len }, buffer{ buf }
  {}

  json_boolean(const json_boolean& rhs): pos{ rhs.pos }, len{ rhs.len }, buffer{ rhs.buffer }
  {}

  json_boolean& operator=(const json_boolean& rhs)
  {
    if (&rhs == this) {
      return *this;
    }

    pos = rhs.pos;
    len = rhs.len;
    buffer = rhs.buffer;

    return *this;
  }

  json_boolean(json_boolean&& rhs): pos{ rhs.pos }, len{ rhs.len }
  {
    buffer = std::move(rhs.buffer);
  }

  json_boolean& operator=(json_boolean&& rhs)
  {
    pos = rhs.pos;
    len = rhs.len;
    buffer = std::move(rhs.buffer);

    return *this;
  }

  bool boolean_value() const noexcept override
  {
    auto str = buffer->substr(pos, len);
    if (0 == str.compare("true")) {
      return true;
    } else {
      return false;
    }
  }

protected:
  value_type type() const noexcept override
  {
    return value_type::boolean;
  }

private:
  unsigned int pos;
  unsigned int len;
  buffer_ptr buffer;
};

MUDI_N_NS_END

#endif
<|endoftext|>


<commit_before>#include "command.hh"
#include "common-args.hh"
#include "shared.hh"
#include "store-api.hh"
#include "fs-accessor.hh"

using namespace nix;

struct CmdBundle : InstallableCommand
{
    std::string bundler = "github:matthewbauer/nix-bundle";
    Path outLink;

    CmdBundle()
    {
        addFlag({
            .longName = "bundler",
            .description = "use custom bundler",
            .labels = {"flake-url"},
            .handler = {&bundler},
            .completer = {[&](size_t, std::string_view prefix) {
                completeFlakeRef(getStore(), prefix);
            }}
        });

        addFlag({
            .longName = "out-link",
            .shortName = 'o',
            .description = "path of the symlink to the build result",
            .labels = {"path"},
            .handler = {&outLink},
            .completer = completePath
        });
    }

    std::string description() override
    {
        return "bundle an application so that it works outside of the Nix store";
    }

    Examples examples() override
    {
        return {
            Example{
                "To bundle Hello:",
                "nix bundle hello"
            },
        };
    }

    Strings getDefaultFlakeAttrPaths() override
    {
        Strings res{"defaultApp." + settings.thisSystem.get()};
        for (auto & s : SourceExprCommand::getDefaultFlakeAttrPaths())
            res.push_back(s);
        return res;
    }

    Strings getDefaultFlakeAttrPathPrefixes() override
    {
        Strings res{"apps." + settings.thisSystem.get() + ".", "packages"};
        for (auto & s : SourceExprCommand::getDefaultFlakeAttrPathPrefixes())
            res.push_back(s);
        return res;
    }

    void run(ref<Store> store) override
    {
        auto evalState = getEvalState();

        auto app = installable->toApp(*evalState);
        store->buildPaths(app.context);

        auto [bundlerFlakeRef, bundlerName] = parseFlakeRefWithFragment(bundler, absPath("."));
        const flake::LockFlags lockFlags{ .writeLockFile = false };
        auto bundler = InstallableFlake(
            evalState, std::move(bundlerFlakeRef),
            Strings{bundlerName == "" ? ("defaultBundler." + settings.thisSystem.get()) : bundlerName},
            Strings({"bundlers." + settings.thisSystem.get() + "."}), lockFlags);

        Value * arg = evalState->allocValue();
        evalState->mkAttrs(*arg, 1);

        PathSet context;
        for (auto & i : app.context)
            context.insert("=" + store->printStorePath(i.path));
        mkString(*evalState->allocAttr(*arg, evalState->symbols.create("program")), app.program, context);

        auto vRes = evalState->allocValue();
        evalState->callFunction(*bundler.toValue(*evalState).first, *arg, *vRes, noPos);

        if (!evalState->isDerivation(*vRes))
            throw Error("the bundler '%s' does not produce a derivation", bundler.what());

        Bindings::iterator i = vRes->attrs->find(evalState->sDrvPath);
        if (i == vRes->attrs->end())
            throw Error("the bundler '%s' does not produce a bderivation", bundler.what());

        PathSet context2;
        StorePath drvPath = store->parseStorePath(evalState->coerceToPath(*i->pos, *i->value, context2));

        i = vRes->attrs->find(evalState->sOutPath);
        if (i == vRes->attrs->end())
            throw Error("the bundler '%s' does not produce a derivation", bundler.what());

        StorePath outPath = store->parseStorePath(evalState->coerceToPath(*i->pos, *i->value, context2));

        store->buildPaths({{drvPath}});

        auto accessor = store->getFSAccessor();
        auto outPathS = store->printStorePath(outPath);
        if (accessor->stat(outPathS).type != FSAccessor::tRegular)
            throw Error("'%s' is not a file; a bundler must only create a single file", outPathS);

        auto info = store->queryPathInfo(outPath);
        if (!info->references.empty())
            throw Error("'%s' has references; a bundler must not leave any references", outPathS);

        if (outLink == "")
            outLink = baseNameOf(app.program);

        store.dynamic_pointer_cast<LocalFSStore>()->addPermRoot(outPath, absPath(outLink), true);
    }
};

static auto r2 = registerCommand<CmdBundle>("bundle");
<commit_msg>Remove single file restriction for bundler<commit_after>#include "command.hh"
#include "common-args.hh"
#include "shared.hh"
#include "store-api.hh"
#include "fs-accessor.hh"

using namespace nix;

struct CmdBundle : InstallableCommand
{
    std::string bundler = "github:matthewbauer/nix-bundle";
    Path outLink;

    CmdBundle()
    {
        addFlag({
            .longName = "bundler",
            .description = "use custom bundler",
            .labels = {"flake-url"},
            .handler = {&bundler},
            .completer = {[&](size_t, std::string_view prefix) {
                completeFlakeRef(getStore(), prefix);
            }}
        });

        addFlag({
            .longName = "out-link",
            .shortName = 'o',
            .description = "path of the symlink to the build result",
            .labels = {"path"},
            .handler = {&outLink},
            .completer = completePath
        });
    }

    std::string description() override
    {
        return "bundle an application so that it works outside of the Nix store";
    }

    Examples examples() override
    {
        return {
            Example{
                "To bundle Hello:",
                "nix bundle hello"
            },
        };
    }

    Strings getDefaultFlakeAttrPaths() override
    {
        Strings res{"defaultApp." + settings.thisSystem.get()};
        for (auto & s : SourceExprCommand::getDefaultFlakeAttrPaths())
            res.push_back(s);
        return res;
    }

    Strings getDefaultFlakeAttrPathPrefixes() override
    {
        Strings res{"apps." + settings.thisSystem.get() + ".", "packages"};
        for (auto & s : SourceExprCommand::getDefaultFlakeAttrPathPrefixes())
            res.push_back(s);
        return res;
    }

    void run(ref<Store> store) override
    {
        auto evalState = getEvalState();

        auto app = installable->toApp(*evalState);
        store->buildPaths(app.context);

        auto [bundlerFlakeRef, bundlerName] = parseFlakeRefWithFragment(bundler, absPath("."));
        const flake::LockFlags lockFlags{ .writeLockFile = false };
        auto bundler = InstallableFlake(
            evalState, std::move(bundlerFlakeRef),
            Strings{bundlerName == "" ? ("defaultBundler." + settings.thisSystem.get()) : bundlerName},
            Strings({"bundlers." + settings.thisSystem.get() + "."}), lockFlags);

        Value * arg = evalState->allocValue();
        evalState->mkAttrs(*arg, 1);

        PathSet context;
        for (auto & i : app.context)
            context.insert("=" + store->printStorePath(i.path));
        mkString(*evalState->allocAttr(*arg, evalState->symbols.create("program")), app.program, context);

        auto vRes = evalState->allocValue();
        evalState->callFunction(*bundler.toValue(*evalState).first, *arg, *vRes, noPos);

        if (!evalState->isDerivation(*vRes))
            throw Error("the bundler '%s' does not produce a derivation", bundler.what());

        Bindings::iterator i = vRes->attrs->find(evalState->sDrvPath);
        if (i == vRes->attrs->end())
            throw Error("the bundler '%s' does not produce a bderivation", bundler.what());

        PathSet context2;
        StorePath drvPath = store->parseStorePath(evalState->coerceToPath(*i->pos, *i->value, context2));

        i = vRes->attrs->find(evalState->sOutPath);
        if (i == vRes->attrs->end())
            throw Error("the bundler '%s' does not produce a derivation", bundler.what());

        StorePath outPath = store->parseStorePath(evalState->coerceToPath(*i->pos, *i->value, context2));

        store->buildPaths({{drvPath}});

        auto outPathS = store->printStorePath(outPath);

        auto info = store->queryPathInfo(outPath);
        if (!info->references.empty())
            throw Error("'%s' has references; a bundler must not leave any references", outPathS);

        if (outLink == "")
            outLink = baseNameOf(app.program);

        store.dynamic_pointer_cast<LocalFSStore>()->addPermRoot(outPath, absPath(outLink), true);
    }
};

static auto r2 = registerCommand<CmdBundle>("bundle");
<|endoftext|>


<commit_before>/**
 ** \file object/fwd.hh
 ** \brief Forward declarations of all node-classes of OBJECT
 ** (needed by the visitors)
 */
#ifndef OBJECT_FWD_HH
# define OBJECT_FWD_HH

# include <vector>

# include <libport/fwd.hh>
# include <libport/shared-ptr.hh>

namespace runner
{
  class Runner;
}

namespace object
{
  // state.hh
  struct State;

  // rObject & objects_type.
  class Object;
  // We don't know yet that Object inherits RefCounted, so we have to force
  // the second template argument.
  typedef libport::shared_ptr<Object, true> rObject;
  typedef std::vector<rObject> objects_type;

  /// \a Macro should be a binary macro whose first arg, \p What, is
  /// the lower case C++ name, and the second argument, \p Name, the
  /// capitalized URBI name.  This is used in many different contexts,
  /// such as defining enums, so we do not use terminators here (;
  /// etc.): Macro must do it.
# define APPLY_ON_ALL_PRIMITIVES_BUT_OBJECT(Macro)	\
  Macro(alien,      Alien)				\
  Macro(code,       Code)				\
  Macro(delegate,   Delegate)				\
  Macro(dictionary, Dictionary)                         \
  Macro(float,      Float)				\
  Macro(integer,    Integer)				\
  Macro(list,       List)				\
  Macro(lobby,      Lobby)				\
  Macro(primitive,  Primitive)				\
  Macro(string,     String)

# define APPLY_ON_ALL_PRIMITIVES(Macro)			\
  APPLY_ON_ALL_PRIMITIVES_BUT_OBJECT(Macro)		\
  Macro(object,    Object)

# define APPLY_ON_ALL_ROOT_CLASSES_BUT_OBJECT(Macro)	\
  APPLY_ON_ALL_PRIMITIVES_BUT_OBJECT(Macro)		\
  Macro(global,     Global)				\
  Macro(scope,      Scope)				\
  Macro(tag, Tag)					\
  Macro(task, Task)

# define APPLY_ON_ALL_ROOT_CLASSES(Macro)	\
  APPLY_ON_ALL_ROOT_CLASSES_BUT_OBJECT(Macro)	\
  Macro(object, Object)

  /*
    Help the generation of precompiled symbols.

    SYMBOL(Alien)
    SYMBOL(Call)
    SYMBOL(Code)
    SYMBOL(Delegate)
    SYMBOL(Float)
    SYMBOL(Integer)
    SYMBOL(List)
    SYMBOL(Lobby)
    SYMBOL(Object)
    SYMBOL(Primitive)
    SYMBOL(String)
    SYMBOL(Task)

  */

  // All the atoms.
  template <typename Traits>
  class Atom;

  /// Define a primitive as an Atom parametrized with a traits.
# define DEFINE(What, Name)				\
  struct What ## _traits;				\
  typedef Atom< What ## _traits > Name;			\
  typedef libport::shared_ptr < Name, true > r ## Name;

  /* You have to understand that the primitives are defined here.  For
   * example, a Code is manipulated through a rCode (r = ref counted) and in
   * fact Code is just a typedef for Atom<code_traits>.  If you get compilation
   * errors about non existent members, it's most likely because you did
   * obj.get_value () instead of obj->get_value ().  This is a side effect
   * of the operator-> used for the ref-counting.  Keep that in mind. */
  APPLY_ON_ALL_PRIMITIVES_BUT_OBJECT(DEFINE)
# undef DEFINE

  // urbi-exception.hh
  class IDelegate;
  class UrbiException;
  class LookupError;
  class RedefinitionError;
  class PrimitiveError;
  class WrongArgumentType;
  class WrongArgumentCount;

  extern rObject nil_class;
  extern rObject task_class;
  extern rObject void_class;
} // namespace object

#endif // !OBJECT_FWD_HH
<commit_msg>Fix indentation.<commit_after>/**
 ** \file object/fwd.hh
 ** \brief Forward declarations of all node-classes of OBJECT
 ** (needed by the visitors)
 */
#ifndef OBJECT_FWD_HH
# define OBJECT_FWD_HH

# include <vector>

# include <libport/fwd.hh>
# include <libport/shared-ptr.hh>

namespace runner
{
  class Runner;
}

namespace object
{
  // state.hh
  struct State;

  // rObject & objects_type.
  class Object;
  // We don't know yet that Object inherits RefCounted, so we have to force
  // the second template argument.
  typedef libport::shared_ptr<Object, true> rObject;
  typedef std::vector<rObject> objects_type;

  /// \a Macro should be a binary macro whose first arg, \p What, is
  /// the lower case C++ name, and the second argument, \p Name, the
  /// capitalized URBI name.  This is used in many different contexts,
  /// such as defining enums, so we do not use terminators here (;
  /// etc.): Macro must do it.
# define APPLY_ON_ALL_PRIMITIVES_BUT_OBJECT(Macro)	\
  Macro(alien,      Alien)				\
  Macro(code,       Code)				\
  Macro(delegate,   Delegate)				\
  Macro(dictionary, Dictionary)                         \
  Macro(float,      Float)				\
  Macro(integer,    Integer)				\
  Macro(list,       List)				\
  Macro(lobby,      Lobby)				\
  Macro(primitive,  Primitive)				\
  Macro(string,     String)

# define APPLY_ON_ALL_PRIMITIVES(Macro)			\
  APPLY_ON_ALL_PRIMITIVES_BUT_OBJECT(Macro)		\
  Macro(object,    Object)

# define APPLY_ON_ALL_ROOT_CLASSES_BUT_OBJECT(Macro)	\
  APPLY_ON_ALL_PRIMITIVES_BUT_OBJECT(Macro)		\
  Macro(global, Global)					\
  Macro(scope, Scope)					\
  Macro(tag, Tag)					\
  Macro(task, Task)

# define APPLY_ON_ALL_ROOT_CLASSES(Macro)	\
  APPLY_ON_ALL_ROOT_CLASSES_BUT_OBJECT(Macro)	\
  Macro(object, Object)

  /*
    Help the generation of precompiled symbols.

    SYMBOL(Alien)
    SYMBOL(Call)
    SYMBOL(Code)
    SYMBOL(Delegate)
    SYMBOL(Float)
    SYMBOL(Integer)
    SYMBOL(List)
    SYMBOL(Lobby)
    SYMBOL(Object)
    SYMBOL(Primitive)
    SYMBOL(String)
    SYMBOL(Task)

  */

  // All the atoms.
  template <typename Traits>
  class Atom;

  /// Define a primitive as an Atom parametrized with a traits.
# define DEFINE(What, Name)				\
  struct What ## _traits;				\
  typedef Atom< What ## _traits > Name;			\
  typedef libport::shared_ptr < Name, true > r ## Name;

  /* You have to understand that the primitives are defined here.  For
   * example, a Code is manipulated through a rCode (r = ref counted) and in
   * fact Code is just a typedef for Atom<code_traits>.  If you get compilation
   * errors about non existent members, it's most likely because you did
   * obj.get_value () instead of obj->get_value ().  This is a side effect
   * of the operator-> used for the ref-counting.  Keep that in mind. */
  APPLY_ON_ALL_PRIMITIVES_BUT_OBJECT(DEFINE)
# undef DEFINE

  // urbi-exception.hh
  class IDelegate;
  class UrbiException;
  class LookupError;
  class RedefinitionError;
  class PrimitiveError;
  class WrongArgumentType;
  class WrongArgumentCount;

  extern rObject nil_class;
  extern rObject task_class;
  extern rObject void_class;
} // namespace object

#endif // !OBJECT_FWD_HH
<|endoftext|>


<commit_before>#include "../include/page_swap.hpp"

page_swap_algorithm::page_swap_algorithm() {
    //create the block store
    init_backing_store();

    //set temp vars, couldve done this with one but you know it looks more cool with
    //long var names
    uint32_t tempFrameIdCounter = 0;
    uint32_t tempPageIdCount = 0;

    //init the page table setting the id and setting vaild to true
    for( auto& page : page_table){
        page.idx = tempPageIdCount++;
        page.valid = true;
        //allocate a block for each page that we have
        if(block_store_allocate(backing_store) == 0){
            //I tried adding the whon whon sound from mario for all the exceptions
            // but it broke...so i took it out
            throw std::runtime_error("Error when allocating blockstore block");
        }

        //init the block to array of @ signs using hex...
        //yea I finally learned hex to acii :)
        uint8_t buffer[frame_size] = {0x40};

        if(!write_to_back_store(buffer,page.idx)){
            throw std::runtime_error("Error while writing to backstore");
        }
    }

    //init the frame table and reading from the blockstore for the data
    for( auto& frame : frame_table){
        //initialize the pageId for the frame
        frame.page_table_idx = tempFrameIdCounter++;

        //read data from backing store into each frame's data
        if(!read_from_back_store(frame.data, frame.page_table_idx)){
            throw std::runtime_error("Could not read from backing store when initilizing frame table");
        }
        frame.tracking_byte = 0;
        frame.access_bit = 0;
    }
}

void page_swap_algorithm::init_backing_store() {
    backing_store = block_store_create();
    if (backing_store)
        return;
    throw std::runtime_error(std::string("Could not create block_store because ").append(block_store_strerror(bs_errno)));
}

page_swap_algorithm::~page_swap_algorithm() {
    block_store_destroy(backing_store, BS_NO_FLUSH);
}

void page_swap_algorithm::fault_printer(const uint32_t request, const uint32_t frame_replaced, const uint32_t page_replaced) {
    std::cout << "PAGE FAULT: PAGE REQUESTED: " << request << " FRAME REPLACED: " << frame_replaced << " PAGE REPLACED: " << page_replaced << std::endl;
}

bool page_swap_algorithm::read_from_back_store(uint8_t *buffer, uint32_t pageId) {
    //param check
    if(buffer && pageId >= 0){
        //I'm just going to hard code the block size value for reading the entire block...yep best practices
        //also since i'll always be reading in the entire block, another great hardcode
        if(block_store_read(backing_store,pageId+8,buffer,frame_size,0)){
            return true;
        }
        return false;
    }
    return false;

}

bool page_swap_algorithm::write_to_back_store(uint8_t *buffer, uint32_t pageId) {
    //params check
    if(buffer && pageId >= 0){
        //have to add 8 to pageid to account for begining in the backing store
        if(block_store_write(backing_store,pageId+8,buffer,frame_size,0)){
            return true;
        }
        return false;
    }
    return false;
}

std::vector<uint32_t> page_swap_algorithm::read_page_requests(const std::string &fname) {
    //check string isn't null
    if(!fname.empty()){
        //get file descriptor for bin file
        const int fd = open(fname.c_str(),O_RDONLY);
        //check file was opened correctly
        if (fd >= 0) {
            //init vecotre to hold the page requests
            std::vector<uint32_t> pRequests;
            uint32_t numRequests;
            //try to read in the number of Requests in the file
            if(read(fd,&numRequests,sizeof(uint32_t)) == sizeof(uint32_t)){

                uint32_t buffer;
                for(uint32_t i = 0;i < numRequests; i++){
                    //init buffer to zero each time
                    buffer = 0;
                    if(read(fd,&buffer,sizeof(uint32_t)) != sizeof(uint32_t)){
                        throw std::runtime_error(std::string("failed to read request "));
                    }
                    pRequests.push_back(buffer);
                }
                int counter = 0;
                for ( auto test : pRequests){
                    std::cout<<test<<" ";
                    if(counter > 10){
                        break;
                    }
                    counter++;
                }

                return pRequests;

            }
            throw std::runtime_error("could not read number of blocks");
        }
        throw std::runtime_error("could not open file");
    }
    throw std::runtime_error("Bad Params bro");
}
<commit_msg>removed print out testing<commit_after>#include "../include/page_swap.hpp"

page_swap_algorithm::page_swap_algorithm() {
    //create the block store
    init_backing_store();

    //set temp vars, couldve done this with one but you know it looks more cool with
    //long var names
    uint32_t tempFrameIdCounter = 0;
    uint32_t tempPageIdCount = 0;

    //init the page table setting the id and setting vaild to true
    for( auto& page : page_table){
        page.idx = tempPageIdCount++;
        page.valid = true;
        //allocate a block for each page that we have
        if(block_store_allocate(backing_store) == 0){
            //I tried adding the whon whon sound from mario for all the exceptions
            // but it broke...so i took it out
            throw std::runtime_error("Error when allocating blockstore block");
        }

        //init the block to array of @ signs using hex...
        //yea I finally learned hex to acii :)
        uint8_t buffer[frame_size] = {0x40};

        if(!write_to_back_store(buffer,page.idx)){
            throw std::runtime_error("Error while writing to backstore");
        }
    }

    //init the frame table and reading from the blockstore for the data
    for( auto& frame : frame_table){
        //initialize the pageId for the frame
        frame.page_table_idx = tempFrameIdCounter++;

        //read data from backing store into each frame's data
        if(!read_from_back_store(frame.data, frame.page_table_idx)){
            throw std::runtime_error("Could not read from backing store when initilizing frame table");
        }
        frame.tracking_byte = 0;
        frame.access_bit = 0;
    }
}

void page_swap_algorithm::init_backing_store() {
    backing_store = block_store_create();
    if (backing_store)
        return;
    throw std::runtime_error(std::string("Could not create block_store because ").append(block_store_strerror(bs_errno)));
}

page_swap_algorithm::~page_swap_algorithm() {
    block_store_destroy(backing_store, BS_NO_FLUSH);
}

void page_swap_algorithm::fault_printer(const uint32_t request, const uint32_t frame_replaced, const uint32_t page_replaced) {
    std::cout << "PAGE FAULT: PAGE REQUESTED: " << request << " FRAME REPLACED: " << frame_replaced << " PAGE REPLACED: " << page_replaced << std::endl;
}

bool page_swap_algorithm::read_from_back_store(uint8_t *buffer, uint32_t pageId) {
    //param check
    if(buffer && pageId >= 0){
        //I'm just going to hard code the block size value for reading the entire block...yep best practices
        //also since i'll always be reading in the entire block, another great hardcode
        if(block_store_read(backing_store,pageId+8,buffer,frame_size,0)){
            return true;
        }
        return false;
    }
    return false;

}

bool page_swap_algorithm::write_to_back_store(uint8_t *buffer, uint32_t pageId) {
    //params check
    if(buffer && pageId >= 0){
        //have to add 8 to pageid to account for begining in the backing store
        if(block_store_write(backing_store,pageId+8,buffer,frame_size,0)){
            return true;
        }
        return false;
    }
    return false;
}

std::vector<uint32_t> page_swap_algorithm::read_page_requests(const std::string &fname) {
    //check string isn't null
    if(!fname.empty()){
        //get file descriptor for bin file
        const int fd = open(fname.c_str(),O_RDONLY);
        //check file was opened correctly
        if (fd >= 0) {
            //init vecotre to hold the page requests
            std::vector<uint32_t> pRequests;
            uint32_t numRequests;
            //try to read in the number of Requests in the file
            if(read(fd,&numRequests,sizeof(uint32_t)) == sizeof(uint32_t)){

                uint32_t buffer;
                for(uint32_t i = 0;i < numRequests; i++){
                    //init buffer to zero each time
                    buffer = 0;
                    if(read(fd,&buffer,sizeof(uint32_t)) != sizeof(uint32_t)){
                        throw std::runtime_error(std::string("failed to read request "));
                    }
                    //add the request from the file onto the vector
                    pRequests.push_back(buffer);
                }

                return pRequests;

            }
            throw std::runtime_error("could not read number of blocks");
        }
        throw std::runtime_error("could not open file");
    }
    throw std::runtime_error("Bad Params bro");
}
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
/// \file  pcapcut.cpp
//------------------------------------------------------------------------------
/// \brief Utility for cutting a part of a large pcap file
/// \see
///      Alternative implementation using pcap.h
//------------------------------------------------------------------------------
// Copyright (c) 2016 Serge Aleynikov <saleyn@gmail.com>
// Created: 2016-11-28
//------------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file is part of the utxx open-source project.

Copyright (C) 2016 Serge Aleynikov <saleyn@gmail.com>

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

***** END LICENSE BLOCK *****
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <signal.h>
#include <utxx/pcap.hpp>
#include <utxx/string.hpp>
#include <utxx/path.hpp>
#include <utxx/get_option.hpp>
#include <utxx/buffer.hpp>
#include <utxx/version.hpp>

using namespace std;

//------------------------------------------------------------------------------
void usage(std::string const& err="")
{
    auto prog = utxx::path::basename(
        utxx::path::program::name().c_str(),
        utxx::path::program::name().c_str() + utxx::path::program::name().size()
    );

    if (!err.empty())
        cerr << "Invalid option: " << err << "\n\n";
    else {
        cerr << prog <<
        " - Tool for extracting packets from a pcap file\n"
        "Copyright (c) 2016 Serge Aleynikov\n"  <<
        VERSION() << "\n\n"                     <<
        "Usage: " << prog                       <<
        "[-V] [-h] -f InputFile -s StartPktNum -e EndPktNum [-n NumPkts] [-c|--count]"
                    " -o|-O OutputFile [-h]\n\n"
        "   -V|--version            - Version\n"
        "   -h|--help               - Help screen\n"
        "   -f InputFile            - Input file name\n"
        "   -o OutputFile           - Ouput file name (don't overwrite if exists)\n"
        "   -O OutputFile           - Ouput file name (overwrite if exists)\n"
        "   -s|--start StartPktNum  - Starting packet number (counting from 1)\n"
        "   -e|--end   EndPktNum    - Ending packet number (must be >= StartPktNum)\n"
        "   -n|--num   TotNumPkts   - Number of packets to save\n"
        "   -r|--raw                - Output raw packet payload only without pcap format\n"
        "   -c|--count              - Count number of packets in the file\n";
    }

    exit(1);
}

//------------------------------------------------------------------------------
void unhandled_exception() {
  auto p = current_exception();
  try    { rethrow_exception(p); }
  catch  ( exception& e ) { cerr << e.what() << endl; }
  catch  ( ... )          { cerr << "Unknown exception" << endl; }
  exit(1);
}

//------------------------------------------------------------------------------
//  MAIN
//------------------------------------------------------------------------------
int main(int argc, char *argv[])
{
    string in_file;
    string out_file;
    size_t pk_start  = 1, pk_end = 0, pk_cnt = 0;
    bool   overwrite = false;
    bool   raw_mode  = false;
    bool   count     = false;

    set_terminate (&unhandled_exception);

    utxx::opts_parser opts(argc, argv);

    while (opts.next()) {
        if (opts.match("-f", "",        &in_file))  continue;
        if (opts.match("-o", "",        &out_file)) continue;
        if (opts.match("-O", "",        &out_file)){overwrite=true; continue;}
        if (opts.match("-r", "--raw",   &raw_mode)) continue;
        if (opts.match("-s", "--start", &pk_start)) continue;
        if (opts.match("-e", "--end",   &pk_end))   continue;
        if (opts.match("-n", "--num",   &pk_cnt))   continue;
        if (opts.match("-c", "--count", &count))    continue;
        if (opts.match("-V", "--version")) throw std::runtime_error(VERSION());
        if (opts.is_help())                         usage();

        usage(opts());
    }

    if (pk_end > 0 && pk_cnt > 0)
        throw std::runtime_error("Cannot specify both -n and -e options!");
    else if (!pk_end && !pk_cnt && !count)
        throw std::runtime_error("Must specify either -n or -e option!");
    else if (!pk_start && !count)
        throw std::runtime_error("PktStartNumber (-s) must be greater than 0!");
    else if (pk_end && pk_end < pk_start)
        throw std::runtime_error
             ("Ending packet number (-e) must not be less than starting packet number (-s)!");
    else if (in_file.empty() || (!count && out_file.empty()))
        throw std::runtime_error("Must specify -f and -o options!");
    else if (!count && utxx::path::file_exists(out_file)) {
        if (!overwrite)
            throw std::runtime_error("Found existing output file: " + out_file);
        if (!utxx::path::file_unlink(out_file))
            throw std::runtime_error("Error deleting file " + out_file +
                                     ": " + strerror(errno));
    }

    if (pk_cnt) {
        pk_end = pk_start + pk_cnt - 1;
        pk_cnt = 0;
    }

    utxx::pcap fin;
    if (fin.open_read(in_file) < 0)
        throw std::runtime_error("Error opening " + in_file + ": " + strerror(errno));
    else if (fin.read_file_header() < 0)
        throw std::runtime_error("File " + in_file + " is not in PCAP format!");

    int n = 0;
    utxx::pcap fout(fin.big_endian(), fin.nsec_time());

    if (!count) {
        n = raw_mode ? fout.open(out_file.c_str(), "wb")
                    : fout.open_write(out_file, false, fin.get_link_type());
        if (n < 0)
            throw std::runtime_error("Error creating file " + out_file + ": " + strerror(errno));
    }

    utxx::basic_io_buffer<(1024*1024)> buf;

    while ((n = fin.read(buf.wr_ptr(), buf.capacity())) > 0) {
        buf.commit(n);
        while (buf.size() > sizeof(utxx::pcap::packet_header)) {
            const char*       header;
            const char*       begin  = header = buf.rd_ptr();
            int               frame_sz, sz;
            utxx::pcap::proto proto;

            // sz - total size of payload including frame_sz
            std::tie(frame_sz, sz, proto) = fin.read_packet_hdr_and_frame(begin, n);

            if (frame_sz < 0 || int(buf.size()) < sz) { // Not enough data in the buffer
                buf.reserve(sz);
                break;
            }

            if (++pk_cnt >= pk_start && !count) {
                if (pk_cnt > pk_end)
                    goto DONE;

                // Write to the output file
                if (!raw_mode) {
                    fout.write_packet_header(fin.packet());
                    buf.read(sizeof(utxx::pcap::packet_header));
                    sz -= sizeof(utxx::pcap::packet_header);
                } else {
                    buf.read(frame_sz);
                    sz -= frame_sz;
                }
                if (fout.write(buf.rd_ptr(), sz) < 0)
                    throw std::runtime_error(string("Error writing to file: ") + strerror(errno));
            }

            buf.read(sz);
        }

        buf.crunch();
    }

  DONE:
    fout.close();
    fin.close();

    if (count)
        cout << pk_cnt << " packets\n";

    return 0;
}<commit_msg>Add verbose option<commit_after>//------------------------------------------------------------------------------
/// \file  pcapcut.cpp
//------------------------------------------------------------------------------
/// \brief Utility for cutting a part of a large pcap file
/// \see
///      Alternative implementation using pcap.h
//------------------------------------------------------------------------------
// Copyright (c) 2016 Serge Aleynikov <saleyn@gmail.com>
// Created: 2016-11-28
//------------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file is part of the utxx open-source project.

Copyright (C) 2016 Serge Aleynikov <saleyn@gmail.com>

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

***** END LICENSE BLOCK *****
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <signal.h>
#include <utxx/pcap.hpp>
#include <utxx/string.hpp>
#include <utxx/path.hpp>
#include <utxx/get_option.hpp>
#include <utxx/buffer.hpp>
#include <utxx/version.hpp>

using namespace std;

//------------------------------------------------------------------------------
void usage(std::string const& err="")
{
    auto prog = utxx::path::basename(
        utxx::path::program::name().c_str(),
        utxx::path::program::name().c_str() + utxx::path::program::name().size()
    );

    if (!err.empty())
        cerr << "Invalid option: " << err << "\n\n";
    else {
        cerr << prog <<
        " - Tool for extracting packets from a pcap file\n"
        "Copyright (c) 2016 Serge Aleynikov\n"  <<
        VERSION() << "\n\n"                     <<
        "Usage: " << prog                       <<
        "[-V] [-h] -f InputFile -s StartPktNum -e EndPktNum [-n NumPkts] [-c|--count]"
                    " -o|-O OutputFile [-h]\n\n"
        "   -V|--version            - Version\n"
        "   -h|--help               - Help screen\n"
        "   -f InputFile            - Input file name\n"
        "   -o OutputFile           - Ouput file name (don't overwrite if exists)\n"
        "   -O OutputFile           - Ouput file name (overwrite if exists)\n"
        "   -s|--start StartPktNum  - Starting packet number (counting from 1)\n"
        "   -e|--end   EndPktNum    - Ending packet number (must be >= StartPktNum)\n"
        "   -n|--num   TotNumPkts   - Number of packets to save\n"
        "   -r|--raw                - Output raw packet payload only without pcap format\n"
        "   -c|--count              - Count number of packets in the file\n"
        "   -v                      - Verbose\n\n";
    }

    exit(1);
}

//------------------------------------------------------------------------------
void unhandled_exception() {
  auto p = current_exception();
  try    { rethrow_exception(p); }
  catch  ( exception& e ) { cerr << e.what() << endl; }
  catch  ( ... )          { cerr << "Unknown exception" << endl; }
  exit(1);
}

//------------------------------------------------------------------------------
//  MAIN
//------------------------------------------------------------------------------
int main(int argc, char *argv[])
{
    string in_file;
    string out_file;
    size_t pk_start  = 1, pk_end = 0, pk_cnt = 0;
    bool   overwrite = false;
    bool   raw_mode  = false;
    bool   count     = false;
    bool   verbose   = false;

    set_terminate (&unhandled_exception);

    utxx::opts_parser opts(argc, argv);

    while (opts.next()) {
        if (opts.match("-f", "",        &in_file))  continue;
        if (opts.match("-o", "",        &out_file)) continue;
        if (opts.match("-O", "",        &out_file)){overwrite=true; continue;}
        if (opts.match("-r", "--raw",   &raw_mode)) continue;
        if (opts.match("-s", "--start", &pk_start)) continue;
        if (opts.match("-e", "--end",   &pk_end))   continue;
        if (opts.match("-n", "--num",   &pk_cnt))   continue;
        if (opts.match("-c", "--count", &count))    continue;
        if (opts.match("-v", "",        &verbose))  continue;
        if (opts.match("-V", "--version")) throw std::runtime_error(VERSION());
        if (opts.is_help())                         usage();

        usage(opts());
    }

    if (pk_end > 0 && pk_cnt > 0)
        throw std::runtime_error("Cannot specify both -n and -e options!");
    else if (!pk_end && !pk_cnt && !count)
        throw std::runtime_error("Must specify either -n or -e option!");
    else if (!pk_start && !count)
        throw std::runtime_error("PktStartNumber (-s) must be greater than 0!");
    else if (pk_end && pk_end < pk_start)
        throw std::runtime_error
             ("Ending packet number (-e) must not be less than starting packet number (-s)!");
    else if (in_file.empty() || (!count && out_file.empty()))
        throw std::runtime_error("Must specify -f and -o options!");
    else if (!count && utxx::path::file_exists(out_file)) {
        if (!overwrite)
            throw std::runtime_error("Found existing output file: " + out_file);
        if (!utxx::path::file_unlink(out_file))
            throw std::runtime_error("Error deleting file " + out_file +
                                     ": " + strerror(errno));
    }

    if (pk_cnt) {
        pk_end = pk_start + pk_cnt - 1;
        pk_cnt = 0;
    }

    utxx::pcap fin;
    if (fin.open_read(in_file) < 0)
        throw std::runtime_error("Error opening " + in_file + ": " + strerror(errno));
    else if (fin.read_file_header() < 0)
        throw std::runtime_error("File " + in_file + " is not in PCAP format!");

    int n = 0;
    utxx::pcap fout(fin.big_endian(), fin.nsec_time());

    if (!count) {
        n = raw_mode ? fout.open(out_file.c_str(), "wb")
                    : fout.open_write(out_file, false, fin.get_link_type());
        if (n < 0)
            throw std::runtime_error("Error creating file " + out_file + ": " + strerror(errno));
    }

    utxx::basic_io_buffer<(1024*1024)> buf;

    while ((n = fin.read(buf.wr_ptr(), buf.capacity())) > 0) {
        buf.commit(n);
        while (buf.size() > sizeof(utxx::pcap::packet_header)) {
            const char*       header;
            const char*       begin  = header = buf.rd_ptr();
            int               frame_sz, sz;
            utxx::pcap::proto proto;

            // sz - total size of payload including frame_sz
            std::tie(frame_sz, sz, proto) = fin.read_packet_hdr_and_frame(begin, n);

            bool ok = (frame_sz < 0 || int(buf.size()) < sz);

            if (verbose)
                cerr << "Pkt#"     << (pk_cnt+1) << " FrameSz=" << setw(2)    << frame_sz
                     << " Bytes="  << sz         << " BufSz="   << buf.size()
                     << " Offset=" << fin.tell() << (ok ? "" : " ***")        << endl;

            if (!ok) { // Not enough data in the buffer
                buf.reserve(sz);
                break;
            }

            if (++pk_cnt >= pk_start && !count) {
                if (pk_cnt > pk_end)
                    goto DONE;

                // Write to the output file
                if (!raw_mode) {
                    fout.write_packet_header(fin.packet());
                    buf.read(sizeof(utxx::pcap::packet_header));
                    sz    -= sizeof(utxx::pcap::packet_header);
                } else {
                    buf.read(frame_sz);
                    sz    -= frame_sz;
                }
                if (fout.write(buf.rd_ptr(), sz) < 0)
                    throw std::runtime_error(string("Error writing to file: ") + strerror(errno));
            }

            buf.read(sz);
        }

        buf.crunch();
    }

  DONE:
    fout.close();
    fin.close();

    if (count)
        cout << pk_cnt << " packets\n";

    return 0;
}<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- vim:set ts=4 sw=4 sts=4 noet: */
#include "reach.hh"

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <unordered_map>

#include <boost/functional/hash.hpp>
#include <boost/ptr_container/ptr_map.hpp>
#include <boost/ptr_container/ptr_set.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_io.hpp>

#include "db/input-port-loader.h"
#include "db/output-port-loader.h"
#include "db/reach-driver.h"
#include "db/scope-loader.h"
#include "db/span-loader.h"
#include "reduction.hh"

using std::cerr;
using std::endl;
using std::make_pair;
using std::multimap;
using std::set;
using std::string;
using std::pair;

namespace flint {
namespace phml {
namespace {

class Scope {
public:
	Scope(const Scope &) = delete;
	Scope &operator=(const Scope &) = delete;

	Scope(boost::uuids::uuid uuid, boost::uuids::uuid module_id)
		: uuid_(uuid),
		  module_id_(module_id),
		  label_()
	{
	}

	Scope(boost::uuids::uuid uuid, boost::uuids::uuid module_id, string label)
		: uuid_(uuid),
		  module_id_(module_id),
		  label_(label)
	{
	}

	const boost::uuids::uuid &uuid() const {return uuid_;}
	const boost::uuids::uuid &module_id() const {return module_id_;}
	const string &label() const {return label_;}

	// comparison wrt module_id_ & uuid_ (but not label_)
	bool operator<(const Scope &other) const {
		if (module_id_ < other.module_id_) return true;
		if (module_id_ == other.module_id_ &&
			uuid_ < other.uuid_) return true;
		return false;
	}

private:
	boost::uuids::uuid uuid_;
	boost::uuids::uuid module_id_;
	string label_;
};

class Port {
public:
	Port(boost::uuids::uuid module_id, int port_id, int physical_quantity_id,
		 char pq_type, Reduction reduction)
		: module_id_(module_id),
		  port_id_(port_id),
		  physical_quantity_id_(physical_quantity_id),
		  pq_type_(pq_type)
		, reduction_(reduction)
	{
	}

	const boost::uuids::uuid &module_id() const {return module_id_;}
	int port_id() const {return port_id_;}
	int physical_quantity_id() const {return physical_quantity_id_;}
	char pq_type() const {return pq_type_;}
	Reduction reduction() const {return reduction_;}

private:
	boost::uuids::uuid module_id_;
	int port_id_;
	int physical_quantity_id_;
	char pq_type_;
	Reduction reduction_;
};

class Node {
public:
	Node(boost::uuids::uuid uuid, int port_id) : uuid_(uuid), port_id_(port_id) {}

	const boost::uuids::uuid &uuid() const {return uuid_;}
	int port_id() const {return port_id_;}

	bool operator<(const Node &other) const {
		if (uuid_ < other.uuid_) return true;
		if (uuid_ == other.uuid_ &&
			port_id_ < other.port_id_) return true;
		return false;
	}

private:
	boost::uuids::uuid uuid_;
	int port_id_;
};

class InputPortHandler {
public:
	InputPortHandler(const InputPortHandler &) = delete;
	InputPortHandler &operator=(const InputPortHandler &) = delete;

	explicit InputPortHandler(boost::ptr_multimap<boost::uuids::uuid, Port> *ports)
		: ports_(ports)
	{
	}

	bool Handle(boost::uuids::uuid uuid, int port_id, int pq_id,
				char pq_type, Reduction reduction)
	{
		ports_->insert(uuid, new Port(uuid, port_id, pq_id, pq_type, reduction));
		return true;
	}

private:
	boost::ptr_multimap<boost::uuids::uuid, Port> *ports_;
};

bool LoadInputPorts(sqlite3 *db, boost::ptr_multimap<boost::uuids::uuid, Port> *ports)
{
	std::unique_ptr<db::InputPortLoader> loader(new db::InputPortLoader(db));
	std::unique_ptr<InputPortHandler> handler(new InputPortHandler(ports));
	return loader->Load(handler.get());
}

class OutputPortHandler {
public:
	OutputPortHandler(const OutputPortHandler &) = delete;
	OutputPortHandler &operator=(const OutputPortHandler &) = delete;

	explicit OutputPortHandler(std::map<Node, Port> *ports)
		: ports_(ports)
	{
	}

	bool Handle(boost::uuids::uuid uuid, int port_id, int pq_id, char pq_type) {
		Node node(uuid, port_id);
		// reduction makes little sense for output port, so just call it unspecified
		ports_->emplace(std::make_pair(node, Port(uuid, port_id, pq_id, pq_type, Reduction::kUnspecified)));
		return true;
	}

private:
	std::map<Node, Port> *ports_;
};

bool LoadOutputPorts(sqlite3 *db, std::map<Node, Port> *ports)
{
	std::unique_ptr<db::OutputPortLoader> loader(new db::OutputPortLoader(db));
	std::unique_ptr<OutputPortHandler> handler(new OutputPortHandler(ports));
	return loader->Load(handler.get());
}

typedef boost::ptr_set<Scope> ScopeSet;
typedef multimap<boost::uuids::uuid, ScopeSet::iterator> Mmap;
typedef std::unordered_map<boost::uuids::uuid,
						   ScopeSet::iterator,
						   boost::hash<boost::uuids::uuid>
						   > Umap;

class ScopeHandler {
public:
	ScopeHandler(const ScopeHandler &) = delete;
	ScopeHandler &operator=(const ScopeHandler &) = delete;

	ScopeHandler(ScopeSet *scopes, Mmap *mmap, Umap *umap)
		: scopes_(scopes),
		  mmap_(mmap),
		  umap_(umap)
	{}

	bool Handle(boost::uuids::uuid uuid, boost::uuids::uuid space_id, const char *label) {
		pair<ScopeSet::iterator, bool> p;
		if (label) {
			p = scopes_->insert(new Scope(uuid, space_id, string(label)));
		} else {
			p = scopes_->insert(new Scope(uuid, space_id));
		}
		if (!p.second) {
			cerr << "duplicate entry of scope: " << uuid << endl;
			return false;
		}
		mmap_->insert(make_pair(space_id, p.first));
		umap_->insert(make_pair(uuid, p.first));
		return true;
	}

private:
	ScopeSet *scopes_;
	Mmap *mmap_;
	Umap *umap_;
};

bool LoadScopes(sqlite3 *db, ScopeSet *scopes, Mmap *mmap, Umap *umap)
{
	std::unique_ptr<db::ScopeLoader> loader(new db::ScopeLoader(db));
	std::unique_ptr<ScopeHandler> handler(new ScopeHandler(scopes, mmap, umap));
	return loader->Load(handler.get());
}

class SpanHandler {
public:
	SpanHandler(const SpanHandler &) = delete;
	SpanHandler &operator=(const SpanHandler &) = delete;

	explicit SpanHandler(multimap<Node, Node> *spans) : spans_(spans) {}

	bool Handle(boost::uuids::uuid tail_uuid, int tail_port_id,
				boost::uuids::uuid head_uuid, int head_port_id) {
		// reverse direction: from head to tail
		spans_->insert(make_pair(Node(head_uuid, head_port_id),
								 Node(tail_uuid, tail_port_id)));
		return true;
	}

private:
	multimap<Node, Node> *spans_;
};

bool LoadEdges(sqlite3 *db, multimap<Node, Node> *edges)
{
	std::unique_ptr<db::SpanLoader> loader(new db::SpanLoader(db));
	std::unique_ptr<SpanHandler> handler(new SpanHandler(edges));
	return loader->Load(handler.get());
}

void Lookup(const Node &p, multimap<Node, Node> &edges, set<Node> *q)
{
	pair<multimap<Node, Node>::iterator, multimap<Node, Node>::iterator> r;
	r = edges.equal_range(p);
	if (r.first == r.second) {
		q->insert(p);
		return;
	}
	set<Node> s;
	for (multimap<Node, Node>::iterator it=r.first;it!=r.second;++it) {
		const Node &tail = it->second;
		s.insert(tail);
	}
	for (set<Node>::const_iterator it=s.begin();it!=s.end();++it) {
		Lookup(*it, edges, q);
	}
}

void PrintIncompatiblePorts(const Port *from, const Port &to)
{
	cerr << "  from" << endl
		 << "    port-id: " << from->port_id() << endl
		 << "    module-id: " << from->module_id() << endl
		 << "  to" << endl
		 << "    port-id: " << to.port_id() << endl
		 << "    module-id: " << to.module_id() << endl;
}

} // namespace

bool Reach(sqlite3 *db)
{
	boost::ptr_multimap<boost::uuids::uuid, Port> inports;
	if (!LoadInputPorts(db, &inports)) return false;

	std::map<Node, Port> outports;
	if (!LoadOutputPorts(db, &outports)) return false;

	ScopeSet scopes;
	Mmap mmap;
	Umap umap;
	if (!LoadScopes(db, &scopes, &mmap, &umap)) return false;

	multimap<Node, Node> edges;
	if (!LoadEdges(db, &edges)) return false;

	std::unique_ptr<db::ReachDriver> driver(new db::ReachDriver(db));
	// trace from each input-port
	for (boost::ptr_multimap<boost::uuids::uuid, Port>::const_iterator it=inports.begin();it!=inports.end();++it) {
		const boost::uuids::uuid &module_id = it->first;
		const Port *inport = it->second;

		pair<Mmap::iterator, Mmap::iterator> r;
		r = mmap.equal_range(module_id);
		for (Mmap::iterator rit=r.first;rit!=r.second;++rit) {
			const boost::uuids::uuid &uuid = rit->second->uuid();
			Node p(uuid, inport->port_id());
			set<Node> t;
			Lookup(p, edges, &t);
			for (set<Node>::const_iterator tit=t.begin();tit!=t.end();++tit) {
				const Node &o = *tit;
				if (o.port_id() <= 0) {
					cerr << "invalid port-id of edge: " << o.port_id() << endl;
					return false;
				}
				// find corresponding output-port
				Umap::const_iterator uit = umap.find(o.uuid());
				if (uit == umap.end()) {
					cerr << "missing node with uuid: " << o.uuid() << endl;
					return false;
				}
				const boost::uuids::uuid &om = uit->second->module_id();
				Node ok(om, o.port_id());
				std::map<Node, Port>::const_iterator oit = outports.find(ok);
				if (oit == outports.end()) {
					cerr << "lost without corresponding edge or output-port" << endl;
					cerr << "  port-id: " << o.port_id() << endl;
					cerr << "  module-id: " << uit->second->module_id() << endl;
					cerr << "  uuid: " << uit->second->uuid() << endl;
					if (!uit->second->label().empty()) cerr << "  label: " <<  uit->second->label() << endl;
					return false;
				}
				// check if PQ types of both sides are compatible
				if (inport->pq_type() == 's') {
					switch (oit->second.pq_type()) {
					case 'x':
						cerr << "found invalid edge from a state to a static-parameter" << endl;
						PrintIncompatiblePorts(inport, oit->second);
						return false;
					case 'v':
						cerr << "found invalid edge from a variable-parameter to a static-parameter" << endl;
						PrintIncompatiblePorts(inport, oit->second);
						return false;
					}
				}
				if (!driver->Save(tit->uuid(), oit->second.physical_quantity_id(),
								  uuid, inport->physical_quantity_id(),
								  inport->reduction()))
					return false;
			}
		}
	}
	return true;
}

}
}
<commit_msg>Replace boost::ptr_multimap with std::multimap<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- vim:set ts=4 sw=4 sts=4 noet: */
#include "reach.hh"

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <unordered_map>

#include <boost/functional/hash.hpp>
#include <boost/ptr_container/ptr_set.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_io.hpp>

#include "db/input-port-loader.h"
#include "db/output-port-loader.h"
#include "db/reach-driver.h"
#include "db/scope-loader.h"
#include "db/span-loader.h"
#include "reduction.hh"

using std::cerr;
using std::endl;
using std::make_pair;
using std::multimap;
using std::set;
using std::string;
using std::pair;

namespace flint {
namespace phml {
namespace {

class Scope {
public:
	Scope(const Scope &) = delete;
	Scope &operator=(const Scope &) = delete;

	Scope(boost::uuids::uuid uuid, boost::uuids::uuid module_id)
		: uuid_(uuid),
		  module_id_(module_id),
		  label_()
	{
	}

	Scope(boost::uuids::uuid uuid, boost::uuids::uuid module_id, string label)
		: uuid_(uuid),
		  module_id_(module_id),
		  label_(label)
	{
	}

	const boost::uuids::uuid &uuid() const {return uuid_;}
	const boost::uuids::uuid &module_id() const {return module_id_;}
	const string &label() const {return label_;}

	// comparison wrt module_id_ & uuid_ (but not label_)
	bool operator<(const Scope &other) const {
		if (module_id_ < other.module_id_) return true;
		if (module_id_ == other.module_id_ &&
			uuid_ < other.uuid_) return true;
		return false;
	}

private:
	boost::uuids::uuid uuid_;
	boost::uuids::uuid module_id_;
	string label_;
};

class Port {
public:
	Port(boost::uuids::uuid module_id, int port_id, int physical_quantity_id,
		 char pq_type, Reduction reduction)
		: module_id_(module_id),
		  port_id_(port_id),
		  physical_quantity_id_(physical_quantity_id),
		  pq_type_(pq_type)
		, reduction_(reduction)
	{
	}

	const boost::uuids::uuid &module_id() const {return module_id_;}
	int port_id() const {return port_id_;}
	int physical_quantity_id() const {return physical_quantity_id_;}
	char pq_type() const {return pq_type_;}
	Reduction reduction() const {return reduction_;}

private:
	boost::uuids::uuid module_id_;
	int port_id_;
	int physical_quantity_id_;
	char pq_type_;
	Reduction reduction_;
};

class Node {
public:
	Node(boost::uuids::uuid uuid, int port_id) : uuid_(uuid), port_id_(port_id) {}

	const boost::uuids::uuid &uuid() const {return uuid_;}
	int port_id() const {return port_id_;}

	bool operator<(const Node &other) const {
		if (uuid_ < other.uuid_) return true;
		if (uuid_ == other.uuid_ &&
			port_id_ < other.port_id_) return true;
		return false;
	}

private:
	boost::uuids::uuid uuid_;
	int port_id_;
};

class InputPortHandler {
public:
	InputPortHandler(const InputPortHandler &) = delete;
	InputPortHandler &operator=(const InputPortHandler &) = delete;

	explicit InputPortHandler(std::multimap<boost::uuids::uuid, Port> *ports)
		: ports_(ports)
	{
	}

	bool Handle(boost::uuids::uuid uuid, int port_id, int pq_id,
				char pq_type, Reduction reduction)
	{
		ports_->emplace(std::make_pair(uuid, Port(uuid, port_id, pq_id, pq_type, reduction)));
		return true;
	}

private:
	std::multimap<boost::uuids::uuid, Port> *ports_;
};

bool LoadInputPorts(sqlite3 *db, std::multimap<boost::uuids::uuid, Port> *ports)
{
	std::unique_ptr<db::InputPortLoader> loader(new db::InputPortLoader(db));
	std::unique_ptr<InputPortHandler> handler(new InputPortHandler(ports));
	return loader->Load(handler.get());
}

class OutputPortHandler {
public:
	OutputPortHandler(const OutputPortHandler &) = delete;
	OutputPortHandler &operator=(const OutputPortHandler &) = delete;

	explicit OutputPortHandler(std::map<Node, Port> *ports)
		: ports_(ports)
	{
	}

	bool Handle(boost::uuids::uuid uuid, int port_id, int pq_id, char pq_type) {
		Node node(uuid, port_id);
		// reduction makes little sense for output port, so just call it unspecified
		ports_->emplace(std::make_pair(node, Port(uuid, port_id, pq_id, pq_type, Reduction::kUnspecified)));
		return true;
	}

private:
	std::map<Node, Port> *ports_;
};

bool LoadOutputPorts(sqlite3 *db, std::map<Node, Port> *ports)
{
	std::unique_ptr<db::OutputPortLoader> loader(new db::OutputPortLoader(db));
	std::unique_ptr<OutputPortHandler> handler(new OutputPortHandler(ports));
	return loader->Load(handler.get());
}

typedef boost::ptr_set<Scope> ScopeSet;
typedef multimap<boost::uuids::uuid, ScopeSet::iterator> Mmap;
typedef std::unordered_map<boost::uuids::uuid,
						   ScopeSet::iterator,
						   boost::hash<boost::uuids::uuid>
						   > Umap;

class ScopeHandler {
public:
	ScopeHandler(const ScopeHandler &) = delete;
	ScopeHandler &operator=(const ScopeHandler &) = delete;

	ScopeHandler(ScopeSet *scopes, Mmap *mmap, Umap *umap)
		: scopes_(scopes),
		  mmap_(mmap),
		  umap_(umap)
	{}

	bool Handle(boost::uuids::uuid uuid, boost::uuids::uuid space_id, const char *label) {
		pair<ScopeSet::iterator, bool> p;
		if (label) {
			p = scopes_->insert(new Scope(uuid, space_id, string(label)));
		} else {
			p = scopes_->insert(new Scope(uuid, space_id));
		}
		if (!p.second) {
			cerr << "duplicate entry of scope: " << uuid << endl;
			return false;
		}
		mmap_->insert(make_pair(space_id, p.first));
		umap_->insert(make_pair(uuid, p.first));
		return true;
	}

private:
	ScopeSet *scopes_;
	Mmap *mmap_;
	Umap *umap_;
};

bool LoadScopes(sqlite3 *db, ScopeSet *scopes, Mmap *mmap, Umap *umap)
{
	std::unique_ptr<db::ScopeLoader> loader(new db::ScopeLoader(db));
	std::unique_ptr<ScopeHandler> handler(new ScopeHandler(scopes, mmap, umap));
	return loader->Load(handler.get());
}

class SpanHandler {
public:
	SpanHandler(const SpanHandler &) = delete;
	SpanHandler &operator=(const SpanHandler &) = delete;

	explicit SpanHandler(multimap<Node, Node> *spans) : spans_(spans) {}

	bool Handle(boost::uuids::uuid tail_uuid, int tail_port_id,
				boost::uuids::uuid head_uuid, int head_port_id) {
		// reverse direction: from head to tail
		spans_->insert(make_pair(Node(head_uuid, head_port_id),
								 Node(tail_uuid, tail_port_id)));
		return true;
	}

private:
	multimap<Node, Node> *spans_;
};

bool LoadEdges(sqlite3 *db, multimap<Node, Node> *edges)
{
	std::unique_ptr<db::SpanLoader> loader(new db::SpanLoader(db));
	std::unique_ptr<SpanHandler> handler(new SpanHandler(edges));
	return loader->Load(handler.get());
}

void Lookup(const Node &p, multimap<Node, Node> &edges, set<Node> *q)
{
	pair<multimap<Node, Node>::iterator, multimap<Node, Node>::iterator> r;
	r = edges.equal_range(p);
	if (r.first == r.second) {
		q->insert(p);
		return;
	}
	set<Node> s;
	for (multimap<Node, Node>::iterator it=r.first;it!=r.second;++it) {
		const Node &tail = it->second;
		s.insert(tail);
	}
	for (set<Node>::const_iterator it=s.begin();it!=s.end();++it) {
		Lookup(*it, edges, q);
	}
}

void PrintIncompatiblePorts(const Port &from, const Port &to)
{
	cerr << "  from" << endl
		 << "    port-id: " << from.port_id() << endl
		 << "    module-id: " << from.module_id() << endl
		 << "  to" << endl
		 << "    port-id: " << to.port_id() << endl
		 << "    module-id: " << to.module_id() << endl;
}

} // namespace

bool Reach(sqlite3 *db)
{
	std::multimap<boost::uuids::uuid, Port> inports;
	if (!LoadInputPorts(db, &inports)) return false;

	std::map<Node, Port> outports;
	if (!LoadOutputPorts(db, &outports)) return false;

	ScopeSet scopes;
	Mmap mmap;
	Umap umap;
	if (!LoadScopes(db, &scopes, &mmap, &umap)) return false;

	multimap<Node, Node> edges;
	if (!LoadEdges(db, &edges)) return false;

	std::unique_ptr<db::ReachDriver> driver(new db::ReachDriver(db));
	// trace from each input-port
	for (auto it=inports.cbegin();it!=inports.cend();++it) {
		const boost::uuids::uuid &module_id = it->first;
		const Port &inport = it->second;

		pair<Mmap::iterator, Mmap::iterator> r;
		r = mmap.equal_range(module_id);
		for (Mmap::iterator rit=r.first;rit!=r.second;++rit) {
			const boost::uuids::uuid &uuid = rit->second->uuid();
			Node p(uuid, inport.port_id());
			set<Node> t;
			Lookup(p, edges, &t);
			for (set<Node>::const_iterator tit=t.begin();tit!=t.end();++tit) {
				const Node &o = *tit;
				if (o.port_id() <= 0) {
					cerr << "invalid port-id of edge: " << o.port_id() << endl;
					return false;
				}
				// find corresponding output-port
				Umap::const_iterator uit = umap.find(o.uuid());
				if (uit == umap.end()) {
					cerr << "missing node with uuid: " << o.uuid() << endl;
					return false;
				}
				const boost::uuids::uuid &om = uit->second->module_id();
				Node ok(om, o.port_id());
				std::map<Node, Port>::const_iterator oit = outports.find(ok);
				if (oit == outports.end()) {
					cerr << "lost without corresponding edge or output-port" << endl;
					cerr << "  port-id: " << o.port_id() << endl;
					cerr << "  module-id: " << uit->second->module_id() << endl;
					cerr << "  uuid: " << uit->second->uuid() << endl;
					if (!uit->second->label().empty()) cerr << "  label: " <<  uit->second->label() << endl;
					return false;
				}
				// check if PQ types of both sides are compatible
				if (inport.pq_type() == 's') {
					switch (oit->second.pq_type()) {
					case 'x':
						cerr << "found invalid edge from a state to a static-parameter" << endl;
						PrintIncompatiblePorts(inport, oit->second);
						return false;
					case 'v':
						cerr << "found invalid edge from a variable-parameter to a static-parameter" << endl;
						PrintIncompatiblePorts(inport, oit->second);
						return false;
					}
				}
				if (!driver->Save(tit->uuid(), oit->second.physical_quantity_id(),
								  uuid, inport.physical_quantity_id(),
								  inport.reduction()))
					return false;
			}
		}
	}
	return true;
}

}
}
<|endoftext|>


<commit_before>#include "playsound.hpp"
#include "soundsystem.hpp"

PlaySound::PlaySound(SoundSystem* soundSystem, SoundComponent::Sound& sound) :
    soundSystem(soundSystem),
    sound(sound) { }

void PlaySound::execute() {
    soundSystem->playSound(sound);
}
<commit_msg>Sound is copied by value into PlaySound-command instead of reference, which caused segfaults<commit_after>#include "playsound.hpp"
#include "soundsystem.hpp"

PlaySound::PlaySound(SoundSystem* soundSystem, SoundComponent::Sound sound) :
    soundSystem(soundSystem),
    sound(sound) { }

void PlaySound::execute() {
    soundSystem->playSound(sound);
}
<|endoftext|>