<commit_before>#include <chrono>
#include <iostream>
#include <memory>
#include <string.h>
#include "../lcd/LcdDisplay.h"
#include "../src2/HealthStatus.h"

using namespace std;
using namespace std::chrono;

int main() {
    unique_ptr<LcdDisplay> lcd(LcdDisplay::getLcdDisplayInstance());
    lcd->init();
    StatusInformation status;
    beacon_info beacon;
    memset(&beacon, sizeof(beacon), 0);
    status.setScannerID("Room206");

    // Add some events
    sprintf(beacon.uuid, "UUID-%.10d", 66);
    beacon.minor = 66;
    beacon.major = 1;
    beacon.manufacturer = 0xdead;
    beacon.code = 0xbeef;
    beacon.count = 3;
    beacon.rssi = -68;
    milliseconds now = duration_cast<milliseconds >(high_resolution_clock::now().time_since_epoch());
    beacon.time = now.count();
    status.addEvent(beacon, false);

    beacon.isHeartbeat = true;
    beacon.minor = 206;
    beacon.time += 10;
    status.addEvent(beacon, true);

    beacon.isHeartbeat = false;
    beacon.minor = 56;
    beacon.time += 10;
    status.addEvent(beacon, false);

    beacon.isHeartbeat = true;
    beacon.minor = 206;
    beacon.time += 10;
    status.addEvent(beacon, true);

    HealthStatus healthStatus;
    healthStatus.calculateStatus(status);
    Properties statusProps = status.getLastStatus();
    printf("StatusProps dump:\n");
    for(Properties::const_iterator iter = statusProps.begin(); iter != statusProps.end(); iter ++) {
        printf("%s = %s\n", iter->first.c_str(), iter->second.c_str());
    }
    printf("+++ End dump\n\n");

    char tmp[21];

    snprintf(tmp, sizeof(tmp), "01234567890123456789");
    lcd->displayText(tmp, 0, 0);

    cout << "\nEnter any key to test local layout: ";
    std::string line;
    std::getline(std::cin, line);
    lcd->clear();

    snprintf(tmp, sizeof(tmp), "%s:%.5d;%d", status.getScannerID().c_str(), status.getHeartbeatCount(), status.getHeartbeatRSSI());
    lcd->displayText(tmp, 0, 0);
    string uptime = statusProps["Uptime"];
    const char *uptimeStr = uptime.c_str();
    printf("%s; length=%d\n", uptimeStr, uptime.size());
    int days=0, hrs=0, mins=0;
    int count = sscanf (uptimeStr, "uptime: %*d, days:%d, hrs:%d, min:%d", &days, &hrs, &mins);
    printf("matched:%d, UP D:%d H:%d M:%d\n", count, days, hrs, mins);
    snprintf(tmp, sizeof(tmp), "UP D:%d H:%d M:%d", days, hrs, mins);
    lcd->displayText(tmp, 0, 1);
    const char *load = statusProps["LoadAverage"].c_str();
    printf("Load: %s\n", load);
    lcd->displayText(load, 0, 2);
    snprintf(tmp, sizeof(tmp), "Events: %d; Msgs: %d", status.getRawEventCount(), status.getPublishEventCount());
    lcd->displayText(tmp, 0, 3);

    cout << "\nEnter any key to call displayStatus: ";
    std::getline(std::cin, line);
    lcd->clear();
    lcd->displayStatus(status);

    cout << "\nEnter any key to call exit: ";
    std::getline(std::cin, line);
    lcd->clear();
}
<commit_msg>Truncate the scanner name to 7 chars<commit_after>#include <chrono>
#include <iostream>
#include <memory>
#include <string.h>
#include "../lcd/LcdDisplay.h"
#include "../src2/HealthStatus.h"

using namespace std;
using namespace std::chrono;

static inline void truncateName(string& name) {
    size_t length = name.length();
    if(length > 7) {
        int middle = length/2;
        size_t count = length - 7;
        middle -= count / 2;
        name.erase(middle, count);
    }
}

int main() {
    unique_ptr<LcdDisplay> lcd(LcdDisplay::getLcdDisplayInstance());
    lcd->init();
    StatusInformation status;
    beacon_info beacon;
    memset(&beacon, sizeof(beacon), 0);
    status.setScannerID("LCDScanner");

    // Add some events
    sprintf(beacon.uuid, "UUID-%.10d", 66);
    beacon.minor = 66;
    beacon.major = 1;
    beacon.manufacturer = 0xdead;
    beacon.code = 0xbeef;
    beacon.count = 3;
    beacon.rssi = -68;
    milliseconds now = duration_cast<milliseconds >(high_resolution_clock::now().time_since_epoch());
    beacon.time = now.count();
    status.addEvent(beacon, false);

    beacon.isHeartbeat = true;
    beacon.minor = 206;
    beacon.time += 10;
    status.addEvent(beacon, true);

    beacon.isHeartbeat = false;
    beacon.minor = 56;
    beacon.time += 10;
    status.addEvent(beacon, false);

    beacon.isHeartbeat = true;
    beacon.minor = 206;
    beacon.time += 10;
    status.addEvent(beacon, true);

    HealthStatus healthStatus;
    healthStatus.calculateStatus(status);
    Properties statusProps = status.getLastStatus();
    printf("StatusProps dump:\n");
    for(Properties::const_iterator iter = statusProps.begin(); iter != statusProps.end(); iter ++) {
        printf("%s = %s\n", iter->first.c_str(), iter->second.c_str());
    }
    printf("+++ End dump\n\n");

    char tmp[21];

    snprintf(tmp, sizeof(tmp), "01234567890123456789");
    lcd->displayText(tmp, 0, 0);

    cout << "\nEnter any key to test local layout: ";
    std::string line;
    std::getline(std::cin, line);
    lcd->clear();

    string name(status.getScannerID());
    truncateName(name);
    snprintf(tmp, sizeof(tmp), "%s:%.7d;%d", name.c_str(), status.getHeartbeatCount(), status.getHeartbeatRSSI());
    lcd->displayText(tmp, 0, 0);
    string uptime = statusProps["Uptime"];
    const char *uptimeStr = uptime.c_str();
    printf("%s; length=%d\n", uptimeStr, uptime.size());
    int days=0, hrs=0, mins=0;
    int count = sscanf (uptimeStr, "uptime: %*d, days:%d, hrs:%d, min:%d", &days, &hrs, &mins);
    printf("matched:%d, UP D:%d H:%d M:%d\n", count, days, hrs, mins);
    snprintf(tmp, sizeof(tmp), "UP D:%d H:%d M:%d", days, hrs, mins);
    lcd->displayText(tmp, 0, 1);
    const char *load = statusProps["LoadAverage"].c_str();
    printf("Load: %s\n", load);
    lcd->displayText(load, 0, 2);
    snprintf(tmp, sizeof(tmp), "Events: %d; Msgs: %d", status.getRawEventCount(), status.getPublishEventCount());
    lcd->displayText(tmp, 0, 3);

    cout << "\nEnter any key to call displayStatus: ";
    std::getline(std::cin, line);
    lcd->clear();
    lcd->displayStatus(status);

    cout << "\nEnter any key to call exit: ";
    std::getline(std::cin, line);
    lcd->clear();
}
<|endoftext|>


<commit_before>/*
	Flexisip, a flexible SIP proxy server with media capabilities.
	Copyright (C) 2010-2015  Belledonne Communications SARL, All rights reserved.

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

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

	You should have received a copy of the GNU Affero General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef module_hh
#define module_hh

#include "sofia-sip/nta_tport.h"
#include "sofia-sip/tport.h"
#include "sofia-sip/msg_header.h"

#include <string>
#include <memory>
#include <list>
#include "configmanager.hh"
#include "event.hh"
#include "transaction.hh"

class ModuleInfoBase;
class Module;
class Agent;
class StatCounter64;

class ModuleFactory {
  public:
	static ModuleFactory *get();
	Module *createModuleInstance(Agent *ag, const std::string &modname);
	const std::list<ModuleInfoBase *> &moduleInfos() {
		return mModules;
	}

  private:
	void registerModule(ModuleInfoBase *m);
	std::list<ModuleInfoBase *> mModules;
	static ModuleFactory *sInstance;
	friend class ModuleInfoBase;
};

typedef enum { ModuleTypeExperimental, ModuleTypeProduction } ModuleType_e;

class ModuleInfoBase {
	const std::string mName;
	const std::string mHelp;
	const oid mOidIndex;
	static oid indexCount;

  public:
	Module *create(Agent *ag);
	virtual Module *_create(Agent *ag) = 0;
	const std::string &getModuleName() const {
		return mName;
	}
	const std::string &getModuleHelp() const {
		return mHelp;
	}
	unsigned int getOidIndex() const {
		return mOidIndex;
	}
	virtual ~ModuleInfoBase();

	ModuleType_e type() const {
		return mType;
	}

	enum ModuleOid {
		DoSProtection = 2,
		SanityChecker = 3,
		GarbageIn = 5,
		NatHelper = 30,
		Authentication = 60,
		DateHandler = 75,
		GatewayAdapter = 90,
		Registrar = 120,
		StatisticsCollector = 123,
		Router = 125,
		PushNotification = 130,
		ContactRouteInserter = 150,
		LoadBalancer = 180,
		MediaRelay = 210,
		Transcoder = 240,
		Forward = 270,
		Redirect = 290,
		Presence = 300,
		InterDomainConnections = 310
	};

  protected:
	ModuleInfoBase(const char *modname, const char *help, enum ModuleOid oid, ModuleType_e type)
		: mName(modname), mHelp(help), mOidIndex(oid), mType(type) {
		// Oid::oidFromHashedString(modname)
		ModuleFactory::get()->registerModule(this);
	}
	ModuleType_e mType;
};

template <typename _module_> class ModuleInfo : public ModuleInfoBase {
  public:
	ModuleInfo(const char *modname, const char *help, ModuleOid oid, ModuleType_e type = ModuleTypeProduction)
		: ModuleInfoBase(modname, help, oid, type) {
	}

  protected:
	virtual Module *_create(Agent *ag);
};

class EntryFilter;

/**
 * Abstract base class for all Flexisip module.
 * A module is an object that is able to process sip requests and sip responses.
 * It must implements at least:
 * virtual void onRequest(SipEvent *ev)=0;
 * virtual void onResponse(SipEvent *ev)=0;
**/
class Module : protected ConfigValueListener {
	friend class ModuleInfoBase;

  public:
	Module(Agent *);
	virtual ~Module();
	Agent *getAgent() const;
	nta_agent_t *getSofiaAgent() const;
	const std::string &getModuleName() const;
	void declare(GenericStruct *root);
	void checkConfig();
	void load();
	void reload();
	void processRequest(std::shared_ptr<RequestSipEvent> &ev);
	void processResponse(std::shared_ptr<ResponseSipEvent> &ev);
	StatCounter64 &findStat(const std::string &statName) const;
	void idle();
	bool isEnabled() const;
	ModuleType_e type() const;

	inline void process(std::shared_ptr<RequestSipEvent> &ev) {
		processRequest(ev);
	}
	inline void process(std::shared_ptr<ResponseSipEvent> &ev) {
		processResponse(ev);
	}

  protected:
	virtual void onDeclare(GenericStruct *root) {
	}
	virtual void onLoad(const GenericStruct *root) {
	}
	virtual void onUnload() {
	}

	virtual void onRequest(std::shared_ptr<RequestSipEvent> &ev) throw (FlexisipException) = 0;
	virtual void onResponse(std::shared_ptr<ResponseSipEvent> &ev) throw (FlexisipException) = 0;

	virtual bool doOnConfigStateChanged(const ConfigValue &conf, ConfigState state);
	virtual void onIdle() {
	}
	virtual bool onCheckValidNextConfig() {
		return true;
	}
	virtual bool isValidNextConfig(const ConfigValue &cv) {
		return true;
	}
	void sendTrap(const std::string &msg) {
		GenericManager::get()->sendTrap(mModuleConfig, msg);
	}
	Agent *mAgent;

  protected:
	static std::list<std::string> sPushNotifParams;
	su_home_t *getHome() {
		return &mHome;
	}

  private:
	void setInfo(ModuleInfoBase *i);
	ModuleInfoBase *mInfo;
	GenericStruct *mModuleConfig;
	EntryFilter *mFilter;
	bool mDirtyConfig;
	su_home_t mHome;
};

inline std::ostringstream &operator<<(std::ostringstream &__os, const Module &m) {
	__os << m.getModuleName();
	return __os;
}

template <typename _modtype> Module *ModuleInfo<_modtype>::_create(Agent *ag) {
	Module *mod = new _modtype(ag);
	return mod;
}

/**
 * Some useful routines any module can use by derivating from this class.
**/
class ModuleToolbox {
  public:
	static msg_auth_t *findAuthorizationForRealm(su_home_t *home, msg_auth_t *au, const char *realm);
	static const tport_t *getIncomingTport(const std::shared_ptr<RequestSipEvent> &ev, Agent *ag);
	static void addRecordRouteIncoming(su_home_t *home, Agent *ag, const std::shared_ptr<RequestSipEvent> &ev);
	static url_t *urlFromTportName(su_home_t *home, const tp_name_t *name);
	static void addRecordRoute(su_home_t *home, Agent *ag, const std::shared_ptr<RequestSipEvent> &ev,
							   const tport_t *tport);
	static void cleanAndPrependRoute(Agent *ag, msg_t *msg, sip_t *sip, sip_route_t *route);
	static bool sipPortEquals(const char *p1, const char *p2, const char *transport = NULL);
	static int sipPortToInt(const char *port);
	static bool fromMatch(const sip_from_t *from1, const sip_from_t *from2);
	static bool matchesOneOf(const char *item, const std::list<std::string> &set);
	static bool fixAuthChallengeForSDP(su_home_t *home, msg_t *msg, sip_t *sip);
	static bool transportEquals(const char *tr1, const char *tr2);
	static bool isNumeric(const char *host);
	static bool isManagedDomain(const Agent *agent, const std::list<std::string> &domains, const url_t *url);
	static void addRoutingParam(su_home_t *home, sip_contact_t *contacts, const std::string &routingParam,
								const char *domain);
	static struct sip_route_s *prependNewRoutable(msg_t *msg, sip_t *sip, sip_route_t *&sipr, sip_route_t *value);
	static void addPathHeader(Agent *ag, const std::shared_ptr<RequestSipEvent> &ev, const tport_t *tport,
							  const char *uniq = NULL);
	/*these methods do host comparison taking into account that each one of argument can be an ipv6 address enclosed in
	 * brakets*/
	static bool urlHostMatch(const char *host1, const char *host2);
	static bool urlHostMatch(url_t *url, const char *host);
	/*returns the host taking into account that if it is an ipv6 address, then brakets are removed*/
	static string getHost(const char *host);
	static string urlGetHost(url_t *url);
	static void urlSetHost(su_home_t *home, url_t *url, const char *host);
	static bool urlIsResolved(url_t *uri);
	/**
	* Returns true if via and url represent the same network address.
	**/
	static bool urlViaMatch(const url_t *url, const sip_via_t *via, bool use_received_rport);
	/**
	 * Returns true if the destination represented by url is present in the via chain.
	**/
	static bool viaContainsUrl(const sip_via_t *vias, const url_t *url);
	/*returns true if the two url represent the same transport channel (IP, port and protocol)*/
	static bool urlTransportMatch(const url_t *url1, const url_t *url2);
	static string urlGetTransport(const url_t *url);
	static void removeParamsFromContacts(su_home_t *home, sip_contact_t *c, std::list<std::string> &params);
	static void removeParamsFromUrl(su_home_t *home, url_t *u, std::list<std::string> &params);
	static sip_unknown_t *getCustomHeaderByName(sip_t *sip, const char *name);
	static int getCpuCount();
};

/*nice wrapper of the sofia-sip su_home_t, that performs automatic destruction of the home when it leaving a code block
 * or function.*/
class SofiaAutoHome {
  public:
	SofiaAutoHome() {
		su_home_init(&mHome);
	}
	su_home_t *home() {
		return &mHome;
	}
	~SofiaAutoHome() {
		su_home_deinit(&mHome);
	}

  private:
	su_home_t mHome;
};

#endif
<commit_msg>Change the Oid of DosProtection module<commit_after>/*
	Flexisip, a flexible SIP proxy server with media capabilities.
	Copyright (C) 2010-2015  Belledonne Communications SARL, All rights reserved.

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

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

	You should have received a copy of the GNU Affero General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef module_hh
#define module_hh

#include "sofia-sip/nta_tport.h"
#include "sofia-sip/tport.h"
#include "sofia-sip/msg_header.h"

#include <string>
#include <memory>
#include <list>
#include "configmanager.hh"
#include "event.hh"
#include "transaction.hh"

class ModuleInfoBase;
class Module;
class Agent;
class StatCounter64;

class ModuleFactory {
  public:
	static ModuleFactory *get();
	Module *createModuleInstance(Agent *ag, const std::string &modname);
	const std::list<ModuleInfoBase *> &moduleInfos() {
		return mModules;
	}

  private:
	void registerModule(ModuleInfoBase *m);
	std::list<ModuleInfoBase *> mModules;
	static ModuleFactory *sInstance;
	friend class ModuleInfoBase;
};

typedef enum { ModuleTypeExperimental, ModuleTypeProduction } ModuleType_e;

class ModuleInfoBase {
	const std::string mName;
	const std::string mHelp;
	const oid mOidIndex;
	static oid indexCount;

  public:
	Module *create(Agent *ag);
	virtual Module *_create(Agent *ag) = 0;
	const std::string &getModuleName() const {
		return mName;
	}
	const std::string &getModuleHelp() const {
		return mHelp;
	}
	unsigned int getOidIndex() const {
		return mOidIndex;
	}
	virtual ~ModuleInfoBase();

	ModuleType_e type() const {
		return mType;
	}

	enum ModuleOid {
		SanityChecker = 3,
		DoSProtection = 4,
		GarbageIn = 5,
		NatHelper = 30,
		Authentication = 60,
		DateHandler = 75,
		GatewayAdapter = 90,
		Registrar = 120,
		StatisticsCollector = 123,
		Router = 125,
		PushNotification = 130,
		ContactRouteInserter = 150,
		LoadBalancer = 180,
		MediaRelay = 210,
		Transcoder = 240,
		Forward = 270,
		Redirect = 290,
		Presence = 300,
		InterDomainConnections = 310
	};

  protected:
	ModuleInfoBase(const char *modname, const char *help, enum ModuleOid oid, ModuleType_e type)
		: mName(modname), mHelp(help), mOidIndex(oid), mType(type) {
		// Oid::oidFromHashedString(modname)
		ModuleFactory::get()->registerModule(this);
	}
	ModuleType_e mType;
};

template <typename _module_> class ModuleInfo : public ModuleInfoBase {
  public:
	ModuleInfo(const char *modname, const char *help, ModuleOid oid, ModuleType_e type = ModuleTypeProduction)
		: ModuleInfoBase(modname, help, oid, type) {
	}

  protected:
	virtual Module *_create(Agent *ag);
};

class EntryFilter;

/**
 * Abstract base class for all Flexisip module.
 * A module is an object that is able to process sip requests and sip responses.
 * It must implements at least:
 * virtual void onRequest(SipEvent *ev)=0;
 * virtual void onResponse(SipEvent *ev)=0;
**/
class Module : protected ConfigValueListener {
	friend class ModuleInfoBase;

  public:
	Module(Agent *);
	virtual ~Module();
	Agent *getAgent() const;
	nta_agent_t *getSofiaAgent() const;
	const std::string &getModuleName() const;
	void declare(GenericStruct *root);
	void checkConfig();
	void load();
	void reload();
	void processRequest(std::shared_ptr<RequestSipEvent> &ev);
	void processResponse(std::shared_ptr<ResponseSipEvent> &ev);
	StatCounter64 &findStat(const std::string &statName) const;
	void idle();
	bool isEnabled() const;
	ModuleType_e type() const;

	inline void process(std::shared_ptr<RequestSipEvent> &ev) {
		processRequest(ev);
	}
	inline void process(std::shared_ptr<ResponseSipEvent> &ev) {
		processResponse(ev);
	}

  protected:
	virtual void onDeclare(GenericStruct *root) {
	}
	virtual void onLoad(const GenericStruct *root) {
	}
	virtual void onUnload() {
	}

	virtual void onRequest(std::shared_ptr<RequestSipEvent> &ev) throw (FlexisipException) = 0;
	virtual void onResponse(std::shared_ptr<ResponseSipEvent> &ev) throw (FlexisipException) = 0;

	virtual bool doOnConfigStateChanged(const ConfigValue &conf, ConfigState state);
	virtual void onIdle() {
	}
	virtual bool onCheckValidNextConfig() {
		return true;
	}
	virtual bool isValidNextConfig(const ConfigValue &cv) {
		return true;
	}
	void sendTrap(const std::string &msg) {
		GenericManager::get()->sendTrap(mModuleConfig, msg);
	}
	Agent *mAgent;

  protected:
	static std::list<std::string> sPushNotifParams;
	su_home_t *getHome() {
		return &mHome;
	}

  private:
	void setInfo(ModuleInfoBase *i);
	ModuleInfoBase *mInfo;
	GenericStruct *mModuleConfig;
	EntryFilter *mFilter;
	bool mDirtyConfig;
	su_home_t mHome;
};

inline std::ostringstream &operator<<(std::ostringstream &__os, const Module &m) {
	__os << m.getModuleName();
	return __os;
}

template <typename _modtype> Module *ModuleInfo<_modtype>::_create(Agent *ag) {
	Module *mod = new _modtype(ag);
	return mod;
}

/**
 * Some useful routines any module can use by derivating from this class.
**/
class ModuleToolbox {
  public:
	static msg_auth_t *findAuthorizationForRealm(su_home_t *home, msg_auth_t *au, const char *realm);
	static const tport_t *getIncomingTport(const std::shared_ptr<RequestSipEvent> &ev, Agent *ag);
	static void addRecordRouteIncoming(su_home_t *home, Agent *ag, const std::shared_ptr<RequestSipEvent> &ev);
	static url_t *urlFromTportName(su_home_t *home, const tp_name_t *name);
	static void addRecordRoute(su_home_t *home, Agent *ag, const std::shared_ptr<RequestSipEvent> &ev,
							   const tport_t *tport);
	static void cleanAndPrependRoute(Agent *ag, msg_t *msg, sip_t *sip, sip_route_t *route);
	static bool sipPortEquals(const char *p1, const char *p2, const char *transport = NULL);
	static int sipPortToInt(const char *port);
	static bool fromMatch(const sip_from_t *from1, const sip_from_t *from2);
	static bool matchesOneOf(const char *item, const std::list<std::string> &set);
	static bool fixAuthChallengeForSDP(su_home_t *home, msg_t *msg, sip_t *sip);
	static bool transportEquals(const char *tr1, const char *tr2);
	static bool isNumeric(const char *host);
	static bool isManagedDomain(const Agent *agent, const std::list<std::string> &domains, const url_t *url);
	static void addRoutingParam(su_home_t *home, sip_contact_t *contacts, const std::string &routingParam,
								const char *domain);
	static struct sip_route_s *prependNewRoutable(msg_t *msg, sip_t *sip, sip_route_t *&sipr, sip_route_t *value);
	static void addPathHeader(Agent *ag, const std::shared_ptr<RequestSipEvent> &ev, const tport_t *tport,
							  const char *uniq = NULL);
	/*these methods do host comparison taking into account that each one of argument can be an ipv6 address enclosed in
	 * brakets*/
	static bool urlHostMatch(const char *host1, const char *host2);
	static bool urlHostMatch(url_t *url, const char *host);
	/*returns the host taking into account that if it is an ipv6 address, then brakets are removed*/
	static string getHost(const char *host);
	static string urlGetHost(url_t *url);
	static void urlSetHost(su_home_t *home, url_t *url, const char *host);
	static bool urlIsResolved(url_t *uri);
	/**
	* Returns true if via and url represent the same network address.
	**/
	static bool urlViaMatch(const url_t *url, const sip_via_t *via, bool use_received_rport);
	/**
	 * Returns true if the destination represented by url is present in the via chain.
	**/
	static bool viaContainsUrl(const sip_via_t *vias, const url_t *url);
	/*returns true if the two url represent the same transport channel (IP, port and protocol)*/
	static bool urlTransportMatch(const url_t *url1, const url_t *url2);
	static string urlGetTransport(const url_t *url);
	static void removeParamsFromContacts(su_home_t *home, sip_contact_t *c, std::list<std::string> &params);
	static void removeParamsFromUrl(su_home_t *home, url_t *u, std::list<std::string> &params);
	static sip_unknown_t *getCustomHeaderByName(sip_t *sip, const char *name);
	static int getCpuCount();
};

/*nice wrapper of the sofia-sip su_home_t, that performs automatic destruction of the home when it leaving a code block
 * or function.*/
class SofiaAutoHome {
  public:
	SofiaAutoHome() {
		su_home_init(&mHome);
	}
	su_home_t *home() {
		return &mHome;
	}
	~SofiaAutoHome() {
		su_home_deinit(&mHome);
	}

  private:
	su_home_t mHome;
};

#endif
<|endoftext|>


<commit_before>#include <algorithm>
#include <ctime>
#include <functional>
#include <map>
#include <memory>
#include "BrickCache.h"
#include "Controller/StackTimer.h"

namespace tuvok {

// This is used to basically get rid of a type.  You can do:
//   std::vector<TypeErase> data;
//   std::vector<uint8_t> foo;
//   std::vector<uint16_t> bar;
//   data.push_back(TypeErase<std::vector<uint8_t>>(foo));
//   data.push_back(TypeErase<std::vector<uint16_t>>(bar));
// with 'MyTypeOne' and 'MyTypeTwo' being completely unrelated (they do not
// need to have a common base class)
struct TypeErase {
  struct GenericType {
    virtual ~GenericType() {}
    virtual size_t elems() const { return 0; }
  };
  template<typename T> struct TypeEraser : GenericType {
    TypeEraser(const T& t) : thing(t) {}
    TypeEraser(T&& t) : thing(std::forward<T>(t)) {}
    virtual ~TypeEraser() {}
    T& get() { return thing; }
    size_t elems() const { return thing.size(); }
    private: T thing;
  };

  std::shared_ptr<GenericType> gt;
  size_t width;

  TypeErase(const TypeErase& other)
    : gt(other.gt)
    , width(other.width)
  {}

  TypeErase(TypeErase&& other)
    : gt(std::move(other.gt))
    , width(other.width) // width should stay the same right?
  {}

  TypeErase& operator=(const TypeErase& other) {
    if (this != &other) {
      gt = other.gt;
      width = other.width;
    }
    return *this;
  }

  TypeErase& operator=(TypeErase&& other) {
    if (this != &other) {
      gt = std::move(other.gt);
      width = other.width;  // width should stay the same right?
    }
    return *this;
  }

  // this isn't a very good type eraser, because we require that the type has
  // an internal typedef 'value_type' which we can use to obtain the size of
  // it.  not to mention the '.size()' member function that TypeEraser<>
  // requires, above.
  // But that's fine for our usage here; we're really just using this to store
  // vectors and erase the value_type in there anyway.
  template<typename T> TypeErase(const T& t)
    : gt(new TypeEraser<T>(t))
    , width(sizeof(typename T::value_type))
  {}

  template<typename T> TypeErase(T&& t)
    : gt(new TypeEraser<T>(std::forward<T>(t)))
    , width(sizeof(typename std::remove_reference<T>::type::value_type))
  {}
};

struct BrickInfo {
  BrickKey key;
  uint64_t access_time;
  BrickInfo(const BrickKey& k, time_t t) : key(k),
                                           access_time(uint64_t(t)) {}
};

struct CacheLRU {
  typedef std::pair<BrickInfo, TypeErase> CacheElem;
  bool operator()(const CacheElem& a, const CacheElem& b) const {
    return a.first.access_time > b.first.access_time;
  }
};

struct BrickCache::bcinfo {
    bcinfo(): bytes(0) {}
    // this is wordy but they all just forward to a real implementation below.
    const void* lookup(const BrickKey& k) {
      return this->typed_lookup<uint8_t>(k);
    }

    // the erasure means we can just do the insert with the thing we already
    // have: it'll make a shared_ptr out of it and insert it into the
    // container.
    ///@{
    const void* add(const BrickKey& k, std::vector<uint8_t>& data) {
      return this->typed_add<uint8_t>(k, data);
    }
    const void* add(const BrickKey& k, std::vector<uint16_t>& data) {
      return this->typed_add<uint16_t>(k, data);
    }
    const void* add(const BrickKey& k, std::vector<uint32_t>& data) {
      return this->typed_add<uint32_t>(k, data);
    }
    const void* add(const BrickKey& k, std::vector<uint64_t>& data) {
      return this->typed_add<uint64_t>(k, data);
    }
    const void* add(const BrickKey& k, std::vector<int8_t>& data) {
      return this->typed_add<int8_t>(k, data);
    }
    const void* add(const BrickKey& k, std::vector<int16_t>& data) {
      return this->typed_add<int16_t>(k, data);
    }
    const void* add(const BrickKey& k, std::vector<int32_t>& data) {
      return this->typed_add<int32_t>(k, data);
    }
    const void* add(const BrickKey& k, std::vector<int64_t>& data) {
      return this->typed_add<int64_t>(k, data);
    }
    const void* add(const BrickKey& k, std::vector<float>& data) {
      return this->typed_add<float>(k, data);
    }
    ///@}
    void remove() {
      if(!cache.empty()) {
        // libstdc++ complains it's not a heap otherwise.. somehow.  bug?
        std::make_heap(this->cache.begin(), this->cache.end(), CacheLRU());
        const CacheElem& entry = this->cache.front();
        TypeErase::GenericType& gt = *(entry.second.gt);
        assert((entry.second.width * gt.elems()) <= this->bytes);
        this->bytes -= entry.second.width * gt.elems();

        std::pop_heap(this->cache.begin(), this->cache.end(), CacheLRU());
        this->cache.pop_back();
      }
      assert(this->size() == this->bytes);
    }
    size_t size() const { return this->bytes; }

  private:
    template<typename T> const void* typed_lookup(const BrickKey& k);
    template<typename T> const void* typed_add(const BrickKey&,
                                               std::vector<T>&);

  private:
    typedef std::pair<BrickInfo, TypeErase> CacheElem;
    std::vector<CacheElem> cache;
    size_t bytes; ///< how much memory we're currently using for data.
};

struct KeyMatches {
  bool operator()(const BrickKey& key,
                  const std::pair<BrickInfo,TypeErase>& a) const {
    return key == a.first.key;
  }
};

// if the key doesn't exist, you get an empty vector.
template<typename T>
const void* BrickCache::bcinfo::typed_lookup(const BrickKey& k) {
  using namespace std::placeholders;
  KeyMatches km;
  auto func = std::bind(&KeyMatches::operator(), km, k, _1);

  // gcc can't seem to deduce this with 'auto'.
  typedef std::vector<CacheElem> maptype;
  maptype::iterator i = std::find_if(this->cache.begin(), this->cache.end(),
                                     func);
  if(i == this->cache.end()) { return NULL; }

  i->first.access_time = time(NULL);
  TypeErase::GenericType& gt = *(i->second.gt);
  assert(this->size() == this->bytes);
  return dynamic_cast<TypeErase::TypeEraser<std::vector<T>>&>(gt).get().data();
}

template<typename T>
const void* BrickCache::bcinfo::typed_add(const BrickKey& k,
                                          std::vector<T>& data) {
  // maybe the case of a general cache allows duplicate insert, but for our uses
  // there should never be a duplicate entry.
#ifndef NDEBUG
  KeyMatches km;
  using namespace std::placeholders;
  auto func = std::bind(&KeyMatches::operator(), km, k, _1);
  assert(std::find_if(this->cache.begin(), this->cache.end(), func) ==
         this->cache.end());
#endif
  this->bytes += sizeof(T) * data.size();
  this->cache.push_back(std::make_pair(BrickInfo(k, time(NULL)),
                        std::move(data)));

  assert(this->size() == this->bytes);
  return this->typed_lookup<T>(k);
}

BrickCache::BrickCache() : ci(new BrickCache::bcinfo) {}
BrickCache::~BrickCache() {}

const void* BrickCache::lookup(const BrickKey& k) {
  return this->ci->lookup(k);
}
#if 0
void BrickCache::lookup(const BrickKey& k, std::vector<uint16_t>& data) {
  return this->ci->lookup(k, data);
}
void BrickCache::lookup(const BrickKey& k, std::vector<uint32_t>& data) {
  return this->ci->lookup(k, data);
}
void BrickCache::lookup(const BrickKey& k, std::vector<uint64_t>& data) {
  return this->ci->lookup(k, data);
}
void BrickCache::lookup(const BrickKey& k, std::vector<int8_t>& data) {
  return this->ci->lookup(k, data);
}
void BrickCache::lookup(const BrickKey& k, std::vector<int16_t>& data) {
  return this->ci->lookup(k, data);
}
void BrickCache::lookup(const BrickKey& k, std::vector<int32_t>& data) {
  return this->ci->lookup(k, data);
}
void BrickCache::lookup(const BrickKey& k, std::vector<int64_t>& data) {
  return this->ci->lookup(k, data);
}
void BrickCache::lookup(const BrickKey& k, std::vector<float>& data) {
  return this->ci->lookup(k, data);
}
#endif

const void* BrickCache::add(const BrickKey& k,
                            std::vector<uint8_t>& data) {
  return this->ci->add(k, data);
}
const void* BrickCache::add(const BrickKey& k,
                            std::vector<uint16_t>& data) {
  return this->ci->add(k, data);
}
const void* BrickCache::add(const BrickKey& k,
                            std::vector<uint32_t>& data) {
  return this->ci->add(k, data);
}
const void* BrickCache::add(const BrickKey& k,
                            std::vector<uint64_t>& data) {
  return this->ci->add(k, data);
}
const void* BrickCache::add(const BrickKey& k,
                           std::vector<int8_t>& data) {
  return this->ci->add(k, data);
}
const void* BrickCache::add(const BrickKey& k,
                            std::vector<int16_t>& data) {
  return this->ci->add(k, data);
}
const void* BrickCache::add(const BrickKey& k,
                            std::vector<int32_t>& data) {
  return this->ci->add(k, data);
}
const void* BrickCache::add(const BrickKey& k,
                            std::vector<int64_t>& data) {
  return this->ci->add(k, data);
}
const void* BrickCache::add(const BrickKey& k,
                          std::vector<float>& data) {
  return this->ci->add(k, data);
}

void BrickCache::remove() { this->ci->remove(); }
size_t BrickCache::size() const { return this->ci->size(); }

}
/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2013 Scientific Computing and Imaging Institute,
   University of Utah.

   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.
*/
<commit_msg>remove unused overloads<commit_after>#include <algorithm>
#include <ctime>
#include <functional>
#include <map>
#include <memory>
#include "BrickCache.h"
#include "Controller/StackTimer.h"

namespace tuvok {

// This is used to basically get rid of a type.  You can do:
//   std::vector<TypeErase> data;
//   std::vector<uint8_t> foo;
//   std::vector<uint16_t> bar;
//   data.push_back(TypeErase<std::vector<uint8_t>>(foo));
//   data.push_back(TypeErase<std::vector<uint16_t>>(bar));
// with 'MyTypeOne' and 'MyTypeTwo' being completely unrelated (they do not
// need to have a common base class)
struct TypeErase {
  struct GenericType {
    virtual ~GenericType() {}
    virtual size_t elems() const { return 0; }
  };
  template<typename T> struct TypeEraser : GenericType {
    TypeEraser(T&& t) : thing(std::forward<T>(t)) {}
    virtual ~TypeEraser() {}
    T& get() { return thing; }
    size_t elems() const { return thing.size(); }
    private: T thing;
  };

  std::shared_ptr<GenericType> gt;
  size_t width;

  TypeErase(TypeErase&& other)
    : gt(std::move(other.gt))
    , width(other.width) // width should stay the same right?
  {}

  TypeErase& operator=(TypeErase&& other) {
    if (this != &other) {
      gt = std::move(other.gt);
      width = other.width;  // width should stay the same right?
    }
    return *this;
  }

  // this isn't a very good type eraser, because we require that the type has
  // an internal typedef 'value_type' which we can use to obtain the size of
  // it.  not to mention the '.size()' member function that TypeEraser<>
  // requires, above.
  // But that's fine for our usage here; we're really just using this to store
  // vectors and erase the value_type in there anyway.
  template<typename T> TypeErase(T&& t)
    : gt(new TypeEraser<T>(std::forward<T>(t)))
    , width(sizeof(typename std::remove_reference<T>::type::value_type))
  {}
};

struct BrickInfo {
  BrickKey key;
  uint64_t access_time;
  BrickInfo(const BrickKey& k, time_t t) : key(k),
                                           access_time(uint64_t(t)) {}
};

struct CacheLRU {
  typedef std::pair<BrickInfo, TypeErase> CacheElem;
  bool operator()(const CacheElem& a, const CacheElem& b) const {
    return a.first.access_time > b.first.access_time;
  }
};

struct BrickCache::bcinfo {
    bcinfo(): bytes(0) {}
    // this is wordy but they all just forward to a real implementation below.
    const void* lookup(const BrickKey& k) {
      return this->typed_lookup<uint8_t>(k);
    }

    // the erasure means we can just do the insert with the thing we already
    // have: it'll make a shared_ptr out of it and insert it into the
    // container.
    ///@{
    const void* add(const BrickKey& k, std::vector<uint8_t>& data) {
      return this->typed_add<uint8_t>(k, data);
    }
    const void* add(const BrickKey& k, std::vector<uint16_t>& data) {
      return this->typed_add<uint16_t>(k, data);
    }
    const void* add(const BrickKey& k, std::vector<uint32_t>& data) {
      return this->typed_add<uint32_t>(k, data);
    }
    const void* add(const BrickKey& k, std::vector<uint64_t>& data) {
      return this->typed_add<uint64_t>(k, data);
    }
    const void* add(const BrickKey& k, std::vector<int8_t>& data) {
      return this->typed_add<int8_t>(k, data);
    }
    const void* add(const BrickKey& k, std::vector<int16_t>& data) {
      return this->typed_add<int16_t>(k, data);
    }
    const void* add(const BrickKey& k, std::vector<int32_t>& data) {
      return this->typed_add<int32_t>(k, data);
    }
    const void* add(const BrickKey& k, std::vector<int64_t>& data) {
      return this->typed_add<int64_t>(k, data);
    }
    const void* add(const BrickKey& k, std::vector<float>& data) {
      return this->typed_add<float>(k, data);
    }
    ///@}
    void remove() {
      if(!cache.empty()) {
        // libstdc++ complains it's not a heap otherwise.. somehow.  bug?
        std::make_heap(this->cache.begin(), this->cache.end(), CacheLRU());
        const CacheElem& entry = this->cache.front();
        TypeErase::GenericType& gt = *(entry.second.gt);
        assert((entry.second.width * gt.elems()) <= this->bytes);
        this->bytes -= entry.second.width * gt.elems();

        std::pop_heap(this->cache.begin(), this->cache.end(), CacheLRU());
        this->cache.pop_back();
      }
      assert(this->size() == this->bytes);
    }
    size_t size() const { return this->bytes; }

  private:
    template<typename T> const void* typed_lookup(const BrickKey& k);
    template<typename T> const void* typed_add(const BrickKey&,
                                               std::vector<T>&);

  private:
    typedef std::pair<BrickInfo, TypeErase> CacheElem;
    std::vector<CacheElem> cache;
    size_t bytes; ///< how much memory we're currently using for data.
};

struct KeyMatches {
  bool operator()(const BrickKey& key,
                  const std::pair<BrickInfo,TypeErase>& a) const {
    return key == a.first.key;
  }
};

// if the key doesn't exist, you get an empty vector.
template<typename T>
const void* BrickCache::bcinfo::typed_lookup(const BrickKey& k) {
  using namespace std::placeholders;
  KeyMatches km;
  auto func = std::bind(&KeyMatches::operator(), km, k, _1);

  // gcc can't seem to deduce this with 'auto'.
  typedef std::vector<CacheElem> maptype;
  maptype::iterator i = std::find_if(this->cache.begin(), this->cache.end(),
                                     func);
  if(i == this->cache.end()) { return NULL; }

  i->first.access_time = time(NULL);
  TypeErase::GenericType& gt = *(i->second.gt);
  assert(this->size() == this->bytes);
  return dynamic_cast<TypeErase::TypeEraser<std::vector<T>>&>(gt).get().data();
}

template<typename T>
const void* BrickCache::bcinfo::typed_add(const BrickKey& k,
                                          std::vector<T>& data) {
  // maybe the case of a general cache allows duplicate insert, but for our uses
  // there should never be a duplicate entry.
#ifndef NDEBUG
  KeyMatches km;
  using namespace std::placeholders;
  auto func = std::bind(&KeyMatches::operator(), km, k, _1);
  assert(std::find_if(this->cache.begin(), this->cache.end(), func) ==
         this->cache.end());
#endif
  this->bytes += sizeof(T) * data.size();
  this->cache.push_back(std::make_pair(BrickInfo(k, time(NULL)),
                        std::move(data)));

  assert(this->size() == this->bytes);
  return this->typed_lookup<T>(k);
}

BrickCache::BrickCache() : ci(new BrickCache::bcinfo) {}
BrickCache::~BrickCache() {}

const void* BrickCache::lookup(const BrickKey& k) {
  return this->ci->lookup(k);
}
#if 0
void BrickCache::lookup(const BrickKey& k, std::vector<uint16_t>& data) {
  return this->ci->lookup(k, data);
}
void BrickCache::lookup(const BrickKey& k, std::vector<uint32_t>& data) {
  return this->ci->lookup(k, data);
}
void BrickCache::lookup(const BrickKey& k, std::vector<uint64_t>& data) {
  return this->ci->lookup(k, data);
}
void BrickCache::lookup(const BrickKey& k, std::vector<int8_t>& data) {
  return this->ci->lookup(k, data);
}
void BrickCache::lookup(const BrickKey& k, std::vector<int16_t>& data) {
  return this->ci->lookup(k, data);
}
void BrickCache::lookup(const BrickKey& k, std::vector<int32_t>& data) {
  return this->ci->lookup(k, data);
}
void BrickCache::lookup(const BrickKey& k, std::vector<int64_t>& data) {
  return this->ci->lookup(k, data);
}
void BrickCache::lookup(const BrickKey& k, std::vector<float>& data) {
  return this->ci->lookup(k, data);
}
#endif

const void* BrickCache::add(const BrickKey& k,
                            std::vector<uint8_t>& data) {
  return this->ci->add(k, data);
}
const void* BrickCache::add(const BrickKey& k,
                            std::vector<uint16_t>& data) {
  return this->ci->add(k, data);
}
const void* BrickCache::add(const BrickKey& k,
                            std::vector<uint32_t>& data) {
  return this->ci->add(k, data);
}
const void* BrickCache::add(const BrickKey& k,
                            std::vector<uint64_t>& data) {
  return this->ci->add(k, data);
}
const void* BrickCache::add(const BrickKey& k,
                           std::vector<int8_t>& data) {
  return this->ci->add(k, data);
}
const void* BrickCache::add(const BrickKey& k,
                            std::vector<int16_t>& data) {
  return this->ci->add(k, data);
}
const void* BrickCache::add(const BrickKey& k,
                            std::vector<int32_t>& data) {
  return this->ci->add(k, data);
}
const void* BrickCache::add(const BrickKey& k,
                            std::vector<int64_t>& data) {
  return this->ci->add(k, data);
}
const void* BrickCache::add(const BrickKey& k,
                          std::vector<float>& data) {
  return this->ci->add(k, data);
}

void BrickCache::remove() { this->ci->remove(); }
size_t BrickCache::size() const { return this->ci->size(); }

}
/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2013 Scientific Computing and Imaging Institute,
   University of Utah.

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


<commit_before>#include <cmath>
#include <iostream>
#include <valarray>
#include "nbody.hpp"

/*
 * TODO:
 *     parse input file / arguments
 */

int main(int argc, char *argv[]) {
    // number of bodies
    //const int n = 2;
    const int n = 3;

    // time step
    double dt = 1e-5;
    int steps = 2e5;

    // masses
    //double m[n] = {1.0, 0.1};
    double m[n] = {150.0, 200.0, 250.0};

    // positions and velocities
    //double x_init[6 * n] = {0.0, 1.0, 0.0, 0.0,  0.02, 0.0,
    //                        5.0, 0.0, 0.0, 0.0, -0.2,  0.0};
    double x_init[6 * n] = { 3.0,  1.0, 0.0, 0.0, 0.0, 0.0,
                            -1.0, -2.0, 0.0, 0.0, 0.0, 0.0,
                            -1.0,  1.0, 0.0, 0.0, 0.0, 0.0};

    std::valarray<double> x(x_init, 6 * n);
    print_array(x);
    x = rk4_integrate(x, m, n, dt, steps);

    return 0;
}

void print_array(std::valarray<double> a) {
    for (int i = 0; i < a.size() - 1; i++) {
        std::cout << a[i] << " ";
    }
    std::cout << a[a.size() - 1] << "\n";
}

double dist(std::valarray<double> a, std::valarray<double> b) {
    return sqrt(pow(b - a, 2).sum());
}

std::valarray<double> pos(std::valarray<double> x, int i) {
    return x[std::slice(i * 6, 3, 1)];
}

std::valarray<double> vel(std::valarray<double> x, int i) {
    return x[std::slice(i * 6 + 3, 3, 1)];
}

std::slice pos_sel(int i) { return std::slice(i * 6, 3, 1); }

std::slice vel_sel(int i) { return std::slice(i * 6 + 3, 3, 1); }

std::valarray<double> newton(std::valarray<double> x, double m[], int n) {
    std::valarray<double> ri(3), rj(3);
    std::valarray<double> x_dot(n * 6);

    for (int i = 0; i < n; i++) {
        ri = pos(x, i);
        x_dot[pos_sel(i)] = vel(x, i);

        for (int j = 0; j < n; j++) {
            if (j != i) {
                rj = pos(x, j);
                x_dot[vel_sel(i)] += G * m[j] * (rj - ri)
                                     / pow(dist(rj, ri), 3);
            }
        }
    }

    return x_dot;
}

std::valarray<double> rk4_step(std::valarray<double> x, double m[], int n,
                          double dt) {
    std::valarray<double> k1(n * 6), k2(n * 6), k3(n * 6), k4(n * 6);

    k1 = dt * newton(x, m, n);
    k2 = dt * newton(x + k1 / 2.0, m, n);
    k3 = dt * newton(x + k2 / 2.0, m, n);
    k4 = dt * newton(x + k3, m, n);

    x += (k1 + 2.0 * k2 + 2.0 * k3 + k4) / 6.0;
    print_array(x);

    return x;
}

std::valarray<double> rk4_integrate(std::valarray<double> x, double m[],
                                    int n, double dt, int steps) {
    while (steps--) {
        x = rk4_step(x, m, n, dt);
    }

    return x;
}
<commit_msg>Base n-body integrator class<commit_after>#include <cmath>
#include <cstdlib>
#include <iostream>
#include <valarray>
#include "nbody.hpp"

void NBody::print_state() {
    std::cout << t << " ";
    for (int i = 0; i < X.size() - 1; i++)
        std::cout << X[i] << " ";
    std::cout << X[X.size() - 1] << "\n";
}

void NBody::write_state() {
    // TODO
    ;
}

double NBody::dist(std::valarray<double> a, std::valarray<double> b) {
    return std::sqrt(std::pow(b - a, 2).sum());
}

std::slice NBody::pos_sel(int i_body) {
    return std::slice(2 * n_dims * i_body, n_dims, 1);
}

std::slice NBody::vel_sel(int i_body) {
    return std::slice(2 * n_dims * i_body + n_dims, n_dims, 1);
}

std::valarray<double> NBody::pos(std::valarray<double> x, int i_body) {
    return x[pos_sel(i_body)];
}

std::valarray<double> NBody::vel(std::valarray<double> x, int i_body) {
    return x[vel_sel(i_body)];
}
<|endoftext|>


<commit_before>#include "indexer/feature_meta.hpp"

#include "std/algorithm.hpp"
#include "std/target_os.hpp"

namespace feature
{

namespace
{
char constexpr const * kBaseWikiUrl =
#ifdef OMIM_OS_MOBILE
    ".m.wikipedia.org/wiki/";
#else
    ".wikipedia.org/wiki/";
#endif
} // namespace

string Metadata::GetWikiURL() const
{
  string v = this->Get(FMD_WIKIPEDIA);
  if (v.empty())
    return v;

  auto const colon = v.find(':');
  if (colon == string::npos)
    return v;

  // Spaces and % sign should be replaced in urls.
  replace(v.begin() + colon, v.end(), ' ', '_');
  string::size_type percent, pos = colon;
  string const escapedPercent("%25");
  while ((percent = v.find('%', pos)) != string::npos)
  {
    v.replace(percent, 1, escapedPercent);
    pos = percent + escapedPercent.size();
  }
  // Trying to avoid redirects by constructing the right link.
  // TODO: Wikipedia article could be opened it a user's language, but need
  // generator level support to check for available article languages first.
  return "https://" + v.substr(0, colon) + kBaseWikiUrl + v.substr(colon + 1);
}

}  // namespace feature

// Prints types in osm-friendly format.
string DebugPrint(feature::Metadata::EType type)
{
  using feature::Metadata;
  switch (type)
  {
  case Metadata::FMD_CUISINE: return "cuisine";
  case Metadata::FMD_OPEN_HOURS: return "opening_hours";
  case Metadata::FMD_PHONE_NUMBER: return "phone";
  case Metadata::FMD_FAX_NUMBER: return "fax";
  case Metadata::FMD_STARS: return "stars";
  case Metadata::FMD_OPERATOR: return "operator";
  case Metadata::FMD_URL: return "url";
  case Metadata::FMD_WEBSITE: return "website";
  case Metadata::FMD_INTERNET: return "internet_access";
  case Metadata::FMD_ELE: return "elevation";
  case Metadata::FMD_TURN_LANES: return "turn:lanes";
  case Metadata::FMD_TURN_LANES_FORWARD: return "turn:lanes:forward";
  case Metadata::FMD_TURN_LANES_BACKWARD: return "turn:lanes:backward";
  case Metadata::FMD_EMAIL: return "email";
  case Metadata::FMD_POSTCODE: return "addr:postcode";
  case Metadata::FMD_WIKIPEDIA: return "wikipedia";
  case Metadata::FMD_MAXSPEED: return "maxspeed";
  case Metadata::FMD_FLATS: return "addr:flats";
  case Metadata::FMD_HEIGHT: return "height";
  case Metadata::FMD_MIN_HEIGHT: return "min_height";
  case Metadata::FMD_DENOMINATION: return "denomination";
  case Metadata::FMD_COUNT: CHECK(false, ("FMD_COUNT can not be used as a type."));
  };

  return string();
}
<commit_msg>Missing switch case for Metadata::FMD_BUILDING_LEVELS.<commit_after>#include "indexer/feature_meta.hpp"

#include "std/algorithm.hpp"
#include "std/target_os.hpp"

namespace feature
{

namespace
{
char constexpr const * kBaseWikiUrl =
#ifdef OMIM_OS_MOBILE
    ".m.wikipedia.org/wiki/";
#else
    ".wikipedia.org/wiki/";
#endif
} // namespace

string Metadata::GetWikiURL() const
{
  string v = this->Get(FMD_WIKIPEDIA);
  if (v.empty())
    return v;

  auto const colon = v.find(':');
  if (colon == string::npos)
    return v;

  // Spaces and % sign should be replaced in urls.
  replace(v.begin() + colon, v.end(), ' ', '_');
  string::size_type percent, pos = colon;
  string const escapedPercent("%25");
  while ((percent = v.find('%', pos)) != string::npos)
  {
    v.replace(percent, 1, escapedPercent);
    pos = percent + escapedPercent.size();
  }
  // Trying to avoid redirects by constructing the right link.
  // TODO: Wikipedia article could be opened it a user's language, but need
  // generator level support to check for available article languages first.
  return "https://" + v.substr(0, colon) + kBaseWikiUrl + v.substr(colon + 1);
}

}  // namespace feature

// Prints types in osm-friendly format.
string DebugPrint(feature::Metadata::EType type)
{
  using feature::Metadata;
  switch (type)
  {
  case Metadata::FMD_CUISINE: return "cuisine";
  case Metadata::FMD_OPEN_HOURS: return "opening_hours";
  case Metadata::FMD_PHONE_NUMBER: return "phone";
  case Metadata::FMD_FAX_NUMBER: return "fax";
  case Metadata::FMD_STARS: return "stars";
  case Metadata::FMD_OPERATOR: return "operator";
  case Metadata::FMD_URL: return "url";
  case Metadata::FMD_WEBSITE: return "website";
  case Metadata::FMD_INTERNET: return "internet_access";
  case Metadata::FMD_ELE: return "elevation";
  case Metadata::FMD_TURN_LANES: return "turn:lanes";
  case Metadata::FMD_TURN_LANES_FORWARD: return "turn:lanes:forward";
  case Metadata::FMD_TURN_LANES_BACKWARD: return "turn:lanes:backward";
  case Metadata::FMD_EMAIL: return "email";
  case Metadata::FMD_POSTCODE: return "addr:postcode";
  case Metadata::FMD_WIKIPEDIA: return "wikipedia";
  case Metadata::FMD_MAXSPEED: return "maxspeed";
  case Metadata::FMD_FLATS: return "addr:flats";
  case Metadata::FMD_HEIGHT: return "height";
  case Metadata::FMD_MIN_HEIGHT: return "min_height";
  case Metadata::FMD_DENOMINATION: return "denomination";
  case Metadata::FMD_BUILDING_LEVELS: return "building:levels";
  case Metadata::FMD_COUNT: CHECK(false, ("FMD_COUNT can not be used as a type."));
  };

  return string();
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// @brief Class to allow simple byExample matching of mptr.
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2014-2015 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Michael Hackstein
/// @author Copyright 2014-2015, ArangoDB GmbH, Cologne, Germany
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "ExampleMatcher.h"
#include "Basics/JsonHelper.h"
#include "Basics/StringUtils.h"
#include "Utils/V8ResolverGuard.h"
#include "V8/v8-utils.h"
#include "V8/v8-conv.h"
#include "V8Server/v8-shape-conv.h"
#include "V8Server/v8-vocbaseprivate.h"
#include "VocBase/VocShaper.h"

using namespace std;
using namespace triagens::arango;
using namespace triagens::basics;

////////////////////////////////////////////////////////////////////////////////
/// @brief cleans up the example object
////////////////////////////////////////////////////////////////////////////////

void ExampleMatcher::cleanup () {
  auto zone = _shaper->memoryZone();
  // clean shaped json objects
  for (auto& def : definitions) {
    for (auto& it : def._values) {
      TRI_FreeShapedJson(zone, it);
    }
  }
}

void ExampleMatcher::fillExampleDefinition (v8::Isolate* isolate,
                                            v8::Handle<v8::Object> const& example,
                                            v8::Handle<v8::Array> const& names,
                                            size_t& n,
                                            std::string& errorMessage,
                                            ExampleDefinition& def) {
  TRI_IF_FAILURE("ExampleNoContextVocbase") {
    // intentionally fail
    THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
  }

  TRI_vocbase_t* vocbase = GetContextVocBase(isolate);
  if (vocbase == nullptr) {
    // This should never be thrown as we are already in a transaction
    THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
  }

  def._pids.reserve(n);
  def._values.reserve(n);

  for (size_t i = 0;  i < n;  ++i) {
    v8::Handle<v8::Value> key = names->Get((uint32_t) i);
    v8::Handle<v8::Value> val = example->Get(key);
    TRI_Utf8ValueNFC keyStr(TRI_UNKNOWN_MEM_ZONE, key);
    if (*keyStr != nullptr) {
      auto pid = _shaper->lookupAttributePathByName(*keyStr);

      if (pid == 0) {
        // Internal attributes do have pid == 0.
        if (strncmp("_", *keyStr, 1) == 0) {
          string const key(*keyStr, (size_t) keyStr.length());
          string keyVal = TRI_ObjectToString(val);
          if (TRI_VOC_ATTRIBUTE_KEY == key) {
            def._internal.insert(make_pair(internalAttr::key, DocumentId(0, keyVal)));
          }
          else if (TRI_VOC_ATTRIBUTE_REV == key) {
            def._internal.insert(make_pair(internalAttr::rev, DocumentId(0, keyVal)));
          }
          else {
            // We need a Collection Name Resolver here now!
            V8ResolverGuard resolverGuard(vocbase);
            CollectionNameResolver const* resolver = resolverGuard.getResolver();
            string colName = keyVal.substr(0, keyVal.find("/"));
            keyVal = keyVal.substr(keyVal.find("/") + 1, keyVal.length());
            if (TRI_VOC_ATTRIBUTE_ID == key) {
              def._internal.insert(make_pair(internalAttr::id, DocumentId(resolver->getCollectionId(colName), keyVal)));
            }
            else if (TRI_VOC_ATTRIBUTE_FROM == key) {
              def._internal.insert(make_pair(internalAttr::from, DocumentId(resolver->getCollectionId(colName), keyVal)));
            }
            else if (TRI_VOC_ATTRIBUTE_TO == key) {
              def._internal.insert(make_pair(internalAttr::to, DocumentId(resolver->getCollectionId(colName), keyVal)));
            }
            else {
              // no attribute path found. this means the result will be empty
              THROW_ARANGO_EXCEPTION(TRI_RESULT_ELEMENT_NOT_FOUND);
            }
          }
        }
        else {
          // no attribute path found. this means the result will be empty
          THROW_ARANGO_EXCEPTION(TRI_RESULT_ELEMENT_NOT_FOUND);
        }
      }
      else {
        def._pids.push_back(pid);

        auto value = TRI_ShapedJsonV8Object(isolate, val, _shaper, false);

        if (value == nullptr) {
          THROW_ARANGO_EXCEPTION(TRI_RESULT_ELEMENT_NOT_FOUND);
        }
        def._values.push_back(value);
      }
    }
    else {
      errorMessage = "cannot convert attribute path to UTF8";
      THROW_ARANGO_EXCEPTION(TRI_ERROR_BAD_PARAMETER);
    }
  }
}

void ExampleMatcher::fillExampleDefinition (TRI_json_t const* example,
                                            CollectionNameResolver const* resolver,
                                            ExampleDefinition& def) {

  if ( TRI_IsStringJson(example) ) {
    // Example is an _id value
    char const* _key = strchr(example->_value._string.data, '/');
    if (_key != nullptr) {
      _key += 1;
      def._internal.insert(make_pair(internalAttr::key, DocumentId(0, _key)));
      return;
    } else {
      THROW_ARANGO_EXCEPTION(TRI_RESULT_ELEMENT_NOT_FOUND);
    }
  }
  TRI_vector_t objects = example->_value._objects;

  // Trolololol std::vector in C... ;(
  size_t n = TRI_LengthVector(&objects);

  def._pids.reserve(n);
  def._values.reserve(n);

  try {
    for (size_t i = 0; i < n; i += 2) {
      auto keyObj = static_cast<TRI_json_t const*>(TRI_AtVector(&objects, i));
      TRI_ASSERT(TRI_IsStringJson(keyObj));
      char const* keyStr = keyObj->_value._string.data;
      auto pid = _shaper->lookupAttributePathByName(keyStr);

      if (pid == 0) {
        // Internal attributes do have pid == 0.
        if (strncmp("_", keyStr, 1) == 0) {
          string const key(keyStr);
          auto jsonValue = static_cast<TRI_json_t const*>(TRI_AtVector(&objects, i + 1));
          if (! TRI_IsStringJson(jsonValue)) {
            THROW_ARANGO_EXCEPTION(TRI_ERROR_TYPE_ERROR);
          }
          string keyVal(jsonValue->_value._string.data);
          if (TRI_VOC_ATTRIBUTE_KEY == key) {
            def._internal.insert(make_pair(internalAttr::key, DocumentId(0, keyVal)));
          }
          else if (TRI_VOC_ATTRIBUTE_REV == key) {
            def._internal.insert(make_pair(internalAttr::rev, DocumentId(0, keyVal)));
          }
          else {
            string colName = keyVal.substr(0, keyVal.find("/"));
            keyVal = keyVal.substr(keyVal.find("/") + 1, keyVal.length());
            if (TRI_VOC_ATTRIBUTE_ID == key) {
              def._internal.insert(make_pair(internalAttr::id, DocumentId(resolver->getCollectionId(colName), keyVal)));
            }
            else if (TRI_VOC_ATTRIBUTE_FROM == key) {
              def._internal.insert(make_pair(internalAttr::from, DocumentId(resolver->getCollectionId(colName), keyVal)));
            }
            else if (TRI_VOC_ATTRIBUTE_TO == key) {
              def._internal.insert(make_pair(internalAttr::to, DocumentId(resolver->getCollectionId(colName), keyVal)));
            }
            else {
              // no attribute path found. this means the result will be empty
              THROW_ARANGO_EXCEPTION(TRI_RESULT_ELEMENT_NOT_FOUND);
            }

          }
        }
        else {
          // no attribute path found. this means the result will be empty
          THROW_ARANGO_EXCEPTION(TRI_RESULT_ELEMENT_NOT_FOUND);
        }
      }
      else {
        def._pids.push_back(pid);
        auto jsonValue = static_cast<TRI_json_t const*>(TRI_AtVector(&objects, i + 1));
        auto value = TRI_ShapedJsonJson(_shaper, jsonValue, false);

        if (value == nullptr) {
          THROW_ARANGO_EXCEPTION(TRI_RESULT_ELEMENT_NOT_FOUND);
        }

        def._values.push_back(value);
      }
    }
  }
  catch (bad_alloc&) {
    ExampleMatcher::cleanup();
    throw;
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief Constructor using a v8::Object example
////////////////////////////////////////////////////////////////////////////////

ExampleMatcher::ExampleMatcher (v8::Isolate* isolate,
                                v8::Handle<v8::Object> const example,
                                VocShaper* shaper,
                                std::string& errorMessage)
  : _shaper(shaper) {

  v8::Handle<v8::Array> names = example->GetOwnPropertyNames();
  size_t n = names->Length();

  ExampleDefinition def;

  try {
    ExampleMatcher::fillExampleDefinition(isolate, example, names, n, errorMessage, def);
  }
  catch (...) {
    ExampleMatcher::cleanup();
    throw;
  }
  definitions.emplace_back(move(def));
}

////////////////////////////////////////////////////////////////////////////////
/// @brief Constructor using an v8::Array of v8::Object examples
////////////////////////////////////////////////////////////////////////////////

ExampleMatcher::ExampleMatcher (v8::Isolate* isolate,
                                v8::Handle<v8::Array> const examples,
                                VocShaper* shaper,
                                std::string& errorMessage)
  : _shaper(shaper) {

  size_t exCount = examples->Length();
  for (size_t j = 0; j < exCount; ++j) {
    auto tmp = examples->Get((uint32_t) j);
    if (! tmp->IsObject() || tmp->IsArray()) {
      // Right now silently ignore this example
      continue;
    }
    v8::Handle<v8::Object> example = v8::Handle<v8::Object>::Cast(tmp);
    v8::Handle<v8::Array> names = example->GetOwnPropertyNames();
    size_t n = names->Length();

    ExampleDefinition def;

    try {
      ExampleMatcher::fillExampleDefinition(isolate, example, names, n, errorMessage, def);
    }
    catch (...) {
      ExampleMatcher::cleanup();
      throw;
    }
    definitions.emplace_back(move(def));
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief Constructor using a TRI_json_t object
////////////////////////////////////////////////////////////////////////////////

ExampleMatcher::ExampleMatcher (TRI_json_t const* example,
                                VocShaper* shaper,
                                CollectionNameResolver const* resolver)
  : _shaper(shaper) {

  if (TRI_IsObjectJson(example) || TRI_IsStringJson(example)) {
    ExampleDefinition def;
    try {
      ExampleMatcher::fillExampleDefinition(example, resolver, def);
    }
    catch (...) {
      ExampleMatcher::cleanup();
      throw;
    }
    definitions.emplace_back(move(def));
  }
  else if (TRI_IsArrayJson(example)) {
    size_t size = TRI_LengthArrayJson(example);
    for (size_t i = 0; i < size; ++i) {
      ExampleDefinition def;
      try {
        ExampleMatcher::fillExampleDefinition(TRI_LookupArrayJson(example, i), resolver, def);
        definitions.emplace_back(move(def));
      }
      catch (triagens::basics::Exception& e) {
        if (e.code() != TRI_RESULT_ELEMENT_NOT_FOUND) {
          ExampleMatcher::cleanup();
          throw;
        }
        // Result not found might happen. Ignore here because all other elemens
        // might be matched.
      }
    }
    if (definitions.size() == 0) {
      // None of the given examples could ever match.
      // Throw result not found so client can short circuit.
      THROW_ARANGO_EXCEPTION(TRI_RESULT_ELEMENT_NOT_FOUND);
    }
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief Checks if the given mptr matches the examples in this class
////////////////////////////////////////////////////////////////////////////////

bool ExampleMatcher::matches (TRI_voc_cid_t cid, TRI_doc_mptr_t const* mptr) const {
  if (mptr == nullptr) {
    return false;
  }
  TRI_shaped_json_t document;
  TRI_EXTRACT_SHAPED_JSON_MARKER(document, mptr->getDataPtr());
  for (auto def : definitions) {
    if (def._internal.size() > 0) {
      // Match _key
      auto it = def._internal.find(internalAttr::key);
      if (it != def._internal.end()) {
        if (strcmp(it->second.key.c_str(), TRI_EXTRACT_MARKER_KEY(mptr)) != 0) {
          goto nextExample;
        }
      }
      // Match _rev
      it = def._internal.find(internalAttr::rev);
      if (it != def._internal.end()) {
        if (triagens::basics::StringUtils::uint64(it->second.key) != mptr->_rid) {
          goto nextExample;
        }
      }
      // Match _id
      it = def._internal.find(internalAttr::id);
      if (it != def._internal.end()) {
        if (cid != it->second.cid) {
          goto nextExample;
        }
        if (strcmp(it->second.key.c_str(), TRI_EXTRACT_MARKER_KEY(mptr)) != 0) {
          goto nextExample;
        }
      }
      // Match _to
      it = def._internal.find(internalAttr::to);
      if (it != def._internal.end()) {
        if (it->second.cid != TRI_EXTRACT_MARKER_TO_CID(mptr)) {
          goto nextExample;
        }
        if (strcmp(it->second.key.c_str(), TRI_EXTRACT_MARKER_TO_KEY(mptr)) != 0) {
          goto nextExample;
        }
      }
      // Match _from
      it = def._internal.find(internalAttr::from);
      if (it != def._internal.end()) {
        if (it->second.cid != TRI_EXTRACT_MARKER_FROM_CID(mptr)) {
          goto nextExample;
        }
        if (strcmp(it->second.key.c_str(), TRI_EXTRACT_MARKER_FROM_KEY(mptr)) != 0) {
          goto nextExample;
        }
      }
    }
    TRI_shaped_json_t result;
    TRI_shape_t const* shape;

    for (size_t i = 0;  i < def._values.size();  ++i) {
      TRI_shaped_json_t* example = def._values[i];

      bool ok = _shaper->extractShapedJson(&document,
                                           example->_sid,
                                           def._pids[i],
                                           &result,
                                           &shape);

      if (! ok || shape == nullptr) {
        goto nextExample;
      }

      if (result._data.length != example->_data.length) {
        // suppress excessive log spam
        // LOG_TRACE("expecting length %lu, got length %lu for path %lu",
        //           (unsigned long) result._data.length,
        //           (unsigned long) example->_data.length,
        //           (unsigned long) pids[i]);

        goto nextExample;
      }

      if (memcmp(result._data.data, example->_data.data, example->_data.length) != 0) {
        // suppress excessive log spam
        // LOG_TRACE("data mismatch at path %lu", (unsigned long) pids[i]);
        goto nextExample;
      }
    }
    // If you get here this example matches. Successful hit.
    return true;
    nextExample:
    // This Example does not match, try the next one. Goto requires a statement
    continue;
  }
  return false;
}
<commit_msg>Potential fix for memleak<commit_after>////////////////////////////////////////////////////////////////////////////////
/// @brief Class to allow simple byExample matching of mptr.
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2014-2015 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Michael Hackstein
/// @author Copyright 2014-2015, ArangoDB GmbH, Cologne, Germany
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "ExampleMatcher.h"
#include "Basics/JsonHelper.h"
#include "Basics/StringUtils.h"
#include "Utils/V8ResolverGuard.h"
#include "V8/v8-utils.h"
#include "V8/v8-conv.h"
#include "V8Server/v8-shape-conv.h"
#include "V8Server/v8-vocbaseprivate.h"
#include "VocBase/VocShaper.h"

using namespace std;
using namespace triagens::arango;
using namespace triagens::basics;

////////////////////////////////////////////////////////////////////////////////
/// @brief cleans up the example object
////////////////////////////////////////////////////////////////////////////////

void ExampleMatcher::cleanup () {
  auto zone = _shaper->memoryZone();
  // clean shaped json objects
  for (auto& def : definitions) {
    for (auto& it : def._values) {
      TRI_FreeShapedJson(zone, it);
      it = nullptr;
    }
  }
}

void ExampleMatcher::fillExampleDefinition (v8::Isolate* isolate,
                                            v8::Handle<v8::Object> const& example,
                                            v8::Handle<v8::Array> const& names,
                                            size_t& n,
                                            std::string& errorMessage,
                                            ExampleDefinition& def) {
  TRI_IF_FAILURE("ExampleNoContextVocbase") {
    // intentionally fail
    THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
  }

  TRI_vocbase_t* vocbase = GetContextVocBase(isolate);
  if (vocbase == nullptr) {
    // This should never be thrown as we are already in a transaction
    THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
  }

  def._pids.reserve(n);
  def._values.reserve(n);

  for (size_t i = 0;  i < n;  ++i) {
    v8::Handle<v8::Value> key = names->Get((uint32_t) i);
    v8::Handle<v8::Value> val = example->Get(key);
    TRI_Utf8ValueNFC keyStr(TRI_UNKNOWN_MEM_ZONE, key);
    if (*keyStr != nullptr) {
      auto pid = _shaper->lookupAttributePathByName(*keyStr);

      if (pid == 0) {
        // Internal attributes do have pid == 0.
        if (strncmp("_", *keyStr, 1) == 0) {
          string const key(*keyStr, (size_t) keyStr.length());
          string keyVal = TRI_ObjectToString(val);
          if (TRI_VOC_ATTRIBUTE_KEY == key) {
            def._internal.insert(make_pair(internalAttr::key, DocumentId(0, keyVal)));
          }
          else if (TRI_VOC_ATTRIBUTE_REV == key) {
            def._internal.insert(make_pair(internalAttr::rev, DocumentId(0, keyVal)));
          }
          else {
            // We need a Collection Name Resolver here now!
            V8ResolverGuard resolverGuard(vocbase);
            CollectionNameResolver const* resolver = resolverGuard.getResolver();
            string colName = keyVal.substr(0, keyVal.find("/"));
            keyVal = keyVal.substr(keyVal.find("/") + 1, keyVal.length());
            if (TRI_VOC_ATTRIBUTE_ID == key) {
              def._internal.insert(make_pair(internalAttr::id, DocumentId(resolver->getCollectionId(colName), keyVal)));
            }
            else if (TRI_VOC_ATTRIBUTE_FROM == key) {
              def._internal.insert(make_pair(internalAttr::from, DocumentId(resolver->getCollectionId(colName), keyVal)));
            }
            else if (TRI_VOC_ATTRIBUTE_TO == key) {
              def._internal.insert(make_pair(internalAttr::to, DocumentId(resolver->getCollectionId(colName), keyVal)));
            }
            else {
              // no attribute path found. this means the result will be empty
              THROW_ARANGO_EXCEPTION(TRI_RESULT_ELEMENT_NOT_FOUND);
            }
          }
        }
        else {
          // no attribute path found. this means the result will be empty
          THROW_ARANGO_EXCEPTION(TRI_RESULT_ELEMENT_NOT_FOUND);
        }
      }
      else {
        def._pids.push_back(pid);

        std::unique_ptr<TRI_shaped_json_t> value(TRI_ShapedJsonV8Object(isolate, val, _shaper, false));

        if (value.get() == nullptr) {
          THROW_ARANGO_EXCEPTION(TRI_RESULT_ELEMENT_NOT_FOUND);
        }
        def._values.push_back(value.get());
        value.release();
      }
    }
    else {
      errorMessage = "cannot convert attribute path to UTF8";
      THROW_ARANGO_EXCEPTION(TRI_ERROR_BAD_PARAMETER);
    }
  }
}

void ExampleMatcher::fillExampleDefinition (TRI_json_t const* example,
                                            CollectionNameResolver const* resolver,
                                            ExampleDefinition& def) {

  if ( TRI_IsStringJson(example) ) {
    // Example is an _id value
    char const* _key = strchr(example->_value._string.data, '/');
    if (_key != nullptr) {
      _key += 1;
      def._internal.insert(make_pair(internalAttr::key, DocumentId(0, _key)));
      return;
    } else {
      THROW_ARANGO_EXCEPTION(TRI_RESULT_ELEMENT_NOT_FOUND);
    }
  }
  TRI_vector_t objects = example->_value._objects;

  // Trolololol std::vector in C... ;(
  size_t n = TRI_LengthVector(&objects);

  def._pids.reserve(n);
  def._values.reserve(n);

  try {
    for (size_t i = 0; i < n; i += 2) {
      auto keyObj = static_cast<TRI_json_t const*>(TRI_AtVector(&objects, i));
      TRI_ASSERT(TRI_IsStringJson(keyObj));
      char const* keyStr = keyObj->_value._string.data;
      auto pid = _shaper->lookupAttributePathByName(keyStr);

      if (pid == 0) {
        // Internal attributes do have pid == 0.
        if (strncmp("_", keyStr, 1) == 0) {
          string const key(keyStr);
          auto jsonValue = static_cast<TRI_json_t const*>(TRI_AtVector(&objects, i + 1));
          if (! TRI_IsStringJson(jsonValue)) {
            THROW_ARANGO_EXCEPTION(TRI_ERROR_TYPE_ERROR);
          }
          string keyVal(jsonValue->_value._string.data);
          if (TRI_VOC_ATTRIBUTE_KEY == key) {
            def._internal.insert(make_pair(internalAttr::key, DocumentId(0, keyVal)));
          }
          else if (TRI_VOC_ATTRIBUTE_REV == key) {
            def._internal.insert(make_pair(internalAttr::rev, DocumentId(0, keyVal)));
          }
          else {
            string colName = keyVal.substr(0, keyVal.find("/"));
            keyVal = keyVal.substr(keyVal.find("/") + 1, keyVal.length());
            if (TRI_VOC_ATTRIBUTE_ID == key) {
              def._internal.insert(make_pair(internalAttr::id, DocumentId(resolver->getCollectionId(colName), keyVal)));
            }
            else if (TRI_VOC_ATTRIBUTE_FROM == key) {
              def._internal.insert(make_pair(internalAttr::from, DocumentId(resolver->getCollectionId(colName), keyVal)));
            }
            else if (TRI_VOC_ATTRIBUTE_TO == key) {
              def._internal.insert(make_pair(internalAttr::to, DocumentId(resolver->getCollectionId(colName), keyVal)));
            }
            else {
              // no attribute path found. this means the result will be empty
              THROW_ARANGO_EXCEPTION(TRI_RESULT_ELEMENT_NOT_FOUND);
            }

          }
        }
        else {
          // no attribute path found. this means the result will be empty
          THROW_ARANGO_EXCEPTION(TRI_RESULT_ELEMENT_NOT_FOUND);
        }
      }
      else {
        def._pids.push_back(pid);
        auto jsonValue = static_cast<TRI_json_t const*>(TRI_AtVector(&objects, i + 1));
        auto value = TRI_ShapedJsonJson(_shaper, jsonValue, false);

        if (value == nullptr) {
          THROW_ARANGO_EXCEPTION(TRI_RESULT_ELEMENT_NOT_FOUND);
        }

        def._values.push_back(value);
      }
    }
  }
  catch (bad_alloc&) {
    ExampleMatcher::cleanup();
    throw;
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief Constructor using a v8::Object example
////////////////////////////////////////////////////////////////////////////////

ExampleMatcher::ExampleMatcher (v8::Isolate* isolate,
                                v8::Handle<v8::Object> const example,
                                VocShaper* shaper,
                                std::string& errorMessage)
  : _shaper(shaper) {

  v8::Handle<v8::Array> names = example->GetOwnPropertyNames();
  size_t n = names->Length();

  ExampleDefinition def;

  try {
    ExampleMatcher::fillExampleDefinition(isolate, example, names, n, errorMessage, def);
  }
  catch (...) {
    ExampleMatcher::cleanup();
    throw;
  }
  definitions.emplace_back(move(def));
}

////////////////////////////////////////////////////////////////////////////////
/// @brief Constructor using an v8::Array of v8::Object examples
////////////////////////////////////////////////////////////////////////////////

ExampleMatcher::ExampleMatcher (v8::Isolate* isolate,
                                v8::Handle<v8::Array> const examples,
                                VocShaper* shaper,
                                std::string& errorMessage)
  : _shaper(shaper) {

  size_t exCount = examples->Length();
  for (size_t j = 0; j < exCount; ++j) {
    auto tmp = examples->Get((uint32_t) j);
    if (! tmp->IsObject() || tmp->IsArray()) {
      // Right now silently ignore this example
      continue;
    }
    v8::Handle<v8::Object> example = v8::Handle<v8::Object>::Cast(tmp);
    v8::Handle<v8::Array> names = example->GetOwnPropertyNames();
    size_t n = names->Length();

    ExampleDefinition def;

    try {
      ExampleMatcher::fillExampleDefinition(isolate, example, names, n, errorMessage, def);
    }
    catch (...) {
      ExampleMatcher::cleanup();
      throw;
    }
    definitions.emplace_back(move(def));
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief Constructor using a TRI_json_t object
////////////////////////////////////////////////////////////////////////////////

ExampleMatcher::ExampleMatcher (TRI_json_t const* example,
                                VocShaper* shaper,
                                CollectionNameResolver const* resolver)
  : _shaper(shaper) {

  if (TRI_IsObjectJson(example) || TRI_IsStringJson(example)) {
    ExampleDefinition def;
    try {
      ExampleMatcher::fillExampleDefinition(example, resolver, def);
    }
    catch (...) {
      ExampleMatcher::cleanup();
      throw;
    }
    definitions.emplace_back(move(def));
  }
  else if (TRI_IsArrayJson(example)) {
    size_t size = TRI_LengthArrayJson(example);
    for (size_t i = 0; i < size; ++i) {
      ExampleDefinition def;
      try {
        ExampleMatcher::fillExampleDefinition(TRI_LookupArrayJson(example, i), resolver, def);
        definitions.emplace_back(move(def));
      }
      catch (triagens::basics::Exception& e) {
        if (e.code() != TRI_RESULT_ELEMENT_NOT_FOUND) {
          ExampleMatcher::cleanup();
          throw;
        }
        // Result not found might happen. Ignore here because all other elemens
        // might be matched.
      }
    }
    if (definitions.size() == 0) {
      // None of the given examples could ever match.
      // Throw result not found so client can short circuit.
      THROW_ARANGO_EXCEPTION(TRI_RESULT_ELEMENT_NOT_FOUND);
    }
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief Checks if the given mptr matches the examples in this class
////////////////////////////////////////////////////////////////////////////////

bool ExampleMatcher::matches (TRI_voc_cid_t cid, TRI_doc_mptr_t const* mptr) const {
  if (mptr == nullptr) {
    return false;
  }
  TRI_shaped_json_t document;
  TRI_EXTRACT_SHAPED_JSON_MARKER(document, mptr->getDataPtr());
  for (auto def : definitions) {
    if (def._internal.size() > 0) {
      // Match _key
      auto it = def._internal.find(internalAttr::key);
      if (it != def._internal.end()) {
        if (strcmp(it->second.key.c_str(), TRI_EXTRACT_MARKER_KEY(mptr)) != 0) {
          goto nextExample;
        }
      }
      // Match _rev
      it = def._internal.find(internalAttr::rev);
      if (it != def._internal.end()) {
        if (triagens::basics::StringUtils::uint64(it->second.key) != mptr->_rid) {
          goto nextExample;
        }
      }
      // Match _id
      it = def._internal.find(internalAttr::id);
      if (it != def._internal.end()) {
        if (cid != it->second.cid) {
          goto nextExample;
        }
        if (strcmp(it->second.key.c_str(), TRI_EXTRACT_MARKER_KEY(mptr)) != 0) {
          goto nextExample;
        }
      }
      // Match _to
      it = def._internal.find(internalAttr::to);
      if (it != def._internal.end()) {
        if (it->second.cid != TRI_EXTRACT_MARKER_TO_CID(mptr)) {
          goto nextExample;
        }
        if (strcmp(it->second.key.c_str(), TRI_EXTRACT_MARKER_TO_KEY(mptr)) != 0) {
          goto nextExample;
        }
      }
      // Match _from
      it = def._internal.find(internalAttr::from);
      if (it != def._internal.end()) {
        if (it->second.cid != TRI_EXTRACT_MARKER_FROM_CID(mptr)) {
          goto nextExample;
        }
        if (strcmp(it->second.key.c_str(), TRI_EXTRACT_MARKER_FROM_KEY(mptr)) != 0) {
          goto nextExample;
        }
      }
    }
    TRI_shaped_json_t result;
    TRI_shape_t const* shape;

    for (size_t i = 0;  i < def._values.size();  ++i) {
      TRI_shaped_json_t* example = def._values[i];

      bool ok = _shaper->extractShapedJson(&document,
                                           example->_sid,
                                           def._pids[i],
                                           &result,
                                           &shape);

      if (! ok || shape == nullptr) {
        goto nextExample;
      }

      if (result._data.length != example->_data.length) {
        // suppress excessive log spam
        // LOG_TRACE("expecting length %lu, got length %lu for path %lu",
        //           (unsigned long) result._data.length,
        //           (unsigned long) example->_data.length,
        //           (unsigned long) pids[i]);

        goto nextExample;
      }

      if (memcmp(result._data.data, example->_data.data, example->_data.length) != 0) {
        // suppress excessive log spam
        // LOG_TRACE("data mismatch at path %lu", (unsigned long) pids[i]);
        goto nextExample;
      }
    }
    // If you get here this example matches. Successful hit.
    return true;
    nextExample:
    // This Example does not match, try the next one. Goto requires a statement
    continue;
  }
  return false;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2014-2016 CyberVision, Inc.
 *
 * 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 "kaa/failover/DefaultFailoverStrategy.hpp"

namespace kaa {

const std::size_t DefaultFailoverStrategy::DEFAULT_BOOTSTRAP_SERVERS_RETRY_PERIOD;
const std::size_t DefaultFailoverStrategy::DEFAULT_OPERATION_SERVERS_RETRY_PERIOD;
const std::size_t DefaultFailoverStrategy::DEFAULT_NO_OPERATION_SERVERS_RETRY_PERIOD;
const std::size_t DefaultFailoverStrategy::DEFAULT_CURRENT_BOOTSTRAP_SERVER_NA;
const std::size_t DefaultFailoverStrategy::DEFAULT_NO_CONNECTIVITY_RETRY_PERIOD;

FailoverStrategyDecision DefaultFailoverStrategy::onFailover(KaaFailoverReason failover)
{
        switch (failover) {
        case KaaFailoverReason::BOOTSTRAP_SERVERS_NA:
            return FailoverStrategyDecision(FailoverStrategyAction::RETRY,
                                            bootstrapServersRetryPeriod_);

        case KaaFailoverReason::NO_OPERATION_SERVERS_RECEIVED:
            return FailoverStrategyDecision(FailoverStrategyAction::USE_NEXT_BOOTSTRAP,
                                            noOperationServersRetryPeriod_);

        case KaaFailoverReason::OPERATION_SERVERS_NA:
            return FailoverStrategyDecision(FailoverStrategyAction::RETRY,
                                            operationServersRetryPeriod_);

        case KaaFailoverReason::NO_CONNECTIVITY:
            return FailoverStrategyDecision(FailoverStrategyAction::RETRY,
                                            noConnectivityRetryPeriod_);

        case KaaFailoverReason::CREDENTIALS_REVOKED:
        case KaaFailoverReason::ENDPOINT_NOT_REGISTERED:
            return FailoverStrategyDecision(FailoverStrategyAction::STOP_APP);

        default:
            return FailoverStrategyDecision(FailoverStrategyAction::NOOP);
        }
}

}
<commit_msg>KAA-965 Change default behaviour<commit_after>/*
 * Copyright 2014-2016 CyberVision, Inc.
 *
 * 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 "kaa/failover/DefaultFailoverStrategy.hpp"

namespace kaa {

const std::size_t DefaultFailoverStrategy::DEFAULT_BOOTSTRAP_SERVERS_RETRY_PERIOD;
const std::size_t DefaultFailoverStrategy::DEFAULT_OPERATION_SERVERS_RETRY_PERIOD;
const std::size_t DefaultFailoverStrategy::DEFAULT_NO_OPERATION_SERVERS_RETRY_PERIOD;
const std::size_t DefaultFailoverStrategy::DEFAULT_CURRENT_BOOTSTRAP_SERVER_NA;
const std::size_t DefaultFailoverStrategy::DEFAULT_NO_CONNECTIVITY_RETRY_PERIOD;

FailoverStrategyDecision DefaultFailoverStrategy::onFailover(KaaFailoverReason failover)
{
        switch (failover) {
        case KaaFailoverReason::BOOTSTRAP_SERVERS_NA:
            return FailoverStrategyDecision(FailoverStrategyAction::RETRY,
                                            bootstrapServersRetryPeriod_);

        case KaaFailoverReason::NO_OPERATION_SERVERS_RECEIVED:
            return FailoverStrategyDecision(FailoverStrategyAction::USE_NEXT_BOOTSTRAP,
                                            noOperationServersRetryPeriod_);

        case KaaFailoverReason::OPERATION_SERVERS_NA:
            return FailoverStrategyDecision(FailoverStrategyAction::RETRY,
                                            operationServersRetryPeriod_);

        case KaaFailoverReason::NO_CONNECTIVITY:
            return FailoverStrategyDecision(FailoverStrategyAction::RETRY,
                                            noConnectivityRetryPeriod_);

        case KaaFailoverReason::CREDENTIALS_REVOKED:
        case KaaFailoverReason::ENDPOINT_NOT_REGISTERED:
            return FailoverStrategyDecision(FailoverStrategyAction::RETRY);

        default:
            return FailoverStrategyDecision(FailoverStrategyAction::NOOP);
        }
}

}
<|endoftext|>


<commit_before>/*The MIT License (MIT)

Copyright (c) 2014 Johannes Häggqvist

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 "extract.h"
#include "pretty.h"
#include "options.h"
#include "path.h"

#include <ZAP/Archive.h>

#include <fstream>
#include <iostream>
#include <iomanip>
#include <string>

namespace cli
{
	static void print(const ZAP::Archive &archive)
	{
		std::cout <<
			"Version: " << getPrettyVersion(archive.getVersion()) <<
			"\nCompression: " << getPrettyCompression(archive.getCompression()) << (archive.isSupportedCompression() ? " (supported)" : " (unsupported)") <<
			"\nFile count: " << archive.getFileCount() <<
			"\n\n";

		ZAP::Archive::EntryList filelist;
		archive.getFileList(filelist);

		static const int fieldMargin = 1;
		int field0 = 4+fieldMargin, field1 = 10+fieldMargin, field2 = 12+fieldMargin;
		for (const ZAP::Archive::Entry &entry : filelist)
		{
			int newField0 = entry.virtual_path.size()+fieldMargin;
			int newField1 = getPrettySize(entry.compressed_size).size()+fieldMargin;
			int newField2 = getPrettySize(entry.decompressed_size).size()+fieldMargin;
			if (newField0 > field0)
				field0 = newField0;
			if (newField1 > field1)
				field1 = newField1;
			if (newField2 > field2)
				field2 = newField2;
		}

		int totalComp = 0, totalDecomp = 0;

		std::ios::fmtflags nameFlags = std::ios::left;
		std::ios::fmtflags sizeFlags = std::ios::right;

		std::cout <<
			std::setiosflags(nameFlags) <<
			std::setw(field0) << "Path" <<
			std::setiosflags(sizeFlags) <<
			std::setw(field1) << "Comp. size" <<
			std::setw(field2) << "Decomp. size" <<
			std::resetiosflags(sizeFlags) <<
			'\n';
		for (const ZAP::Archive::Entry &file : filelist)
		{
			totalComp += file.compressed_size;
			totalDecomp += file.decompressed_size;
			std::cout <<
				std::setiosflags(nameFlags) <<
				std::setw(field0) << file.virtual_path <<
				std::setiosflags(sizeFlags) <<
				std::setw(field1) << getPrettySize(file.compressed_size) <<
				std::setw(field2) << getPrettySize(file.decompressed_size) <<
				std::resetiosflags(sizeFlags) <<
				'\n';
		}

		std::cout <<
			std::setw(16) << "\nTotal comp.: " << getPrettySize(totalComp) <<
			std::setw(16) << "\nTotal decomp.: " << getPrettySize(totalDecomp) <<
			'\n';

		std::cout << std::flush;
	}

	int extract(option::Parser &parse, option::Option *options)
	{
		if (parse.nonOptionsCount() < 1)
		{
			std::cerr << "Filename required" << std::endl;
			return 1;
		}
		std::string path = parse.nonOption(0);

		ZAP::Archive archive;
		if (!archive.openFile(path))
		{
			std::cerr << "Could not open file" << std::endl;
			return 1;
		}

		if (options[LIST])
		{
			print(archive);
		}
		else
		{
			std::string outPath = ".";
			if (parse.nonOptionsCount() >= 2)
			{
				outPath = parse.nonOption(1);
			}
			if (!isDirectory(outPath))
			{
				std::cerr << "Output is not a directory" << std::endl;
				return 1;
			}

			ZAP::Archive::EntryList list;
			archive.getFileList(list);

			for (const ZAP::Archive::Entry &entry : list)
			{
				std::string fullpath = (outPath + '/' + entry.virtual_path);
				cleanPath(fullpath);
				if (!createPath(fullpath))
				{
					std::cerr << "Could not create path " << fullpath << std::endl;
					continue;
				}

				std::fstream stream(fullpath.c_str(), std::ios::out | std::ios::binary | std::ios::trunc);
				if (!stream.is_open())
				{
					std::cerr << "Could not create file " << entry.virtual_path << std::endl;
					continue;
				}

				char *data;
				size_t size;

				bool extractSuccess = false;
				if (options[RAW])
					extractSuccess = archive.getRawData(entry.virtual_path, data, size);
				else
					extractSuccess = archive.getData(entry.virtual_path, data, size);

				if (!extractSuccess)
				{
					std::cerr << "Could not extract file " << entry.virtual_path << std::endl;
					continue;
				}

				stream.write(data, size);

				delete[] data;
			}
		}

		return 0;
	}
}
<commit_msg>Changed "Could not open file" to "Could not open archive"<commit_after>/*The MIT License (MIT)

Copyright (c) 2014 Johannes Häggqvist

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 "extract.h"
#include "pretty.h"
#include "options.h"
#include "path.h"

#include <ZAP/Archive.h>

#include <fstream>
#include <iostream>
#include <iomanip>
#include <string>

namespace cli
{
	static void print(const ZAP::Archive &archive)
	{
		std::cout <<
			"Version: " << getPrettyVersion(archive.getVersion()) <<
			"\nCompression: " << getPrettyCompression(archive.getCompression()) << (archive.isSupportedCompression() ? " (supported)" : " (unsupported)") <<
			"\nFile count: " << archive.getFileCount() <<
			"\n\n";

		ZAP::Archive::EntryList filelist;
		archive.getFileList(filelist);

		static const int fieldMargin = 1;
		int field0 = 4+fieldMargin, field1 = 10+fieldMargin, field2 = 12+fieldMargin;
		for (const ZAP::Archive::Entry &entry : filelist)
		{
			int newField0 = entry.virtual_path.size()+fieldMargin;
			int newField1 = getPrettySize(entry.compressed_size).size()+fieldMargin;
			int newField2 = getPrettySize(entry.decompressed_size).size()+fieldMargin;
			if (newField0 > field0)
				field0 = newField0;
			if (newField1 > field1)
				field1 = newField1;
			if (newField2 > field2)
				field2 = newField2;
		}

		int totalComp = 0, totalDecomp = 0;

		std::ios::fmtflags nameFlags = std::ios::left;
		std::ios::fmtflags sizeFlags = std::ios::right;

		std::cout <<
			std::setiosflags(nameFlags) <<
			std::setw(field0) << "Path" <<
			std::setiosflags(sizeFlags) <<
			std::setw(field1) << "Comp. size" <<
			std::setw(field2) << "Decomp. size" <<
			std::resetiosflags(sizeFlags) <<
			'\n';
		for (const ZAP::Archive::Entry &file : filelist)
		{
			totalComp += file.compressed_size;
			totalDecomp += file.decompressed_size;
			std::cout <<
				std::setiosflags(nameFlags) <<
				std::setw(field0) << file.virtual_path <<
				std::setiosflags(sizeFlags) <<
				std::setw(field1) << getPrettySize(file.compressed_size) <<
				std::setw(field2) << getPrettySize(file.decompressed_size) <<
				std::resetiosflags(sizeFlags) <<
				'\n';
		}

		std::cout <<
			std::setw(16) << "\nTotal comp.: " << getPrettySize(totalComp) <<
			std::setw(16) << "\nTotal decomp.: " << getPrettySize(totalDecomp) <<
			'\n';

		std::cout << std::flush;
	}

	int extract(option::Parser &parse, option::Option *options)
	{
		if (parse.nonOptionsCount() < 1)
		{
			std::cerr << "Filename required" << std::endl;
			return 1;
		}
		std::string path = parse.nonOption(0);

		ZAP::Archive archive;
		if (!archive.openFile(path))
		{
			std::cerr << "Could not open archive" << std::endl;
			return 1;
		}

		if (options[LIST])
		{
			print(archive);
		}
		else
		{
			std::string outPath = ".";
			if (parse.nonOptionsCount() >= 2)
			{
				outPath = parse.nonOption(1);
			}
			if (!isDirectory(outPath))
			{
				std::cerr << "Output is not a directory" << std::endl;
				return 1;
			}

			ZAP::Archive::EntryList list;
			archive.getFileList(list);

			for (const ZAP::Archive::Entry &entry : list)
			{
				std::string fullpath = (outPath + '/' + entry.virtual_path);
				cleanPath(fullpath);
				if (!createPath(fullpath))
				{
					std::cerr << "Could not create path " << fullpath << std::endl;
					continue;
				}

				std::fstream stream(fullpath.c_str(), std::ios::out | std::ios::binary | std::ios::trunc);
				if (!stream.is_open())
				{
					std::cerr << "Could not create file " << entry.virtual_path << std::endl;
					continue;
				}

				char *data;
				size_t size;

				bool extractSuccess = false;
				if (options[RAW])
					extractSuccess = archive.getRawData(entry.virtual_path, data, size);
				else
					extractSuccess = archive.getData(entry.virtual_path, data, size);

				if (!extractSuccess)
				{
					std::cerr << "Could not extract file " << entry.virtual_path << std::endl;
					continue;
				}

				stream.write(data, size);

				delete[] data;
			}
		}

		return 0;
	}
}
<|endoftext|>