<commit_before>#include "message.h"

#include "animated_sprite.h"
#include "graphics.h"

Message::Message(Graphics& graphics) {
  text.reset(new Text(graphics));

  box.reset(new Sprite(graphics, "message", 0, 0, 640, 128));
  mouth.reset(new AnimatedSprite(graphics, "message", 0, 128, 32, 16, 5));
}

void Message::update(unsigned int elapsed) {
  if (timer > 0) {
    timer -= elapsed;
    if (timer <= 0) {
      messages.pop();
    }
  } else if (!messages.empty()) {
    timer = messages.front().length() * 250;
  }
}

void Message::draw(Graphics& graphics) {
  if (timer > 0) {
    box->draw(graphics, 0, 352);
    mouth->draw(graphics, 32, 432);
    text->draw(graphics, 96, 368, messages.front());
  }
}

void Message::show(std::string text) {
  messages.push(text);
}

void Message::dismiss() {
  timer = 0;
}
<commit_msg>Move messages to top of screen<commit_after>#include "message.h"

#include "animated_sprite.h"
#include "graphics.h"

Message::Message(Graphics& graphics) {
  text.reset(new Text(graphics));

  box.reset(new Sprite(graphics, "message", 0, 0, 640, 128));
  mouth.reset(new AnimatedSprite(graphics, "message", 0, 128, 32, 16, 5));
}

void Message::update(unsigned int elapsed) {
  if (timer > 0) {
    timer -= elapsed;
    if (timer <= 0) {
      messages.pop();
    }
  } else if (!messages.empty()) {
    timer = messages.front().length() * 250;
  }
}

void Message::draw(Graphics& graphics) {
  if (timer > 0) {
    box->draw(graphics, 0, 16);
    mouth->draw(graphics, 32, 96);
    text->draw(graphics, 96, 32, messages.front());
  }
}

void Message::show(std::string text) {
  messages.push(text);
}

void Message::dismiss() {
  timer = 0;
}
<|endoftext|>


<commit_before>#include "module.h"

Module::Module(std::string modName, std::map<std::string, std::string> conf, std::string workDir, unsigned short debug, Base* botptr) : moduleName(modName), workingDir(workDir), config(conf), debugLevel(debug), bot(botptr) {}

Module::~Module() {}
// This is just here because we need a virtual destructor.

inline void Module::sendPrivMsg(const std::string& server, const std::string& client, const std::string& target, const std::string& message) {
	bot->sendPrivMsg(server, client, target, message);
}

inline void Module::sendNotice(const std::string& server, const std::string& client, const std::string& target, const std::string& message) {
	bot->sendNotice(server, client, target, message);
}

inline void Module::sendCTCP(const std::string& server, const std::string& client, const std::string& target, const std::string& ctcp, const std::string& params = "") {
	bot->sendCTCP(server, client, target, ctcp, params);
}

inline void Module::sendCTCPReply(const std::string& server, const std::string& client, const std::string& target, const std::string& ctcp, const std::string& params = "") {
	bot->sendCTCPReply(server, client, target, ctcp, params);
}

inline void Module::setMode(const std::string& server, const std::string& client, const std::string& target, const std::list<std::string>& setModes, const std::list<std::string>& remModes) {
	bot->setMode(server, client, target, setModes, remModes);
}

inline void Module::setSNOmask(const std::string& server, const std::string& client, bool add, char snomask) {
	bot->setSNOmask(server, client, add, snomask);
}

inline void Module::joinChan(const std::string& server, const std::string& client, const std::string& channel, const std::string& key = "") {
	bot->joinChan(server, client, channel, key);
}

inline void Module::partChan(const std::string& server, const std::string& client, const std::string& channel, const std::string& reason) {
	bot->partChan(server, client, channel, reason);
}

inline void Module::kickUser(const std::string& server, const std::string& client, const std::string& channel, const std::string& user, const std::string& reason) {
	bot->kickUser(server, client, channel, user, reason);
}

inline std::string Module::addClient(const std::string& server, std::string& nick, std::string& ident, std::string& host, std::string& gecos) {
	return bot->addClient(server, nick, ident, host, gecos);
}

inline void Module::removeClient(const std::string& server, const std::string& client) {
	bot->removeClient(server, client);
}

inline void Module::setTopic(const std::string& server, const std::string& client, const std::string& channel, const std::string& topic) {
	bot->setTopic(server, client, channel, topic);
}

inline void Module::inviteUser(const std::string& server, const std::string& client, const std::string& channel, const std::string& user) {
	bot->inviteUser(server, client, channel, user);
}

inline void Module::knockOnChannel(const std::string& server, const std::string& client, const std::string& channel, const std::string& reason) {
	bot->knockOnChannel(server, client, channel, reason);
}

inline void Module::changeNick(const std::string& server, const std::string& user, const std::string& newNick) {
	bot->changeNick(server, user, newNick);
}

inline void Module::sendPing(const std::string& server, const std::string& remoteServer) {
	bot->sendPing(server, remoteServer);
}

inline void Module::operUp(const std::string& server, const std::string& client, const std::string& usernameOrType, const std::string& password) {
	bot->operUp(server, client, usernameOrType, password);
}

inline void Module::sendServerNotice(const std::string& server, char snomask, const std::string& message) {
	bot->sendServerNotice(server, snomask, message);
}

inline void Module::setMetadata(const std::string& server, const std::string& target, const std::string& key, const std::string& value) {
	bot->setMetadata(server, target, key, value);
}

inline void Module::setXLine(const std::string& server, const std::string& client, const std::string& lineType, const std::string& mask, time_t duration, const std::string& reason) {
	bot->setXLine(server, client, lineType, mask, duration, reason);
}

inline void Module::remXLine(const std::string& server, const std::string& client, const std::string& lineType, const std::string& mask) {
	bot->remXLine(server, client, lineType, mask);
}

inline void Module::changeIdent(const std::string& server, const std::string& user, const std::string& newIdent) {
	bot->changeIdent(server, user, newIdent);
}

inline void Module::changeHost(const std::string& server, const std::string& user, const std::string& newHost) {
	bot->changeHost(server, user, newHost);
}

inline void Module::changeGecos(const std::string& server, const std::string& user, const std::string& newGecos) {
	bot->changeGecos(server, user, newGecos);
}

inline void Module::sendWallops(const std::string& server, const std::string& client, const std::string& message) {
	bot->sendWallops(server, client, message);
}

inline void Module::sendOtherData(const std::string& server, const std::string& client, const std::string& line) {
	bot->sendOtherData(server, client, line);
}

inline void Module::connectServer(const std::string& server) {
	bot->connectServer(server);
}

inline void Module::disconnectServer(const std::string& server) {
	bot->disconnectServer(server);
}

inline LoadResult Module::loadModule(const std::string& modName) {
	return bot->loadModule(modName);
}

inline void Module::unloadModule(const std::string& modName) {
	if (modName == moduleName)
		std::thread(&Base::unloadModule, bot, modName, true).detach();
	else
		bot->unloadModule(modName, true);
}

inline std::shared_ptr<Socket> Module::assignSocket(const std::string& socketType) {
	return bot->loadSocket(socketType);
}

inline void Module::rehash() {
	bot->rehash();
}

inline unsigned int Module::botVersion() {
	return 2900; // 3.0.0 Pre-alpha Development
}

inline std::list<std::string> Module::activeServers() {
	return bot->activeServers();
}

inline std::list<std::string> Module::connectedServers() {
	return bot->connectedServers();
}

inline std::list<std::string> Module::loadedModules() {
	return bot->loadedModules();
}

inline std::string Module::serverType(const std::string& server) {
	return bot->serverType(server);
}

inline bool Module::serverIsClient(const std::string& server) {
	return bot->serverIsClient(server);
}

inline std::set<std::string> Module::providedServices() {
	return bot->providedServices();
}

inline bool Module::serviceIsProvided(const std::string& service) {
	return bot->serviceIsProvided(service);
}

inline std::list<std::string> Module::serviceProviders(const std::string& service) {
	return bot->serviceProviders(service);
}

inline std::list<std::string> Module::serviceUsers(const std::string& service) {
	return bot->serviceUsers(service);
}

inline void Module::refreshServices() {
	bot->refreshServices(moduleName, this);
}

inline std::list<std::string> Module::networkServerList(const std::string& server) {
	return bot->networkServerList(server);
}

inline std::list<std::string> Module::xLineTypes(const std::string& server) {
	return bot->xLineTypes(server);
}

inline std::list<std::string> Module::xLineList(const std::string& server, const std::string& lineType) {
	return bot->xLineList(server, lineType);
}

inline time_t Module::xLineExpiry(const std::string& server, const std::string& lineType, const std::string& mask) {
	return bot->xLineExpiry(server, lineType, mask);
}

inline std::string Module::xLineReason(const std::string& server, const std::string& lineType, const std::string& mask) {
	return bot->xLineReason(server, lineType, mask);
}

inline std::list<std::string> Module::chanListModes(const std::string& server) {
	return bot->chanListModes(server);
}

inline std::list<std::string> Module::chanParamModes(const std::string& server) {
	return bot->chanParamModes(server);
}

inline std::list<std::string> Module::chanNoParamModes(const std::string& server) {
	return bot->chanNoParamModes(server);
}

inline std::list<std::pair<std::string, char>> Module::chanPrefixes(const std::string& server) {
	return bot->chanPrefixes(server);
}

inline std::pair<std::string, char> Module::compareStatus(const std::string& server, const std::string& status0, const std::string& status1) {
	return bot->compareStatus(server, status0, status1);
}

inline std::pair<std::string, char> Module::compareStatus(const std::string& server, const std::string& status0, char status1) {
	return bot->compareStatus(server, status0, status1);
}

inline std::pair<std::string, char> Module::compareStatus(const std::string& server, char status0, const std::string& status1) {
	return bot->compareStatus(server, status1, status0);
}

inline std::pair<std::string, char> Module::compareStatus(const std::string& server, char status0, char status1) {
	return bot->compareStatus(server, status0, status1);
}

inline std::string Module::chanTopic(const std::string& server, const std::string& channel) {
	return bot->chanTopic(server, channel);
}

inline time_t Module::chanTimestamp(const std::string& server, const std::string& channel) {
	return bot->chanTimestamp(server, channel);
}

inline std::set<std::string> Module::chanUsers(const std::string& server, const std::string& channel) {
	return bot->chanUsers(server, channel);
}

inline bool Module::userInChan(const std::string& server, const std::string& channel, const std::string& user) {
	return bot->userInChan(server, channel, user);
}

inline std::pair<std::string, char> Module::userStatus(const std::string& server, const std::string& channel, const std::string& user) {
	return bot->userStatus(server, channel, user);
}

inline bool Module::userHasStatus(const std::string& server, const std::string& channel, const std::string& user, const std::string& status) {
	return bot->userHasStatus(server, channel, user, status);
}

inline bool Module::userHasStatus(const std::string& server, const std::string& channel, const std::string& user, char status) {
	return bot->userHasStatus(server, channel, user, status);
}

inline bool Module::userHasStatusOrGreater(const std::string& server, const std::string& channel, const std::string& user, const std::string& status) {
	return bot->userHasStatusOrGreater(server, channel, user, status);
}

inline bool Module::userHasStatusOrGreater(const std::string& server, const std::string& channel, const std::string& user, char status) {
	return bot->userHasStatusOrGreater(server, channel, user, status);
}

inline std::list<std::string> Module::chanModes(const std::string& server, const std::string& channel) {
	return bot->chanModes(server, channel);
}

inline std::list<std::string> Module::chanListModeList(const std::string& server, const std::string& channel, const std::string& listMode) {
	return bot->chanListModeList(server, channel, listMode);
}

inline bool Module::chanHasMode(const std::string& server, const std::string& channel, const std::string& mode) {
	return bot->chanHasMode(server, channel, mode);
}

inline std::string Module::chanModeParam(const std::string& server, const std::string& channel, const std::string& mode) {
	return bot->chanModeParam(server, channel, mode);
}

inline std::list<std::string> Module::clientList(const std::string& server) {
	return bot->clientList(server);
}

inline std::string Module::clientNick(const std::string& server, const std::string& client) {
	return bot->clientNick(server, client);
}

inline std::string Module::userIdent(const std::string& server, const std::string& user) {
	return bot->userIdent(server, user);
}

inline std::string Module::userHost(const std::string& server, const std::string& user) {
	return bot->userHost(server, user);
}

inline std::string Module::userGecos(const std::string& server, const std::string& user) {
	return bot->userGecos(server, user);
}

inline std::set<std::string> Module::userModes(const std::string& server, const std::string& user) {
	return bot->userModes(server, user);
}

inline bool Module::userHasMode(const std::string& server, const std::string& user, const std::string& mode) {
	return bot->userHasMode(server, user, mode);
}

inline std::set<char> Module::userSNOmasks(const std::string& server, const std::string& user) {
	return bot->userSNOmasks(server, user);
}

inline bool Module::userHasSNOmask(const std::string& server, const std::string& user, const std::string& mode) {
	return bot->userHasSNOmask(server, user, mode);
}

inline std::set<std::string> Module::userChans(const std::string& server, const std::string& user) {
	return bot->userChans(server, user);
}

inline time_t Module::userTimestamp(const std::string& server, const std::string& user) {
	return bot->userTimestamp(server, user);
}

inline time_t Module::userNickTimestamp(const std::string& server, const std::string& user) {
	return bot->userNickTimestamp(server, user);
}
<commit_msg>Fix the constructor param types of Module to match changes<commit_after>#include "module.h"

Module::Module(const std::string& modName, const std::map<std::string, std::string>& conf, const std::string& workDir, unsigned short debug, Base* botptr) : moduleName(modName), workingDir(workDir), config(conf), debugLevel(debug), bot(botptr) {}

Module::~Module() {}
// This is just here because we need a virtual destructor.

inline void Module::sendPrivMsg(const std::string& server, const std::string& client, const std::string& target, const std::string& message) {
	bot->sendPrivMsg(server, client, target, message);
}

inline void Module::sendNotice(const std::string& server, const std::string& client, const std::string& target, const std::string& message) {
	bot->sendNotice(server, client, target, message);
}

inline void Module::sendCTCP(const std::string& server, const std::string& client, const std::string& target, const std::string& ctcp, const std::string& params = "") {
	bot->sendCTCP(server, client, target, ctcp, params);
}

inline void Module::sendCTCPReply(const std::string& server, const std::string& client, const std::string& target, const std::string& ctcp, const std::string& params = "") {
	bot->sendCTCPReply(server, client, target, ctcp, params);
}

inline void Module::setMode(const std::string& server, const std::string& client, const std::string& target, const std::list<std::string>& setModes, const std::list<std::string>& remModes) {
	bot->setMode(server, client, target, setModes, remModes);
}

inline void Module::setSNOmask(const std::string& server, const std::string& client, bool add, char snomask) {
	bot->setSNOmask(server, client, add, snomask);
}

inline void Module::joinChan(const std::string& server, const std::string& client, const std::string& channel, const std::string& key = "") {
	bot->joinChan(server, client, channel, key);
}

inline void Module::partChan(const std::string& server, const std::string& client, const std::string& channel, const std::string& reason) {
	bot->partChan(server, client, channel, reason);
}

inline void Module::kickUser(const std::string& server, const std::string& client, const std::string& channel, const std::string& user, const std::string& reason) {
	bot->kickUser(server, client, channel, user, reason);
}

inline std::string Module::addClient(const std::string& server, std::string& nick, std::string& ident, std::string& host, std::string& gecos) {
	return bot->addClient(server, nick, ident, host, gecos);
}

inline void Module::removeClient(const std::string& server, const std::string& client) {
	bot->removeClient(server, client);
}

inline void Module::setTopic(const std::string& server, const std::string& client, const std::string& channel, const std::string& topic) {
	bot->setTopic(server, client, channel, topic);
}

inline void Module::inviteUser(const std::string& server, const std::string& client, const std::string& channel, const std::string& user) {
	bot->inviteUser(server, client, channel, user);
}

inline void Module::knockOnChannel(const std::string& server, const std::string& client, const std::string& channel, const std::string& reason) {
	bot->knockOnChannel(server, client, channel, reason);
}

inline void Module::changeNick(const std::string& server, const std::string& user, const std::string& newNick) {
	bot->changeNick(server, user, newNick);
}

inline void Module::sendPing(const std::string& server, const std::string& remoteServer) {
	bot->sendPing(server, remoteServer);
}

inline void Module::operUp(const std::string& server, const std::string& client, const std::string& usernameOrType, const std::string& password) {
	bot->operUp(server, client, usernameOrType, password);
}

inline void Module::sendServerNotice(const std::string& server, char snomask, const std::string& message) {
	bot->sendServerNotice(server, snomask, message);
}

inline void Module::setMetadata(const std::string& server, const std::string& target, const std::string& key, const std::string& value) {
	bot->setMetadata(server, target, key, value);
}

inline void Module::setXLine(const std::string& server, const std::string& client, const std::string& lineType, const std::string& mask, time_t duration, const std::string& reason) {
	bot->setXLine(server, client, lineType, mask, duration, reason);
}

inline void Module::remXLine(const std::string& server, const std::string& client, const std::string& lineType, const std::string& mask) {
	bot->remXLine(server, client, lineType, mask);
}

inline void Module::changeIdent(const std::string& server, const std::string& user, const std::string& newIdent) {
	bot->changeIdent(server, user, newIdent);
}

inline void Module::changeHost(const std::string& server, const std::string& user, const std::string& newHost) {
	bot->changeHost(server, user, newHost);
}

inline void Module::changeGecos(const std::string& server, const std::string& user, const std::string& newGecos) {
	bot->changeGecos(server, user, newGecos);
}

inline void Module::sendWallops(const std::string& server, const std::string& client, const std::string& message) {
	bot->sendWallops(server, client, message);
}

inline void Module::sendOtherData(const std::string& server, const std::string& client, const std::string& line) {
	bot->sendOtherData(server, client, line);
}

inline void Module::connectServer(const std::string& server) {
	bot->connectServer(server);
}

inline void Module::disconnectServer(const std::string& server) {
	bot->disconnectServer(server);
}

inline LoadResult Module::loadModule(const std::string& modName) {
	return bot->loadModule(modName);
}

inline void Module::unloadModule(const std::string& modName) {
	if (modName == moduleName)
		std::thread(&Base::unloadModule, bot, modName, true).detach();
	else
		bot->unloadModule(modName, true);
}

inline std::shared_ptr<Socket> Module::assignSocket(const std::string& socketType) {
	return bot->loadSocket(socketType);
}

inline void Module::rehash() {
	bot->rehash();
}

inline unsigned int Module::botVersion() {
	return 2900; // 3.0.0 Pre-alpha Development
}

inline std::list<std::string> Module::activeServers() {
	return bot->activeServers();
}

inline std::list<std::string> Module::connectedServers() {
	return bot->connectedServers();
}

inline std::list<std::string> Module::loadedModules() {
	return bot->loadedModules();
}

inline std::string Module::serverType(const std::string& server) {
	return bot->serverType(server);
}

inline bool Module::serverIsClient(const std::string& server) {
	return bot->serverIsClient(server);
}

inline std::set<std::string> Module::providedServices() {
	return bot->providedServices();
}

inline bool Module::serviceIsProvided(const std::string& service) {
	return bot->serviceIsProvided(service);
}

inline std::list<std::string> Module::serviceProviders(const std::string& service) {
	return bot->serviceProviders(service);
}

inline std::list<std::string> Module::serviceUsers(const std::string& service) {
	return bot->serviceUsers(service);
}

inline void Module::refreshServices() {
	bot->refreshServices(moduleName, this);
}

inline std::list<std::string> Module::networkServerList(const std::string& server) {
	return bot->networkServerList(server);
}

inline std::list<std::string> Module::xLineTypes(const std::string& server) {
	return bot->xLineTypes(server);
}

inline std::list<std::string> Module::xLineList(const std::string& server, const std::string& lineType) {
	return bot->xLineList(server, lineType);
}

inline time_t Module::xLineExpiry(const std::string& server, const std::string& lineType, const std::string& mask) {
	return bot->xLineExpiry(server, lineType, mask);
}

inline std::string Module::xLineReason(const std::string& server, const std::string& lineType, const std::string& mask) {
	return bot->xLineReason(server, lineType, mask);
}

inline std::list<std::string> Module::chanListModes(const std::string& server) {
	return bot->chanListModes(server);
}

inline std::list<std::string> Module::chanParamModes(const std::string& server) {
	return bot->chanParamModes(server);
}

inline std::list<std::string> Module::chanNoParamModes(const std::string& server) {
	return bot->chanNoParamModes(server);
}

inline std::list<std::pair<std::string, char>> Module::chanPrefixes(const std::string& server) {
	return bot->chanPrefixes(server);
}

inline std::pair<std::string, char> Module::compareStatus(const std::string& server, const std::string& status0, const std::string& status1) {
	return bot->compareStatus(server, status0, status1);
}

inline std::pair<std::string, char> Module::compareStatus(const std::string& server, const std::string& status0, char status1) {
	return bot->compareStatus(server, status0, status1);
}

inline std::pair<std::string, char> Module::compareStatus(const std::string& server, char status0, const std::string& status1) {
	return bot->compareStatus(server, status1, status0);
}

inline std::pair<std::string, char> Module::compareStatus(const std::string& server, char status0, char status1) {
	return bot->compareStatus(server, status0, status1);
}

inline std::string Module::chanTopic(const std::string& server, const std::string& channel) {
	return bot->chanTopic(server, channel);
}

inline time_t Module::chanTimestamp(const std::string& server, const std::string& channel) {
	return bot->chanTimestamp(server, channel);
}

inline std::set<std::string> Module::chanUsers(const std::string& server, const std::string& channel) {
	return bot->chanUsers(server, channel);
}

inline bool Module::userInChan(const std::string& server, const std::string& channel, const std::string& user) {
	return bot->userInChan(server, channel, user);
}

inline std::pair<std::string, char> Module::userStatus(const std::string& server, const std::string& channel, const std::string& user) {
	return bot->userStatus(server, channel, user);
}

inline bool Module::userHasStatus(const std::string& server, const std::string& channel, const std::string& user, const std::string& status) {
	return bot->userHasStatus(server, channel, user, status);
}

inline bool Module::userHasStatus(const std::string& server, const std::string& channel, const std::string& user, char status) {
	return bot->userHasStatus(server, channel, user, status);
}

inline bool Module::userHasStatusOrGreater(const std::string& server, const std::string& channel, const std::string& user, const std::string& status) {
	return bot->userHasStatusOrGreater(server, channel, user, status);
}

inline bool Module::userHasStatusOrGreater(const std::string& server, const std::string& channel, const std::string& user, char status) {
	return bot->userHasStatusOrGreater(server, channel, user, status);
}

inline std::list<std::string> Module::chanModes(const std::string& server, const std::string& channel) {
	return bot->chanModes(server, channel);
}

inline std::list<std::string> Module::chanListModeList(const std::string& server, const std::string& channel, const std::string& listMode) {
	return bot->chanListModeList(server, channel, listMode);
}

inline bool Module::chanHasMode(const std::string& server, const std::string& channel, const std::string& mode) {
	return bot->chanHasMode(server, channel, mode);
}

inline std::string Module::chanModeParam(const std::string& server, const std::string& channel, const std::string& mode) {
	return bot->chanModeParam(server, channel, mode);
}

inline std::list<std::string> Module::clientList(const std::string& server) {
	return bot->clientList(server);
}

inline std::string Module::clientNick(const std::string& server, const std::string& client) {
	return bot->clientNick(server, client);
}

inline std::string Module::userIdent(const std::string& server, const std::string& user) {
	return bot->userIdent(server, user);
}

inline std::string Module::userHost(const std::string& server, const std::string& user) {
	return bot->userHost(server, user);
}

inline std::string Module::userGecos(const std::string& server, const std::string& user) {
	return bot->userGecos(server, user);
}

inline std::set<std::string> Module::userModes(const std::string& server, const std::string& user) {
	return bot->userModes(server, user);
}

inline bool Module::userHasMode(const std::string& server, const std::string& user, const std::string& mode) {
	return bot->userHasMode(server, user, mode);
}

inline std::set<char> Module::userSNOmasks(const std::string& server, const std::string& user) {
	return bot->userSNOmasks(server, user);
}

inline bool Module::userHasSNOmask(const std::string& server, const std::string& user, const std::string& mode) {
	return bot->userHasSNOmask(server, user, mode);
}

inline std::set<std::string> Module::userChans(const std::string& server, const std::string& user) {
	return bot->userChans(server, user);
}

inline time_t Module::userTimestamp(const std::string& server, const std::string& user) {
	return bot->userTimestamp(server, user);
}

inline time_t Module::userNickTimestamp(const std::string& server, const std::string& user) {
	return bot->userNickTimestamp(server, user);
}
<|endoftext|>


<commit_before>#include "../config.h"

#include <iostream>
#include <fstream>
#include <getopt.h>
#include <netinet/in.h>
#include <ev.h>
#include <sysexits.h>

#include "../Socket/Socket.hxx"
#include "../Log/TimestampLog.hxx"

static const size_t READ_SIZE = 4096;
static const int MAX_CONN_BACKLOG = 32;

std::string logfilename;
std::ofstream logfile;
std::auto_ptr<std::ostream> log;

std::auto_ptr<SockAddr::SockAddr> bind_addr_outgoing;

void received_sigint(EV_P_ ev_signal *w, int revents) throw() {
	*log << "Received SIGINT, exiting\n" << std::flush;
	ev_break(EV_A_ EVUNLOOP_ALL);
}
void received_sigterm(EV_P_ ev_signal *w, int revents) throw() {
	*log << "Received SIGTERM, exiting\n" << std::flush;
	ev_break(EV_A_ EVUNLOOP_ALL);
}

void received_sighup(EV_P_ ev_signal *w, int revents) throw() {
	*log << "Received SIGHUP, closing this logfile\n" << std::flush;
	logfile.close();
	logfile.open(logfilename.c_str(), std::ios_base::app | std::ios_base::out );
	*log << "Received SIGHUP, (re)opening this logfile\n" << std::flush;
}

static void listening_socket_ready_for_read(EV_P_ ev_io *w, int revents) {
	Socket* socket = reinterpret_cast<Socket*>( w->data );

	std::auto_ptr<SockAddr::SockAddr> client_addr;
	Socket client_socket = socket->accept(&client_addr);

	std::auto_ptr<SockAddr::SockAddr> server_addr;
	server_addr = client_socket.getsockname();

	*log << "Connection intercepted "
	     << client_addr->string() << "-->"
	     << server_addr->string() << "\n" << std::flush;

	Socket server_socket = Socket::socket(AF_INET, SOCK_STREAM, 0);

	if( bind_addr_outgoing.get() != NULL ) {
		server_socket.bind( *bind_addr_outgoing );
		*log << "Connecting " << bind_addr_outgoing->string()
		    << "-->";
	} else {
#if HAVE_DECL_IP_TRANSPARENT
		int value = 1;
		server_socket.setsockopt(SOL_IP, IP_TRANSPARENT, &value, sizeof(value));
#endif
		server_socket.bind( *client_addr );
		*log << "Connecting " << client_addr->string()
		    << "-->";
	}
	*log << server_addr->string() << "\n" << std::flush;

	server_socket.connect( *server_addr );

	// TODO: keep client_socket around
	// TODO: keep server_socket around
	// TODO: connect these sockets
	// TODO: make connect async
}

int main(int argc, char* argv[]) {
	// Defaults
	struct {
		bool fork;
		std::string pid_file;
		std::string bind_addr_listen;
		std::string bind_addr_outgoing;
	} options = {
		/* fork = */ true,
		/* pid_file = */ "",
		/* bind_addr_listen = */ "[0.0.0.0]:[5000]",
		/* bind_addr_outgoing = */ "[0.0.0.0]:[0]"
		};
	log.reset( new TimestampLog( std::cerr ) );

	{ // Parse options
		char optstring[] = "?hVfp:b:B:l:";
		struct option longopts[] = {
			{"help",			no_argument, NULL, '?'},
			{"version",			no_argument, NULL, 'V'},
			{"forgeground",		no_argument, NULL, 'f'},
			{"pid-file",		required_argument, NULL, 'p'},
			{"bind-listen",		required_argument, NULL, 'b'},
			{"bind-outgoing",	required_argument, NULL, 'B'},
			{"log",				required_argument, NULL, 'l'},
			{NULL, 0, 0, 0}
		};
		int longindex;
		int opt;
		while( (opt = getopt_long(argc, argv, optstring, longopts, &longindex)) != -1 ) {
			switch(opt) {
			case '?':
			case 'h':
				std::cerr <<
				//  >---------------------- Standard terminal width ---------------------------------<
					"Options:\n"
					"  -h -? --help                    Displays this help message and exits\n"
					"  -V --version                    Displays the version and exits\n"
					"  --foreground -f                 Don't fork into the background after init\n"
					"  --pid-file -p file              The file to write the PID to, especially\n"
					"                                  usefull when running as a daemon\n"
					"  --bind-listen -b host:port      Bind to the specified address for incomming\n"
					"                                  connections.\n"
					"                                  host and port resolving can be bypassed by\n"
					"                                  placing [] around them\n"
					"  --bind-outgoing -b host:port    Bind to the specified address for outgoing\n"
					"                                  connections.\n"
					"                                  host and port resolving can be bypassed by\n"
					"                                  placing [] around them\n"
					"                                  the special string \"client\" can be used to\n"
					"                                  reuse the client's source address. Note that\n"
					"                                  you should take care that the return packets\n"
					"                                  pass through this process again!\n"
					"  --log -l file                   Log to file\n"
					;
				exit(EX_USAGE);
			case 'V':
				std::cout << PACKAGE_NAME << " version " << PACKAGE_VERSION
				          << " (" << PACKAGE_GITREVISION << ")\n";
				exit(EX_OK);
			case 'f':
				options.fork = false;
				break;
			case 'p':
				options.pid_file = optarg;
				break;
			case 'b':
				options.bind_addr_listen = optarg;
				break;
			case 'B':
				options.bind_addr_outgoing = optarg;
				break;
			case 'l':
				logfilename = optarg;
				logfile.open(logfilename.c_str(), std::ios_base::app | std::ios_base::out );
				log.reset( new TimestampLog( logfile ) );
				break;
			}
		}
	}

	*log << "Parsed options, opening listening socket on "
	     << options.bind_addr_listen << "\n" << std::flush;

	Socket s_listen;
	{ // Open listening socket
		std::string host, port;

		/* Address format is
		 *   - hostname:portname
		 *   - [numeric ip]:portname
		 *   - hostname:[portnumber]
		 *   - [numeric ip]:[portnumber]
		 */
		size_t c = options.bind_addr_listen.rfind(":");
		if( c == std::string::npos ) {
			std::cerr << "Invalid bind string \"" << options.bind_addr_listen << "\": could not find ':'\n";
			exit(EX_DATAERR);
		}
		host = options.bind_addr_listen.substr(0, c);
		port = options.bind_addr_listen.substr(c+1);

		std::auto_ptr< boost::ptr_vector< SockAddr::SockAddr> > bind_sa
			= SockAddr::resolve( host, port, 0, SOCK_STREAM, 0);
		if( bind_sa->size() == 0 ) {
			std::cerr << "Can not bind to \"" << options.bind_addr_listen << "\": Could not resolve\n";
			exit(EX_DATAERR);
		} else if( bind_sa->size() > 1 ) {
			// TODO: allow this
			std::cerr << "Can not bind to \"" << options.bind_addr_listen << "\": Resolves to multiple entries:\n";
			for( typeof(bind_sa->begin()) i = bind_sa->begin(); i != bind_sa->end(); i++ ) {
				std::cerr << "  " << i->string() << "\n";
			}
			exit(EX_DATAERR);
		}
		s_listen = Socket::socket( (*bind_sa)[0].proto_family() , SOCK_STREAM, 0);
		s_listen.set_reuseaddr();
		s_listen.bind((*bind_sa)[0]);
		s_listen.listen(MAX_CONN_BACKLOG);

#if HAVE_DECL_IP_TRANSPARENT
		int value = 1;
		s_listen.setsockopt(SOL_IP, IP_TRANSPARENT, &value, sizeof(value));
#endif

		*log << "Listening on " << (*bind_sa)[0].string() << "\n" << std::flush;
	}

	if( options.bind_addr_outgoing == "client" ) {
		bind_addr_outgoing.reset(NULL);
	} else { // Resolve client address
		std::string host, port;

		/* Address format is
		 *   - hostname:portname
		 *   - [numeric ip]:portname
		 *   - hostname:[portnumber]
		 *   - [numeric ip]:[portnumber]
		 */
		size_t c = options.bind_addr_outgoing.rfind(":");
		if( c == std::string::npos ) {
			std::cerr << "Invalid bind string \"" << options.bind_addr_outgoing << "\": could not find ':'\n";
			exit(EX_DATAERR);
		}
		host = options.bind_addr_outgoing.substr(0, c);
		port = options.bind_addr_outgoing.substr(c+1);

		std::auto_ptr< boost::ptr_vector< SockAddr::SockAddr> > bind_sa
			= SockAddr::resolve( host, port, 0, SOCK_STREAM, 0);
		if( bind_sa->size() == 0 ) {
			std::cerr << "Can not bind to \"" << options.bind_addr_outgoing << "\": Could not resolve\n";
			exit(EX_DATAERR);
		} else if( bind_sa->size() > 1 ) {
			std::cerr << "Can not bind to \"" << options.bind_addr_outgoing << "\": Resolves to multiple entries:\n";
			for( typeof(bind_sa->begin()) i = bind_sa->begin(); i != bind_sa->end(); i++ ) {
				std::cerr << "  " << i->string() << "\n";
			}
			exit(EX_DATAERR);
		}
		bind_addr_outgoing.reset( bind_sa->release(bind_sa->begin()).release() ); // Transfer ownership; TODO: this should be simpeler that double release()

		*log << "Outgoing connections will connect from "
		     << bind_addr_outgoing->string() << "\n" << std::flush;
	}

	{
		ev_signal ev_sigint_watcher;
		ev_signal_init( &ev_sigint_watcher, received_sigint, SIGINT);
		ev_signal_start( EV_DEFAULT_ &ev_sigint_watcher);
		ev_signal ev_sigterm_watcher;
		ev_signal_init( &ev_sigterm_watcher, received_sigterm, SIGTERM);
		ev_signal_start( EV_DEFAULT_ &ev_sigterm_watcher);

		ev_signal ev_sighup_watcher;
		ev_signal_init( &ev_sighup_watcher, received_sighup, SIGHUP);
		ev_signal_start( EV_DEFAULT_ &ev_sighup_watcher);

		ev_io e_listen;
		e_listen.data = &s_listen;
		ev_io_init( &e_listen, listening_socket_ready_for_read, s_listen, EV_READ );
		ev_io_start( EV_DEFAULT_ &e_listen );

		*log << "Setup done, starting event loop\n" << std::flush;
		ev_run(EV_DEFAULT_ 0);
	}

	*log << "Exiting...\n" << std::flush;
	return 0;
}
<commit_msg>help-option should not return EX_USAGE<commit_after>#include "../config.h"

#include <iostream>
#include <fstream>
#include <getopt.h>
#include <netinet/in.h>
#include <ev.h>
#include <sysexits.h>

#include "../Socket/Socket.hxx"
#include "../Log/TimestampLog.hxx"

static const size_t READ_SIZE = 4096;
static const int MAX_CONN_BACKLOG = 32;

std::string logfilename;
std::ofstream logfile;
std::auto_ptr<std::ostream> log;

std::auto_ptr<SockAddr::SockAddr> bind_addr_outgoing;

void received_sigint(EV_P_ ev_signal *w, int revents) throw() {
	*log << "Received SIGINT, exiting\n" << std::flush;
	ev_break(EV_A_ EVUNLOOP_ALL);
}
void received_sigterm(EV_P_ ev_signal *w, int revents) throw() {
	*log << "Received SIGTERM, exiting\n" << std::flush;
	ev_break(EV_A_ EVUNLOOP_ALL);
}

void received_sighup(EV_P_ ev_signal *w, int revents) throw() {
	*log << "Received SIGHUP, closing this logfile\n" << std::flush;
	logfile.close();
	logfile.open(logfilename.c_str(), std::ios_base::app | std::ios_base::out );
	*log << "Received SIGHUP, (re)opening this logfile\n" << std::flush;
}

static void listening_socket_ready_for_read(EV_P_ ev_io *w, int revents) {
	Socket* socket = reinterpret_cast<Socket*>( w->data );

	std::auto_ptr<SockAddr::SockAddr> client_addr;
	Socket client_socket = socket->accept(&client_addr);

	std::auto_ptr<SockAddr::SockAddr> server_addr;
	server_addr = client_socket.getsockname();

	*log << "Connection intercepted "
	     << client_addr->string() << "-->"
	     << server_addr->string() << "\n" << std::flush;

	Socket server_socket = Socket::socket(AF_INET, SOCK_STREAM, 0);

	if( bind_addr_outgoing.get() != NULL ) {
		server_socket.bind( *bind_addr_outgoing );
		*log << "Connecting " << bind_addr_outgoing->string()
		    << "-->";
	} else {
#if HAVE_DECL_IP_TRANSPARENT
		int value = 1;
		server_socket.setsockopt(SOL_IP, IP_TRANSPARENT, &value, sizeof(value));
#endif
		server_socket.bind( *client_addr );
		*log << "Connecting " << client_addr->string()
		    << "-->";
	}
	*log << server_addr->string() << "\n" << std::flush;

	server_socket.connect( *server_addr );

	// TODO: keep client_socket around
	// TODO: keep server_socket around
	// TODO: connect these sockets
	// TODO: make connect async
}

int main(int argc, char* argv[]) {
	// Default options
	struct {
		bool fork;
		std::string pid_file;
		std::string bind_addr_listen;
		std::string bind_addr_outgoing;
	} options = {
		/* fork = */ true,
		/* pid_file = */ "",
		/* bind_addr_listen = */ "[0.0.0.0]:[5000]",
		/* bind_addr_outgoing = */ "[0.0.0.0]:[0]"
		};
	log.reset( new TimestampLog( std::cerr ) );

	{ // Parse options
		char optstring[] = "hVfp:b:B:l:";
		struct option longopts[] = {
			{"help",			no_argument, NULL, 'h'},
			{"version",			no_argument, NULL, 'V'},
			{"forgeground",		no_argument, NULL, 'f'},
			{"pid-file",		required_argument, NULL, 'p'},
			{"bind-listen",		required_argument, NULL, 'b'},
			{"bind-outgoing",	required_argument, NULL, 'B'},
			{"log",				required_argument, NULL, 'l'},
			{NULL, 0, 0, 0}
		};
		int longindex;
		int opt;
		while( (opt = getopt_long(argc, argv, optstring, longopts, &longindex)) != -1 ) {
			switch(opt) {
			case '?':
			case 'h':
				std::cerr <<
				//  >---------------------- Standard terminal width ---------------------------------<
					"Options:\n"
					"  -h -? --help                    Displays this help message and exits\n"
					"  -V --version                    Displays the version and exits\n"
					"  --foreground -f                 Don't fork into the background after init\n"
					"  --pid-file -p file              The file to write the PID to, especially\n"
					"                                  usefull when running as a daemon\n"
					"  --bind-listen -b host:port      Bind to the specified address for incomming\n"
					"                                  connections.\n"
					"                                  host and port resolving can be bypassed by\n"
					"                                  placing [] around them\n"
					"  --bind-outgoing -b host:port    Bind to the specified address for outgoing\n"
					"                                  connections.\n"
					"                                  host and port resolving can be bypassed by\n"
					"                                  placing [] around them\n"
					"                                  the special string \"client\" can be used to\n"
					"                                  reuse the client's source address. Note that\n"
					"                                  you should take care that the return packets\n"
					"                                  pass through this process again!\n"
					"  --log -l file                   Log to file\n"
					;
				if( opt == '?' ) exit(EX_USAGE);
				exit(EX_OK);
			case 'V':
				std::cout << PACKAGE_NAME << " version " << PACKAGE_VERSION
				          << " (" << PACKAGE_GITREVISION << ")\n";
				exit(EX_OK);
			case 'f':
				options.fork = false;
				break;
			case 'p':
				options.pid_file = optarg;
				break;
			case 'b':
				options.bind_addr_listen = optarg;
				break;
			case 'B':
				options.bind_addr_outgoing = optarg;
				break;
			case 'l':
				logfilename = optarg;
				logfile.open(logfilename.c_str(), std::ios_base::app | std::ios_base::out );
				log.reset( new TimestampLog( logfile ) );
				break;
			}
		}
	}

	*log << "Parsed options, opening listening socket on "
	     << options.bind_addr_listen << "\n" << std::flush;

	Socket s_listen;
	{ // Open listening socket
		std::string host, port;

		/* Address format is
		 *   - hostname:portname
		 *   - [numeric ip]:portname
		 *   - hostname:[portnumber]
		 *   - [numeric ip]:[portnumber]
		 */
		size_t c = options.bind_addr_listen.rfind(":");
		if( c == std::string::npos ) {
			std::cerr << "Invalid bind string \"" << options.bind_addr_listen << "\": could not find ':'\n";
			exit(EX_DATAERR);
		}
		host = options.bind_addr_listen.substr(0, c);
		port = options.bind_addr_listen.substr(c+1);

		std::auto_ptr< boost::ptr_vector< SockAddr::SockAddr> > bind_sa
			= SockAddr::resolve( host, port, 0, SOCK_STREAM, 0);
		if( bind_sa->size() == 0 ) {
			std::cerr << "Can not bind to \"" << options.bind_addr_listen << "\": Could not resolve\n";
			exit(EX_DATAERR);
		} else if( bind_sa->size() > 1 ) {
			// TODO: allow this
			std::cerr << "Can not bind to \"" << options.bind_addr_listen << "\": Resolves to multiple entries:\n";
			for( typeof(bind_sa->begin()) i = bind_sa->begin(); i != bind_sa->end(); i++ ) {
				std::cerr << "  " << i->string() << "\n";
			}
			exit(EX_DATAERR);
		}
		s_listen = Socket::socket( (*bind_sa)[0].proto_family() , SOCK_STREAM, 0);
		s_listen.set_reuseaddr();
		s_listen.bind((*bind_sa)[0]);
		s_listen.listen(MAX_CONN_BACKLOG);

#if HAVE_DECL_IP_TRANSPARENT
		int value = 1;
		s_listen.setsockopt(SOL_IP, IP_TRANSPARENT, &value, sizeof(value));
#endif

		*log << "Listening on " << (*bind_sa)[0].string() << "\n" << std::flush;
	}

	if( options.bind_addr_outgoing == "client" ) {
		bind_addr_outgoing.reset(NULL);
	} else { // Resolve client address
		std::string host, port;

		/* Address format is
		 *   - hostname:portname
		 *   - [numeric ip]:portname
		 *   - hostname:[portnumber]
		 *   - [numeric ip]:[portnumber]
		 */
		size_t c = options.bind_addr_outgoing.rfind(":");
		if( c == std::string::npos ) {
			std::cerr << "Invalid bind string \"" << options.bind_addr_outgoing << "\": could not find ':'\n";
			exit(EX_DATAERR);
		}
		host = options.bind_addr_outgoing.substr(0, c);
		port = options.bind_addr_outgoing.substr(c+1);

		std::auto_ptr< boost::ptr_vector< SockAddr::SockAddr> > bind_sa
			= SockAddr::resolve( host, port, 0, SOCK_STREAM, 0);
		if( bind_sa->size() == 0 ) {
			std::cerr << "Can not bind to \"" << options.bind_addr_outgoing << "\": Could not resolve\n";
			exit(EX_DATAERR);
		} else if( bind_sa->size() > 1 ) {
			std::cerr << "Can not bind to \"" << options.bind_addr_outgoing << "\": Resolves to multiple entries:\n";
			for( typeof(bind_sa->begin()) i = bind_sa->begin(); i != bind_sa->end(); i++ ) {
				std::cerr << "  " << i->string() << "\n";
			}
			exit(EX_DATAERR);
		}
		bind_addr_outgoing.reset( bind_sa->release(bind_sa->begin()).release() ); // Transfer ownership; TODO: this should be simpeler that double release()

		*log << "Outgoing connections will connect from "
		     << bind_addr_outgoing->string() << "\n" << std::flush;
	}

	{
		ev_signal ev_sigint_watcher;
		ev_signal_init( &ev_sigint_watcher, received_sigint, SIGINT);
		ev_signal_start( EV_DEFAULT_ &ev_sigint_watcher);
		ev_signal ev_sigterm_watcher;
		ev_signal_init( &ev_sigterm_watcher, received_sigterm, SIGTERM);
		ev_signal_start( EV_DEFAULT_ &ev_sigterm_watcher);

		ev_signal ev_sighup_watcher;
		ev_signal_init( &ev_sighup_watcher, received_sighup, SIGHUP);
		ev_signal_start( EV_DEFAULT_ &ev_sighup_watcher);

		ev_io e_listen;
		e_listen.data = &s_listen;
		ev_io_init( &e_listen, listening_socket_ready_for_read, s_listen, EV_READ );
		ev_io_start( EV_DEFAULT_ &e_listen );

		*log << "Setup done, starting event loop\n" << std::flush;
		ev_run(EV_DEFAULT_ 0);
	}

	*log << "Exiting...\n" << std::flush;
	return 0;
}
<|endoftext|>


<commit_before>/*
   The MIT License (MIT)

   Copyright (c) 2014 Antonio SJ Musumeci <trapexit@spawn.link>

   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.
*/

#ifndef __POLICY_HPP__
#define __POLICY_HPP__

#include <string>
#include <vector>
#include <map>

#include "fs.hpp"
#include "category.hpp"

namespace mergerfs
{
  class Policy
  {
  public:
    struct Enum
    {
      enum Type
        {
          invalid = -1,
          BEGIN   = 0,
          all     = BEGIN,
          einval,
          enosys,
          enotsup,
          epmfs,
          erofs,
          exdev,
          ff,
          ffwp,
          fwfs,
          lfs,
          mfs,
          newest,
          rand,
          END
        };

      static size_t begin() { return BEGIN; }
      static size_t end()   { return END; }
    };

    struct Func
    {
      typedef std::string string;
      typedef std::size_t size_t;
      typedef std::vector<string> strvec;
      typedef const string cstring;
      typedef const size_t csize_t;
      typedef const strvec cstrvec;
      typedef const Category::Enum::Type CType;

      typedef int (*Ptr)(CType,cstrvec&,cstring&,csize_t,strvec&);

      class Action
      {
      public:
        Action(const Policy *p)
          : func(p->_func)
        {}

        int
        operator()(cstrvec& b,cstring& c,csize_t d,strvec& e)
        {
          return func(Category::Enum::action,b,c,d,e);
        }

      private:
        const Ptr func;
      };

      class Create
      {
      public:
        Create(const Policy *p)
          : func(p->_func)
        {}

        int
        operator()(cstrvec& b,cstring& c,csize_t d,strvec& e)
        {
          return func(Category::Enum::create,b,c,d,e);
        }

      private:
        const Ptr func;
      };

      class Search
      {
      public:
        Search(const Policy *p)
          : func(p->_func)
        {}

        int
        operator()(cstrvec& b,cstring& c,csize_t d,strvec& e)
        {
          return func(Category::Enum::search,b,c,d,e);
        }

      private:
        const Ptr func;
      };

      static int all(CType,cstrvec&,cstring&,csize_t,strvec&);
      static int einval(CType,cstrvec&,cstring&,csize_t,strvec&);
      static int enosys(CType,cstrvec&,cstring&,csize_t,strvec&);
      static int enotsup(CType,cstrvec&,cstring&,csize_t,strvec&);
      static int epmfs(CType,cstrvec&,cstring&,csize_t,strvec&);
      static int erofs(CType,cstrvec&,cstring&,csize_t,strvec&);
      static int exdev(CType,cstrvec&,cstring&,csize_t,strvec&);
      static int ff(CType,cstrvec&,cstring&,csize_t,strvec&);
      static int ffwp(CType,cstrvec&,cstring&,csize_t,strvec&);
      static int fwfs(CType,cstrvec&,cstring&,csize_t,strvec&);
      static int invalid(CType,cstrvec&,cstring&,csize_t,strvec&);
      static int lfs(CType,cstrvec&,cstring&,csize_t,strvec&);
      static int mfs(CType,cstrvec&,cstring&,csize_t,strvec&);
      static int newest(CType,cstrvec&,cstring&,csize_t,strvec&);
      static int rand(CType,cstrvec&,cstring&,csize_t,strvec&);
    };

  private:
    Enum::Type  _enum;
    std::string _str;
    Func::Ptr   _func;

  public:
    Policy()
      : _enum(invalid),
        _str(invalid),
        _func(invalid)
    {
    }

    Policy(const Enum::Type   enum_,
           const std::string &str_,
           const Func::Ptr    func_)
      : _enum(enum_),
        _str(str_),
        _func(func_)
    {
    }

  public:
    operator const Enum::Type() const { return _enum; }
    operator const std::string&() const { return _str; }
    operator const Func::Ptr() const { return _func; }
    operator const Policy*() const { return this; }

    bool operator==(const Enum::Type enum_) const
    { return _enum == enum_; }
    bool operator==(const std::string &str_) const
    { return _str == str_; }
    bool operator==(const Func::Ptr func_) const
    { return _func == func_; }

    bool operator!=(const Policy &r) const
    { return _enum != r._enum; }

    bool operator<(const Policy &r) const
    { return _enum < r._enum; }

  public:
    static const Policy &find(const std::string&);
    static const Policy &find(const Enum::Type);

  public:
    static const std::vector<Policy>  _policies_;
    static const Policy * const       policies;

    static const Policy &invalid;
    static const Policy &all;
    static const Policy &einval;
    static const Policy &enosys;
    static const Policy &enotsup;
    static const Policy &epmfs;
    static const Policy &erofs;
    static const Policy &exdev;
    static const Policy &ff;
    static const Policy &ffwp;
    static const Policy &fwfs;
    static const Policy &lfs;
    static const Policy &mfs;
    static const Policy &newest;
    static const Policy &rand;
  };
}

#endif
<commit_msg>change to using template for policy class<commit_after>/*
   The MIT License (MIT)

   Copyright (c) 2014 Antonio SJ Musumeci <trapexit@spawn.link>

   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.
*/

#ifndef __POLICY_HPP__
#define __POLICY_HPP__

#include <string>
#include <vector>
#include <map>

#include "fs.hpp"
#include "category.hpp"

namespace mergerfs
{
  class Policy
  {
  public:
    struct Enum
    {
      enum Type
        {
          invalid = -1,
          BEGIN   = 0,
          all     = BEGIN,
          einval,
          enosys,
          enotsup,
          epmfs,
          erofs,
          exdev,
          ff,
          ffwp,
          fwfs,
          lfs,
          mfs,
          newest,
          rand,
          END
        };

      static size_t begin() { return BEGIN; }
      static size_t end()   { return END; }
    };

    struct Func
    {
      typedef std::string string;
      typedef std::size_t size_t;
      typedef std::vector<string> strvec;
      typedef const string cstring;
      typedef const size_t csize_t;
      typedef const strvec cstrvec;
      typedef const Category::Enum::Type CType;

      typedef int (*Ptr)(CType,cstrvec&,cstring&,csize_t,strvec&);

      template <CType T>
      class Base
      {
      public:
        Base(const Policy *p)
          : func(p->_func)
        {}

        int
        operator()(cstrvec& b,cstring& c,csize_t d,strvec& e)
        {
          return func(T,b,c,d,e);
        }

        int
        operator()(cstrvec& b,cstring& c,csize_t d,string& e)
        {
          int rv;
          strvec vec;

          rv = func(T,b,c,d,vec);
          if(!vec.empty())
            e = vec[0];

          return rv;
        }

      private:
        const Ptr func;
      };

      typedef Base<Category::Enum::action> Action;
      typedef Base<Category::Enum::create> Create;
      typedef Base<Category::Enum::search> Search;

      static int all(CType,cstrvec&,cstring&,csize_t,strvec&);
      static int einval(CType,cstrvec&,cstring&,csize_t,strvec&);
      static int enosys(CType,cstrvec&,cstring&,csize_t,strvec&);
      static int enotsup(CType,cstrvec&,cstring&,csize_t,strvec&);
      static int epmfs(CType,cstrvec&,cstring&,csize_t,strvec&);
      static int erofs(CType,cstrvec&,cstring&,csize_t,strvec&);
      static int exdev(CType,cstrvec&,cstring&,csize_t,strvec&);
      static int ff(CType,cstrvec&,cstring&,csize_t,strvec&);
      static int ffwp(CType,cstrvec&,cstring&,csize_t,strvec&);
      static int fwfs(CType,cstrvec&,cstring&,csize_t,strvec&);
      static int invalid(CType,cstrvec&,cstring&,csize_t,strvec&);
      static int lfs(CType,cstrvec&,cstring&,csize_t,strvec&);
      static int mfs(CType,cstrvec&,cstring&,csize_t,strvec&);
      static int newest(CType,cstrvec&,cstring&,csize_t,strvec&);
      static int rand(CType,cstrvec&,cstring&,csize_t,strvec&);
    };

  private:
    Enum::Type  _enum;
    std::string _str;
    Func::Ptr   _func;

  public:
    Policy()
      : _enum(invalid),
        _str(invalid),
        _func(invalid)
    {
    }

    Policy(const Enum::Type   enum_,
           const std::string &str_,
           const Func::Ptr    func_)
      : _enum(enum_),
        _str(str_),
        _func(func_)
    {
    }

  public:
    operator const Enum::Type() const { return _enum; }
    operator const std::string&() const { return _str; }
    operator const Func::Ptr() const { return _func; }
    operator const Policy*() const { return this; }

    bool operator==(const Enum::Type enum_) const
    { return _enum == enum_; }
    bool operator==(const std::string &str_) const
    { return _str == str_; }
    bool operator==(const Func::Ptr func_) const
    { return _func == func_; }

    bool operator!=(const Policy &r) const
    { return _enum != r._enum; }

    bool operator<(const Policy &r) const
    { return _enum < r._enum; }

  public:
    static const Policy &find(const std::string&);
    static const Policy &find(const Enum::Type);

  public:
    static const std::vector<Policy>  _policies_;
    static const Policy * const       policies;

    static const Policy &invalid;
    static const Policy &all;
    static const Policy &einval;
    static const Policy &enosys;
    static const Policy &enotsup;
    static const Policy &epmfs;
    static const Policy &erofs;
    static const Policy &exdev;
    static const Policy &ff;
    static const Policy &ffwp;
    static const Policy &fwfs;
    static const Policy &lfs;
    static const Policy &mfs;
    static const Policy &newest;
    static const Policy &rand;
  };
}

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2015-2017 The Silk Network developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <boost/assign/list_of.hpp> // for 'map_list_of()'

#include "proofs.h"

#include "chainparams.h"
#include "main.h"
#include "uint256.h"
#include "util.h"
#include "amount.h"
#include "checkpoints.h"

#include <math.h>
#include <stdint.h>

unsigned int nStakeMinAge       = 8 * 60 * 60;
unsigned int nModifierInterval  = 2 * 60 * 60;

MapCheckpoints mapPremineSendBlocks =
	boost::assign::map_list_of
	(1,	("0x0000004cf5ffbf2e31a9aa07c86298efb01a30b8911b80af7473d1114715084b") ) // Premine
;

uint256 CBlock::GetHash() const {
	return GetPoWHash();
}

uint256 CBlock::GetPoWHash() const {
	return Hash(BEGIN(nVersion), END(nNonce));
}

int DetermineCoinbaseMaturity() {
	if(pindexBest->nHeight <= 100) {
		return (int)10; // This will allow for premine distribution to propogate faster
	} else {
		return (int)60; // Coinbase will take approx. 1 hr to reach confirmation
	}
}

// miner's coin base reward
int64_t GetCoinbaseValue(int nHeight, CAmount nFees)
{
    CAmount nSubsidy = 0;

	if(nHeight == 1) {
		nSubsidy = 16400000 * COIN;
	}

    return nSubsidy;
}

// miner's coin stake reward based on coin age spent (coin-days)
int64_t GetCoinstakeValue(int64_t nCoinAge, CAmount nFees, int nHeight)
{
	CAmount nSubsidy = 0.2 * COIN;

	if(nHeight <= 125146) {
		nSubsidy = 23 * COIN;
	} else if(nHeight <= 568622) {
		nSubsidy = 17 * COIN;
	} else if(nHeight <= 1012098) {
		nSubsidy = 11.5 * COIN;
	} else if(nHeight <= 1455574) {
		nSubsidy = 5.75 * COIN;
	} else if(nHeight <= 3675950) {
		nSubsidy = 1.85 * COIN;
	} else {
		nSubsidy = 0.2 * COIN;
	}

    return nSubsidy + nFees;
}

unsigned int GetNextTargetRequired(const CBlockIndex* pindexLast, bool fProofOfStake)
{
    uint256 bnTargetLimit = fProofOfStake ? Params().ProofOfStakeLimit() : Params().ProofOfWorkLimit();

    if (pindexLast == NULL)
        return bnTargetLimit.GetCompact(); // genesis block

    const CBlockIndex* pindexPrev = GetLastBlockIndex(pindexLast, fProofOfStake);
    if (pindexPrev->pprev == NULL)
        return bnTargetLimit.GetCompact(); // first block
    const CBlockIndex* pindexPrevPrev = GetLastBlockIndex(pindexPrev->pprev, fProofOfStake);
    if (pindexPrevPrev->pprev == NULL)
        return bnTargetLimit.GetCompact(); // second block

    int64_t nActualSpacing = pindexPrev->GetBlockTime() - pindexPrevPrev->GetBlockTime();

    if (nActualSpacing < 0) {
        nActualSpacing = nTargetSpacing;
    }
    else if (fProofOfStake && nActualSpacing > nTargetSpacing * 10) {
         nActualSpacing = nTargetSpacing * 10;
    }

    // target change every block
    // retarget with exponential moving toward target spacing
    // Includes fix for wrong retargeting difficulty by Mammix2
    uint256 bnNew;
    bnNew.SetCompact(pindexPrev->nBits);

    int64_t nInterval = fProofOfStake ? 10 : 10;
    bnNew *= ((nInterval - 1) * nTargetSpacing + nActualSpacing + nActualSpacing);
    bnNew /= ((nInterval + 1) * nTargetSpacing);

    if (bnNew <= 0 || bnNew > bnTargetLimit)
        bnNew = bnTargetLimit;

    return bnNew.GetCompact();
}

bool CheckProofOfWork(uint256 hash, unsigned int nBits)
{
    uint256 bnTarget;
    bnTarget.SetCompact(nBits);

    // Check range
    if (bnTarget <= 0 || bnTarget > Params().ProofOfWorkLimit())
        return error("CheckProofOfWork() : nBits below minimum work");

    // Check proof of work matches claimed amount
    if (hash > bnTarget)
        return error("CheckProofOfWork() : hash doesn't match nBits");

    return true;
}
<commit_msg>[Proof] Change the param<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2015-2017 The Silk Network developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <boost/assign/list_of.hpp> // for 'map_list_of()'

#include "proofs.h"

#include "chainparams.h"
#include "main.h"
#include "uint256.h"
#include "util.h"
#include "amount.h"
#include "checkpoints.h"

#include <math.h>
#include <stdint.h>

unsigned int nStakeMinAge       = 8 * 60 * 60;
unsigned int nModifierInterval  = 2 * 60 * 60;

MapCheckpoints mapPremineSendBlocks =
	boost::assign::map_list_of
	(1,	("0x0000004cf5ffbf2e31a9aa07c86298efb01a30b8911b80af7473d1114715084b") ) // Premine
;

uint256 CBlock::GetHash() const {
	return GetPoWHash();
}

uint256 CBlock::GetPoWHash() const {
	return Hash(BEGIN(nVersion), END(nNonce));
}

int DetermineCoinbaseMaturity() {
	if(pindexBest->nHeight <= 100) {
		return (int)10; // This will allow for premine distribution to propogate faster
	} else {
		return (int)60; // Coinbase will take approx. 1 hr to reach confirmation
	}
}

// miner's coin base reward
int64_t GetCoinbaseValue(int nHeight, CAmount nFees)
{
    CAmount nSubsidy = 0;

	if(nHeight == 1) {
		nSubsidy = 16400000 * COIN;
	}

    return nSubsidy;
}

// miner's coin stake reward based on coin age spent (coin-days)
int64_t GetCoinstakeValue(int64_t nCoinAge, CAmount nFees, int nHeight)
{
	CAmount nSubsidy = 0.2 * COIN;

	if(nHeight <= 125146) {
		nSubsidy = 23 * COIN;
	} else if(nHeight <= 568622) {
		nSubsidy = 17 * COIN;
	} else if(nHeight <= 1012098) {
		nSubsidy = 11.5 * COIN;
	} else if(nHeight <= 1455574) {
		nSubsidy = 5.75 * COIN;
	} else if(nHeight <= 3675950) {
		nSubsidy = 1.85 * COIN;
	} else {
		nSubsidy = 0.2 * COIN;
	}

    return nSubsidy + nFees;
}

unsigned int GetNextTargetRequired(const CBlockIndex* pindexLast, bool fProofOfStake)
{
    uint256 bnTargetLimit = fProofOfStake ? Params().ProofOfStakeLimit() : Params().ProofOfWorkLimit();

    if (pindexLast == NULL)
        return bnTargetLimit.GetCompact(); // genesis block

    const CBlockIndex* pindexPrev = GetLastBlockIndex(pindexLast, fProofOfStake);
    if (pindexPrev->pprev == NULL)
        return bnTargetLimit.GetCompact(); // first block
    const CBlockIndex* pindexPrevPrev = GetLastBlockIndex(pindexPrev->pprev, fProofOfStake);
    if (pindexPrevPrev->pprev == NULL)
        return bnTargetLimit.GetCompact(); // second block

    int64_t nActualSpacing = pindexPrev->GetBlockTime() - pindexPrevPrev->GetBlockTime();

    if (nActualSpacing < 0) {
        nActualSpacing = nTargetSpacing;
    }
    else if (fProofOfStake && nActualSpacing > nTargetSpacing * 10) {
         nActualSpacing = nTargetSpacing * 10;
    }

    // target change every block
    // retarget with exponential moving toward target spacing
    // Includes fix for wrong retargeting difficulty by Mammix2
    uint256 bnNew;
    bnNew.SetCompact(pindexPrev->nBits);

    int64_t nInterval = fProofOfStake ? 10 : 10;
    bnNew *= ((nInterval - 1) * nTargetSpacing + nActualSpacing + nActualSpacing);
    bnNew /= ((nInterval + 1) * nTargetSpacing);

    if (bnNew <= 0 || bnNew > bnTargetLimit)
        bnNew = bnTargetLimit;

    return bnNew.GetCompact();
}

bool CheckProofOfWork(uint256 hash, unsigned int nBits)
{
    uint256 bnTarget;
    bnTarget.SetCompact(nBits);

    // Check range
    if (bnTarget <= 0 || bnTarget > Params().ProofOfWorkLimit())
        return error("CheckProofOfWork() : nBits below minimum work");

    // Check proof of work matches claimed amount
    if (hash > bnTarget)
        return error("CheckProofOfWork() : hash doesn't match nBits");

    return true;
}
<|endoftext|>


<commit_before>#include <test/unit/math/test_ad.hpp>
#include <vector>

TEST(MathMixMatFun, logDeterminant) {
  auto f = [](const auto& x) { return stan::math::log_determinant(x); };

  // repeat symmetric pos def tests
  Eigen::MatrixXd a(2, 2);
  a << 3, 0, 0, 4;
  stan::test::expect_ad(f, a);

  Eigen::MatrixXd b(2, 2);
  b << 2, 1, 1, 3;
  stan::test::expect_ad(f, b);

  Eigen::MatrixXd c(2, 2);
  c << 1, 0, 0, 3;
  stan::test::expect_ad(f, c);

  for (const auto& rho : std::vector<double>{0, 0.9}) {
    for (const auto& y : stan::test::ar_test_cov_matrices(1, 3, rho)) {
      stan::test::expect_ad(f, y);
    }
  }

  // asymmetric tests
  Eigen::MatrixXd d(2, 3);
  d << 1, 2, 3, 4, 5, 6;
  stan::test::expect_ad(f, d);

  Eigen::MatrixXd e(2, 2);
  e << 0, 1, 2, 3;
  stan::test::expect_ad(f, e);

  Eigen::MatrixXd g(2, 2);
  e << 2, 3, 5, 7;
  stan::test::expect_ad(f, g);
}
<commit_msg>log_determinant test init<commit_after>#include <test/unit/math/test_ad.hpp>
#include <vector>

TEST(MathMixMatFun, logDeterminant) {
  auto f = [](const auto& x) { return stan::math::log_determinant(x); };

  // repeat symmetric pos def tests
  Eigen::MatrixXd a(2, 2);
  a << 3, 0, 0, 4;
  stan::test::expect_ad(f, a);

  Eigen::MatrixXd b(2, 2);
  b << 2, 1, 1, 3;
  stan::test::expect_ad(f, b);

  Eigen::MatrixXd c(2, 2);
  c << 1, 0, 0, 3;
  stan::test::expect_ad(f, c);

  for (const auto& rho : std::vector<double>{0, 0.9}) {
    for (const auto& y : stan::test::ar_test_cov_matrices(1, 3, rho)) {
      stan::test::expect_ad(f, y);
    }
  }

  // asymmetric tests
  Eigen::MatrixXd d(2, 3);
  d << 1, 2, 3, 4, 5, 6;
  stan::test::expect_ad(f, d);

  Eigen::MatrixXd e(2, 2);
  e << 0, 1, 2, 3;
  stan::test::expect_ad(f, e);

  Eigen::MatrixXd g(2, 2);
  g << 2, 3, 5, 7;
  stan::test::expect_ad(f, g);
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2016-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

#include "qmatrix.h"

#include <assert.h>
#include <cmath>
#include <iostream>

namespace fasttext {

QMatrix::QMatrix() : qnorm_(false),
  m_(0), n_(0), codesize_(0) {}

QMatrix::QMatrix(const Matrix& mat, int32_t dsub, bool qnorm)
      : qnorm_(qnorm), m_(mat.m_), n_(mat.n_),
        codesize_(m_ * std::ceil(n_ / dsub)) {
  codes_ = new uint8_t[codesize_];
  pq_ = std::unique_ptr<ProductQuantizer>( new ProductQuantizer(n_, dsub));
  if (qnorm_) {
    norm_codes_ = new uint8_t[m_];
    npq_ = std::unique_ptr<ProductQuantizer>( new ProductQuantizer(1, 1));
  }
  quantize(mat);
}

QMatrix::~QMatrix() {
  delete[] codes_;
  if (qnorm_) { delete[] norm_codes_; }
}

void QMatrix::quantizeNorm(const Vector& norms) {
  assert(qnorm_);
  assert(norms.m_ == m_);
  auto dataptr = norms.data_;
  npq_->train(m_, dataptr);
  npq_->compute_codes(dataptr, norm_codes_, m_);
}

void QMatrix::quantize(const Matrix& matrix) {
  assert(n_ == matrix.n_);
  assert(m_ == matrix.m_);
  Matrix temp(matrix);
  if (qnorm_) {
    Vector norms(temp.m_);
    temp.l2NormRow(norms);
    temp.divideRow(norms);
    quantizeNorm(norms);
  }
  auto dataptr = temp.data_;
  pq_->train(m_, dataptr);
  pq_->compute_codes(dataptr, codes_, m_);
}

void QMatrix::addToVector(Vector& x, int32_t t) const {
  real norm = 1;
  if (qnorm_) {
    norm = npq_->get_centroids(0, norm_codes_[t])[0];
  }
  pq_->addcode(x, codes_, t, norm);
}

real QMatrix::dotRow(const Vector& vec, int64_t i) const {
  assert(i >= 0);
  assert(i < m_);
  assert(vec.size() == n_);
  real norm = 1;
  if (qnorm_) {
    norm = npq_->get_centroids(0, norm_codes_[i])[0];
  }
  return pq_->mulcode(vec, codes_, i, norm);
}

int64_t QMatrix::getM() const {
  return m_;
}

int64_t QMatrix::getN() const {
  return n_;
}

void QMatrix::save(std::ostream& out) {
    out.write((char*) &qnorm_, sizeof(qnorm_));
    out.write((char*) &m_, sizeof(m_));
    out.write((char*) &n_, sizeof(n_));
    out.write((char*) &codesize_, sizeof(codesize_));
    out.write((char*) codes_, codesize_ * sizeof(uint8_t));
    pq_->save(out);
    if (qnorm_) {
      out.write((char*) norm_codes_, m_ * sizeof(uint8_t));
      npq_->save(out);
    }
}

void QMatrix::load(std::istream& in) {
    in.read((char*) &qnorm_, sizeof(qnorm_));
    in.read((char*) &m_, sizeof(m_));
    in.read((char*) &n_, sizeof(n_));
    in.read((char*) &codesize_, sizeof(codesize_));
    codes_ = new uint8_t[codesize_];
    in.read((char*) codes_, codesize_ * sizeof(uint8_t));
    pq_ = std::unique_ptr<ProductQuantizer>( new ProductQuantizer());
    pq_->load(in);
    if (qnorm_) {
      norm_codes_ = new uint8_t[m_];
      in.read((char*) norm_codes_, m_ * sizeof(uint8_t));
      npq_ = std::unique_ptr<ProductQuantizer>( new ProductQuantizer());
      npq_->load(in);
    }
}

}
<commit_msg>fixing a delete without checking for the existence of the object<commit_after>/**
 * Copyright (c) 2016-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

#include "qmatrix.h"

#include <assert.h>
#include <cmath>
#include <iostream>

namespace fasttext {

QMatrix::QMatrix() : qnorm_(false),
  m_(0), n_(0), codesize_(0) {}

QMatrix::QMatrix(const Matrix& mat, int32_t dsub, bool qnorm)
      : qnorm_(qnorm), m_(mat.m_), n_(mat.n_),
        codesize_(m_ * std::ceil(n_ / dsub)) {
  codes_ = new uint8_t[codesize_];
  pq_ = std::unique_ptr<ProductQuantizer>( new ProductQuantizer(n_, dsub));
  if (qnorm_) {
    norm_codes_ = new uint8_t[m_];
    npq_ = std::unique_ptr<ProductQuantizer>( new ProductQuantizer(1, 1));
  }
  quantize(mat);
}

QMatrix::~QMatrix() {
  if (codesize_) { delete[] codes_; }
  if (qnorm_) { delete[] norm_codes_; }
}

void QMatrix::quantizeNorm(const Vector& norms) {
  assert(qnorm_);
  assert(norms.m_ == m_);
  auto dataptr = norms.data_;
  npq_->train(m_, dataptr);
  npq_->compute_codes(dataptr, norm_codes_, m_);
}

void QMatrix::quantize(const Matrix& matrix) {
  assert(n_ == matrix.n_);
  assert(m_ == matrix.m_);
  Matrix temp(matrix);
  if (qnorm_) {
    Vector norms(temp.m_);
    temp.l2NormRow(norms);
    temp.divideRow(norms);
    quantizeNorm(norms);
  }
  auto dataptr = temp.data_;
  pq_->train(m_, dataptr);
  pq_->compute_codes(dataptr, codes_, m_);
}

void QMatrix::addToVector(Vector& x, int32_t t) const {
  real norm = 1;
  if (qnorm_) {
    norm = npq_->get_centroids(0, norm_codes_[t])[0];
  }
  pq_->addcode(x, codes_, t, norm);
}

real QMatrix::dotRow(const Vector& vec, int64_t i) const {
  assert(i >= 0);
  assert(i < m_);
  assert(vec.size() == n_);
  real norm = 1;
  if (qnorm_) {
    norm = npq_->get_centroids(0, norm_codes_[i])[0];
  }
  return pq_->mulcode(vec, codes_, i, norm);
}

int64_t QMatrix::getM() const {
  return m_;
}

int64_t QMatrix::getN() const {
  return n_;
}

void QMatrix::save(std::ostream& out) {
    out.write((char*) &qnorm_, sizeof(qnorm_));
    out.write((char*) &m_, sizeof(m_));
    out.write((char*) &n_, sizeof(n_));
    out.write((char*) &codesize_, sizeof(codesize_));
    out.write((char*) codes_, codesize_ * sizeof(uint8_t));
    pq_->save(out);
    if (qnorm_) {
      out.write((char*) norm_codes_, m_ * sizeof(uint8_t));
      npq_->save(out);
    }
}

void QMatrix::load(std::istream& in) {
    in.read((char*) &qnorm_, sizeof(qnorm_));
    in.read((char*) &m_, sizeof(m_));
    in.read((char*) &n_, sizeof(n_));
    in.read((char*) &codesize_, sizeof(codesize_));
    codes_ = new uint8_t[codesize_];
    in.read((char*) codes_, codesize_ * sizeof(uint8_t));
    pq_ = std::unique_ptr<ProductQuantizer>( new ProductQuantizer());
    pq_->load(in);
    if (qnorm_) {
      norm_codes_ = new uint8_t[m_];
      in.read((char*) norm_codes_, m_ * sizeof(uint8_t));
      npq_ = std::unique_ptr<ProductQuantizer>( new ProductQuantizer());
      npq_->load(in);
    }
}

}
<|endoftext|>


<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "random.h"

#include "support/cleanse.h"
#ifdef WIN32
#include "compat.h" // for Windows API
#endif
#include "serialize.h"        // for begin_ptr(vec)
#include "util.h"             // for LogPrint()
#include "utilstrencodings.h" // for GetTime()

#include <limits>

#ifndef WIN32
#include <sys/time.h>
#endif

#include <openssl/err.h>
#include <openssl/rand.h>

static inline int64_t GetPerformanceCounter()
{
    int64_t nCounter = 0;
#ifdef WIN32
    QueryPerformanceCounter((LARGE_INTEGER*)&nCounter);
#else
    timeval t;
    gettimeofday(&t, NULL);
    nCounter = (int64_t)(t.tv_sec * 1000000 + t.tv_usec);
#endif
    return nCounter;
}

void RandAddSeed()
{
    // Seed with CPU performance counter
    int64_t nCounter = GetPerformanceCounter();
    RAND_add(&nCounter, sizeof(nCounter), 1.5);
    memory_cleanse((void*)&nCounter, sizeof(nCounter));
}

void RandAddSeedPerfmon()
{
    RandAddSeed();

    // This can take up to 2 seconds, so only do it every 10 minutes
    static int64_t nLastPerfmon;
    if (GetTime() < nLastPerfmon + 10 * 60)
        return;
    nLastPerfmon = GetTime();

#ifdef WIN32
    // Don't need this on Linux, OpenSSL automatically uses /dev/urandom
    // Seed with the entire set of perfmon data
    std::vector<unsigned char> vData(250000, 0);
    long ret = 0;
    unsigned long nSize = 0;
    const size_t nMaxSize = 10000000; // Bail out at more than 10MB of performance data
    while (true) {
        nSize = vData.size();
        ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, begin_ptr(vData), &nSize);
        if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize)
            break;
        vData.resize(std::max((vData.size() * 3) / 2, nMaxSize)); // Grow size of buffer exponentially
    }
    RegCloseKey(HKEY_PERFORMANCE_DATA);
    if (ret == ERROR_SUCCESS) {
        RAND_add(begin_ptr(vData), nSize, nSize / 100.0);
        memory_cleanse(begin_ptr(vData), nSize);
        LogPrint("rand", "%s: %lu bytes\n", __func__, nSize);
    } else {
        static bool warned = false; // Warn only once
        if (!warned) {
            LogPrintf("%s: Warning: RegQueryValueExA(HKEY_PERFORMANCE_DATA) failed with code %i\n", __func__, ret);
            warned = true;
        }
    }
#endif
}

void GetRandBytes(unsigned char* buf, int num)
{
    if (RAND_bytes(buf, num) != 1) {
        LogPrintf("%s: OpenSSL RAND_bytes() failed with error: %s\n", __func__, ERR_error_string(ERR_get_error(), NULL));
        assert(false);
    }
}

uint64_t GetRand(uint64_t nMax)
{
    if (nMax == 0)
        return 0;

    // The range of the random source must be a multiple of the modulus
    // to give every possible output value an equal possibility
    uint64_t nRange = (std::numeric_limits<uint64_t>::max() / nMax) * nMax;
    uint64_t nRand = 0;
    do {
        GetRandBytes((unsigned char*)&nRand, sizeof(nRand));
    } while (nRand >= nRange);
    return (nRand % nMax);
}

int GetRandInt(int nMax)
{
    return GetRand(nMax);
}

uint256 GetRandHash()
{
    uint256 hash;
    GetRandBytes((unsigned char*)&hash, sizeof(hash));
    return hash;
}

uint32_t insecure_rand_Rz = 11;
uint32_t insecure_rand_Rw = 11;
void seed_insecure_rand(bool fDeterministic)
{
    // The seed values have some unlikely fixed points which we avoid.
    if (fDeterministic) {
        insecure_rand_Rz = insecure_rand_Rw = 11;
    } else {
        uint32_t tmp;
        do {
            GetRandBytes((unsigned char*)&tmp, 4);
        } while (tmp == 0 || tmp == 0x9068ffffU);
        insecure_rand_Rz = tmp;
        do {
            GetRandBytes((unsigned char*)&tmp, 4);
        } while (tmp == 0 || tmp == 0x464fffffU);
        insecure_rand_Rw = tmp;
    }
}
<commit_msg>WIN32 Seed Cleanup: Move nLastPerfmon behind win32 ifdef. Code to avoid calling Perfmon too often is only needed when perfmon is actually going to get called. This is not intended to make any functional difference in the addition of entropy to the random pool.<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "random.h"

#include "support/cleanse.h"
#ifdef WIN32
#include "compat.h" // for Windows API
#endif
#include "serialize.h"        // for begin_ptr(vec)
#include "util.h"             // for LogPrint()
#include "utilstrencodings.h" // for GetTime()

#include <limits>

#ifndef WIN32
#include <sys/time.h>
#endif

#include <openssl/err.h>
#include <openssl/rand.h>

static inline int64_t GetPerformanceCounter()
{
    int64_t nCounter = 0;
#ifdef WIN32
    QueryPerformanceCounter((LARGE_INTEGER*)&nCounter);
#else
    timeval t;
    gettimeofday(&t, NULL);
    nCounter = (int64_t)(t.tv_sec * 1000000 + t.tv_usec);
#endif
    return nCounter;
}

void RandAddSeed()
{
    // Seed with CPU performance counter
    int64_t nCounter = GetPerformanceCounter();
    RAND_add(&nCounter, sizeof(nCounter), 1.5);
    memory_cleanse((void*)&nCounter, sizeof(nCounter));
}

void RandAddSeedPerfmon()
{
    RandAddSeed();

#ifdef WIN32
    // Don't need this on Linux, OpenSSL automatically uses /dev/urandom
    // Seed with the entire set of perfmon data

    // This can take up to 2 seconds, so only do it every 10 minutes
    static int64_t nLastPerfmon;
    if (GetTime() < nLastPerfmon + 10 * 60)
        return;
    nLastPerfmon = GetTime();

    std::vector<unsigned char> vData(250000, 0);
    long ret = 0;
    unsigned long nSize = 0;
    const size_t nMaxSize = 10000000; // Bail out at more than 10MB of performance data
    while (true) {
        nSize = vData.size();
        ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, begin_ptr(vData), &nSize);
        if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize)
            break;
        vData.resize(std::max((vData.size() * 3) / 2, nMaxSize)); // Grow size of buffer exponentially
    }
    RegCloseKey(HKEY_PERFORMANCE_DATA);
    if (ret == ERROR_SUCCESS) {
        RAND_add(begin_ptr(vData), nSize, nSize / 100.0);
        memory_cleanse(begin_ptr(vData), nSize);
        LogPrint("rand", "%s: %lu bytes\n", __func__, nSize);
    } else {
        static bool warned = false; // Warn only once
        if (!warned) {
            LogPrintf("%s: Warning: RegQueryValueExA(HKEY_PERFORMANCE_DATA) failed with code %i\n", __func__, ret);
            warned = true;
        }
    }
#endif
}

void GetRandBytes(unsigned char* buf, int num)
{
    if (RAND_bytes(buf, num) != 1) {
        LogPrintf("%s: OpenSSL RAND_bytes() failed with error: %s\n", __func__, ERR_error_string(ERR_get_error(), NULL));
        assert(false);
    }
}

uint64_t GetRand(uint64_t nMax)
{
    if (nMax == 0)
        return 0;

    // The range of the random source must be a multiple of the modulus
    // to give every possible output value an equal possibility
    uint64_t nRange = (std::numeric_limits<uint64_t>::max() / nMax) * nMax;
    uint64_t nRand = 0;
    do {
        GetRandBytes((unsigned char*)&nRand, sizeof(nRand));
    } while (nRand >= nRange);
    return (nRand % nMax);
}

int GetRandInt(int nMax)
{
    return GetRand(nMax);
}

uint256 GetRandHash()
{
    uint256 hash;
    GetRandBytes((unsigned char*)&hash, sizeof(hash));
    return hash;
}

uint32_t insecure_rand_Rz = 11;
uint32_t insecure_rand_Rw = 11;
void seed_insecure_rand(bool fDeterministic)
{
    // The seed values have some unlikely fixed points which we avoid.
    if (fDeterministic) {
        insecure_rand_Rz = insecure_rand_Rw = 11;
    } else {
        uint32_t tmp;
        do {
            GetRandBytes((unsigned char*)&tmp, 4);
        } while (tmp == 0 || tmp == 0x9068ffffU);
        insecure_rand_Rz = tmp;
        do {
            GetRandBytes((unsigned char*)&tmp, 4);
        } while (tmp == 0 || tmp == 0x464fffffU);
        insecure_rand_Rw = tmp;
    }
}
<|endoftext|>


<commit_before>#include <node.h>
#include <v8.h>
#include <vector>
#include "mouse.h"
#include "deadbeef_rand.h"
#include "screen.h"
#include "screengrab.h"
#include "keypress.h"

using namespace v8;

/*
 __  __
|  \/  | ___  _   _ ___  ___
| |\/| |/ _ \| | | / __|/ _ \
| |  | | (_) | |_| \__ \  __/
|_|  |_|\___/ \__,_|___/\___|
 */

Handle<Value> moveMouse(const Arguments& args)
{
  HandleScope scope;
  if (args.Length() < 2)
  {
    ThrowException(Exception::TypeError(String::New("Wrong number of arguments")));
    return scope.Close(Undefined());
  }
  size_t x = args[0]->Int32Value();
  size_t y = args[1]->Int32Value();

  MMPoint point;
  point = MMPointMake(x, y);
  moveMouse(point);
  return scope.Close(String::New("1"));
}

Handle<Value> getMousePos(const Arguments& args)
{
  HandleScope scope;

  MMPoint pos = getMousePos();

  //Return object with .x and .y.
  Local<Object> obj = Object::New();
  obj->Set(String::NewSymbol("x"), Number::New(pos.x));
  obj->Set(String::NewSymbol("y"), Number::New(pos.y));
  return scope.Close(obj);
}

Handle<Value> mouseClick(const Arguments& args)
{
  HandleScope scope;

  MMMouseButton button = LEFT_BUTTON;

  clickMouse(button);
  return scope.Close(String::New("1"));
}

/*
 _  __          _                         _
| |/ /___ _   _| |__   ___   __ _ _ __ __| |
| ' // _ \ | | | '_ \ / _ \ / _` | '__/ _` |
| . \  __/ |_| | |_) | (_) | (_| | | | (_| |
|_|\_\___|\__, |_.__/ \___/ \__,_|_|  \__,_|
          |___/
 */

char *get(v8::Local<v8::Value> value, const char *fallback = "")
{
    if (value->IsString())
    {
        v8::String::AsciiValue string(value);
        char *str = (char *) malloc(string.length() + 1);
        strcpy(str, *string);
        return str;
    }
    char *str = (char *) malloc(strlen(fallback) + 1);
    strcpy(str, fallback);
    return str;
}

Handle<Value> keyTap(const Arguments& args)
{
  HandleScope scope;

  MMKeyFlags flags = MOD_NONE;

  char c = get(args[0])[0];

  if (strlen(&c)==1)
  {
    tapKey(c, flags);
  }

  return scope.Close(String::New("1"));
}

Handle<Value> typeString(const Arguments& args)
{
  HandleScope scope;

  char *str = get(args[0]);

  typeString(str);

  return scope.Close(String::New("1"));
}

//Screen

Handle<Value> captureScreen(const Arguments& args)
{
  HandleScope scope;

  MMRect rect;
  MMBitmapRef bitmap = NULL;
  MMSize displaySize = getMainDisplaySize();

  rect = MMRectMake(0, 0, displaySize.width, displaySize.height);

  bitmap = copyMMBitmapFromDisplayInRect(rect);

  return scope.Close(External::Wrap(bitmap));

  //return scope.Close(String::New("1"));
}

Handle<Value> getWindows(const Arguments& args)
{
  HandleScope scope;

  CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
  CFIndex windowNum = CFArrayGetCount(windowList);

  std::vector<Object> windows;
  Local<Object> obj = Object::New();

  for (int i = 0; i < (int)windowNum; i++)
  {
        CFDictionaryRef info = (CFDictionaryRef)CFArrayGetValueAtIndex(windowList, i);
        CFNumberRef currentPID = (CFNumberRef)CFDictionaryGetValue(info, kCGWindowOwnerPID);
        CFNumberRef currentWindowNumber = (CFNumberRef)CFDictionaryGetValue(info, kCGWindowNumber);
        CFStringRef currentTitle = (CFStringRef)CFDictionaryGetValue(info, kCGWindowName);
        CFIndex length = CFStringGetLength(currentTitle);
        CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8);
        char *buffer = (char *)malloc(maxSize);
        CFStringGetCString(currentTitle, buffer, maxSize, kCFStringEncodingUTF8);
        obj->Set(String::NewSymbol("title"), String::New(buffer));
        obj->Set(String::NewSymbol("id"), Number::New(*(int *)currentWindowNumber));
        printf(buffer);
        printf("\n");
        //windows.push_back(obj);

  }

  //return scope.Close(String::New("1"));

  return scope.Close(String::New("1"));
}

void init(Handle<Object> target)
{
  target->Set(String::NewSymbol("moveMouse"),
      FunctionTemplate::New(moveMouse)->GetFunction());

  target->Set(String::NewSymbol("getMousePos"),
      FunctionTemplate::New(getMousePos)->GetFunction());

  target->Set(String::NewSymbol("mouseClick"),
      FunctionTemplate::New(mouseClick)->GetFunction());

  target->Set(String::NewSymbol("keyTap"),
      FunctionTemplate::New(keyTap)->GetFunction());

  target->Set(String::NewSymbol("typeString"),
      FunctionTemplate::New(typeString)->GetFunction());

  target->Set(String::NewSymbol("captureScreen"),
      FunctionTemplate::New(captureScreen)->GetFunction());

  target->Set(String::NewSymbol("getWindows"),
      FunctionTemplate::New(getWindows)->GetFunction());
}

NODE_MODULE(robotjs, init)
<commit_msg>Cleaning up the code, moving window code to new branch.<commit_after>#include <node.h>
#include <v8.h>
#include <vector>
#include "mouse.h"
#include "deadbeef_rand.h"
#include "screen.h"
#include "screengrab.h"
#include "keypress.h"

using namespace v8;

/*
 __  __
|  \/  | ___  _   _ ___  ___
| |\/| |/ _ \| | | / __|/ _ \
| |  | | (_) | |_| \__ \  __/
|_|  |_|\___/ \__,_|___/\___|

 */

Handle<Value> moveMouse(const Arguments& args)
{
  HandleScope scope;
  if (args.Length() < 2)
  {
    ThrowException(Exception::TypeError(String::New("Wrong number of arguments")));
    return scope.Close(Undefined());
  }
  size_t x = args[0]->Int32Value();
  size_t y = args[1]->Int32Value();

  MMPoint point;
  point = MMPointMake(x, y);
  moveMouse(point);
  return scope.Close(String::New("1"));
}

Handle<Value> getMousePos(const Arguments& args)
{
  HandleScope scope;

  MMPoint pos = getMousePos();

  //Return object with .x and .y.
  Local<Object> obj = Object::New();
  obj->Set(String::NewSymbol("x"), Number::New(pos.x));
  obj->Set(String::NewSymbol("y"), Number::New(pos.y));
  return scope.Close(obj);
}

Handle<Value> mouseClick(const Arguments& args)
{
  HandleScope scope;

  MMMouseButton button = LEFT_BUTTON;

  clickMouse(button);
  return scope.Close(String::New("1"));
}

/*
 _  __          _                         _
| |/ /___ _   _| |__   ___   __ _ _ __ __| |
| ' // _ \ | | | '_ \ / _ \ / _` | '__/ _` |
| . \  __/ |_| | |_) | (_) | (_| | | | (_| |
|_|\_\___|\__, |_.__/ \___/ \__,_|_|  \__,_|
          |___/
 */

char *get(v8::Local<v8::Value> value, const char *fallback = "")
{
    if (value->IsString())
    {
        v8::String::AsciiValue string(value);
        char *str = (char *) malloc(string.length() + 1);
        strcpy(str, *string);
        return str;
    }
    char *str = (char *) malloc(strlen(fallback) + 1);
    strcpy(str, fallback);
    return str;
}

Handle<Value> keyTap(const Arguments& args)
{
  HandleScope scope;

  MMKeyFlags flags = MOD_NONE;

  char c = get(args[0])[0];

  if (strlen(&c)==1)
  {
    tapKey(c, flags);
  }

  return scope.Close(String::New("1"));
}

Handle<Value> typeString(const Arguments& args)
{
  HandleScope scope;

  char *str = get(args[0]);

  typeString(str);

  return scope.Close(String::New("1"));
}

/*
  _____
 / ____|
| (___   ___ _ __ ___  ___ _ __
 \___ \ / __| '__/ _ \/ _ \ '_ \
 ____) | (__| | |  __/  __/ | | |
|_____/ \___|_|  \___|\___|_| |_|

 */

Handle<Value> captureScreen(const Arguments& args)
{
  HandleScope scope;

  MMRect rect;
  MMBitmapRef bitmap = NULL;
  MMSize displaySize = getMainDisplaySize();

  rect = MMRectMake(0, 0, displaySize.width, displaySize.height);

  bitmap = copyMMBitmapFromDisplayInRect(rect);

  return scope.Close(External::Wrap(bitmap));

  //return scope.Close(String::New("1"));
}

void init(Handle<Object> target)
{
  target->Set(String::NewSymbol("moveMouse"),
      FunctionTemplate::New(moveMouse)->GetFunction());

  target->Set(String::NewSymbol("getMousePos"),
      FunctionTemplate::New(getMousePos)->GetFunction());

  target->Set(String::NewSymbol("mouseClick"),
      FunctionTemplate::New(mouseClick)->GetFunction());

  target->Set(String::NewSymbol("keyTap"),
      FunctionTemplate::New(keyTap)->GetFunction());

  target->Set(String::NewSymbol("typeString"),
      FunctionTemplate::New(typeString)->GetFunction());

  target->Set(String::NewSymbol("captureScreen"),
      FunctionTemplate::New(captureScreen)->GetFunction());
}

NODE_MODULE(robotjs, init)
<|endoftext|>