<commit_before>#include "tags.h"
#include "clock.h"

#include <0mq/message.h>
#include <0mq/context.h>
#include <0mq/socket.h>
#include <0mq/poller.h>

#include <chrono>
#include <cstddef>
#include <list>
#include <memory>
#include <unordered_map>
#include <iostream>
#include <iomanip>
#include <stdexcept>

namespace zmqmap {

typedef std::chrono::time_point<steadyclock_type> timepoint_type;

typedef zmq::Message identity_type;
typedef zmq::Message jobid_type;
typedef zmq::Message call_type;

class IdentityHash {
public:
    size_t operator() (const identity_type& identity) const {
      std::size_t h = 0;
      const char* d = identity.data();
      for (std::size_t i = 0; i < identity.size(); ++i) {
        h = (h << 1) ^ (std::hash<char>()(d[i]));
      }

      return h;
    }
};

class Worker {
  public:
    Worker(const identity_type& identity)
      : heartbeatInterval_(1000 * 3), identity_(identity)
    {
    }

    void update(const timepoint_type& timePoint) {
      latestHeartBeat_ = timePoint +
        std::chrono::milliseconds(heartbeatInterval_);
    }

    bool isVanished(const timepoint_type& timePoint) const {
      return timePoint > latestHeartBeat_;
    }

    const identity_type& getIdentity() const {
      return identity_;
    }

  private:
    const std::size_t heartbeatInterval_;

    const identity_type identity_;
    timepoint_type latestHeartBeat_;
};

class BrokerApplication {
  private:
    typedef std::unordered_map<identity_type, Worker, IdentityHash> workermap_type;

  public:
    BrokerApplication()
    : heartbeatInterval_(1000), cacheQueueLength_(100),
      context_(), frontendSocket_(), backendSocket_(),
      cacheQueue_(), idleWorkers_(), busyWorkers_()
    {
    }

    void init() {
      connect();
    }

    void go() {
      //  Send out heartbeats at regular intervals
      timepoint_type nextHeartBeat;
      nextHeartBeat = steadyclock_type::now() +
        std::chrono::milliseconds(heartbeatInterval_);

      while (true) {
        std::vector<zmq::Socket> items = { backendSocket_, frontendSocket_ };

        std::vector<short> state = zmq::poll(items, heartbeatInterval_);

        // handle backend
        if (state[0] & ZMQ_POLLIN) {
          handleBackend();
        }

        // handle frontend
        if (state[1] & ZMQ_POLLIN) {
          handleFrontend();
        }

        checkWorkers(idleWorkers_);
        checkWorkers(busyWorkers_);

        assignJobs();

        timepoint_type now = steadyclock_type::now();
        if (now > nextHeartBeat) {
          sendHeartBeat(idleWorkers_);
          sendHeartBeat(busyWorkers_);

          sendJobQueued();

          nextHeartBeat = now +
            std::chrono::milliseconds(heartbeatInterval_);

          printStats();
        }
      }
    }

  private:
    void printStats() const {
      std::cout << "idle: " << std::setw(3) << idleWorkers_.size()
        << ", busy: " << std::setw(3) << busyWorkers_.size() << ", cache: "
        << std::setw(3) << cacheQueue_.size() << std::endl;
    }

    void handleBackend() {
      zmq::Socket::messages_type messages = backendSocket_.receive();
      // check if we got Interrupted
      const std::size_t messageCount = messages.size();

      if (messageCount < 2) {
        throw std::runtime_error("BrokerApplication::go: receive invalid "
            "message");
      }

      zmq::Socket::messages_type::iterator messagePtr =
        messages.begin();
      const zmq::Message& identity = *messagePtr++;
      const zmq::Message& tag = *messagePtr++;

      if (tag.size() != 1) {
        throw std::runtime_error("BrokerApplication::go: invalid tag size");
      }

      zmq::Socket::messages_type messagesTail;
      messagesTail.splice(messagesTail.begin(), messages, messagePtr,
          messages.end());

      switch (tag.data()[0]) {
        case WORKER_HEARTBEAT_TAG:
          // this worker is idle again; in case it was busy, remove it from
          // the busy queue
          busyWorkers_.erase(identity);

          updateWorkers(idleWorkers_, identity);
          break;
        case WORKER_UPDATE_TAG:
          // worker busy messages are directly forwarded to the clients,
          // they have to take care if a worker dies
          updateWorkers(busyWorkers_, identity);
          frontendSocket_.send(messagesTail);
          break;
        default:
          throw std::runtime_error("BrokerApplication::go: invalid tag:");
          break;
      }
    }

    void sendJobQueued() {
      for (const auto& job : cacheQueue_) {
        zmq::Socket::messages_type::const_iterator messagePtr =
          job.begin();
        const zmq::Message& client = *messagePtr++;
        const zmq::Message& jobID = *messagePtr++;
        const zmq::Message& call = *messagePtr++;

        sendJobTag(client, JOB_QUEUED, jobID, call);
      }
    }

    void handleFrontend() {
      zmq::Socket::messages_type messages = frontendSocket_.receive();

      // check if we got Interrupted
      if (messages.empty()) {
        throw std::runtime_error("BrokerApplication::go: got interrupted");
      }

      if (cacheQueue_.size() < cacheQueueLength_) {
        cacheQueue_.push_back(messages);
      } else {
        // send wait and drop job
        zmq::Socket::messages_type::iterator messagePtr =
          messages.begin();
        const zmq::Message& client = *messagePtr++;
        const zmq::Message& jobID = *messagePtr++;
        const zmq::Message& call = *messagePtr++;

        sendJobTag(client, JOB_WAIT, jobID, call);
      }
    }

    void sendJobTag(const identity_type& client, const int tag, const
        jobid_type& jobID, const call_type& call) {
      zmq::Socket::messages_type reply;
      reply.push_back(client);

      zmq::Message jobReplyTag(1);
      jobReplyTag.data()[0] = tag;
      reply.push_back(std::move(jobReplyTag));
      reply.push_back(jobID);
      reply.push_back(call);

      frontendSocket_.send(reply);
    }

    void assignJobs() {
      auto jobIt = cacheQueue_.begin();
      auto workerIt = idleWorkers_.begin();

      while (workerIt != idleWorkers_.end() && jobIt != cacheQueue_.end()) {
        zmq::Socket::messages_type assigment;
        assigment.push_back(workerIt->second.getIdentity());

        zmq::Message queueTag(1);
        queueTag.data()[0] = QUEUE_JOB_TAG;
        assigment.push_back(std::move(queueTag));

        assigment.splice(assigment.end(), *jobIt);

        backendSocket_.send(assigment);

        // remove worker
        updateWorkers(busyWorkers_, workerIt->first);
        workerIt = idleWorkers_.erase(workerIt);
        jobIt = cacheQueue_.erase(jobIt);
      }
    }

    void sendHeartBeat(const workermap_type& workers) {
      zmq::Message tag(1);
      tag.data()[0] = QUEUE_HEARTBEAT_TAG;

      for (const auto& worker : workers) {
        zmq::Socket::messages_type heartbeat;
        heartbeat.push_back(worker.second.getIdentity());
        heartbeat.push_back(tag);

        backendSocket_.send(heartbeat);
      }
    }

    void checkWorkers(workermap_type& workers) const {
      timepoint_type now = steadyclock_type::now();

      workermap_type::iterator workerIt = workers.begin();
      while (workerIt != workers.end()) {
        if (workerIt->second.isVanished(now)) {
          std::cout << "delete" << std::endl;
          workerIt = workers.erase(workerIt);
        } else {
          ++workerIt;
        }
      }
    }

    void updateWorkers(workermap_type& workers, const
        identity_type& identity) const {
      workermap_type::iterator it = workers.find(identity);

      if (it == workers.end()) {
        it = workers.insert(std::make_pair(identity, Worker(identity))).first;
      }

      timepoint_type now = steadyclock_type::now();
      it->second.update(now);
    }

    void connect() {
      frontendSocket_ = context_.createSocket(ZMQ_ROUTER);
      backendSocket_ = context_.createSocket(ZMQ_ROUTER);
      frontendSocket_.bind("tcp://*:5555");
      backendSocket_.bind("tcp://*:5556");
    }

    // do not copy
    BrokerApplication(const BrokerApplication&);

    const std::size_t heartbeatInterval_;
    const std::size_t cacheQueueLength_;

    zmq::Context context_;
    zmq::Socket frontendSocket_;
    zmq::Socket backendSocket_;

    std::list<zmq::Socket::messages_type> cacheQueue_;
    workermap_type idleWorkers_;
    workermap_type busyWorkers_;
};

}

int main(int /*argc*/, const char** /*argv*/) {
  zmqmap::BrokerApplication app;
  app.init();

  app.go();

  return 0;
}
<commit_msg>Adds addresses to broker app.<commit_after>#include "tags.h"
#include "clock.h"

#include <0mq/message.h>
#include <0mq/context.h>
#include <0mq/socket.h>
#include <0mq/poller.h>

#include <chrono>
#include <cstddef>
#include <list>
#include <memory>
#include <unordered_map>
#include <iostream>
#include <iomanip>
#include <stdexcept>

namespace zmqmap {

typedef std::chrono::time_point<steadyclock_type> timepoint_type;

typedef zmq::Message identity_type;
typedef zmq::Message jobid_type;
typedef zmq::Message call_type;

class IdentityHash {
public:
    size_t operator() (const identity_type& identity) const {
      std::size_t h = 0;
      const char* d = identity.data();
      for (std::size_t i = 0; i < identity.size(); ++i) {
        h = (h << 1) ^ (std::hash<char>()(d[i]));
      }

      return h;
    }
};

class Worker {
  public:
    Worker(const identity_type& identity)
      : heartbeatInterval_(1000 * 3), identity_(identity)
    {
    }

    void update(const timepoint_type& timePoint) {
      latestHeartBeat_ = timePoint +
        std::chrono::milliseconds(heartbeatInterval_);
    }

    bool isVanished(const timepoint_type& timePoint) const {
      return timePoint > latestHeartBeat_;
    }

    const identity_type& getIdentity() const {
      return identity_;
    }

  private:
    const std::size_t heartbeatInterval_;

    const identity_type identity_;
    timepoint_type latestHeartBeat_;
};

class BrokerApplication {
  private:
    typedef std::unordered_map<identity_type, Worker, IdentityHash> workermap_type;

  public:
    BrokerApplication()
    : heartbeatInterval_(1000), cacheQueueLength_(100),
      context_(), frontendSocket_(), backendSocket_(),
      cacheQueue_(), idleWorkers_(), busyWorkers_()
    {
    }

    void init(const std::string& frontend, const std::string& backend) {
      connect(frontend, backend);
    }

    void go() {
      //  Send out heartbeats at regular intervals
      timepoint_type nextHeartBeat;
      nextHeartBeat = steadyclock_type::now() +
        std::chrono::milliseconds(heartbeatInterval_);

      while (true) {
        std::vector<zmq::Socket> items = { backendSocket_, frontendSocket_ };

        std::vector<short> state = zmq::poll(items, heartbeatInterval_);

        // handle backend
        if (state[0] & ZMQ_POLLIN) {
          handleBackend();
        }

        // handle frontend
        if (state[1] & ZMQ_POLLIN) {
          handleFrontend();
        }

        checkWorkers(idleWorkers_);
        checkWorkers(busyWorkers_);

        assignJobs();

        timepoint_type now = steadyclock_type::now();
        if (now > nextHeartBeat) {
          sendHeartBeat(idleWorkers_);
          sendHeartBeat(busyWorkers_);

          sendJobQueued();

          nextHeartBeat = now +
            std::chrono::milliseconds(heartbeatInterval_);

          printStats();
        }
      }
    }

  private:
    void printStats() const {
      std::cout << "idle: " << std::setw(3) << idleWorkers_.size()
        << ", busy: " << std::setw(3) << busyWorkers_.size() << ", cache: "
        << std::setw(3) << cacheQueue_.size() << std::endl;
    }

    void handleBackend() {
      zmq::Socket::messages_type messages = backendSocket_.receive();
      // check if we got Interrupted
      const std::size_t messageCount = messages.size();

      if (messageCount < 2) {
        throw std::runtime_error("BrokerApplication::go: receive invalid "
            "message");
      }

      zmq::Socket::messages_type::iterator messagePtr =
        messages.begin();
      const zmq::Message& identity = *messagePtr++;
      const zmq::Message& tag = *messagePtr++;

      if (tag.size() != 1) {
        throw std::runtime_error("BrokerApplication::go: invalid tag size");
      }

      zmq::Socket::messages_type messagesTail;
      messagesTail.splice(messagesTail.begin(), messages, messagePtr,
          messages.end());

      switch (tag.data()[0]) {
        case WORKER_HEARTBEAT_TAG:
          // this worker is idle again; in case it was busy, remove it from
          // the busy queue
          busyWorkers_.erase(identity);

          updateWorkers(idleWorkers_, identity);
          break;
        case WORKER_UPDATE_TAG:
          // worker busy messages are directly forwarded to the clients,
          // they have to take care if a worker dies
          updateWorkers(busyWorkers_, identity);
          frontendSocket_.send(messagesTail);
          break;
        default:
          throw std::runtime_error("BrokerApplication::go: invalid tag:");
          break;
      }
    }

    void sendJobQueued() {
      for (const auto& job : cacheQueue_) {
        zmq::Socket::messages_type::const_iterator messagePtr =
          job.begin();
        const zmq::Message& client = *messagePtr++;
        const zmq::Message& jobID = *messagePtr++;
        const zmq::Message& call = *messagePtr++;

        sendJobTag(client, JOB_QUEUED, jobID, call);
      }
    }

    void handleFrontend() {
      zmq::Socket::messages_type messages = frontendSocket_.receive();

      // check if we got Interrupted
      if (messages.empty()) {
        throw std::runtime_error("BrokerApplication::go: got interrupted");
      }

      if (cacheQueue_.size() < cacheQueueLength_) {
        cacheQueue_.push_back(messages);
      } else {
        // send wait and drop job
        zmq::Socket::messages_type::iterator messagePtr =
          messages.begin();
        const zmq::Message& client = *messagePtr++;
        const zmq::Message& jobID = *messagePtr++;
        const zmq::Message& call = *messagePtr++;

        sendJobTag(client, JOB_WAIT, jobID, call);
      }
    }

    void sendJobTag(const identity_type& client, const int tag, const
        jobid_type& jobID, const call_type& call) {
      zmq::Socket::messages_type reply;
      reply.push_back(client);

      zmq::Message jobReplyTag(1);
      jobReplyTag.data()[0] = tag;
      reply.push_back(std::move(jobReplyTag));
      reply.push_back(jobID);
      reply.push_back(call);

      frontendSocket_.send(reply);
    }

    void assignJobs() {
      auto jobIt = cacheQueue_.begin();
      auto workerIt = idleWorkers_.begin();

      while (workerIt != idleWorkers_.end() && jobIt != cacheQueue_.end()) {
        zmq::Socket::messages_type assigment;
        assigment.push_back(workerIt->second.getIdentity());

        zmq::Message queueTag(1);
        queueTag.data()[0] = QUEUE_JOB_TAG;
        assigment.push_back(std::move(queueTag));

        assigment.splice(assigment.end(), *jobIt);

        backendSocket_.send(assigment);

        // remove worker
        updateWorkers(busyWorkers_, workerIt->first);
        workerIt = idleWorkers_.erase(workerIt);
        jobIt = cacheQueue_.erase(jobIt);
      }
    }

    void sendHeartBeat(const workermap_type& workers) {
      zmq::Message tag(1);
      tag.data()[0] = QUEUE_HEARTBEAT_TAG;

      for (const auto& worker : workers) {
        zmq::Socket::messages_type heartbeat;
        heartbeat.push_back(worker.second.getIdentity());
        heartbeat.push_back(tag);

        backendSocket_.send(heartbeat);
      }
    }

    void checkWorkers(workermap_type& workers) const {
      timepoint_type now = steadyclock_type::now();

      workermap_type::iterator workerIt = workers.begin();
      while (workerIt != workers.end()) {
        if (workerIt->second.isVanished(now)) {
          std::cout << "delete" << std::endl;
          workerIt = workers.erase(workerIt);
        } else {
          ++workerIt;
        }
      }
    }

    void updateWorkers(workermap_type& workers, const
        identity_type& identity) const {
      workermap_type::iterator it = workers.find(identity);

      if (it == workers.end()) {
        it = workers.insert(std::make_pair(identity, Worker(identity))).first;
      }

      timepoint_type now = steadyclock_type::now();
      it->second.update(now);
    }

    void connect(const std::string& frontend, const std::string& backend) {
      frontendSocket_ = context_.createSocket(ZMQ_ROUTER);
      backendSocket_ = context_.createSocket(ZMQ_ROUTER);
      frontendSocket_.bind(frontend);
      backendSocket_.bind(backend);
    }

    // do not copy
    BrokerApplication(const BrokerApplication&);

    const std::size_t heartbeatInterval_;
    const std::size_t cacheQueueLength_;

    zmq::Context context_;
    zmq::Socket frontendSocket_;
    zmq::Socket backendSocket_;

    std::list<zmq::Socket::messages_type> cacheQueue_;
    workermap_type idleWorkers_;
    workermap_type busyWorkers_;
};

}

int main(int argc, const char** argv) {
  if (argc < 3) {
    std::cerr << "Usage: " << argv[0] << " <frontend> <backend>" << std::endl
      << "e.g. " << argv[0] << " 'tcp://*:5555' 'tcp://*:5556'" << std::endl;

    return 1;
  }

  zmqmap::BrokerApplication app;
  app.init(argv[1], argv[2]);

  app.go();

  return 0;
}
<|endoftext|>


<commit_before>#include "Player.h"

Player::Player(Scene *s, float x, float y)
{
	this->scene = s;
	this->object_position = glm::vec2(x, y);
	this->object_scale = glm::vec2(0.03f, 0.03f);
	this->mouse = new GraphicDebug();
	this->mouse->InitPoint(glm::vec2(0, 0), 0.8, glm::vec3(0.9, 0.9, 0.9));
	this->color = glm::vec3(0, 0, 0);
	this->CDrail = false;
	this->rail = new GraphicDebug();
	this->mouse->InitLine(glm::vec2(0, 0), glm::vec2(1,1), color);
	this->shooting_pos = object_position;
	this->shooting_target = object_position;
}

Player::~Player()
{

}

void Player::Move(glm::vec2 move, double delta_time)
{
	SetLength(move, PLAYER_SPEED);
	move *= delta_time;
	object_position += move;
	object_heading = mouse->getPosition() -object_position;
	Normalize(object_heading);

}

void Player::Rotate(glm::vec2 heading)
{
	object_heading = heading-object_position;

	Normalize(object_heading);
	this->mouse->UpdatePoint(heading, 0.5, glm::vec3(0.9, 0.9, 0.9));

}

void Player::Shoot(glm::vec2 fire)
{
	if (!CDrail){
		color = glm::vec3(1, 1, 1);
		CDrail = true;
		RailPhysics();
	}

}

void Player::Update(double delta_time)
{
	model_matrix = glm::mat4(1.0f);
	model_matrix = glm::scale(model_matrix, glm::vec3(object_scale, 1.0f));
	model_matrix = glm::translate(model_matrix, glm::vec3(object_position, 0.0f));
	model_matrix = glm::rotate(model_matrix, GetAngle(glm::vec2(0, 1), object_heading), glm::vec3(0, 0, 1));

	if (color.x - 0.016f > 0.0){
		color -= 0.016f;
	}else{
		color *= 0;
		CDrail = false;
		shooting_pos = object_position;
		shooting_target = object_heading;
		shooting_target *= 1000;
		shooting_target += this->GetObjectPosition();
	}

	this->rail->UpdateLine(shooting_pos, shooting_target, color);
}

void Player::RailPhysics(){

	float distance=1000,tmpDist=0;

	for (unsigned int i = 0; i < scene->obstacles.size(); ++i){
		glm::vec2 target = object_heading;
		Obstacle *obstacle = scene->obstacles[i];
		tmpDist = GetDistance(obstacle->GetObjectPosition(), this->GetObjectPosition());
		SetLength(target, tmpDist);
		target += this->GetObjectPosition();
		if (GetDistance(obstacle->GetObjectPosition(), target) < obstacle->GetCollisionRadius()){
			if (tmpDist < distance){
				distance = tmpDist;
				shooting_target = target;
			}
		}
	}

	for (unsigned int i = 0; i < scene->zombies.size(); ++i)
	{
		glm::vec2 target = object_heading;
		Zombie *zombie = scene->zombies[i];
		SetLength(target, GetDistance(zombie->GetObjectPosition(), this->GetObjectPosition()));
		target += this->GetObjectPosition();
		if (GetDistance(zombie->GetObjectPosition(), target) < zombie->GetCollisionRadius() && GetDistance(zombie->GetObjectPosition(), this->GetObjectPosition())<distance){
			zombie->gotHit();
		}
	}

}
void Player::Draw()
{
	mouse->DrawPoint();
	rail->DrawLine();
	float a, b;
	glEnable(GL_LINE_SMOOTH);
	glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);

	glPushMatrix();
	GLfloat Matrix[16];
	MatrixToArray(Matrix, model_matrix, scene->GetViewMatrix());
	glLoadMatrixf(Matrix);

	glBegin(GL_TRIANGLES);
		glColor3f(0.0f, 1.0f, 1.0f);
		glVertex3f(-0.50f, -0.60f, 0.f);
		glVertex3f(0.50f, -0.60f, 0.f);
		glVertex3f(0.00f, 0.75f, 0.f);
	glEnd();

	glBegin(GL_LINES);
		glColor3f(0.5f, 0.5f, 0.0f);

		a = 1.0f * (float)cos(359 * PI / 180.0f);
		b = 1.0f * (float)sin(359 * PI / 180.0f);
		for (int j = 0; j < 360; j++)
		{
			glVertex2f(a, b);
			a = 1.0f * (float)cos(j * PI / 180.0f);
			b = 1.0f * (float)sin(j * PI / 180.0f);
			glVertex2f(a, b);
		}
	glEnd();
	glPopMatrix();
	glDisable(GL_LINE_SMOOTH);
}<commit_msg>Player collision<commit_after>#include "Player.h"

Player::Player(Scene *s, float x, float y)
{
	this->scene = s;
	this->object_position = glm::vec2(x, y);
	this->object_scale = glm::vec2(0.03f, 0.03f);
	this->mouse = new GraphicDebug();
	this->mouse->InitPoint(glm::vec2(0, 0), 0.8, glm::vec3(0.9, 0.9, 0.9));
	this->color = glm::vec3(0, 0, 0);
	this->CDrail = false;
	this->rail = new GraphicDebug();
	this->mouse->InitLine(glm::vec2(0, 0), glm::vec2(1,1), color);
	this->shooting_pos = object_position;
	this->shooting_target = object_position;
}

Player::~Player()
{

}

void Player::Move(glm::vec2 move, double delta_time)
{
	SetLength(move, PLAYER_SPEED);
	move *= delta_time;
	object_position += move;
	if (object_position.x < -32 || object_position.x > 32 || object_position.y < -32 || object_position.y > 32)
	{
		object_position -= move;
	}

	float radius = this->GetCollisionRadius();

	for (unsigned int i = 0; i < scene->obstacles.size(); ++i){
		Obstacle *obstacle = scene->obstacles[i];
		float radius = this->GetCollisionRadius() + obstacle->GetCollisionRadius();
		if (radius>GetDistance(object_position, obstacle->GetObjectPosition())){
			object_position -= move;
		}
	}

	object_heading = mouse->getPosition() -object_position;
	Normalize(object_heading);

}

void Player::Rotate(glm::vec2 heading)
{
	object_heading = heading-object_position;

	Normalize(object_heading);
	this->mouse->UpdatePoint(heading, 0.5, glm::vec3(0.9, 0.9, 0.9));

}

void Player::Shoot(glm::vec2 fire)
{
	if (!CDrail){
		color = glm::vec3(1, 1, 1);
		CDrail = true;
		RailPhysics();
	}

}

void Player::Update(double delta_time)
{
	model_matrix = glm::mat4(1.0f);
	model_matrix = glm::scale(model_matrix, glm::vec3(object_scale, 1.0f));
	model_matrix = glm::translate(model_matrix, glm::vec3(object_position, 0.0f));
	model_matrix = glm::rotate(model_matrix, GetAngle(glm::vec2(0, 1), object_heading), glm::vec3(0, 0, 1));

	if (color.x - 0.016f > 0.0){
		color -= 0.016f;
	}else{
		color *= 0;
		CDrail = false;
		shooting_pos = object_position;
		shooting_target = object_heading;
		shooting_target *= 1000;
		shooting_target += this->GetObjectPosition();
	}

	this->rail->UpdateLine(shooting_pos, shooting_target, color);
}

void Player::RailPhysics(){

	float distance=1000,tmpDist=0;

	for (unsigned int i = 0; i < scene->obstacles.size(); ++i){
		glm::vec2 target = object_heading;
		Obstacle *obstacle = scene->obstacles[i];
		tmpDist = GetDistance(obstacle->GetObjectPosition(), this->GetObjectPosition());
		SetLength(target, tmpDist);
		target += this->GetObjectPosition();
		if (GetDistance(obstacle->GetObjectPosition(), target) < obstacle->GetCollisionRadius()){
			if (tmpDist < distance){
				distance = tmpDist;
				shooting_target = target;
			}
		}
	}

	for (unsigned int i = 0; i < scene->zombies.size(); ++i)
	{
		glm::vec2 target = object_heading;
		Zombie *zombie = scene->zombies[i];
		SetLength(target, GetDistance(zombie->GetObjectPosition(), this->GetObjectPosition()));
		target += this->GetObjectPosition();
		if (GetDistance(zombie->GetObjectPosition(), target) < zombie->GetCollisionRadius() && GetDistance(zombie->GetObjectPosition(), this->GetObjectPosition())<distance){
			zombie->gotHit();
		}
	}

}
void Player::Draw()
{
	mouse->DrawPoint();
	rail->DrawLine();
	float a, b;
	glEnable(GL_LINE_SMOOTH);
	glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);

	glPushMatrix();
	GLfloat Matrix[16];
	MatrixToArray(Matrix, model_matrix, scene->GetViewMatrix());
	glLoadMatrixf(Matrix);

	glBegin(GL_TRIANGLES);
		glColor3f(0.0f, 1.0f, 1.0f);
		glVertex3f(-0.50f, -0.60f, 0.f);
		glVertex3f(0.50f, -0.60f, 0.f);
		glVertex3f(0.00f, 0.75f, 0.f);
	glEnd();

	glBegin(GL_LINES);
		glColor3f(0.5f, 0.5f, 0.0f);

		a = 1.0f * (float)cos(359 * PI / 180.0f);
		b = 1.0f * (float)sin(359 * PI / 180.0f);
		for (int j = 0; j < 360; j++)
		{
			glVertex2f(a, b);
			a = 1.0f * (float)cos(j * PI / 180.0f);
			b = 1.0f * (float)sin(j * PI / 180.0f);
			glVertex2f(a, b);
		}
	glEnd();
	glPopMatrix();
	glDisable(GL_LINE_SMOOTH);
}<|endoftext|>


<commit_before>/**
   Copyright (c) 2015 Beckhoff Automation GmbH & Co. KG

   Permission is hereby granted, free of charge, to any person obtaining a copy
   of this software and associated documentation files (the "Software"), to deal
   in the Software without restriction, including without limitation the rights
   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   copies of the Software, and to permit persons to whom the Software is
   furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included in
   all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   SOFTWARE.
 */

#include "Frame.h"

#include <algorithm>
#include <cstring>
#include <new>

Frame::Frame(size_t length, const void* data)
    : m_Data(new uint8_t[length])
{
    m_Size = m_Data ? length : 0;
    m_Pos = m_Data.get() + m_Size;
    m_OriginalSize = m_Size;

    if (m_Pos && data) {
        m_Pos -= length;
        memcpy(m_Pos, data, length);
    }
}

uint8_t Frame::operator[](size_t index) const
{
    return m_Pos[index];
}

size_t Frame::capacity() const
{
    return m_Size;
}

Frame& Frame::clear()
{
    return remove(size());
}

const uint8_t* Frame::data() const
{
    return m_Pos;
}

Frame& Frame::limit(size_t newSize)
{
    m_Size = std::min(m_Size, newSize);
    m_Pos = m_Data.get();
    return *this;
}

Frame& Frame::reset()
{
    m_Size = m_OriginalSize;
    m_Pos = m_Data.get() + m_Size;
    return *this;
}

Frame& Frame::prepend(const void* const data, const size_t size)
{
    const size_t bytesFree = m_Pos - m_Data.get();
    if (size > bytesFree) {
        auto newData = new uint8_t[size + m_Size];
        if (NULL == newData) {
            throw std::bad_alloc();
        }

        m_Pos = newData + bytesFree + size;
        memcpy(m_Pos, m_Data.get() + bytesFree, m_Size - bytesFree);
        m_Data.reset(newData);
        m_Size += size;
        m_OriginalSize = m_Size;
        m_Pos = m_Data.get() + bytesFree;
    } else {
        m_Pos -= size;
    }
    memcpy(m_Pos, data, size);
    return *this;
}

uint8_t* Frame::rawData() const
{
    return m_Data.get();
}

Frame& Frame::remove(size_t numBytes)
{
    m_Pos = std::min<uint8_t*>(m_Pos + numBytes, m_Data.get() + m_Size);
    return *this;
}

size_t Frame::size() const
{
    return m_Size - (m_Pos - m_Data.get());
}
<commit_msg>AdsLib: remove dead code in Frame.cpp<commit_after>/**
   Copyright (c) 2015 Beckhoff Automation GmbH & Co. KG

   Permission is hereby granted, free of charge, to any person obtaining a copy
   of this software and associated documentation files (the "Software"), to deal
   in the Software without restriction, including without limitation the rights
   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   copies of the Software, and to permit persons to whom the Software is
   furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included in
   all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   SOFTWARE.
 */

#include "Frame.h"

#include <algorithm>
#include <cstring>
#include <new>

Frame::Frame(size_t length, const void* data)
    : m_Data(new uint8_t[length])
{
    m_Size = m_Data ? length : 0;
    m_Pos = m_Data.get() + m_Size;
    m_OriginalSize = m_Size;

    if (m_Pos && data) {
        m_Pos -= length;
        memcpy(m_Pos, data, length);
    }
}

uint8_t Frame::operator[](size_t index) const
{
    return m_Pos[index];
}

size_t Frame::capacity() const
{
    return m_Size;
}

Frame& Frame::clear()
{
    return remove(size());
}

const uint8_t* Frame::data() const
{
    return m_Pos;
}

Frame& Frame::limit(size_t newSize)
{
    m_Size = std::min(m_Size, newSize);
    m_Pos = m_Data.get();
    return *this;
}

Frame& Frame::reset()
{
    m_Size = m_OriginalSize;
    m_Pos = m_Data.get() + m_Size;
    return *this;
}

Frame& Frame::prepend(const void* const data, const size_t size)
{
    const size_t bytesFree = m_Pos - m_Data.get();
    if (size > bytesFree) {
        auto newData = new uint8_t[size + m_Size];

        m_Pos = newData + bytesFree + size;
        memcpy(m_Pos, m_Data.get() + bytesFree, m_Size - bytesFree);
        m_Data.reset(newData);
        m_Size += size;
        m_OriginalSize = m_Size;
        m_Pos = m_Data.get() + bytesFree;
    } else {
        m_Pos -= size;
    }
    memcpy(m_Pos, data, size);
    return *this;
}

uint8_t* Frame::rawData() const
{
    return m_Data.get();
}

Frame& Frame::remove(size_t numBytes)
{
    m_Pos = std::min<uint8_t*>(m_Pos + numBytes, m_Data.get() + m_Size);
    return *this;
}

size_t Frame::size() const
{
    return m_Size - (m_Pos - m_Data.get());
}
<|endoftext|>


<commit_before>/* mbed Microcontroller Library
 * Copyright (c) 2006-2013 ARM Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "hal/rtc_api.h"

#include "platform/mbed_critical.h"
#include "platform/mbed_rtc_time.h"
#include "platform/SingletonPtr.h"
#include "platform/PlatformMutex.h"

static SingletonPtr<PlatformMutex> _mutex;

#if DEVICE_RTC
static void (*_rtc_init)(void) = rtc_init;
static int (*_rtc_isenabled)(void) = rtc_isenabled;
static time_t (*_rtc_read)(void) = rtc_read;
static void (*_rtc_write)(time_t t) = rtc_write;
#else
static void (*_rtc_init)(void) = NULL;
static int (*_rtc_isenabled)(void) = NULL;
static time_t (*_rtc_read)(void) = NULL;
static void (*_rtc_write)(time_t t) = NULL;
#endif

#ifdef __cplusplus
extern "C" {
#endif
#if defined (__ICCARM__)
time_t __time32(time_t *timer)
#else
time_t time(time_t *timer)
#endif

{
    _mutex->lock();
    if (_rtc_isenabled != NULL) {
        if (!(_rtc_isenabled())) {
            set_time(0);
        }
    }

    time_t t = (time_t)-1;
    if (_rtc_read != NULL) {
        t = _rtc_read();
    }

    if (timer != NULL) {
        *timer = t;
    }
    _mutex->unlock();
    return t;
}

void set_time(time_t t) {
    _mutex->lock();
    if (_rtc_init != NULL) {
        _rtc_init();
    }
    if (_rtc_write != NULL) {
        _rtc_write(t);
    }
    _mutex->unlock();
}

void attach_rtc(time_t (*read_rtc)(void), void (*write_rtc)(time_t), void (*init_rtc)(void), int (*isenabled_rtc)(void)) {
    _mutex->lock();
    _rtc_read = read_rtc;
    _rtc_write = write_rtc;
    _rtc_init = init_rtc;
    _rtc_isenabled = isenabled_rtc;
    _mutex->unlock();
}

#ifdef __cplusplus
}
#endif
<commit_msg>Add low power timer fallback for platforms without RTC<commit_after>/* mbed Microcontroller Library
 * Copyright (c) 2006-2013 ARM Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "hal/rtc_api.h"

#include "platform/mbed_critical.h"
#include "platform/mbed_rtc_time.h"
#include "platform/SingletonPtr.h"
#include "platform/PlatformMutex.h"

static SingletonPtr<PlatformMutex> _mutex;

#if DEVICE_RTC

static void (*_rtc_init)(void) = rtc_init;
static int (*_rtc_isenabled)(void) = rtc_isenabled;
static time_t (*_rtc_read)(void) = rtc_read;
static void (*_rtc_write)(time_t t) = rtc_write;

#elif DEVICE_LOWPOWERTIMER

#include "drivers/LowPowerTimer.h"

static SingletonPtr<mbed::LowPowerTimer> _rtc_lp_timer;
static uint64_t _rtc_lp_base;
static bool _rtc_enabled;

static void _rtc_lpticker_init(void)
{
    _rtc_lp_timer->start();
    _rtc_enabled = true;
}

static int _rtc_lpticker_isenabled(void)
{
    return (_rtc_enabled == true);
}

static time_t _rtc_lpticker_read(void)
{
    return (uint64_t)_rtc_lp_timer->read() + _rtc_lp_base;
}

static void _rtc_lpticker_write(time_t t)
{
    _rtc_lp_base = t;
}

static void (*_rtc_init)(void) = _rtc_lpticker_init;
static int (*_rtc_isenabled)(void) = _rtc_lpticker_isenabled;
static time_t (*_rtc_read)(void) = _rtc_lpticker_read;
static void (*_rtc_write)(time_t t) = _rtc_lpticker_write;

#else /* DEVICE_LOWPOWERTIMER */

static void (*_rtc_init)(void) = NULL;
static int (*_rtc_isenabled)(void) = NULL;
static time_t (*_rtc_read)(void) = NULL;
static void (*_rtc_write)(time_t t) = NULL;
#endif /* DEVICE_LOWPOWERTIMER */

#ifdef __cplusplus
extern "C" {
#endif
#if defined (__ICCARM__)
time_t __time32(time_t *timer)
#else
time_t time(time_t *timer)
#endif

{
    _mutex->lock();
    if (_rtc_isenabled != NULL) {
        if (!(_rtc_isenabled())) {
            set_time(0);
        }
    }

    time_t t = (time_t)-1;
    if (_rtc_read != NULL) {
        t = _rtc_read();
    }

    if (timer != NULL) {
        *timer = t;
    }
    _mutex->unlock();
    return t;
}

void set_time(time_t t) {
    _mutex->lock();
    if (_rtc_init != NULL) {
        _rtc_init();
    }
    if (_rtc_write != NULL) {
        _rtc_write(t);
    }
    _mutex->unlock();
}

void attach_rtc(time_t (*read_rtc)(void), void (*write_rtc)(time_t), void (*init_rtc)(void), int (*isenabled_rtc)(void)) {
    _mutex->lock();
    _rtc_read = read_rtc;
    _rtc_write = write_rtc;
    _rtc_init = init_rtc;
    _rtc_isenabled = isenabled_rtc;
    _mutex->unlock();
}

#ifdef __cplusplus
}
#endif
<|endoftext|>


<commit_before>#ifndef ITER_ENUMERATE_H_
#define ITER_ENUMERATE_H_

#include "internal/iterator_wrapper.hpp"
#include "internal/iterbase.hpp"

#include <functional>
#include <initializer_list>
#include <iterator>
#include <tuple>
#include <type_traits>
#include <utility>

namespace iter {
  namespace impl {
    template <typename Index, typename Elem>
    using EnumBasePair = std::pair<Index, Elem>;

    // "yielded" by the Enumerable::Iterator.  Has a .index, and a
    // .element referencing the value yielded by the subiterator
    template <typename Index, typename Elem>
    class EnumIterYield : public EnumBasePair<Index, Elem> {
      using BasePair = EnumBasePair<Index, Elem>;
      using BasePair::BasePair;

     public:
      typename BasePair::first_type index = BasePair::first;
      typename BasePair::second_type& element = BasePair::second;
    };

    template <typename Container, typename Index>
    class Enumerable;

    using EnumerateFn = IterToolFnOptionalBindSecond<Enumerable, std::size_t>;
  }
  constexpr impl::EnumerateFn enumerate{};
}

namespace std {
  template <typename Index, typename Elem>
  class tuple_size<iter::impl::EnumIterYield<Index, Elem>>
      : public tuple_size<iter::impl::EnumBasePair<Index, Elem>> {};

  template <std::size_t N, typename Index, typename Elem>
  class tuple_element<N, iter::impl::EnumIterYield<Index, Elem>>
      : public tuple_element<N, iter::impl::EnumBasePair<Index, Elem>> {};
}

template <typename Container, typename Index>
class iter::impl::Enumerable {
 private:
  Container container_;
  const Index start_;

  friend EnumerateFn;

  // Value constructor for use only in the enumerate function
  Enumerable(Container&& container, Index start)
      : container_(std::forward<Container>(container)), start_{start} {}

 public:
  Enumerable(Enumerable&&) = default;

  template <typename T>
  using IterYield = EnumIterYield<Index, iterator_deref<T>>;

  //  Holds an iterator of the contained type and an Index for the
  //  index_.  Each call to ++ increments both of these data members.
  //  Each dereference returns an IterYield.
  template <typename ContainerT>
  class Iterator {
   private:
    template <typename>
    friend class Iterator;
    IteratorWrapper<ContainerT> sub_iter_;
    Index index_;

   public:
    using iterator_category = std::input_iterator_tag;
    using value_type = IterYield<ContainerT>;
    using difference_type = std::ptrdiff_t;
    using pointer = value_type*;
    using reference = value_type&;

    Iterator(IteratorWrapper<ContainerT>&& sub_iter, Index start)
        : sub_iter_{std::move(sub_iter)}, index_{start} {}

    IterYield<ContainerT> operator*() {
      return {index_, *sub_iter_};
    }

    ArrowProxy<IterYield<ContainerT>> operator->() {
      return {**this};
    }

    Iterator& operator++() {
      ++sub_iter_;
      ++index_;
      return *this;
    }

    Iterator operator++(int) {
      auto ret = *this;
      ++*this;
      return ret;
    }

    template <typename T>
    bool operator!=(const Iterator<T>& other) const {
      return sub_iter_ != other.sub_iter_;
    }

    template <typename T>
    bool operator==(const Iterator<T>& other) const {
      return !(*this != other);
    }
  };

  Iterator<Container> begin() {
    return {get_begin(container_), start_};
  }

  Iterator<Container> end() {
    return {get_end(container_), start_};
  }

  Iterator<AsConst<Container>> begin() const {
    return {get_begin(std::as_const(container_)), start_};
  }

  Iterator<AsConst<Container>> end() const {
    return {get_end(std::as_const(container_)), start_};
  }
};
#endif
<commit_msg>Removes & from .element in enumerate iter yield<commit_after>#ifndef ITER_ENUMERATE_H_
#define ITER_ENUMERATE_H_

#include "internal/iterator_wrapper.hpp"
#include "internal/iterbase.hpp"

#include <functional>
#include <initializer_list>
#include <iterator>
#include <tuple>
#include <type_traits>
#include <utility>

namespace iter {
  namespace impl {
    template <typename Index, typename Elem>
    using EnumBasePair = std::pair<Index, Elem>;

    // "yielded" by the Enumerable::Iterator.  Has a .index, and a
    // .element referencing the value yielded by the subiterator
    template <typename Index, typename Elem>
    class EnumIterYield : public EnumBasePair<Index, Elem> {
      using BasePair = EnumBasePair<Index, Elem>;
      using BasePair::BasePair;

     public:
      typename BasePair::first_type index = BasePair::first;
      typename BasePair::second_type element = BasePair::second;
    };

    template <typename Container, typename Index>
    class Enumerable;

    using EnumerateFn = IterToolFnOptionalBindSecond<Enumerable, std::size_t>;
  }
  constexpr impl::EnumerateFn enumerate{};
}

namespace std {
  template <typename Index, typename Elem>
  class tuple_size<iter::impl::EnumIterYield<Index, Elem>>
      : public tuple_size<iter::impl::EnumBasePair<Index, Elem>> {};

  template <std::size_t N, typename Index, typename Elem>
  class tuple_element<N, iter::impl::EnumIterYield<Index, Elem>>
      : public tuple_element<N, iter::impl::EnumBasePair<Index, Elem>> {};
}

template <typename Container, typename Index>
class iter::impl::Enumerable {
 private:
  Container container_;
  const Index start_;

  friend EnumerateFn;

  // Value constructor for use only in the enumerate function
  Enumerable(Container&& container, Index start)
      : container_(std::forward<Container>(container)), start_{start} {}

 public:
  Enumerable(Enumerable&&) = default;

  template <typename T>
  using IterYield = EnumIterYield<Index, iterator_deref<T>>;

  //  Holds an iterator of the contained type and an Index for the
  //  index_.  Each call to ++ increments both of these data members.
  //  Each dereference returns an IterYield.
  template <typename ContainerT>
  class Iterator {
   private:
    template <typename>
    friend class Iterator;
    IteratorWrapper<ContainerT> sub_iter_;
    Index index_;

   public:
    using iterator_category = std::input_iterator_tag;
    using value_type = IterYield<ContainerT>;
    using difference_type = std::ptrdiff_t;
    using pointer = value_type*;
    using reference = value_type&;

    Iterator(IteratorWrapper<ContainerT>&& sub_iter, Index start)
        : sub_iter_{std::move(sub_iter)}, index_{start} {}

    IterYield<ContainerT> operator*() {
      return {index_, *sub_iter_};
    }

    ArrowProxy<IterYield<ContainerT>> operator->() {
      return {**this};
    }

    Iterator& operator++() {
      ++sub_iter_;
      ++index_;
      return *this;
    }

    Iterator operator++(int) {
      auto ret = *this;
      ++*this;
      return ret;
    }

    template <typename T>
    bool operator!=(const Iterator<T>& other) const {
      return sub_iter_ != other.sub_iter_;
    }

    template <typename T>
    bool operator==(const Iterator<T>& other) const {
      return !(*this != other);
    }
  };

  Iterator<Container> begin() {
    return {get_begin(container_), start_};
  }

  Iterator<Container> end() {
    return {get_end(container_), start_};
  }

  Iterator<AsConst<Container>> begin() const {
    return {get_begin(std::as_const(container_)), start_};
  }

  Iterator<AsConst<Container>> end() const {
    return {get_end(std::as_const(container_)), start_};
  }
};
#endif
<|endoftext|>


<commit_before>/**
 * Exercise 8 : Read in a gph-file, interpretes it as a Steiner-problem and solves it.
 *
 * @author FirstSanny
 */

#include <iostream>
#include <iomanip>
#include <fstream>
#include <utility>
#include <boost/program_options.hpp>
#include <boost/timer/timer.hpp>
#include "Steiner.h"
#include "GraphChecker.h"

// Constants
namespace {
	const char* FILEEND = ".gph";
	const int MAX_FOR_DEFAULT_TERMINALS = 100;
	const int DEFAULT_THREAD_NUMBER = 8;
}

// declaring print
using std::cout;
using std::endl;
using std::flush;
using std::cerr;
using std::string;

// declaring types
namespace po = boost::program_options;
namespace bTime = boost::timer;
using Primes = std::vector<int >;

/**
 * Computes all primes less than vertexCount
 * by beginning with the prime 2 and trying to divide all numbers smaller than vertexCount
 * and try do divide by all found primes.
 */
Primes getPrimes(unsigned int vertexCount) {
	Primes primes = Primes();
	primes.push_back(2);
	for (unsigned int i = 3; i < vertexCount; i++) {
		char isPrime = true;
		for (int prime : primes) {
			if (i % prime == 0) {
				isPrime = false;
			}
		}
		if (isPrime) {
			primes.push_back(i);
		}
	}
	return primes;
}

/** Parsing the arguments given via command line */
po::variables_map parseCommandLine(po::options_description desc, int argn,
		char* argv[]) {
	desc.add_options()//
			("help,h", "produce help message")//
			("start_nodes,s", po::value<std::vector<int >>(),"nodes, where to start")//
			("thread_number,t", po::value<int>(), "number of threads for parallelization")//
			("input_file,i", po::value<string>(), "input file");
	po::positional_options_description p;
	p.add("input_file", -1);
	po::variables_map vm;
	po::store(
			po::command_line_parser(argn, argv).options(desc).positional(p).run(),
			vm);
	po::notify(vm);
	return vm;
}

/** Reading in a Graphfile, computes the Steiner */
int main(int argn, char *argv[]) {
	bTime::cpu_timer timerProgram;
	if (argn <= 1) {
		cerr << "ERROR : There was no filename" << endl;
		return 1;
	}

	po::options_description desc("Allowed options");
	po::variables_map vm = parseCommandLine(desc, argn, argv);

	if (vm.count("help")) {
	    cout << desc << "\n";
	    return 1;
	}

	std::ifstream fileStream;
	if(vm.count("input_file") == 0){
		cerr << "No input-file was given!" << endl;
		return 1;
	}

	string filename = vm["input_file"].as<string >();
	if(filename.find(FILEEND) == std::string::npos){
		filename += FILEEND;
	}
	cout << "Going to parse the file " << filename << endl;
	fileStream.open(filename.c_str(), std::ios::in);

	if ( (fileStream.rdstate()) != 0 ){
		std::perror("ERROR : Encoutered Problem opening file");
		return 1;
	}

	std::vector<int > startnodes;
	if(vm.count("start_nodes") == 0){
		cout << "Using default startnodes (first 100 primes)" << endl;
	} else {
		startnodes = vm["start_node"].as<std::vector<int >>();
	}

	int threadNumber;
	if(vm.count("thread_number") == 0){
		cout << "Using default number of threads (8)" << endl;
		threadNumber = DEFAULT_THREAD_NUMBER;
	} else {
		threadNumber = vm["thread_number"].as<int >();
	}

	cout << endl;

	string line;

	unsigned int edgeCount;
	unsigned int vertexCount;

	if(std::getline(fileStream, line)){
		sscanf(line.c_str(), "%d %d", &vertexCount, &edgeCount);
		cout << "Vertexcount: " << vertexCount << endl;
		cout << "Edgecount: " << edgeCount << endl;
		line.clear();
		vertexCount++;
	} else {
		cerr << "ERROR : File was empty" << endl;
		return 1;
	}

	Edges* edges = new Edges(edgeCount);
	Weights* weights = new Weights(edgeCount);

	cout << "Reading edges..." << flush;
	int i = 0;
	while (getline(fileStream, line)) {
		int start;
		int end;
		double weight;
		int count = sscanf(line.c_str(), "%d %d %lf", &start, &end, &weight);
		if (count != 3) {
			line.clear();
			continue;
		}
		edges->at(i) = std::make_pair(start, end);
		weights->at(i) = weight;
		i++;
		line.clear();
	}
	cout << "done" << endl << endl;

	Primes terminals = getPrimes(vertexCount);
	if(startnodes.empty()){
		for (unsigned int i = 0;
				i < MAX_FOR_DEFAULT_TERMINALS && i < terminals.size(); i++) {
			startnodes.push_back(terminals[i]);
		}
	}

	cout << "Solves Steiner-tree for " << startnodes.size() << " startnodes..." << flush;
	bTime::cpu_timer timerSteiner;
	Steiner** steiners = new Steiner*[startnodes.size()];
	#pragma omp parallel for
	for(unsigned int i = 0; i < startnodes.size(); i++){
		steiners[i] = new Steiner();
		steiners[i]->computeSteinerTree(vertexCount, edges, *weights, terminals, startnodes[i]);
	}
	bTime::cpu_times timesSteiner = timerSteiner.elapsed();
	cout << "done" << endl;

	Steiner* s = steiners[0];
	int node = startnodes[0];
	int weight = s->getWeight();
	cout << "Searching the one with least weight..." << flush;
	for(unsigned int i = 0; i < startnodes.size(); i++){
		if(weight > steiners[i]->getWeight()){
			s = steiners[i];
			node = startnodes[i];
			weight = steiners[i]->getWeight();
		}
	}
	cout << "done" << endl;
	cout << "It's the one with startnode " << node << endl << endl;

	cout << "Checking for cycle..." << flush;
	Edges steinerEdges = s->getEdges();
	GraphChecker* checker = new GraphChecker(steinerEdges, s->getNodes());
	if(checker->hasCycle()){
		cout << "failed" << endl;
		return 1;
	}
	cout << "passed" << endl;

	cout << "Checking if graph is connected..." << flush;
	if(!checker->isConnected()){
		cout << "failed" << endl;
		return 1;
	}
	cout << "passed" << endl << endl;

	cout << "TLEN: " << s->getWeight() << endl;

	cout << "TREE:";
	for(unsigned int i = 0; i < steinerEdges.size(); i++){
		Edge edge = steinerEdges[i];
		cout << " (" << edge.first << ", " << edge.second << ")";
	}
	cout << endl;

	bTime::cpu_times timesProgram = timerProgram.elapsed();
	cout << "TIME: " << bTime::format(timesProgram, 4, "%t") << endl;
	cout << "WALL: " << bTime::format(timesSteiner, 4, "%w") << endl;

	delete edges;
	delete weights;
	delete checker;
	for(unsigned int i = 0; i < startnodes.size(); i++){
		delete steiners[i];
	}
	delete [] steiners;

	return 0;
}
<commit_msg>uses number of threads for solving the different steiner<commit_after>/**
 * Exercise 8 : Read in a gph-file, interpretes it as a Steiner-problem and solves it.
 *
 * @author FirstSanny
 */

#include <iostream>
#include <iomanip>
#include <fstream>
#include <utility>
#include <boost/program_options.hpp>
#include <boost/timer/timer.hpp>
#include "Steiner.h"
#include "GraphChecker.h"

// Constants
namespace {
	const char* FILEEND = ".gph";
	const int MAX_FOR_DEFAULT_TERMINALS = 100;
	const int DEFAULT_THREAD_NUMBER = 8;
}

// declaring print
using std::cout;
using std::endl;
using std::flush;
using std::cerr;
using std::string;

// declaring types
namespace po = boost::program_options;
namespace bTime = boost::timer;
using Primes = std::vector<int >;

/**
 * Computes all primes less than vertexCount
 * by beginning with the prime 2 and trying to divide all numbers smaller than vertexCount
 * and try do divide by all found primes.
 */
Primes getPrimes(unsigned int vertexCount) {
	Primes primes = Primes();
	primes.push_back(2);
	for (unsigned int i = 3; i < vertexCount; i++) {
		char isPrime = true;
		for (int prime : primes) {
			if (i % prime == 0) {
				isPrime = false;
			}
		}
		if (isPrime) {
			primes.push_back(i);
		}
	}
	return primes;
}

/** Parsing the arguments given via command line */
po::variables_map parseCommandLine(po::options_description desc, int argn,
		char* argv[]) {
	desc.add_options()//
			("help,h", "produce help message")//
			("start_nodes,s", po::value<std::vector<int >>(),"nodes, where to start")//
			("thread_number,t", po::value<int>(), "number of threads for parallelization")//
			("input_file,i", po::value<string>(), "input file");
	po::positional_options_description p;
	p.add("input_file", -1);
	po::variables_map vm;
	po::store(
			po::command_line_parser(argn, argv).options(desc).positional(p).run(),
			vm);
	po::notify(vm);
	return vm;
}

/** Reading in a Graphfile, computes the Steiner */
int main(int argn, char *argv[]) {
	bTime::cpu_timer timerProgram;
	if (argn <= 1) {
		cerr << "ERROR : There was no filename" << endl;
		return 1;
	}

	po::options_description desc("Allowed options");
	po::variables_map vm = parseCommandLine(desc, argn, argv);

	if (vm.count("help")) {
	    cout << desc << "\n";
	    return 1;
	}

	std::ifstream fileStream;
	if(vm.count("input_file") == 0){
		cerr << "No input-file was given!" << endl;
		return 1;
	}

	string filename = vm["input_file"].as<string >();
	if(filename.find(FILEEND) == std::string::npos){
		filename += FILEEND;
	}
	cout << "Going to parse the file " << filename << endl;
	fileStream.open(filename.c_str(), std::ios::in);

	if ( (fileStream.rdstate()) != 0 ){
		std::perror("ERROR : Encoutered Problem opening file");
		return 1;
	}

	std::vector<int > startnodes;
	if(vm.count("start_nodes") == 0){
		cout << "Using default startnodes (first 100 primes)" << endl;
	} else {
		startnodes = vm["start_node"].as<std::vector<int >>();
	}

	int threadNumber;
	if(vm.count("thread_number") == 0){
		cout << "Using default number of threads (8)" << endl;
		threadNumber = DEFAULT_THREAD_NUMBER;
	} else {
		threadNumber = vm["thread_number"].as<int >();
	}

	cout << endl;

	string line;

	unsigned int edgeCount;
	unsigned int vertexCount;

	if(std::getline(fileStream, line)){
		sscanf(line.c_str(), "%d %d", &vertexCount, &edgeCount);
		cout << "Vertexcount: " << vertexCount << endl;
		cout << "Edgecount: " << edgeCount << endl;
		line.clear();
		vertexCount++;
	} else {
		cerr << "ERROR : File was empty" << endl;
		return 1;
	}

	Edges* edges = new Edges(edgeCount);
	Weights* weights = new Weights(edgeCount);

	cout << "Reading edges..." << flush;
	int i = 0;
	while (getline(fileStream, line)) {
		int start;
		int end;
		double weight;
		int count = sscanf(line.c_str(), "%d %d %lf", &start, &end, &weight);
		if (count != 3) {
			line.clear();
			continue;
		}
		edges->at(i) = std::make_pair(start, end);
		weights->at(i) = weight;
		i++;
		line.clear();
	}
	cout << "done" << endl << endl;

	Primes terminals = getPrimes(vertexCount);
	if(startnodes.empty()){
		for (unsigned int i = 0;
				i < MAX_FOR_DEFAULT_TERMINALS && i < terminals.size(); i++) {
			startnodes.push_back(terminals[i]);
		}
	}

	cout << "Solves Steiner-tree for " << startnodes.size() << " startnodes..." << flush;
	bTime::cpu_timer timerSteiner;
	Steiner** steiners = new Steiner*[startnodes.size()];
	#pragma omp parallel for num_threads(threadNumber)
	for(unsigned int i = 0; i < startnodes.size(); i++){
		steiners[i] = new Steiner();
		steiners[i]->computeSteinerTree(vertexCount, edges, *weights, terminals, startnodes[i]);
	}
	bTime::cpu_times timesSteiner = timerSteiner.elapsed();
	cout << "done" << endl;

	Steiner* s = steiners[0];
	int node = startnodes[0];
	int weight = s->getWeight();
	cout << "Searching the one with least weight..." << flush;
	for(unsigned int i = 0; i < startnodes.size(); i++){
		if(weight > steiners[i]->getWeight()){
			s = steiners[i];
			node = startnodes[i];
			weight = steiners[i]->getWeight();
		}
	}
	cout << "done" << endl;
	cout << "It's the one with startnode " << node << endl << endl;

	cout << "Checking for cycle..." << flush;
	Edges steinerEdges = s->getEdges();
	GraphChecker* checker = new GraphChecker(steinerEdges, s->getNodes());
	if(checker->hasCycle()){
		cout << "failed" << endl;
		return 1;
	}
	cout << "passed" << endl;

	cout << "Checking if graph is connected..." << flush;
	if(!checker->isConnected()){
		cout << "failed" << endl;
		return 1;
	}
	cout << "passed" << endl << endl;

	cout << "TLEN: " << s->getWeight() << endl;

	cout << "TREE:";
	for(unsigned int i = 0; i < steinerEdges.size(); i++){
		Edge edge = steinerEdges[i];
		cout << " (" << edge.first << ", " << edge.second << ")";
	}
	cout << endl;

	bTime::cpu_times timesProgram = timerProgram.elapsed();
	cout << "TIME: " << bTime::format(timesProgram, 4, "%t") << endl;
	cout << "WALL: " << bTime::format(timesSteiner, 4, "%w") << endl;

	delete edges;
	delete weights;
	delete checker;
	for(unsigned int i = 0; i < startnodes.size(); i++){
		delete steiners[i];
	}
	delete [] steiners;

	return 0;
}
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
// SOURCE CODE: https://github.com/yunfuliu/pixkit
//
// BEIRF: pixkit-cv contains computer vision related tools and methods which
//		  have been published (on articles, e.g., journal or conference papers).
//
//////////////////////////////////////////////////////////////////////////
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

#include <cmath>
#include <vector>

#ifndef __PIXKIT_CV_HPP__
#define __PIXKIT_CV_HPP__

namespace pixkit{

	namespace detection{

		// bounding box
		class CBBs{
		public:
			cv::Rect	rect;	// position of that BB
			float		conf;	// confidence
		};

		bool	nms_PairwiseMax_2010(std::vector<CBBs> &boxes,float overlap=0.5);

		bool	nms_PairwiseMaxStar_2009(std::vector<CBBs> &boxes,float overlap=0.6);

	}

	namespace labeling{

		// Two-pass connected-component labeling
		bool twoPass(const cv::Mat &src,cv::Mat &dst,const int offset);

	}

}
#endif
<commit_msg>give a parameter 'offset' a default value<commit_after>//////////////////////////////////////////////////////////////////////////
//
// SOURCE CODE: https://github.com/yunfuliu/pixkit
//
// BEIRF: pixkit-cv contains computer vision related tools and methods which
//		  have been published (on articles, e.g., journal or conference papers).
//
//////////////////////////////////////////////////////////////////////////
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

#include <cmath>
#include <vector>

#ifndef __PIXKIT_CV_HPP__
#define __PIXKIT_CV_HPP__

namespace pixkit{

	namespace detection{

		// bounding box
		class CBBs{
		public:
			cv::Rect	rect;	// position of that BB
			float		conf;	// confidence
		};

		bool	nms_PairwiseMax_2010(std::vector<CBBs> &boxes,float overlap=0.5);

		bool	nms_PairwiseMaxStar_2009(std::vector<CBBs> &boxes,float overlap=0.6);

	}

	namespace labeling{

		// Two-pass connected-component labeling
		bool twoPass(const cv::Mat &src,cv::Mat &dst,const int offset=1);

	}

}
#endif
<|endoftext|>


<commit_before>/*
 * Copyright 2019 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "modules/skresources/include/SkResources.h"

#include "include/codec/SkCodec.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkData.h"
#include "include/core/SkImage.h"
#include "include/private/SkTPin.h"
#include "include/utils/SkAnimCodecPlayer.h"
#include "include/utils/SkBase64.h"
#include "src/core/SkOSFile.h"
#include "src/utils/SkOSPath.h"

#if defined(HAVE_VIDEO_DECODER)
    #include "experimental/ffmpeg/SkVideoDecoder.h"
#endif

namespace skresources {
namespace  {

#if defined(HAVE_VIDEO_DECODER)

class VideoAsset final : public ImageAsset {
public:
    static sk_sp<VideoAsset> Make(sk_sp<SkData> data) {
        auto decoder = std::make_unique<SkVideoDecoder>();

        if (!decoder->loadStream(SkMemoryStream::Make(std::move(data))) ||
            decoder->duration() <= 0) {
            return nullptr;
        }

        return sk_sp<VideoAsset>(new VideoAsset(std::move(decoder)));
    }

private:
    explicit VideoAsset(std::unique_ptr<SkVideoDecoder> decoder)
        : fDecoder(std::move(decoder)) {
    }

    bool isMultiFrame() override { return true; }

    // Each frame has a presentation timestamp
    //   => the timespan for frame N is [stamp_N .. stamp_N+1)
    //   => we use a two-frame sliding window to track the current interval.
    void advance() {
        fWindow[0] = std::move(fWindow[1]);
        fWindow[1].frame = fDecoder->nextImage(&fWindow[1].stamp);
        fEof = !fWindow[1].frame;
    }

    sk_sp<SkImage> getFrame(float t_float) override {
        const auto t = SkTPin(static_cast<double>(t_float), 0.0, fDecoder->duration());

        if (t < fWindow[0].stamp) {
            // seeking back requires a full rewind
            fDecoder->rewind();
            fWindow[0].stamp = fWindow[1].stamp = 0;
            fEof = 0;
        }

        while (!fEof && t >= fWindow[1].stamp) {
            this->advance();
        }

        SkASSERT(fWindow[0].stamp <= t && (fEof || t < fWindow[1].stamp));

        return fWindow[0].frame;
    }

    const std::unique_ptr<SkVideoDecoder> fDecoder;

    struct FrameRec {
        sk_sp<SkImage> frame;
        double         stamp = 0;
    };

    FrameRec fWindow[2];
    bool     fEof = false;
};

#endif // defined(HAVE_VIDEO_DECODER)

} // namespace

sk_sp<SkImage> ImageAsset::getFrame(float t) {
    return nullptr;
}

ImageAsset::FrameData ImageAsset::getFrameData(float t) {
    // legacy behavior
    return {
        this->getFrame(t),
        SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNearest),
        SkMatrix::I(),
    };
}

sk_sp<MultiFrameImageAsset> MultiFrameImageAsset::Make(sk_sp<SkData> data, bool predecode) {
    if (auto codec = SkCodec::MakeFromData(std::move(data))) {
        return sk_sp<MultiFrameImageAsset>(
              new MultiFrameImageAsset(std::make_unique<SkAnimCodecPlayer>(std::move(codec)),
                                                                             predecode));
    }

    return nullptr;
}

MultiFrameImageAsset::MultiFrameImageAsset(std::unique_ptr<SkAnimCodecPlayer> player,
                                           bool predecode)
    : fPlayer(std::move(player))
    , fPreDecode(predecode) {
    SkASSERT(fPlayer);
}

bool MultiFrameImageAsset::isMultiFrame() {
    return fPlayer->duration() > 0;
}

sk_sp<SkImage> MultiFrameImageAsset::generateFrame(float t) {
    auto decode = [](sk_sp<SkImage> image) {
        SkASSERT(image->isLazyGenerated());

        static constexpr size_t kMaxArea = 2048 * 2048;
        const auto image_area = SkToSizeT(image->width() * image->height());

        if (image_area > kMaxArea) {
            // When the image is too large, decode and scale down to a reasonable size.
            const auto scale = std::sqrt(static_cast<float>(kMaxArea) / image_area);
            const auto info  = SkImageInfo::MakeN32Premul(scale * image->width(),
                                                          scale * image->height());
            SkBitmap bm;
            if (bm.tryAllocPixels(info, info.minRowBytes()) &&
                    image->scalePixels(bm.pixmap(),
                                       SkSamplingOptions(SkFilterMode::kLinear,
                                                         SkMipmapMode::kNearest),
                                       SkImage::kDisallow_CachingHint)) {
                image = bm.asImage();
            }
        } else {
            // When the image size is OK, just force-decode.
            image = image->makeRasterImage();
        }

        return image;
    };

    fPlayer->seek(static_cast<uint32_t>(t * 1000));
    auto frame = fPlayer->getFrame();

    if (fPreDecode && frame && frame->isLazyGenerated()) {
        // The multi-frame decoder should never return lazy images.
        SkASSERT(!this->isMultiFrame());
        frame = decode(std::move(frame));
    }

    return frame;
}

sk_sp<SkImage> MultiFrameImageAsset::getFrame(float t) {
    // For static images we can reuse the cached frame
    // (which includes the optional pre-decode step).
    if (!fCachedFrame || this->isMultiFrame()) {
        fCachedFrame = this->generateFrame(t);
    }

    return fCachedFrame;
}

sk_sp<FileResourceProvider> FileResourceProvider::Make(SkString base_dir, bool predecode) {
    return sk_isdir(base_dir.c_str())
        ? sk_sp<FileResourceProvider>(new FileResourceProvider(std::move(base_dir), predecode))
        : nullptr;
}

FileResourceProvider::FileResourceProvider(SkString base_dir, bool predecode)
    : fDir(std::move(base_dir))
    , fPredecode(predecode) {}

sk_sp<SkData> FileResourceProvider::load(const char resource_path[],
                                         const char resource_name[]) const {
    const auto full_dir  = SkOSPath::Join(fDir.c_str()    , resource_path),
               full_path = SkOSPath::Join(full_dir.c_str(), resource_name);
    return SkData::MakeFromFileName(full_path.c_str());
}

sk_sp<ImageAsset> FileResourceProvider::loadImageAsset(const char resource_path[],
                                                       const char resource_name[],
                                                       const char[]) const {
    auto data = this->load(resource_path, resource_name);

    if (auto image = MultiFrameImageAsset::Make(data, fPredecode)) {
        return std::move(image);
    }

#if defined(HAVE_VIDEO_DECODER)
    if (auto video = VideoAsset::Make(data)) {
        return std::move(video);
    }
#endif

    return nullptr;
}

ResourceProviderProxyBase::ResourceProviderProxyBase(sk_sp<ResourceProvider> rp)
    : fProxy(std::move(rp)) {}

sk_sp<SkData> ResourceProviderProxyBase::load(const char resource_path[],
                                              const char resource_name[]) const {
    return fProxy ? fProxy->load(resource_path, resource_name)
                  : nullptr;
}

sk_sp<ImageAsset> ResourceProviderProxyBase::loadImageAsset(const char rpath[],
                                                            const char rname[],
                                                            const char rid[]) const {
    return fProxy ? fProxy->loadImageAsset(rpath, rname, rid)
                  : nullptr;
}

sk_sp<SkTypeface> ResourceProviderProxyBase::loadTypeface(const char name[],
                                                          const char url[]) const {
    return fProxy ? fProxy->loadTypeface(name, url)
                  : nullptr;
}

sk_sp<SkData> ResourceProviderProxyBase::loadFont(const char name[], const char url[]) const {
    return fProxy ? fProxy->loadFont(name, url)
                  : nullptr;
}

sk_sp<ExternalTrackAsset> ResourceProviderProxyBase::loadAudioAsset(const char path[],
                                                                    const char name[],
                                                                    const char id[]) {
    return fProxy ? fProxy->loadAudioAsset(path, name, id)
                  : nullptr;
}

CachingResourceProvider::CachingResourceProvider(sk_sp<ResourceProvider> rp)
    : INHERITED(std::move(rp)) {}

sk_sp<ImageAsset> CachingResourceProvider::loadImageAsset(const char resource_path[],
                                                          const char resource_name[],
                                                          const char resource_id[]) const {
    SkAutoMutexExclusive amx(fMutex);

    const SkString key(resource_id);
    if (const auto* asset = fImageCache.find(key)) {
        return *asset;
    }

    auto asset = this->INHERITED::loadImageAsset(resource_path, resource_name, resource_id);
    fImageCache.set(key, asset);

    return asset;
}

sk_sp<DataURIResourceProviderProxy> DataURIResourceProviderProxy::Make(sk_sp<ResourceProvider> rp,
                                                                       bool predecode) {
    return sk_sp<DataURIResourceProviderProxy>(
            new DataURIResourceProviderProxy(std::move(rp), predecode));
}

DataURIResourceProviderProxy::DataURIResourceProviderProxy(sk_sp<ResourceProvider> rp,
                                                           bool predecode)
    : INHERITED(std::move(rp))
    , fPredecode(predecode) {}

static sk_sp<SkData> decode_datauri(const char prefix[], const char uri[]) {
    // We only handle B64 encoded image dataURIs: data:image/<type>;base64,<data>
    // (https://en.wikipedia.org/wiki/Data_URI_scheme)
    static constexpr char kDataURIEncodingStr[] = ";base64,";

    const size_t prefixLen = strlen(prefix);
    if (strncmp(uri, prefix, prefixLen) != 0) {
        return nullptr;
    }

    const char* encoding = strstr(uri + prefixLen, kDataURIEncodingStr);
    if (!encoding) {
        return nullptr;
    }

    const char* b64Data = encoding + std::size(kDataURIEncodingStr) - 1;
    size_t b64DataLen = strlen(b64Data);
    size_t dataLen;
    if (SkBase64::Decode(b64Data, b64DataLen, nullptr, &dataLen) != SkBase64::kNoError) {
        return nullptr;
    }

    sk_sp<SkData> data = SkData::MakeUninitialized(dataLen);
    void* rawData = data->writable_data();
    if (SkBase64::Decode(b64Data, b64DataLen, rawData, &dataLen) != SkBase64::kNoError) {
        return nullptr;
    }

    return data;
}

sk_sp<ImageAsset> DataURIResourceProviderProxy::loadImageAsset(const char rpath[],
                                                               const char rname[],
                                                               const char rid[]) const {
    if (auto data = decode_datauri("data:image/", rname)) {
        return MultiFrameImageAsset::Make(std::move(data), fPredecode);
    }

    return this->INHERITED::loadImageAsset(rpath, rname, rid);
}

sk_sp<SkTypeface> DataURIResourceProviderProxy::loadTypeface(const char name[],
                                                             const char url[]) const {
    if (auto data = decode_datauri("data:font/", url)) {
        return SkTypeface::MakeFromData(std::move(data));
    }

    return this->INHERITED::loadTypeface(name, url);
}

} // namespace skresources
<commit_msg>Add missing SkStream include in SkResources<commit_after>/*
 * Copyright 2019 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "modules/skresources/include/SkResources.h"

#include "include/codec/SkCodec.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkData.h"
#include "include/core/SkImage.h"
#include "include/private/SkTPin.h"
#include "include/utils/SkAnimCodecPlayer.h"
#include "include/utils/SkBase64.h"
#include "src/core/SkOSFile.h"
#include "src/utils/SkOSPath.h"

#if defined(HAVE_VIDEO_DECODER)
    #include "experimental/ffmpeg/SkVideoDecoder.h"
    #include "include/core/SkStream.h"
#endif

namespace skresources {
namespace  {

#if defined(HAVE_VIDEO_DECODER)

class VideoAsset final : public ImageAsset {
public:
    static sk_sp<VideoAsset> Make(sk_sp<SkData> data) {
        auto decoder = std::make_unique<SkVideoDecoder>();

        if (!decoder->loadStream(SkMemoryStream::Make(std::move(data))) ||
            decoder->duration() <= 0) {
            return nullptr;
        }

        return sk_sp<VideoAsset>(new VideoAsset(std::move(decoder)));
    }

private:
    explicit VideoAsset(std::unique_ptr<SkVideoDecoder> decoder)
        : fDecoder(std::move(decoder)) {
    }

    bool isMultiFrame() override { return true; }

    // Each frame has a presentation timestamp
    //   => the timespan for frame N is [stamp_N .. stamp_N+1)
    //   => we use a two-frame sliding window to track the current interval.
    void advance() {
        fWindow[0] = std::move(fWindow[1]);
        fWindow[1].frame = fDecoder->nextImage(&fWindow[1].stamp);
        fEof = !fWindow[1].frame;
    }

    sk_sp<SkImage> getFrame(float t_float) override {
        const auto t = SkTPin(static_cast<double>(t_float), 0.0, fDecoder->duration());

        if (t < fWindow[0].stamp) {
            // seeking back requires a full rewind
            fDecoder->rewind();
            fWindow[0].stamp = fWindow[1].stamp = 0;
            fEof = 0;
        }

        while (!fEof && t >= fWindow[1].stamp) {
            this->advance();
        }

        SkASSERT(fWindow[0].stamp <= t && (fEof || t < fWindow[1].stamp));

        return fWindow[0].frame;
    }

    const std::unique_ptr<SkVideoDecoder> fDecoder;

    struct FrameRec {
        sk_sp<SkImage> frame;
        double         stamp = 0;
    };

    FrameRec fWindow[2];
    bool     fEof = false;
};

#endif // defined(HAVE_VIDEO_DECODER)

} // namespace

sk_sp<SkImage> ImageAsset::getFrame(float t) {
    return nullptr;
}

ImageAsset::FrameData ImageAsset::getFrameData(float t) {
    // legacy behavior
    return {
        this->getFrame(t),
        SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNearest),
        SkMatrix::I(),
    };
}

sk_sp<MultiFrameImageAsset> MultiFrameImageAsset::Make(sk_sp<SkData> data, bool predecode) {
    if (auto codec = SkCodec::MakeFromData(std::move(data))) {
        return sk_sp<MultiFrameImageAsset>(
              new MultiFrameImageAsset(std::make_unique<SkAnimCodecPlayer>(std::move(codec)),
                                                                             predecode));
    }

    return nullptr;
}

MultiFrameImageAsset::MultiFrameImageAsset(std::unique_ptr<SkAnimCodecPlayer> player,
                                           bool predecode)
    : fPlayer(std::move(player))
    , fPreDecode(predecode) {
    SkASSERT(fPlayer);
}

bool MultiFrameImageAsset::isMultiFrame() {
    return fPlayer->duration() > 0;
}

sk_sp<SkImage> MultiFrameImageAsset::generateFrame(float t) {
    auto decode = [](sk_sp<SkImage> image) {
        SkASSERT(image->isLazyGenerated());

        static constexpr size_t kMaxArea = 2048 * 2048;
        const auto image_area = SkToSizeT(image->width() * image->height());

        if (image_area > kMaxArea) {
            // When the image is too large, decode and scale down to a reasonable size.
            const auto scale = std::sqrt(static_cast<float>(kMaxArea) / image_area);
            const auto info  = SkImageInfo::MakeN32Premul(scale * image->width(),
                                                          scale * image->height());
            SkBitmap bm;
            if (bm.tryAllocPixels(info, info.minRowBytes()) &&
                    image->scalePixels(bm.pixmap(),
                                       SkSamplingOptions(SkFilterMode::kLinear,
                                                         SkMipmapMode::kNearest),
                                       SkImage::kDisallow_CachingHint)) {
                image = bm.asImage();
            }
        } else {
            // When the image size is OK, just force-decode.
            image = image->makeRasterImage();
        }

        return image;
    };

    fPlayer->seek(static_cast<uint32_t>(t * 1000));
    auto frame = fPlayer->getFrame();

    if (fPreDecode && frame && frame->isLazyGenerated()) {
        // The multi-frame decoder should never return lazy images.
        SkASSERT(!this->isMultiFrame());
        frame = decode(std::move(frame));
    }

    return frame;
}

sk_sp<SkImage> MultiFrameImageAsset::getFrame(float t) {
    // For static images we can reuse the cached frame
    // (which includes the optional pre-decode step).
    if (!fCachedFrame || this->isMultiFrame()) {
        fCachedFrame = this->generateFrame(t);
    }

    return fCachedFrame;
}

sk_sp<FileResourceProvider> FileResourceProvider::Make(SkString base_dir, bool predecode) {
    return sk_isdir(base_dir.c_str())
        ? sk_sp<FileResourceProvider>(new FileResourceProvider(std::move(base_dir), predecode))
        : nullptr;
}

FileResourceProvider::FileResourceProvider(SkString base_dir, bool predecode)
    : fDir(std::move(base_dir))
    , fPredecode(predecode) {}

sk_sp<SkData> FileResourceProvider::load(const char resource_path[],
                                         const char resource_name[]) const {
    const auto full_dir  = SkOSPath::Join(fDir.c_str()    , resource_path),
               full_path = SkOSPath::Join(full_dir.c_str(), resource_name);
    return SkData::MakeFromFileName(full_path.c_str());
}

sk_sp<ImageAsset> FileResourceProvider::loadImageAsset(const char resource_path[],
                                                       const char resource_name[],
                                                       const char[]) const {
    auto data = this->load(resource_path, resource_name);

    if (auto image = MultiFrameImageAsset::Make(data, fPredecode)) {
        return std::move(image);
    }

#if defined(HAVE_VIDEO_DECODER)
    if (auto video = VideoAsset::Make(data)) {
        return std::move(video);
    }
#endif

    return nullptr;
}

ResourceProviderProxyBase::ResourceProviderProxyBase(sk_sp<ResourceProvider> rp)
    : fProxy(std::move(rp)) {}

sk_sp<SkData> ResourceProviderProxyBase::load(const char resource_path[],
                                              const char resource_name[]) const {
    return fProxy ? fProxy->load(resource_path, resource_name)
                  : nullptr;
}

sk_sp<ImageAsset> ResourceProviderProxyBase::loadImageAsset(const char rpath[],
                                                            const char rname[],
                                                            const char rid[]) const {
    return fProxy ? fProxy->loadImageAsset(rpath, rname, rid)
                  : nullptr;
}

sk_sp<SkTypeface> ResourceProviderProxyBase::loadTypeface(const char name[],
                                                          const char url[]) const {
    return fProxy ? fProxy->loadTypeface(name, url)
                  : nullptr;
}

sk_sp<SkData> ResourceProviderProxyBase::loadFont(const char name[], const char url[]) const {
    return fProxy ? fProxy->loadFont(name, url)
                  : nullptr;
}

sk_sp<ExternalTrackAsset> ResourceProviderProxyBase::loadAudioAsset(const char path[],
                                                                    const char name[],
                                                                    const char id[]) {
    return fProxy ? fProxy->loadAudioAsset(path, name, id)
                  : nullptr;
}

CachingResourceProvider::CachingResourceProvider(sk_sp<ResourceProvider> rp)
    : INHERITED(std::move(rp)) {}

sk_sp<ImageAsset> CachingResourceProvider::loadImageAsset(const char resource_path[],
                                                          const char resource_name[],
                                                          const char resource_id[]) const {
    SkAutoMutexExclusive amx(fMutex);

    const SkString key(resource_id);
    if (const auto* asset = fImageCache.find(key)) {
        return *asset;
    }

    auto asset = this->INHERITED::loadImageAsset(resource_path, resource_name, resource_id);
    fImageCache.set(key, asset);

    return asset;
}

sk_sp<DataURIResourceProviderProxy> DataURIResourceProviderProxy::Make(sk_sp<ResourceProvider> rp,
                                                                       bool predecode) {
    return sk_sp<DataURIResourceProviderProxy>(
            new DataURIResourceProviderProxy(std::move(rp), predecode));
}

DataURIResourceProviderProxy::DataURIResourceProviderProxy(sk_sp<ResourceProvider> rp,
                                                           bool predecode)
    : INHERITED(std::move(rp))
    , fPredecode(predecode) {}

static sk_sp<SkData> decode_datauri(const char prefix[], const char uri[]) {
    // We only handle B64 encoded image dataURIs: data:image/<type>;base64,<data>
    // (https://en.wikipedia.org/wiki/Data_URI_scheme)
    static constexpr char kDataURIEncodingStr[] = ";base64,";

    const size_t prefixLen = strlen(prefix);
    if (strncmp(uri, prefix, prefixLen) != 0) {
        return nullptr;
    }

    const char* encoding = strstr(uri + prefixLen, kDataURIEncodingStr);
    if (!encoding) {
        return nullptr;
    }

    const char* b64Data = encoding + std::size(kDataURIEncodingStr) - 1;
    size_t b64DataLen = strlen(b64Data);
    size_t dataLen;
    if (SkBase64::Decode(b64Data, b64DataLen, nullptr, &dataLen) != SkBase64::kNoError) {
        return nullptr;
    }

    sk_sp<SkData> data = SkData::MakeUninitialized(dataLen);
    void* rawData = data->writable_data();
    if (SkBase64::Decode(b64Data, b64DataLen, rawData, &dataLen) != SkBase64::kNoError) {
        return nullptr;
    }

    return data;
}

sk_sp<ImageAsset> DataURIResourceProviderProxy::loadImageAsset(const char rpath[],
                                                               const char rname[],
                                                               const char rid[]) const {
    if (auto data = decode_datauri("data:image/", rname)) {
        return MultiFrameImageAsset::Make(std::move(data), fPredecode);
    }

    return this->INHERITED::loadImageAsset(rpath, rname, rid);
}

sk_sp<SkTypeface> DataURIResourceProviderProxy::loadTypeface(const char name[],
                                                             const char url[]) const {
    if (auto data = decode_datauri("data:font/", url)) {
        return SkTypeface::MakeFromData(std::move(data));
    }

    return this->INHERITED::loadTypeface(name, url);
}

} // namespace skresources
<|endoftext|>


<commit_before>#include "libpstack/dwarf.h"
#include "libpstack/proc.h"
#include "libpstack/ps_callback.h"
#if defined(WITH_PYTHON2) || defined(WITH_PYTHON3)
#define WITH_PYTHON
#include "libpstack/python.h"
#endif

#include <sys/types.h>
#include <sys/signal.h>

#include <sysexits.h>
#include <unistd.h>

#include <csignal>

#include <iostream>
#include <set>

#define XSTR(a) #a
#define STR(a) XSTR(a)
extern std::ostream & operator << (std::ostream &os, const JSON<ThreadStack, Process *> &jt);

namespace {
bool doJson = false;
volatile bool interrupted = false;

int usage(const char *);
std::ostream &
pstack(Process &proc, std::ostream &os, const PstackOptions &options)
{
    // get its back trace.
    std::list<ThreadStack> threadStacks;
    std::set<pid_t> tracedLwps;
    {
        StopProcess here(&proc);
        proc.listThreads([&proc, &threadStacks, &tracedLwps] (const td_thrhandle_t *thr) {

            Elf::CoreRegisters regs;
            td_err_e the;
#ifdef __linux__
            the = td_thr_getgregs(thr, (elf_greg_t *) &regs);
#else
            the = td_thr_getgregs(thr, &regs);
#endif
            if (the == TD_OK) {
                threadStacks.push_back(ThreadStack());
                td_thr_get_info(thr, &threadStacks.back().info);
                threadStacks.back().unwind(proc, regs);
                tracedLwps.insert(threadStacks.back().info.ti_lid);
            }
            });

        for (auto &lwp : proc.lwps) {
            if (tracedLwps.find(lwp.first) == tracedLwps.end()) {
                threadStacks.push_back(ThreadStack());
                threadStacks.back().info.ti_lid = lwp.first;
                Elf::CoreRegisters regs;
                proc.getRegs(lwp.first,  &regs);
                threadStacks.back().unwind(proc, regs);
            }
        }
    }

    /*
     * resume at this point - maybe a bit optimistic if a shared library gets
     * unloaded while we print stuff out, but worth the risk, normally.
     */
    if (doJson) {
        os << json(threadStacks, &proc);
    } else {
        os << "process: " << *proc.io << "\n";
        for (auto &s : threadStacks) {
            proc.dumpStackText(os, s, options);
            os << std::endl;
        }
    }
    return os;
}

#ifdef WITH_PYTHON
template<int V> void doPy(Process &proc, std::ostream &o, const PstackOptions &options, bool showModules, const PyInterpInfo &info) {
    PythonPrinter<V> printer(proc, o, options, info);
    if (!printer.interpFound())
        throw Exception() << "no python interpreter found";
    printer.printInterpreters(showModules);
}

bool pystack(Process &proc, std::ostream &o, const PstackOptions &options, bool showModules) {
    PyInterpInfo info = getPyInterpInfo(proc);

    if (info.libpython == nullptr) // not a python process or python interpreter not found
        return false;

    if (info.versionHex < V2HEX(3, 0)) { // Python 2.x
#ifdef WITH_PYTHON2
        doPy<2>(proc, o, options, showModules, info);
#else
        throw (Exception() << "no support for discovered python 2 interpreter");
#endif
    } else { // Python 3.x
#ifdef WITH_PYTHON3
        doPy<3>(proc, o, options, showModules, info);
#else
        throw (Exception() << "no support for discovered python 3 interpreter");
#endif
    }

    return true;
}
#endif

int
emain(int argc, char **argv)
{
    int i, c;
    std::string execFile;
    Elf::Object::sptr exec;
    Dwarf::ImageCache imageCache;
    double sleepTime = 0.0;
    PstackOptions options;
    options.maxdepth = 10000;

#if defined(WITH_PYTHON)
    bool python = false;
    bool pythonModules = false;
#endif
    bool coreOnExit = false;

    while ((c = getopt(argc, argv, "F:b:d:CD:hjmsVvag:pltz:r:")) != -1) {
        switch (c) {
        case 'F': g_openPrefix = optarg;
                  break;
        case 'g':
            Elf::globalDebugDirectories.add(optarg);
            break;
        case 'D': {
            auto dumpobj = std::make_shared<Elf::Object>(imageCache, loadFile(optarg));
            auto di = std::make_shared<Dwarf::Info>(dumpobj, imageCache);
            std::cout << json(*di);
            goto done;
        }
        case 'z':
        case 'd': {
            /* Undocumented option to dump image contents */
            std::cout << json(Elf::Object(imageCache, loadFile(optarg)));
            goto done;
        }
        case 'h':
            usage(argv[0]);
            goto done;
        case 'a':
            options.flags.set(PstackOptions::doargs);
            break;
        case 'j':
            doJson = true;
            break;
        case 's':
            options.flags.set(PstackOptions::nosrc);
            break;
        case 'v':
            verbose++;
            break;
        case 'b':
            sleepTime = strtod(optarg, nullptr);
            break;
        case 'm':
#if defined(WITH_PYTHON)
            pythonModules = true;
#else
            std::clog << "no python support compiled in" << std::endl;
#endif
            break;
        case 'p':
#if defined(WITH_PYTHON)
            python = true;
#else
            std::clog << "no python support compiled in" << std::endl;
#endif
            break;
        case 'l':
#if defined(WITH_PYTHON)
            options.flags.set(PstackOptions::dolocals);
#else
            std::clog << "no python support compiled in" << std::endl;
#endif
            break;
        case 't':
            options.flags.set(PstackOptions::nothreaddb);
            break;

        case 'V':
            std::clog << STR(VERSION) << "\n";
            return 0;
        case 'C':
            coreOnExit = true;
            break;
        case 'r':
            options.maxdepth = strtod(optarg, nullptr);
            break;
        default:
            return usage(argv[0]);
        }
    }

    if (optind == argc)
        return usage(argv[0]);

    for (i = optind; i < argc; i++) {
        try {
            auto doStack = [=, &options] (Process &proc) {
                proc.load(options);
                while (!interrupted) {
#if defined(WITH_PYTHON)
                    if (python && pystack(proc, std::cout, options, pythonModules)) {
                        return;
                    }
                    else
#endif
                    {
                        pstack(proc, std::cout, options);
                    }
                    if (sleepTime != 0.0) {
                        usleep(sleepTime * 1000000);
                    } else {
                        break;
                    }
                }
            };
            auto process = Process::load(exec, argv[i], options, imageCache);
            if (process == nullptr) {
                exec = imageCache.getImageForName(argv[i]);
            } else {
                doStack(*process);
            }
        } catch (const std::exception &e) {
            std::cerr << "failed to process " << argv[i] << ": " << e.what() << "\n";
        }
    }
done:
    if (coreOnExit)
        abort();
    return 0;
}

int
usage(const char *name)
{
    std::clog <<
        "usage: " << name << "\n"
        "\t[-<D|d> <elf object>]        dump details of ELF object (D => show DWARF info\n"
        "or\n"
        "\t[-h]                         show this message\n"
        "or\n"
        "\t[-v]                         include verbose information to stderr\n"
        "\t[-V]                         dump git tag of source\n"
        "\t[-s]                         don't include source-level details\n"
        "\t[-g]                         add global debug directory\n"
        "\t[-a]                         show arguments to functions where possible\n"
        "\t[-n]                         don't try to find external debug images\n"
        "\t[-t]                         don't try to use the thread_db library\n"
        "\t[-b<n>]                      batch mode: repeat every 'n' seconds\n"
#ifdef WITH_PYTHON
        "\t[-p]                         print python backtrace if available\n"
        "\t[-l]                         show python locals if available\n"
        "\t[-r<n>]                      the max recursion depth for printing\n"
#endif
        "\t[<pid>|<core>|<executable>]* list cores and pids to examine. An executable\n"
        "\t                             will override use of in-core or in-process information\n"
        "\t                             to predict location of the executable\n"
        ;
    return (EX_USAGE);
}

}

int
main(int argc, char **argv)
{
    try {
        struct sigaction sa;
        memset(&sa, 0, sizeof sa);
        sa.sa_handler = [](int) { interrupted = true; };
        // Only interrupt cleanly once. Then just terminate, in case we're stuck in a loop
        sa.sa_flags = SA_RESETHAND;
        sigaction(SIGINT, &sa, nullptr);
        emain(argc, argv);
    }
    catch (std::exception &ex) {
        std::clog << "error: " << ex.what() << std::endl;
        return EX_SOFTWARE;
    }
}
<commit_msg>Implement -A to print all stacks.<commit_after>#include "libpstack/dwarf.h"
#include "libpstack/proc.h"
#include "libpstack/ps_callback.h"
#if defined(WITH_PYTHON2) || defined(WITH_PYTHON3)
#define WITH_PYTHON
#include "libpstack/python.h"
#endif

#include <sys/types.h>
#include <sys/signal.h>

#include <sysexits.h>
#include <unistd.h>

#include <csignal>

#include <iostream>
#include <set>

#define XSTR(a) #a
#define STR(a) XSTR(a)
extern std::ostream & operator << (std::ostream &os, const JSON<ThreadStack, Process *> &jt);

namespace {
bool doJson = false;
volatile bool interrupted = false;

int usage(const char *);
std::ostream &
pstack(Process &proc, std::ostream &os, const PstackOptions &options)
{
    // get its back trace.
    std::list<ThreadStack> threadStacks;
    std::set<pid_t> tracedLwps;
    {
        StopProcess here(&proc);
        proc.listThreads([&proc, &threadStacks, &tracedLwps] (const td_thrhandle_t *thr) {

            Elf::CoreRegisters regs;
            td_err_e the;
#ifdef __linux__
            the = td_thr_getgregs(thr, (elf_greg_t *) &regs);
#else
            the = td_thr_getgregs(thr, &regs);
#endif
            if (the == TD_OK) {
                threadStacks.push_back(ThreadStack());
                td_thr_get_info(thr, &threadStacks.back().info);
                threadStacks.back().unwind(proc, regs);
                tracedLwps.insert(threadStacks.back().info.ti_lid);
            }
            });

        for (auto &lwp : proc.lwps) {
            if (tracedLwps.find(lwp.first) == tracedLwps.end()) {
                threadStacks.push_back(ThreadStack());
                threadStacks.back().info.ti_lid = lwp.first;
                Elf::CoreRegisters regs;
                proc.getRegs(lwp.first,  &regs);
                threadStacks.back().unwind(proc, regs);
            }
        }
    }

    /*
     * resume at this point - maybe a bit optimistic if a shared library gets
     * unloaded while we print stuff out, but worth the risk, normally.
     */
    if (doJson) {
        os << json(threadStacks, &proc);
    } else {
        os << "process: " << *proc.io << "\n";
        for (auto &s : threadStacks) {
            proc.dumpStackText(os, s, options);
            os << std::endl;
        }
    }
    return os;
}

#ifdef WITH_PYTHON
template<int V> void doPy(Process &proc, std::ostream &o, const PstackOptions &options, bool showModules, const PyInterpInfo &info) {
    PythonPrinter<V> printer(proc, o, options, info);
    if (!printer.interpFound())
        throw Exception() << "no python interpreter found";
    printer.printInterpreters(showModules);
}

/**
 * @brief Given a process, tries to print the Python strack trace of it.
 * If the process wasn't a Python process, returns false.
 * True on successful printing of Python stack trace
 *
 * @param proc          The process
 * @param o             The stream to which to print the otutput
 * @param options       Options
 * @param showModules   Whether to show modules
 * @return              boolean of whether the process was a Python process or not
 */
bool pystack(Process &proc, std::ostream &o, const PstackOptions &options, bool showModules) {
    PyInterpInfo info = getPyInterpInfo(proc);

    if (info.libpython == nullptr) // not a python process or python interpreter not found
        return false;

    if (info.versionHex < V2HEX(3, 0)) { // Python 2.x
#ifdef WITH_PYTHON2
        doPy<2>(proc, o, options, showModules, info);
#else
        throw (Exception() << "no support for discovered python 2 interpreter");
#endif
    } else { // Python 3.x
#ifdef WITH_PYTHON3
        doPy<3>(proc, o, options, showModules, info);
#else
        throw (Exception() << "no support for discovered python 3 interpreter");
#endif
    }

    return true;
}
#endif

int
emain(int argc, char **argv)
{
    int i, c;
    std::string execFile;
    Elf::Object::sptr exec;
    Dwarf::ImageCache imageCache;
    double sleepTime = 0.0;
    PstackOptions options;
    options.maxdepth = 10000;

#if defined(WITH_PYTHON)
    bool python = false;
    bool pythonModules = false;
#endif
    bool coreOnExit = false;
    bool printAllStacks = false;

    while ((c = getopt(argc, argv, "F:b:d:CD:hjmsVvag:pltz:r:A")) != -1) {
        switch (c) {
        case 'F': g_openPrefix = optarg;
                  break;
        case 'g':
            Elf::globalDebugDirectories.add(optarg);
            break;
        case 'D': {
            auto dumpobj = std::make_shared<Elf::Object>(imageCache, loadFile(optarg));
            auto di = std::make_shared<Dwarf::Info>(dumpobj, imageCache);
            std::cout << json(*di);
            goto done;
        }
        case 'z':
        case 'd': {
            /* Undocumented option to dump image contents */
            std::cout << json(Elf::Object(imageCache, loadFile(optarg)));
            goto done;
        }
        case 'h':
            usage(argv[0]);
            goto done;
        case 'a':
            options.flags.set(PstackOptions::doargs);
            break;
        case 'j':
            doJson = true;
            break;
        case 's':
            options.flags.set(PstackOptions::nosrc);
            break;
        case 'v':
            verbose++;
            break;
        case 'b':
            sleepTime = strtod(optarg, nullptr);
            break;
        case 'm':
#if defined(WITH_PYTHON)
            pythonModules = true;
#else
            std::clog << "no python support compiled in" << std::endl;
#endif
            break;
        case 'p':
#if defined(WITH_PYTHON)
            python = true;
#else
            std::clog << "no python support compiled in" << std::endl;
#endif
            break;
        case 'l':
#if defined(WITH_PYTHON)
            options.flags.set(PstackOptions::dolocals);
#else
            std::clog << "no python support compiled in" << std::endl;
#endif
            break;
        case 'A':
            printAllStacks = true;
            break;
        case 't':
            options.flags.set(PstackOptions::nothreaddb);
            break;

        case 'V':
            std::clog << STR(VERSION) << "\n";
            return 0;
        case 'C':
            coreOnExit = true;
            break;
        case 'r':
            options.maxdepth = strtod(optarg, nullptr);
            break;
        default:
            return usage(argv[0]);
        }
    }

    if (optind == argc)
        return usage(argv[0]);

    for (i = optind; i < argc; i++) {
        try {
            auto doStack = [=, &options] (Process &proc) {
                proc.load(options);
                while (!interrupted) {
#if defined(WITH_PYTHON)
                    if (python || printAllStacks) {
                        bool isPythonProcess = pystack(proc, std::cout, options, pythonModules);
                        if (python && !isPythonProcess)
                            throw Exception() << "Couldn't find a Python interpreter"; // error if -p but not python process
                    }

                    if (!python)
#endif
                    {
                        pstack(proc, std::cout, options);
                    }
                    if (sleepTime != 0.0) {
                        usleep(sleepTime * 1000000);
                    } else {
                        break;
                    }
                }
            };
            auto process = Process::load(exec, argv[i], options, imageCache);
            if (process == nullptr) {
                exec = imageCache.getImageForName(argv[i]);
            } else {
                doStack(*process);
            }
        } catch (const std::exception &e) {
            std::cerr << "failed to process " << argv[i] << ": " << e.what() << "\n";
        }
    }
done:
    if (coreOnExit)
        abort();
    return 0;
}

int
usage(const char *name)
{
    std::clog <<
        "usage: " << name << "\n"
        "\t[-<D|d> <elf object>]        dump details of ELF object (D => show DWARF info\n"
        "or\n"
        "\t[-h]                         show this message\n"
        "or\n"
        "\t[-v]                         include verbose information to stderr\n"
        "\t[-V]                         dump git tag of source\n"
        "\t[-s]                         don't include source-level details\n"
        "\t[-g]                         add global debug directory\n"
        "\t[-a]                         show arguments to functions where possible\n"
        "\t[-n]                         don't try to find external debug images\n"
        "\t[-t]                         don't try to use the thread_db library\n"
        "\t[-b<n>]                      batch mode: repeat every 'n' seconds\n"
#ifdef WITH_PYTHON
        "\t[-A]                         print all stack traces\n"
        "\t[-p]                         print python backtrace\n"
        "\t[-l]                         show python locals if available\n"
        "\t[-r<n>]                      the max recursion depth for printing\n"
#endif
        "\t[<pid>|<core>|<executable>]* list cores and pids to examine. An executable\n"
        "\t                             will override use of in-core or in-process information\n"
        "\t                             to predict location of the executable\n"
        ;
    return (EX_USAGE);
}

}

int
main(int argc, char **argv)
{
    try {
        struct sigaction sa;
        memset(&sa, 0, sizeof sa);
        sa.sa_handler = [](int) { interrupted = true; };
        // Only interrupt cleanly once. Then just terminate, in case we're stuck in a loop
        sa.sa_flags = SA_RESETHAND;
        sigaction(SIGINT, &sa, nullptr);
        emain(argc, argv);
    }
    catch (std::exception &ex) {
        std::clog << "error: " << ex.what() << std::endl;
        return EX_SOFTWARE;
    }
}
<|endoftext|>