<commit_before>#include <Cosa/Alarm.hh>
#include <Cosa/AnalogPin.hh>
#include <Cosa/InputPin.hh>
#include <Cosa/PinChangeInterrupt.hh>
#include <Cosa/RTT.hh>
#include <Cosa/Watchdog.hh>
#include <stdint-gcc.h>
#include <NRF24L01P.hh>

//PINS
static const Board::DigitalPin NRF_POWER			= Board::D8;
static const Board::DigitalPin NRF_CSN				= Board::D7;
static const Board::DigitalPin NRF_CE				= Board::D3;
static const Board::ExternalInterruptPin NRF_IRQ	= Board::EXT0;
static const Board::DigitalPin PIR_POWER			= Board::D2;
static const Board::InterruptPin PIR_MOTION_INT		= Board::PCI1;

// NETWORK ADDRESSES
static const uint16_t NETWORK = 0xC05A;
static const uint8_t SERVER_ID = 0x01;
static const uint8_t MODULE_ID = 0x20;

// TIMING CONSTANTS
static const uint32_t STARTUP_LED_TIME_MS = 5000;

static const uint16_t WATCHDOG_PERIOD = 1024;

// PROTOCOL
enum LockStatus
{
	UNKNOWN,
	LOCKED,
	UNLOCKED,
};

enum MessageType
{
	// General messages, used by all sensors
	PING_SERVER = 0x01,
	VOLTAGE_LEVEL = 0x02,

	// Messages specific to the activation module
	LOCK_CODE = 0x10,
	UNLOCK_CODE = 0x11,

	// Messages specific to the motion detection module
	MOTION_DETECTED = 0x20

	// Other messages will go there

} __attribute__((packed));

struct RxPingServer
{
	bool locked;
};

union RxPayload
{
	RxPingServer pingServer;
};

class LowCurrentNRF24L01P: public NRF24L01P
{
public:
	LowCurrentNRF24L01P(uint8_t server, Board::DigitalPin power,
						Board::DigitalPin csn, Board::DigitalPin ce,
						Board::ExternalInterruptPin irq)
		:NRF24L01P(0, 0, csn, ce, irq), _server(server), _power(power) {}

	void power_on()
	{
		// Power up the chip and wait for 100ms
		_power.on();
		delay(POWERUP_TIME_MS);
		NRF24L01P::begin();
		// Avoid infinite loop due to multiple spi.attach(this) in NRF24L01P::begin()
		this->m_next = NULL;
	}
	void power_off()
	{
		// Power down the chip completely
		NRF24L01P::end();
		NRF24L01P::powerdown();
		_power.off();
	}

	int recv(uint8_t expected_port, void* buf, size_t count)
	{
		uint8_t src;
		uint8_t port;
		int size = NRF24L01P::recv(src, port, buf, count, RECV_TIMEOUT_MS);
		return (src == _server && port == expected_port ? size : -1);
	}
	int send(uint8_t port, const void* buf, size_t len)
	{
		return NRF24L01P::send(_server, port, buf, len);
	}

private:
	static const uint8_t RECV_TIMEOUT_MS = 10;
	static const uint32_t POWERUP_TIME_MS = 100;

	const uint8_t _server;
	OutputPin _power;
};

class PingTask: public Alarm
{
public:
	PingTask(::Clock* clock, LowCurrentNRF24L01P& nrf, Alarm& pirActivator)
	:	Alarm(clock, PING_PERIOD_SEC),
		_nrf(nrf), _pirActivator(pirActivator), _pir_power(PIR_POWER), _status(UNKNOWN),
		_ping_count(0), _pings_per_voltage(VOLTAGE_PERIOD_SEC / PING_PERIOD_SEC) {}

	//TODO refactor sendVoltageLevel and pingServerAndGetLockStatus into one method
	LockStatus sendVoltageLevel(uint16_t level)
	{
		_nrf.send(VOLTAGE_LEVEL, &level, sizeof(level));
		return UNKNOWN;
	}

	LockStatus pingServerAndGetLockStatus()
	{
		LockStatus status = UNKNOWN;
		// Ping server
		if (_nrf.send(PING_SERVER, 0, 0) >= 0)
		{
			// Wait for acknowledge with lock status and optional cipher key
			RxPingServer response;
			int size = _nrf.recv(PING_SERVER, &response, sizeof(response));
			if (size > 0)
				status = response.locked ? LOCKED : UNLOCKED;
		}
		return status;
	}

	virtual void run()
	{
		LockStatus status = UNKNOWN;
		if (++_ping_count == _pings_per_voltage)
		{
			_ping_count = 0;
			// Get current voltage level
			uint16_t bandgap = AnalogPin::bandgap();
			// Send it to server
			status = sendVoltageLevel(bandgap);
		}
		else
		{
			// Get lock status from server
			status = pingServerAndGetLockStatus();
		}
		if (_status != status && status != UNKNOWN)
		{
			_status = status;
			bool locked = (_status == LOCKED);
			if (locked)
			{
				// start PIR and delay until PIR ready before lsitening to PIR interrupts
				_pirActivator.start();
			}
			else
			{
				// stop PIR & stop listening to PIR interrupts
				_pirActivator.stop();
				PinChangeInterrupt::end();
			}
			_pir_power.set(locked);
		}
	}

private:
	static const uint32_t PING_PERIOD_SEC = 10;
	static const uint32_t VOLTAGE_PERIOD_SEC = 60;

	LowCurrentNRF24L01P& _nrf;
	Alarm& _pirActivator;
	OutputPin _pir_power;
	LockStatus _status;
	uint16_t _ping_count;
	const uint16_t _pings_per_voltage;
};

class PIRDetector: public PinChangeInterrupt, public Event::Handler
{
public:
	static const uint8_t MOTION_EVENT = Event::USER_TYPE + 1;

	PIRDetector(LowCurrentNRF24L01P& nrf)
		:	PinChangeInterrupt(PIR_MOTION_INT, PinChangeInterrupt::ON_RISING_MODE),
			_nrf(nrf) {}
	virtual void on_interrupt(uint16_t arg)
	{
		// Do nothing yet
		UNUSED(arg);
		Event::push(MOTION_EVENT, this, this);
	}

	virtual void on_event(uint8_t type, uint16_t value)
	{
		UNUSED(type);
		UNUSED(value);
		_nrf.send(MOTION_DETECTED, 0, 0);
	}

private:
	LowCurrentNRF24L01P& _nrf;
};

class PIRActivator: public Alarm
{
public:
	PIRActivator(::Clock* clock):Alarm(clock, PIR_STARTUP_TIME_MS) {}

	virtual void run()
	{
		PinChangeInterrupt::begin();
		Alarm::stop();
	}

private:
	static const uint32_t PIR_STARTUP_TIME_MS = 60;
};

int main()
{
	// Disable analog comparator
	ACSR = _BV(ACD);
	// Disable all modules but ADC (required for bandgap reading)
	Power::all_disable();
	Power::adc_enable();
	// Allow interrupts from here
	sei();

	// Start watchdog
	Watchdog::begin(WATCHDOG_PERIOD);
	Power::set(SLEEP_MODE_PWR_DOWN);		// 5uA

	// DEBUG First light startup LED for 5 seconds
	//TODO if commenting out this code makes it work better (no high currents at start) then
	// perform a new check but with first forcing 0 to Transistor output
//	{
//		OutputPin led = Board::D0;
//		led.on();
//		delay(STARTUP_LED_TIME_MS);
//		led.off();
//	}

	// Needed for Alarms to work properly
	Watchdog::Clock clock;

	LowCurrentNRF24L01P transmitter = LowCurrentNRF24L01P(SERVER_ID, NRF_POWER, NRF_CSN, NRF_CE, NRF_IRQ);
	transmitter.address(NETWORK, MODULE_ID);
	PIRActivator pirActivator(&clock);
	PingTask pingTask(&clock, transmitter, pirActivator);

	PIRDetector detector(transmitter);
	detector.enable();

	// Start all tasks
	// However, do note that detection module is not really started until PinChangeInterrupt has begun
	// which will occur only if alarm is active (i.e. status is LOCKED)
	pingTask.start();
//	PinChangeInterrupt::begin();

	while (true)
	{
		Watchdog::await();

		// If there is at least one event to be dispatched, then change sleep mode, start RTT and NRF
		if (Event::queue.available())
		{
			// Only this mode works when using serial output and full-time RTC
			Power::set(SLEEP_MODE_IDLE);			// 15mA
			// Start using RTT
			RTT::begin();
			//TODO Not sure the following is REALLY necessary...
			RTT::millis(0);
			// Start NRF
			transmitter.power_on();

			Event event;
			while (Event::queue.dequeue(&event))
				event.dispatch();

			// Stop NRF
			transmitter.power_off();
			// Stop using RTT and restore Watchdog
			RTT::end();
			::delay = Watchdog::delay;
			// Lowest consumption mode
			Power::set(SLEEP_MODE_PWR_DOWN);		// 5uA
		}
	}
}
<commit_msg>Consumption measurement prototype: fix PIR delayed activation timer.<commit_after>#include <Cosa/Alarm.hh>
#include <Cosa/AnalogPin.hh>
#include <Cosa/InputPin.hh>
#include <Cosa/PinChangeInterrupt.hh>
#include <Cosa/RTT.hh>
#include <Cosa/Watchdog.hh>
#include <stdint-gcc.h>
#include <NRF24L01P.hh>

//PINS
static const Board::DigitalPin NRF_POWER			= Board::D8;
static const Board::DigitalPin NRF_CSN				= Board::D7;
static const Board::DigitalPin NRF_CE				= Board::D3;
static const Board::ExternalInterruptPin NRF_IRQ	= Board::EXT0;
static const Board::DigitalPin PIR_POWER			= Board::D2;
static const Board::InterruptPin PIR_MOTION_INT		= Board::PCI1;

// NETWORK ADDRESSES
static const uint16_t NETWORK = 0xC05A;
static const uint8_t SERVER_ID = 0x01;
static const uint8_t MODULE_ID = 0x20;

// TIMING CONSTANTS
static const uint32_t STARTUP_LED_TIME_MS = 5000;

static const uint16_t WATCHDOG_PERIOD = 1024;

// PROTOCOL
enum LockStatus
{
	UNKNOWN,
	LOCKED,
	UNLOCKED,
};

enum MessageType
{
	// General messages, used by all sensors
	PING_SERVER = 0x01,
	VOLTAGE_LEVEL = 0x02,

	// Messages specific to the activation module
	LOCK_CODE = 0x10,
	UNLOCK_CODE = 0x11,

	// Messages specific to the motion detection module
	MOTION_DETECTED = 0x20

	// Other messages will go there

} __attribute__((packed));

struct RxPingServer
{
	bool locked;
};

union RxPayload
{
	RxPingServer pingServer;
};

class LowCurrentNRF24L01P: public NRF24L01P
{
public:
	LowCurrentNRF24L01P(uint8_t server, Board::DigitalPin power,
						Board::DigitalPin csn, Board::DigitalPin ce,
						Board::ExternalInterruptPin irq)
		:NRF24L01P(0, 0, csn, ce, irq), _server(server), _power(power) {}

	void power_on()
	{
		// Power up the chip and wait for 100ms
		_power.on();
		delay(POWERUP_TIME_MS);
		NRF24L01P::begin();
		// Avoid infinite loop due to multiple spi.attach(this) in NRF24L01P::begin()
		this->m_next = NULL;
	}
	void power_off()
	{
		// Power down the chip completely
		NRF24L01P::end();
		NRF24L01P::powerdown();
		_power.off();
	}

	int recv(uint8_t expected_port, void* buf, size_t count)
	{
		uint8_t src;
		uint8_t port;
		int size = NRF24L01P::recv(src, port, buf, count, RECV_TIMEOUT_MS);
		return (src == _server && port == expected_port ? size : -1);
	}
	int send(uint8_t port, const void* buf, size_t len)
	{
		return NRF24L01P::send(_server, port, buf, len);
	}

private:
	static const uint8_t RECV_TIMEOUT_MS = 10;
	static const uint32_t POWERUP_TIME_MS = 100;

	const uint8_t _server;
	OutputPin _power;
};

class PIRActivator: public Alarm
{
public:
	PIRActivator(::Clock* clock):Alarm(clock, PIR_STARTUP_TIME_SEC) {}

	void restart()
	{
		Alarm::expire_at(Alarm::time() + PIR_STARTUP_TIME_SEC);
		Alarm::start();
	}

	virtual void run()
	{
		PinChangeInterrupt::begin();
		Alarm::stop();
	}

private:
	static const uint32_t PIR_STARTUP_TIME_SEC = 60;
};

class PingTask: public Alarm
{
public:
	PingTask(::Clock* clock, LowCurrentNRF24L01P& nrf, PIRActivator& pirActivator)
	:	Alarm(clock, PING_PERIOD_SEC),
		_nrf(nrf), _pirActivator(pirActivator), _pir_power(PIR_POWER), _status(UNKNOWN),
		_ping_count(0), _pings_per_voltage(VOLTAGE_PERIOD_SEC / PING_PERIOD_SEC) {}

	//TODO refactor sendVoltageLevel and pingServerAndGetLockStatus into one method
	LockStatus sendVoltageLevel(uint16_t level)
	{
		_nrf.send(VOLTAGE_LEVEL, &level, sizeof(level));
		return UNKNOWN;
	}

	LockStatus pingServerAndGetLockStatus()
	{
		LockStatus status = UNKNOWN;
		// Ping server
		if (_nrf.send(PING_SERVER, 0, 0) >= 0)
		{
			// Wait for acknowledge with lock status and optional cipher key
			RxPingServer response;
			int size = _nrf.recv(PING_SERVER, &response, sizeof(response));
			if (size > 0)
				status = response.locked ? LOCKED : UNLOCKED;
		}
		return status;
	}

	virtual void run()
	{
		LockStatus status = UNKNOWN;
		if (++_ping_count == _pings_per_voltage)
		{
			_ping_count = 0;
			// Get current voltage level
			uint16_t bandgap = AnalogPin::bandgap();
			// Send it to server
			status = sendVoltageLevel(bandgap);
		}
		else
		{
			// Get lock status from server
			status = pingServerAndGetLockStatus();
		}
		if (_status != status && status != UNKNOWN)
		{
			_status = status;
			bool locked = (_status == LOCKED);
			if (locked)
			{
				// start PIR and delay until PIR ready before lsitening to PIR interrupts
				_pirActivator.restart();
			}
			else
			{
				// stop PIR & stop listening to PIR interrupts
				_pirActivator.stop();
				PinChangeInterrupt::end();
			}
			_pir_power.set(locked);
		}
	}

private:
	static const uint32_t PING_PERIOD_SEC = 10;
	static const uint32_t VOLTAGE_PERIOD_SEC = 60;

	LowCurrentNRF24L01P& _nrf;
	PIRActivator& _pirActivator;
	OutputPin _pir_power;
	LockStatus _status;
	uint16_t _ping_count;
	const uint16_t _pings_per_voltage;
};

class PIRDetector: public PinChangeInterrupt, public Event::Handler
{
public:
	static const uint8_t MOTION_EVENT = Event::USER_TYPE + 1;

	PIRDetector(LowCurrentNRF24L01P& nrf)
		:	PinChangeInterrupt(PIR_MOTION_INT, PinChangeInterrupt::ON_RISING_MODE),
			_nrf(nrf) {}
	virtual void on_interrupt(uint16_t arg)
	{
		// Do nothing yet
		UNUSED(arg);
		Event::push(MOTION_EVENT, this, this);
	}

	virtual void on_event(uint8_t type, uint16_t value)
	{
		UNUSED(type);
		UNUSED(value);
		_nrf.send(MOTION_DETECTED, 0, 0);
	}

private:
	LowCurrentNRF24L01P& _nrf;
};

int main()
{
	// Disable analog comparator
	ACSR = _BV(ACD);
	// Disable all modules but ADC (required for bandgap reading)
	Power::all_disable();
	Power::adc_enable();
	// Allow interrupts from here
	sei();

	// Start watchdog
	Watchdog::begin(WATCHDOG_PERIOD);
	Power::set(SLEEP_MODE_PWR_DOWN);		// 5uA

	// DEBUG First light startup LED for 5 seconds
	//TODO if commenting out this code makes it work better (no high currents at start) then
	// perform a new check but with first forcing 0 to Transistor output
//	{
//		OutputPin led = Board::D0;
//		led.on();
//		delay(STARTUP_LED_TIME_MS);
//		led.off();
//	}

	// Needed for Alarms to work properly
	Watchdog::Clock clock;

	LowCurrentNRF24L01P transmitter = LowCurrentNRF24L01P(SERVER_ID, NRF_POWER, NRF_CSN, NRF_CE, NRF_IRQ);
	transmitter.address(NETWORK, MODULE_ID);
	// TODO PIRActivator could be a member of PingTask instead (less arguments))
	PIRActivator pirActivator(&clock);
	PingTask pingTask(&clock, transmitter, pirActivator);

	PIRDetector detector(transmitter);
	detector.enable();

	// Start all tasks
	// However, do note that detection module is not really started until PinChangeInterrupt has begun
	// which will occur only if alarm is active (i.e. status is LOCKED)
	pingTask.start();
//	PinChangeInterrupt::begin();

	while (true)
	{
		Watchdog::await();

		// If there is at least one event to be dispatched, then change sleep mode, start RTT and NRF
		if (Event::queue.available())
		{
			// Only this mode works when using serial output and full-time RTC
			Power::set(SLEEP_MODE_IDLE);			// 15mA
			// Start using RTT
			RTT::begin();
			//TODO Not sure the following is REALLY necessary...
			RTT::millis(0);
			// Start NRF
			transmitter.power_on();

			Event event;
			while (Event::queue.dequeue(&event))
				event.dispatch();

			// Stop NRF
			transmitter.power_off();
			// Stop using RTT and restore Watchdog
			RTT::end();
			::delay = Watchdog::delay;
			// Lowest consumption mode
			Power::set(SLEEP_MODE_PWR_DOWN);		// 5uA
		}
	}
}
<|endoftext|>


<commit_before>/**
 * @file llupdaterservice.cpp
 *
 * $LicenseInfo:firstyear=2010&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#include "linden_common.h"
#include <stdexcept>
#include <boost/format.hpp>
#include "llhttpclient.h"
#include "llsd.h"
#include "llupdatechecker.h"
#include "lluri.h"
#if LL_DARWIN
#include <CoreServices/CoreServices.h>
#endif

#if LL_WINDOWS
#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
#endif

class LLUpdateChecker::CheckError:
	public std::runtime_error
{
public:
	CheckError(const char * message):
		std::runtime_error(message)
	{
		; // No op.
	}
};

// LLUpdateChecker
//-----------------------------------------------------------------------------

LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client):
	mImplementation(new LLUpdateChecker::Implementation(client))
{
	; // No op.
}

void LLUpdateChecker::checkVersion(std::string const & urlBase,
								   std::string const & channel,
								   std::string const & version,
								   std::string const & platform,
								   std::string const & platform_version,
								   unsigned char       uniqueid[MD5HEX_STR_SIZE],
								   bool                willing_to_test)
{
	mImplementation->checkVersion(urlBase, channel, version, platform, platform_version, uniqueid, willing_to_test);
}

// LLUpdateChecker::Implementation
//-----------------------------------------------------------------------------

const char * LLUpdateChecker::Implementation::sProtocolVersion = "v1.1";

LLUpdateChecker::Implementation::Implementation(LLUpdateChecker::Client & client):
	mClient(client),
	mInProgress(false),
	mProtocol(sProtocolVersion)
{
	; // No op.
}

LLUpdateChecker::Implementation::~Implementation()
{
	; // No op.
}

void LLUpdateChecker::Implementation::checkVersion(std::string const & urlBase,
												   std::string const & channel,
												   std::string const & version,
												   std::string const & platform,
												   std::string const & platform_version,
												   unsigned char       uniqueid[MD5HEX_STR_SIZE],
												   bool                willing_to_test)
{
	if (!mInProgress)
	{
		mInProgress = true;

		mUrlBase     	 = urlBase;
		mChannel     	 = channel;
		mVersion     	 = version;
		mPlatform        = platform;
		mPlatformVersion = platform_version;
		memcpy(mUniqueId, uniqueid, MD5HEX_STR_SIZE);
		mWillingToTest   = willing_to_test;

		mProtocol = sProtocolVersion;

		std::string checkUrl = buildUrl(urlBase, channel, version, platform, platform_version, uniqueid, willing_to_test);
		LL_INFOS("UpdaterService") << "checking for updates at " << checkUrl << LL_ENDL;

		mHttpClient.get(checkUrl, this);
	}
	else
	{
		LL_WARNS("UpdaterService") << "attempting to restart a check when one is in progress; ignored" << LL_ENDL;
	}
}

void LLUpdateChecker::Implementation::completed(U32 status,
												const std::string & reason,
												const LLSD & content)
{
	mInProgress = false;

	if(status != 200)
	{
		std::string server_error;
		if ( content.has("error_code") )
		{
			server_error += content["error_code"].asString();
		}
		if ( content.has("error_text") )
		{
			server_error += server_error.empty() ? "" : ": ";
			server_error += content["error_text"].asString();
		}

		if (status == 404)
		{
			if (mProtocol == sProtocolVersion)
			{
				mProtocol = sLegacyProtocolVersion;
				std::string retryUrl = buildUrl(mUrlBase, mChannel, mVersion, mPlatform, mPlatformVersion, mUniqueId, mWillingToTest);

				LL_WARNS("UpdaterService")
					<< "update response using " << sProtocolVersion
					<< " was HTTP 404 (" << server_error
					<< "); retry with legacy protocol " << mProtocol
					<< "\n at " << retryUrl
					<< LL_ENDL;

				mHttpClient.get(retryUrl, this);
			}
			else
			{
				LL_WARNS("UpdaterService")
					<< "update response using " << sLegacyProtocolVersion
					<< " was 404 (" << server_error
					<< "); request failed"
					<< LL_ENDL;
				mClient.error(reason);
			}
		}
		else
		{
			LL_WARNS("UpdaterService") << "response error " << status
									   << " " << reason
									   << " (" << server_error << ")"
									   << LL_ENDL;
			mClient.error(reason);
		}
	}
	else
	{
		mClient.response(content);
	}
}

void LLUpdateChecker::Implementation::error(U32 status, const std::string & reason)
{
	mInProgress = false;
	LL_WARNS("UpdaterService") << "update check failed; " << reason << LL_ENDL;
	mClient.error(reason);
}

std::string LLUpdateChecker::Implementation::buildUrl(std::string const & urlBase,
													  std::string const & channel,
													  std::string const & version,
													  std::string const & platform,
													  std::string const & platform_version,
													  unsigned char       uniqueid[MD5HEX_STR_SIZE],
													  bool                willing_to_test)
{
	LLSD path;
	path.append(mProtocol);
	path.append(channel);
	path.append(version);
	path.append(platform);
	path.append(platform_version);
	path.append(willing_to_test ? "testok" : "testno");
	path.append((char*)uniqueid);
	return LLURI::buildHTTP(urlBase, path).asString();
}
<commit_msg>correct merge error in llupdatechecker.cpp<commit_after>/**
 * @file llupdaterservice.cpp
 *
 * $LicenseInfo:firstyear=2010&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#include "linden_common.h"
#include <stdexcept>
#include <boost/format.hpp>
#include "llhttpclient.h"
#include "llsd.h"
#include "llupdatechecker.h"
#include "lluri.h"
#if LL_DARWIN
#include <CoreServices/CoreServices.h>
#endif

#if LL_WINDOWS
#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
#endif

class LLUpdateChecker::CheckError:
	public std::runtime_error
{
public:
	CheckError(const char * message):
		std::runtime_error(message)
	{
		; // No op.
	}
};

// LLUpdateChecker
//-----------------------------------------------------------------------------

LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client):
	mImplementation(new LLUpdateChecker::Implementation(client))
{
	; // No op.
}

void LLUpdateChecker::checkVersion(std::string const & urlBase,
								   std::string const & channel,
								   std::string const & version,
								   std::string const & platform,
								   std::string const & platform_version,
								   unsigned char       uniqueid[MD5HEX_STR_SIZE],
								   bool                willing_to_test)
{
	mImplementation->checkVersion(urlBase, channel, version, platform, platform_version, uniqueid, willing_to_test);
}

// LLUpdateChecker::Implementation
//-----------------------------------------------------------------------------

const char * LLUpdateChecker::Implementation::sProtocolVersion = "v1.1";

LLUpdateChecker::Implementation::Implementation(LLUpdateChecker::Client & client):
	mClient(client),
	mInProgress(false),
	mProtocol(sProtocolVersion)
{
	; // No op.
}

LLUpdateChecker::Implementation::~Implementation()
{
	; // No op.
}

void LLUpdateChecker::Implementation::checkVersion(std::string const & urlBase,
												   std::string const & channel,
												   std::string const & version,
												   std::string const & platform,
												   std::string const & platform_version,
												   unsigned char       uniqueid[MD5HEX_STR_SIZE],
												   bool                willing_to_test)
{
	if (!mInProgress)
	{
		mInProgress = true;

		mUrlBase     	 = urlBase;
		mChannel     	 = channel;
		mVersion     	 = version;
		mPlatform        = platform;
		mPlatformVersion = platform_version;
		memcpy(mUniqueId, uniqueid, MD5HEX_STR_SIZE);
		mWillingToTest   = willing_to_test;

		mProtocol = sProtocolVersion;

		std::string checkUrl = buildUrl(urlBase, channel, version, platform, platform_version, uniqueid, willing_to_test);
		LL_INFOS("UpdaterService") << "checking for updates at " << checkUrl << LL_ENDL;

		mHttpClient.get(checkUrl, this);
	}
	else
	{
		LL_WARNS("UpdaterService") << "attempting to restart a check when one is in progress; ignored" << LL_ENDL;
	}
}

void LLUpdateChecker::Implementation::completed(U32 status,
												const std::string & reason,
												const LLSD & content)
{
	mInProgress = false;

	if(status != 200)
	{
		std::string server_error;
		if ( content.has("error_code") )
		{
			server_error += content["error_code"].asString();
		}
		if ( content.has("error_text") )
		{
			server_error += server_error.empty() ? "" : ": ";
			server_error += content["error_text"].asString();
		}

		LL_WARNS("UpdaterService") << "response error " << status
								   << " " << reason
								   << " (" << server_error << ")"
								   << LL_ENDL;
		mClient.error(reason);
	}
	else
	{
		mClient.response(content);
	}
}

void LLUpdateChecker::Implementation::error(U32 status, const std::string & reason)
{
	mInProgress = false;
	LL_WARNS("UpdaterService") << "update check failed; " << reason << LL_ENDL;
	mClient.error(reason);
}

std::string LLUpdateChecker::Implementation::buildUrl(std::string const & urlBase,
													  std::string const & channel,
													  std::string const & version,
													  std::string const & platform,
													  std::string const & platform_version,
													  unsigned char       uniqueid[MD5HEX_STR_SIZE],
													  bool                willing_to_test)
{
	LLSD path;
	path.append(mProtocol);
	path.append(channel);
	path.append(version);
	path.append(platform);
	path.append(platform_version);
	path.append(willing_to_test ? "testok" : "testno");
	path.append((char*)uniqueid);
	return LLURI::buildHTTP(urlBase, path).asString();
}
<|endoftext|>


<commit_before>/*
    Copyright 2017 Harald Sitter <sitter@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) version 3, or any
    later version accepted by the membership of KDE e.V. (or its
    successor approved by the membership of KDE e.V.), which shall
    act as a proxy defined in Section 6 of version 3 of the license.

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

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

#include <QObject>
#include <QtTest>

#include <KConfig>
#include <KConfigGroup>
#include <KIconLoader>

#include "testhelpers.h"

/**
 * Represents icon directory to conduct simple icon lookup within.
 */
class Dir
{
public:
    Dir(const KConfigGroup &cg, const QString &themeDir_)
        : themeDir(themeDir_)
        , path(cg.name())
        , size(cg.readEntry("Size", 0))
        , contextString(cg.readEntry("Context", QString()))
        , context(parseContext(contextString))
        , type(parseType(cg.readEntry("Type", QString("Threshold"))))
    {
    }

    static QMetaEnum findEnum(const char *name)
    {
        auto mo = KIconLoader::staticMetaObject;
        for (int i = 0; i < mo.enumeratorCount(); ++i) {
            auto enumerator = mo.enumerator(i);
            if (strcmp(enumerator.name(), name) == 0) {
                return KIconLoader::staticMetaObject.enumerator(i);
            }
        }
        Q_ASSERT(false); // failed to resolve enum
        return QMetaEnum();
    }

    static QMetaEnum typeEnum()
    {
        static auto e = findEnum("Type");
        return e;
    }

    KIconLoader::Context parseContext(const QString &string)
    {
        // Can't use QMetaEnum as the enum names are singular, the entry values are plural though.
        static QHash<QString, int> hash {
            { QStringLiteral("Actions"), KIconLoader::Action },
            { QStringLiteral("Applications"), KIconLoader::Application },
            { QStringLiteral("Categories"), KIconLoader::Category },
            { QStringLiteral("Devices"), KIconLoader::Device },
            { QStringLiteral("Emblems"), KIconLoader::Emblem },
            { QStringLiteral("Emotes"), KIconLoader::Emote },
            { QStringLiteral("MimeTypes"), KIconLoader::MimeType },
            { QStringLiteral("Places"), KIconLoader::Place },
            { QStringLiteral("Status"), KIconLoader::StatusIcon },
        };
        auto value = hash.value(string, -1);
        Q_ASSERT_X(value != -1, Q_FUNC_INFO, QString("unmapped context %1").arg(string).toLatin1());
        return (KIconLoader::Context)value;
    }

    KIconLoader::Type parseType(const QString &string)
    {
        bool ok;
        auto v = (KIconLoader::Type)typeEnum().keyToValue(string.toLatin1(), &ok);
        Q_ASSERT(ok);
        return v;
    }

    QList<QFileInfo> allIcons()
    {
        QList<QFileInfo> icons;
        auto iconDir = QString("%1/%2").arg(themeDir).arg(path);
        QDirIterator it(iconDir);
        while (it.hasNext()) {
            it.next();
            auto suffix = it.fileInfo().suffix();
            if (suffix != "svg" && suffix != "svgz" && suffix != "png") {
                continue; // Probably not an icon.
            }
            icons << it.fileInfo();
        }
        return icons;
    }

    QString themeDir;
    QString path;
    uint size;
    QString contextString;
    KIconLoader::Context context;
    KIconLoader::Type type;
};

// Declare so we can put them into the QTest data table.
Q_DECLARE_METATYPE(KIconLoader::Context)
Q_DECLARE_METATYPE(Dir*)

class ScalableTest : public QObject
{
    Q_OBJECT

private Q_SLOTS:
    // NB: test_scalable_data leaks Dir*. Should this test grow more slots it may be wise to
    //     introduce a cleanup() to make sure the test doesn't OOM.

    void test_scalable_data()
    {
        for (auto dir : ICON_DIRS) {
            auto themeDir = PROJECT_SOURCE_DIR + QStringLiteral("/") + dir;

            QHash<KIconLoader::Context, QList<Dir *>> contextHash;
            QHash<KIconLoader::Context, QString> contextStringHash;

            KConfig config(themeDir + "/index.theme");
            auto directoryPaths = config.group("Icon Theme").readEntry("Directories", QString()).split(",");
            QVERIFY(!directoryPaths.isEmpty());
            for (auto directoryPath : directoryPaths) {
                auto dir = new Dir(config.group(directoryPath), themeDir);
                contextHash[dir->context].append(dir);
                contextStringHash[dir->context] = (dir->contextString);
            }

            QTest::addColumn<KIconLoader::Context>("context");
            QTest::addColumn<QList<Dir *>>("dirs");

            for (auto key : contextHash.keys()) {
                if (key != KIconLoader::Application) {
                    qDebug() << "Only testing Application context for now.";
                    continue;
                }
                // FIXME: go through qenum to stringify the bugger
                // Gets rid of the stupid second hash
                auto contextId = QString(QLatin1String(dir) + ":" + contextStringHash[key]).toLatin1();
                QTest::newRow(contextId) << key << contextHash[key];
            }
        }
    }

    void test_scalable()
    {
        QFETCH(KIconLoader::Context, context);
        QFETCH(QList<Dir *>, dirs);

        QList<Dir *> fixedDirs;
        QList<Dir *> scalableDirs;
        for (auto dir : dirs) {
            switch (dir->type) {
            case KIconLoader::Scalable:
                scalableDirs << dir;
                break;
            case KIconLoader::Fixed:
                fixedDirs << dir;
                break;
            case KIconLoader::Threshold:
                QVERIFY2(false, "Test does not support threshold icons right now.");
            }
        }

        // FIXME: context should be translated through qenum
        switch (context) {
        case KIconLoader::Application:
            // Treat this as a problem.
            QVERIFY2(!scalableDirs.empty(), "This icon context has no scalable directory at all!");
            break;
        default:
            qWarning() << "All context but Application are whitelisted from having a scalable directory.";
            return;
        }

        QStringList fixedIcons;
        for (auto dir : fixedDirs) {
            for (auto iconInfo : dir->allIcons()) {
                fixedIcons << iconInfo.completeBaseName();
            }
        }

        QHash<QString, QList<QFileInfo>> scalableIcons;
        for (auto dir : scalableDirs) {
            for (auto iconInfo : dir->allIcons()) {
                scalableIcons[iconInfo.completeBaseName()].append(iconInfo);
            }
        }

        QStringList notScalableIcons;
        for (auto fixed : fixedIcons) {
            if (scalableIcons.keys().contains(fixed)) {
                continue;
            }
            notScalableIcons << fixed;
        }

        // Assert that each icon has a scalable variant.
        if (notScalableIcons.empty()) {
            return;
        }
        QFAIL(QString("The following icons are not available in a scalable directory:\n  %1")
              .arg(notScalableIcons.join("\n  "))
              .toLatin1());
    }

    void test_scalableDuplicates_data()
    {
        test_scalable_data();
    }

    void test_scalableDuplicates()
    {
        QFETCH(QList<Dir *>, dirs);

        QList<Dir *> scalableDirs;
        for (auto dir : dirs) {
            switch (dir->type) {
            case KIconLoader::Scalable:
                scalableDirs << dir;
                break;
            case KIconLoader::Fixed:
                // Not of interest in this test.
                break;
            case KIconLoader::Threshold:
                QVERIFY2(false, "Test does not support threshold icons right now.");
            }
        }

        QHash<QString, QList<QFileInfo>> scalableIcons;
        for (auto dir : scalableDirs) {
            for (auto iconInfo : dir->allIcons()) {
                scalableIcons[iconInfo.completeBaseName()].append(iconInfo);
            }
        }

        QHash<QString, QList<QFileInfo>> duplicatedScalableIcons;
        for (auto icon: scalableIcons.keys()) {
            auto list = scalableIcons[icon];
            if (list.size() > 1) {
                duplicatedScalableIcons[icon] = list;
            }
        }

        // Assert that there is only one scalable version per icon name.
        // Otherwise apps/32/klipper.svg OR apps/48/klipper.svg may be used.
        if (!duplicatedScalableIcons.empty()) {
            QString msg;
            QTextStream stream(&msg);
            stream << "Duplicated scalable icons:" << endl;
            for (auto icon : duplicatedScalableIcons.keys()) {
                stream << QString("  %1:").arg(icon) << endl;
                for (auto info : duplicatedScalableIcons[icon]) {
                    stream << QString("    %1").arg(info.absoluteFilePath()) << endl;
                }
            }
            QFAIL(msg.toLatin1());
        }
    }
};

QTEST_GUILESS_MAIN(ScalableTest)

#include "scalabletest.moc"
<commit_msg>more documentation to trigger a build<commit_after>/*
    Copyright 2017 Harald Sitter <sitter@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) version 3, or any
    later version accepted by the membership of KDE e.V. (or its
    successor approved by the membership of KDE e.V.), which shall
    act as a proxy defined in Section 6 of version 3 of the license.

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

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

#include <QObject>
#include <QtTest>

#include <KConfig>
#include <KConfigGroup>
#include <KIconLoader>

#include "testhelpers.h"

/**
 * Represents icon directory to conduct simple icon lookup within.
 */
class Dir
{
public:
    Dir(const KConfigGroup &cg, const QString &themeDir_)
        : themeDir(themeDir_)
        , path(cg.name())
        , size(cg.readEntry("Size", 0))
        , contextString(cg.readEntry("Context", QString()))
        , context(parseContext(contextString))
        , type(parseType(cg.readEntry("Type", QString("Threshold"))))
    {
    }

    static QMetaEnum findEnum(const char *name)
    {
        auto mo = KIconLoader::staticMetaObject;
        for (int i = 0; i < mo.enumeratorCount(); ++i) {
            auto enumerator = mo.enumerator(i);
            if (strcmp(enumerator.name(), name) == 0) {
                return KIconLoader::staticMetaObject.enumerator(i);
            }
        }
        Q_ASSERT(false); // failed to resolve enum
        return QMetaEnum();
    }

    static QMetaEnum typeEnum()
    {
        static auto e = findEnum("Type");
        return e;
    }

    KIconLoader::Context parseContext(const QString &string)
    {
        // Can't use QMetaEnum as the enum names are singular, the entry values are plural though.
        static QHash<QString, int> hash {
            { QStringLiteral("Actions"), KIconLoader::Action },
            { QStringLiteral("Applications"), KIconLoader::Application },
            { QStringLiteral("Categories"), KIconLoader::Category },
            { QStringLiteral("Devices"), KIconLoader::Device },
            { QStringLiteral("Emblems"), KIconLoader::Emblem },
            { QStringLiteral("Emotes"), KIconLoader::Emote },
            { QStringLiteral("MimeTypes"), KIconLoader::MimeType },
            { QStringLiteral("Places"), KIconLoader::Place },
            { QStringLiteral("Status"), KIconLoader::StatusIcon },
        };
        auto value = hash.value(string, -1);
        Q_ASSERT_X(value != -1, Q_FUNC_INFO, QString("unmapped context %1").arg(string).toLatin1());
        return (KIconLoader::Context)value;
    }

    KIconLoader::Type parseType(const QString &string)
    {
        bool ok;
        auto v = (KIconLoader::Type)typeEnum().keyToValue(string.toLatin1(), &ok);
        Q_ASSERT(ok);
        return v;
    }

    /**
     * @returns list of all icon's fileinfo (first level only, selected types
     *          only)
     */
    QList<QFileInfo> allIcons()
    {
        QList<QFileInfo> icons;
        auto iconDir = QString("%1/%2").arg(themeDir).arg(path);
        QDirIterator it(iconDir);
        while (it.hasNext()) {
            it.next();
            auto suffix = it.fileInfo().suffix();
            if (suffix != "svg" && suffix != "svgz" && suffix != "png") {
                continue; // Probably not an icon.
            }
            icons << it.fileInfo();
        }
        return icons;
    }

    QString themeDir;
    QString path;
    uint size;
    QString contextString;
    KIconLoader::Context context;
    KIconLoader::Type type;
};

// Declare so we can put them into the QTest data table.
Q_DECLARE_METATYPE(KIconLoader::Context)
Q_DECLARE_METATYPE(Dir*)

class ScalableTest : public QObject
{
    Q_OBJECT

private Q_SLOTS:
    // NB: test_scalable_data leaks Dir*. Should this test grow more slots it may be wise to
    //     introduce a cleanup() to make sure the test doesn't OOM.

    void test_scalable_data()
    {
        for (auto dir : ICON_DIRS) {
            auto themeDir = PROJECT_SOURCE_DIR + QStringLiteral("/") + dir;

            QHash<KIconLoader::Context, QList<Dir *>> contextHash;
            QHash<KIconLoader::Context, QString> contextStringHash;

            KConfig config(themeDir + "/index.theme");
            auto directoryPaths = config.group("Icon Theme").readEntry("Directories", QString()).split(",");
            QVERIFY(!directoryPaths.isEmpty());
            for (auto directoryPath : directoryPaths) {
                auto dir = new Dir(config.group(directoryPath), themeDir);
                contextHash[dir->context].append(dir);
                contextStringHash[dir->context] = (dir->contextString);
            }

            QTest::addColumn<KIconLoader::Context>("context");
            QTest::addColumn<QList<Dir *>>("dirs");

            for (auto key : contextHash.keys()) {
                if (key != KIconLoader::Application) {
                    qDebug() << "Only testing Application context for now.";
                    continue;
                }
                // FIXME: go through qenum to stringify the bugger
                // Gets rid of the stupid second hash
                auto contextId = QString(QLatin1String(dir) + ":" + contextStringHash[key]).toLatin1();
                QTest::newRow(contextId) << key << contextHash[key];
            }
        }
    }

    void test_scalable()
    {
        QFETCH(KIconLoader::Context, context);
        QFETCH(QList<Dir *>, dirs);

        QList<Dir *> fixedDirs;
        QList<Dir *> scalableDirs;
        for (auto dir : dirs) {
            switch (dir->type) {
            case KIconLoader::Scalable:
                scalableDirs << dir;
                break;
            case KIconLoader::Fixed:
                fixedDirs << dir;
                break;
            case KIconLoader::Threshold:
                QVERIFY2(false, "Test does not support threshold icons right now.");
            }
        }

        // FIXME: context should be translated through qenum
        switch (context) {
        case KIconLoader::Application:
            // Treat this as a problem.
            QVERIFY2(!scalableDirs.empty(), "This icon context has no scalable directory at all!");
            break;
        default:
            qWarning() << "All context but Application are whitelisted from having a scalable directory.";
            return;
        }

        QStringList fixedIcons;
        for (auto dir : fixedDirs) {
            for (auto iconInfo : dir->allIcons()) {
                fixedIcons << iconInfo.completeBaseName();
            }
        }

        QHash<QString, QList<QFileInfo>> scalableIcons;
        for (auto dir : scalableDirs) {
            for (auto iconInfo : dir->allIcons()) {
                scalableIcons[iconInfo.completeBaseName()].append(iconInfo);
            }
        }

        QStringList notScalableIcons;
        for (auto fixed : fixedIcons) {
            if (scalableIcons.keys().contains(fixed)) {
                continue;
            }
            notScalableIcons << fixed;
        }

        // Assert that each icon has a scalable variant.
        if (notScalableIcons.empty()) {
            return;
        }
        QFAIL(QString("The following icons are not available in a scalable directory:\n  %1")
              .arg(notScalableIcons.join("\n  "))
              .toLatin1());
    }

    void test_scalableDuplicates_data()
    {
        test_scalable_data();
    }

    void test_scalableDuplicates()
    {
        QFETCH(QList<Dir *>, dirs);

        QList<Dir *> scalableDirs;
        for (auto dir : dirs) {
            switch (dir->type) {
            case KIconLoader::Scalable:
                scalableDirs << dir;
                break;
            case KIconLoader::Fixed:
                // Not of interest in this test.
                break;
            case KIconLoader::Threshold:
                QVERIFY2(false, "Test does not support threshold icons right now.");
            }
        }

        QHash<QString, QList<QFileInfo>> scalableIcons;
        for (auto dir : scalableDirs) {
            for (auto iconInfo : dir->allIcons()) {
                scalableIcons[iconInfo.completeBaseName()].append(iconInfo);
            }
        }

        QHash<QString, QList<QFileInfo>> duplicatedScalableIcons;
        for (auto icon: scalableIcons.keys()) {
            auto list = scalableIcons[icon];
            if (list.size() > 1) {
                duplicatedScalableIcons[icon] = list;
            }
        }

        // Assert that there is only one scalable version per icon name.
        // Otherwise apps/32/klipper.svg OR apps/48/klipper.svg may be used.
        if (!duplicatedScalableIcons.empty()) {
            QString msg;
            QTextStream stream(&msg);
            stream << "Duplicated scalable icons:" << endl;
            for (auto icon : duplicatedScalableIcons.keys()) {
                stream << QString("  %1:").arg(icon) << endl;
                for (auto info : duplicatedScalableIcons[icon]) {
                    stream << QString("    %1").arg(info.absoluteFilePath()) << endl;
                }
            }
            QFAIL(msg.toLatin1());
        }
    }
};

QTEST_GUILESS_MAIN(ScalableTest)

#include "scalabletest.moc"
<|endoftext|>


<commit_before>#include <memory>
#include <vtkDataSet.h>
#include <vtkXMLImageDataReader.h>
#include <vtkXMLStructuredGridReader.h>
#include <vtkImageData.h>
#include <vtkNew.h>
#include <vtkFieldData.h>
#include <vtkStringArray.h>
#include <vtkStdString.h>

#include "io/path.h"

#include "io/gmm_vtk_data_array.h"
#include "io/edda_vtk_reader.h"

using namespace std;

namespace edda {

string getDistrType(vtkFieldData* vtk_data, const string &array_name_prefix)
{
  string array_name = array_name_prefix + "distr_type";
  vtkStringArray *vtk_array = vtkStringArray::SafeDownCast( vtk_data->GetArray(array_name.c_str() ) );
  if (vtk_array==NULL) {
    return "GaussianMixture"; // default distribution type
  }
  return vtk_array->GetValue(0);
}

template <typename T>
shared_ptr<Dataset<T> > loadEddaDataset(const string &edda_file, const string &array_name_prefix)
{
  string ext = getFileExtension(edda_file);
  if (ext.compare("vti")==0) {
    vtkNew<vtkXMLImageDataReader> reader;
    reader->SetFileName(edda_file.c_str());
    reader->Update();
    vtkImageData *vtkdata = reader->GetOutput();

    int *dim = vtkdata->GetDimensions();
    printf("dim: %d %d %d\n", dim[0], dim[1], dim[2]);

    // check dataset type
    string type = getDistrType(vtkdata->GetFieldData(), array_name_prefix);

    if (type.compare("GaussianMixture")==0) {
      shared_ptr<Dataset<T> > dataset = make_Dataset<T>(
                                 new RegularCartesianGrid(dim[0], dim[1], dim[2]),
                                 new GmmVtkDataArray( vtkdata->GetPointData(), array_name_prefix.c_str() )
       );
      return dataset;

    } else if (type.compare("Histogram")==0)
    {
      // TODO
    }
    else {
      cout << "Unknown distribution type: " << type << endl;
      exit(1);
    }

  } else if (ext.compare("vts")==0){ // structured grids

    vtkNew<vtkXMLStructuredGridReader> reader;
    reader->SetFileName(edda_file.c_str());
    reader->Update();
    vtkStructuredGrid *vtkdata = reader->GetOutput();

    int *dim = vtkdata->GetDimensions();
    printf("dim: %d %d %d\n", dim[0], dim[1], dim[2]);

    // TODO : check if gmm dataset
    shared_ptr<Dataset<T> > dataset = make_Dataset<T>(
                                  new RegularCartesianGrid(dim[0], dim[1], dim[2]), // TODO: Curvilinear grids
                                  new GmmVtkDataArray( vtkdata->GetPointData(), array_name_prefix.c_str() )
        );
    // or is histogram dataset

    return dataset;
  } else {
    printf("File format of %s not supported\n", edda_file.c_str());
    exit(1);
  }
}

shared_ptr<Dataset<Real> > loadEddaScalarDataset(const string &edda_file, const string &array_name_prefix)
{
  return loadEddaDataset<Real>(edda_file, array_name_prefix);
}

shared_ptr<Dataset<VECTOR3> > loadEddaVector3Dataset(const string &edda_file, const string &array_name_prefix)
{
  return loadEddaDataset<VECTOR3>(edda_file, array_name_prefix);
}

} // edda
<commit_msg>Prepare curvilinear grids for Cheng's integration<commit_after>#include <memory>
#include <vtkDataSet.h>
#include <vtkXMLImageDataReader.h>
#include <vtkXMLStructuredGridReader.h>
#include <vtkImageData.h>
#include <vtkNew.h>
#include <vtkFieldData.h>
#include <vtkStringArray.h>
#include <vtkStdString.h>
#include <vtkPoints.h>

#include "io/path.h"

#include "io/gmm_vtk_data_array.h"
#include "io/edda_vtk_reader.h"

using namespace std;

namespace edda {

string getDistrType(vtkFieldData* vtk_data, const string &array_name_prefix)
{
  string array_name = array_name_prefix + "distr_type";
  vtkStringArray *vtk_array = vtkStringArray::SafeDownCast( vtk_data->GetArray(array_name.c_str() ) );
  if (vtk_array==NULL) {
    return "GaussianMixture"; // default distribution type
  }
  return vtk_array->GetValue(0);
}

template <typename T>
shared_ptr<Dataset<T> > loadEddaDataset(const string &edda_file, const string &array_name_prefix)
{
  string ext = getFileExtension(edda_file);
  if (ext.compare("vti")==0) {
    vtkNew<vtkXMLImageDataReader> reader;
    reader->SetFileName(edda_file.c_str());
    reader->Update();
    vtkImageData *vtkdata = reader->GetOutput();

    int *dim = vtkdata->GetDimensions();
    printf("dim: %d %d %d\n", dim[0], dim[1], dim[2]);

    // check dataset type
    string type = getDistrType(vtkdata->GetFieldData(), array_name_prefix);

    if (type.compare("GaussianMixture")==0) {
      shared_ptr<Dataset<T> > dataset = make_Dataset<T>(
                                 new RegularCartesianGrid(dim[0], dim[1], dim[2]),
                                 new GmmVtkDataArray( vtkdata->GetPointData(), array_name_prefix.c_str() )
       );
      return dataset;

    } else if (type.compare("Histogram")==0)
    {
      // TODO
    }
    else {
      cout << "Unknown distribution type: " << type << endl;
      exit(1);
    }

  } else if (ext.compare("vts")==0){ // structured grids

    vtkNew<vtkXMLStructuredGridReader> reader;
    reader->SetFileName(edda_file.c_str());
    reader->Update();
    vtkStructuredGrid *vtkdata = reader->GetOutput();

    int *dim = vtkdata->GetDimensions();
    printf("dim: %d %d %d\n", dim[0], dim[1], dim[2]);

    float *point_ary = (float *)vtkdata->GetPoints()->GetVoidPointer(0);

    // check dataset type
    string type = getDistrType(vtkdata->GetFieldData(), array_name_prefix);

    if (type.compare("GaussianMixture")==0) {
      shared_ptr<Dataset<T> > dataset = make_Dataset<T>(
                                 new RegularCartesianGrid(dim[0], dim[1], dim[2]),// TODO: CurvilinearGrid(dim, point_ary)
                                 new GmmVtkDataArray( vtkdata->GetPointData(), array_name_prefix.c_str() )
       );
      return dataset;

    } else if (type.compare("Histogram")==0)
    {
      // TODO
    }
    else {
      cout << "Unknown distribution type: " << type << endl;
      exit(1);
    }

  } else {
    printf("File format of %s not supported\n", edda_file.c_str());
    exit(1);
  }
}

shared_ptr<Dataset<Real> > loadEddaScalarDataset(const string &edda_file, const string &array_name_prefix)
{
  return loadEddaDataset<Real>(edda_file, array_name_prefix);
}

shared_ptr<Dataset<VECTOR3> > loadEddaVector3Dataset(const string &edda_file, const string &array_name_prefix)
{
  return loadEddaDataset<VECTOR3>(edda_file, array_name_prefix);
}

} // edda
<|endoftext|>


<commit_before>/*
 pgmspace.cpp - string functions that support PROGMEM
 Copyright (c) 2015 Michael C. Miller.  All right reserved.

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

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

 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <ctype.h>
#include "pgmspace.h"

size_t strnlen_P(PGM_P s, size_t size) {
    const char* cp;
    for (cp = s; size != 0 && pgm_read_byte(cp) != '\0'; cp++, size--);
    return (size_t) (cp - s);
}

int memcmp_P(const void* buf1, PGM_VOID_P buf2P, size_t size) {
    int result = 0;
    const uint8_t* read1 = (const uint8_t*)buf1;
    const uint8_t* read2 = (const uint8_t*)buf2P;

    while (size > 0) {
        uint8_t ch2 = pgm_read_byte(read2);
        uint8_t ch1 = *read1;
        if (ch1 != ch2) {
            result = (int)(ch1)-(int)(ch2);
            break;
        }

        read1++;
        read2++;
        size--;
    }

    return result;
}

void* memccpy_P(void* dest, PGM_VOID_P src, int c, size_t count) {
    uint8_t* read = (uint8_t*)src;
    uint8_t* write = (uint8_t*)dest;
    void* result = NULL;

    while (count > 0) {
        uint8_t ch = pgm_read_byte(read++);
        *write++ = ch;
        count--;
        if (c == ch) {
            return write; // the value after the found c
        }
    }

    return result;
}

void* memmem_P(const void* buf, size_t bufSize, PGM_VOID_P findP, size_t findPSize) {
    const uint8_t* read = (const uint8_t*)buf;
    const uint8_t* find = (uint8_t*)findP;
    uint8_t first = pgm_read_byte(find++);

    findPSize--;

    while (bufSize > 0) {
        if (*read == first) {
            size_t findSize = findPSize;
            const uint8_t* tag = read + 1;
            size_t tagBufSize = bufSize - 1;
            const uint8_t* findTag = find;

            while (tagBufSize > 0 && findSize > 0) {
                uint8_t ch = pgm_read_byte(findTag++);
                if (ch != *tag) {
                    bufSize--;
                    read++;
                    break;
                }
                findSize--;
                tagBufSize--;
                tag++;
            }
            if (findSize == 0) {
                return (void*)read;
            }
        }
        else {
            bufSize--;
            read++;
        }
    }
    return NULL;
}

char* strncpy_P(char* dest, PGM_P src, size_t size) {
    const char* read = src;
    char* write = dest;
    char ch = '.';
    while (size > 0 && ch != '\0')
    {
        ch = pgm_read_byte(read++);
        *write++ = ch;
        size--;
    }

    return dest;
}

char* strncat_P(char* dest, PGM_P src, size_t size) {
    char* write = dest;

    while (*write != '\0')
    {
        write++;
    }

    const char* read = src;
    char ch = '.';

    while (size > 0 && ch != '\0')
    {
        ch = pgm_read_byte(read++);
        *write++ = ch;

        size--;
    }

    if (ch != '\0')
    {
        *write = '\0';
    }

    return dest;
}

int strncmp_P(const char* str1, PGM_P str2P, size_t size) {
    int result = 0;

    while (size > 0)
    {
        char ch1 = *str1++;
        char ch2 = pgm_read_byte(str2P++);
        result = ch1 - ch2;
        if (result != 0 || ch2 == '\0')
        {
            break;
        }

        size--;
    }

    return result;
}

int strncasecmp_P(const char* str1, PGM_P str2P, size_t size) {
    int result = 0;

    while (size > 0)
    {
        char ch1 = tolower(*str1++);
        char ch2 = tolower(pgm_read_byte(str2P++));
        result = ch1 - ch2;
        if (result != 0 || ch2 == '\0')
        {
            break;
        }

        size--;
    }

    return result;
}

int printf_P(PGM_P formatP, ...) {
    int ret;
    va_list arglist;
    va_start(arglist, formatP);

    size_t fmtLen = strlen_P(formatP);
    char* format = new char[fmtLen + 1];
    strcpy_P(format, formatP);

    ret = os_printf(format, arglist);

    delete[] format;

    va_end(arglist);
    return ret;
}

int sprintf_P(char* str, PGM_P formatP, ...) {
    int ret;
    va_list arglist;
    va_start(arglist, formatP);

    ret = vsnprintf_P(str, SIZE_IRRELEVANT, formatP, arglist);

    va_end(arglist);
    return ret;
}

int snprintf_P(char* str, size_t strSize, PGM_P formatP, ...) {
    int ret;
    va_list arglist;
    va_start(arglist, formatP);

    ret = vsnprintf_P(str, strSize, formatP, arglist);

    va_end(arglist);
    return ret;
}

int vsnprintf_P(char* str, size_t strSize, PGM_P formatP, va_list ap) {
    int ret;

    size_t fmtLen = strlen_P(formatP);
    char* format = new char[fmtLen + 1];
    strcpy_P(format, formatP);

    ret = ets_vsnprintf(str, strSize, format, ap);

    delete[] format;

    return ret;
}
<commit_msg>Re-added lost function memcpy_P<commit_after>/*
 pgmspace.cpp - string functions that support PROGMEM
 Copyright (c) 2015 Michael C. Miller.  All right reserved.

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

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

 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <ctype.h>
#include "pgmspace.h"

size_t strnlen_P(PGM_P s, size_t size) {
    const char* cp;
    for (cp = s; size != 0 && pgm_read_byte(cp) != '\0'; cp++, size--);
    return (size_t) (cp - s);
}

void* memcpy_P(void* dest, PGM_VOID_P src, size_t count) {
    const uint8_t* read = reinterpret_cast<const uint8_t*>(src);
    uint8_t* write = reinterpret_cast<uint8_t*>(dest);

    while (count)
    {
        *write++ = pgm_read_byte(read++);
        count--;
    }

    return dest;
}

int memcmp_P(const void* buf1, PGM_VOID_P buf2P, size_t size) {
    int result = 0;
    const uint8_t* read1 = (const uint8_t*)buf1;
    const uint8_t* read2 = (const uint8_t*)buf2P;

    while (size > 0) {
        uint8_t ch2 = pgm_read_byte(read2);
        uint8_t ch1 = *read1;
        if (ch1 != ch2) {
            result = (int)(ch1)-(int)(ch2);
            break;
        }

        read1++;
        read2++;
        size--;
    }

    return result;
}

void* memccpy_P(void* dest, PGM_VOID_P src, int c, size_t count) {
    uint8_t* read = (uint8_t*)src;
    uint8_t* write = (uint8_t*)dest;
    void* result = NULL;

    while (count > 0) {
        uint8_t ch = pgm_read_byte(read++);
        *write++ = ch;
        count--;
        if (c == ch) {
            return write; // the value after the found c
        }
    }

    return result;
}

void* memmem_P(const void* buf, size_t bufSize, PGM_VOID_P findP, size_t findPSize) {
    const uint8_t* read = (const uint8_t*)buf;
    const uint8_t* find = (uint8_t*)findP;
    uint8_t first = pgm_read_byte(find++);

    findPSize--;

    while (bufSize > 0) {
        if (*read == first) {
            size_t findSize = findPSize;
            const uint8_t* tag = read + 1;
            size_t tagBufSize = bufSize - 1;
            const uint8_t* findTag = find;

            while (tagBufSize > 0 && findSize > 0) {
                uint8_t ch = pgm_read_byte(findTag++);
                if (ch != *tag) {
                    bufSize--;
                    read++;
                    break;
                }
                findSize--;
                tagBufSize--;
                tag++;
            }
            if (findSize == 0) {
                return (void*)read;
            }
        }
        else {
            bufSize--;
            read++;
        }
    }
    return NULL;
}

char* strncpy_P(char* dest, PGM_P src, size_t size) {
    const char* read = src;
    char* write = dest;
    char ch = '.';
    while (size > 0 && ch != '\0')
    {
        ch = pgm_read_byte(read++);
        *write++ = ch;
        size--;
    }

    return dest;
}

char* strncat_P(char* dest, PGM_P src, size_t size) {
    char* write = dest;

    while (*write != '\0')
    {
        write++;
    }

    const char* read = src;
    char ch = '.';

    while (size > 0 && ch != '\0')
    {
        ch = pgm_read_byte(read++);
        *write++ = ch;

        size--;
    }

    if (ch != '\0')
    {
        *write = '\0';
    }

    return dest;
}

int strncmp_P(const char* str1, PGM_P str2P, size_t size) {
    int result = 0;

    while (size > 0)
    {
        char ch1 = *str1++;
        char ch2 = pgm_read_byte(str2P++);
        result = ch1 - ch2;
        if (result != 0 || ch2 == '\0')
        {
            break;
        }

        size--;
    }

    return result;
}

int strncasecmp_P(const char* str1, PGM_P str2P, size_t size) {
    int result = 0;

    while (size > 0)
    {
        char ch1 = tolower(*str1++);
        char ch2 = tolower(pgm_read_byte(str2P++));
        result = ch1 - ch2;
        if (result != 0 || ch2 == '\0')
        {
            break;
        }

        size--;
    }

    return result;
}

int printf_P(PGM_P formatP, ...) {
    int ret;
    va_list arglist;
    va_start(arglist, formatP);

    size_t fmtLen = strlen_P(formatP);
    char* format = new char[fmtLen + 1];
    strcpy_P(format, formatP);

    ret = os_printf(format, arglist);

    delete[] format;

    va_end(arglist);
    return ret;
}

int sprintf_P(char* str, PGM_P formatP, ...) {
    int ret;
    va_list arglist;
    va_start(arglist, formatP);

    ret = vsnprintf_P(str, SIZE_IRRELEVANT, formatP, arglist);

    va_end(arglist);
    return ret;
}

int snprintf_P(char* str, size_t strSize, PGM_P formatP, ...) {
    int ret;
    va_list arglist;
    va_start(arglist, formatP);

    ret = vsnprintf_P(str, strSize, formatP, arglist);

    va_end(arglist);
    return ret;
}

int vsnprintf_P(char* str, size_t strSize, PGM_P formatP, va_list ap) {
    int ret;

    size_t fmtLen = strlen_P(formatP);
    char* format = new char[fmtLen + 1];
    strcpy_P(format, formatP);

    ret = ets_vsnprintf(str, strSize, format, ap);

    delete[] format;

    return ret;
}
<|endoftext|>


<commit_before>// Copyright Daniel Wallin 2006. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#include <boost/python.hpp>
#include <libtorrent/alert.hpp>
#include <libtorrent/alert_types.hpp>

using namespace boost::python;
using namespace libtorrent;

std::string get_buffer(read_piece_alert const& rpa)
{
    return rpa.buffer ? std::string(rpa.buffer.get(), rpa.size)
       : std::string();
}

void bind_alert()
{
    using boost::noncopyable;

    {
        scope alert_scope = class_<alert, noncopyable>("alert", no_init)
            .def("message", &alert::message)
            .def("what", &alert::what)
            .def("category", &alert::category)
#ifndef TORRENT_NO_DEPRECATE
            .def("severity", &alert::severity)
#endif
            .def("__str__", &alert::message)
            ;

#ifndef TORRENT_NO_DEPRECATE
        enum_<alert::severity_t>("severity_levels")
            .value("debug", alert::debug)
            .value("info", alert::info)
            .value("warning", alert::warning)
            .value("critical", alert::critical)
            .value("fatal", alert::fatal)
            .value("none", alert::none)
            ;
#endif

        enum_<alert::category_t>("category_t")
            .value("error_notification", alert::error_notification)
            .value("peer_notification", alert::peer_notification)
            .value("port_mapping_notification", alert::port_mapping_notification)
            .value("storage_notification", alert::storage_notification)
            .value("tracker_notification", alert::tracker_notification)
            .value("debug_notification", alert::debug_notification)
            .value("status_notification", alert::status_notification)
            .value("progress_notification", alert::progress_notification)
            .value("ip_block_notification", alert::ip_block_notification)
            .value("performance_warning", alert::performance_warning)
            .value("all_categories", alert::all_categories)
            ;

    }

    class_<torrent_alert, bases<alert>, noncopyable>(
        "torrent_alert", no_init
    )
        .def_readonly("handle", &torrent_alert::handle)
        ;

    class_<tracker_alert, bases<torrent_alert>, noncopyable>(
        "tracker_alert", no_init
    )
        .def_readonly("url", &tracker_alert::url)
        ;

    class_<read_piece_alert, bases<torrent_alert>, noncopyable>(
        "read_piece_alert", 0, no_init
    )
        .add_property("buffer", get_buffer)
        .def_readonly("piece", &read_piece_alert::piece)
        .def_readonly("size", &read_piece_alert::size)
        ;

    class_<peer_alert, bases<torrent_alert>, noncopyable>(
        "peer_alert", no_init
    )
        .def_readonly("ip", &peer_alert::ip)
        .def_readonly("pid", &peer_alert::pid)
    ;
    class_<tracker_error_alert, bases<tracker_alert>, noncopyable>(
        "tracker_error_alert", no_init
    )
        .def_readonly("msg", &tracker_error_alert::msg)
        .def_readonly("times_in_row", &tracker_error_alert::times_in_row)
        .def_readonly("status_code", &tracker_error_alert::status_code)
        ;

    class_<tracker_warning_alert, bases<tracker_alert>, noncopyable>(
        "tracker_warning_alert", no_init
    );

    class_<tracker_reply_alert, bases<tracker_alert>, noncopyable>(
        "tracker_reply_alert", no_init
    )
        .def_readonly("num_peers", &tracker_reply_alert::num_peers)
        ;

    class_<tracker_announce_alert, bases<tracker_alert>, noncopyable>(
        "tracker_announce_alert", no_init
    );

    class_<hash_failed_alert, bases<torrent_alert>, noncopyable>(
        "hash_failed_alert", no_init
    )
        .def_readonly("piece_index", &hash_failed_alert::piece_index)
        ;

    class_<peer_ban_alert, bases<peer_alert>, noncopyable>(
        "peer_ban_alert", no_init
    );

    class_<peer_error_alert, bases<peer_alert>, noncopyable>(
        "peer_error_alert", no_init
    );

    class_<invalid_request_alert, bases<peer_alert>, noncopyable>(
        "invalid_request_alert", no_init
    )
        .def_readonly("request", &invalid_request_alert::request)
        ;

    class_<peer_request>("peer_request")
        .def_readonly("piece", &peer_request::piece)
        .def_readonly("start", &peer_request::start)
        .def_readonly("length", &peer_request::length)
        .def(self == self)
        ;

    class_<torrent_finished_alert, bases<torrent_alert>, noncopyable>(
        "torrent_finished_alert", no_init
    );

    class_<piece_finished_alert, bases<torrent_alert>, noncopyable>(
        "piece_finished_alert", no_init
    )
        .def_readonly("piece_index", &piece_finished_alert::piece_index)
        ;

    class_<block_finished_alert, bases<peer_alert>, noncopyable>(
        "block_finished_alert", no_init
    )
        .def_readonly("block_index", &block_finished_alert::block_index)
        .def_readonly("piece_index", &block_finished_alert::piece_index)
        ;

    class_<block_downloading_alert, bases<peer_alert>, noncopyable>(
        "block_downloading_alert", no_init
    )
        .def_readonly("peer_speedmsg", &block_downloading_alert::peer_speedmsg)
        .def_readonly("block_index", &block_downloading_alert::block_index)
        .def_readonly("piece_index", &block_downloading_alert::piece_index)
        ;

    class_<storage_moved_alert, bases<torrent_alert>, noncopyable>(
        "storage_moved_alert", no_init
    );

    class_<storage_moved_failed_alert, bases<torrent_alert>, noncopyable>(
        "storage_moved_failed_alert", no_init
    )
        .def_readonly("error", &storage_moved_failed_alert::error)
        ;

    class_<torrent_deleted_alert, bases<torrent_alert>, noncopyable>(
        "torrent_deleted_alert", no_init
    );

    class_<torrent_paused_alert, bases<torrent_alert>, noncopyable>(
        "torrent_paused_alert", no_init
    );

    class_<torrent_checked_alert, bases<torrent_alert>, noncopyable>(
        "torrent_checked_alert", no_init
    );

    class_<url_seed_alert, bases<torrent_alert>, noncopyable>(
        "url_seed_alert", no_init
    )
        .def_readonly("url", &url_seed_alert::url)
        ;

    class_<file_error_alert, bases<torrent_alert>, noncopyable>(
        "file_error_alert", no_init
    )
        .def_readonly("file", &file_error_alert::file)
        ;

    class_<metadata_failed_alert, bases<torrent_alert>, noncopyable>(
        "metadata_failed_alert", no_init
    );

    class_<metadata_received_alert, bases<torrent_alert>, noncopyable>(
        "metadata_received_alert", no_init
    );

    class_<listen_failed_alert, bases<alert>, noncopyable>(
        "listen_failed_alert", no_init
    );

    class_<listen_succeeded_alert, bases<alert>, noncopyable>(
        "listen_succeeded_alert", no_init
    )
        .def_readonly("endpoint", &listen_succeeded_alert::endpoint)
        ;

    class_<portmap_error_alert, bases<alert>, noncopyable>(
        "portmap_error_alert", no_init
    )
        .def_readonly("mapping", &portmap_error_alert::mapping)
        .def_readonly("type", &portmap_error_alert::type)
        ;

    class_<portmap_alert, bases<alert>, noncopyable>(
        "portmap_alert", no_init
    )
        .def_readonly("mapping", &portmap_alert::mapping)
        .def_readonly("external_port", &portmap_alert::external_port)
        .def_readonly("type", &portmap_alert::type)
        ;

    class_<fastresume_rejected_alert, bases<torrent_alert>, noncopyable>(
        "fastresume_rejected_alert", no_init
    );

    class_<peer_blocked_alert, bases<alert>, noncopyable>(
        "peer_blocked_alert", no_init
    )
        .def_readonly("ip", &peer_blocked_alert::ip)
        ;

    class_<scrape_reply_alert, bases<tracker_alert>, noncopyable>(
        "scrape_reply_alert", no_init
    )
        .def_readonly("incomplete", &scrape_reply_alert::incomplete)
        .def_readonly("complete", &scrape_reply_alert::complete)
        ;

    class_<scrape_failed_alert, bases<tracker_alert>, noncopyable>(
        "scrape_failed_alert", no_init
    );

    class_<udp_error_alert, bases<alert>, noncopyable>(
        "udp_error_alert", no_init
    )
        .def_readonly("endpoint", &udp_error_alert::endpoint)
        ;

    class_<external_ip_alert, bases<alert>, noncopyable>(
        "external_ip_alert", no_init
    )
        .def_readonly("external_address", &external_ip_alert::external_address)
        ;

    class_<save_resume_data_alert, bases<torrent_alert>, noncopyable>(
        "save_resume_data_alert", no_init
    )
        .def_readonly("resume_data", &save_resume_data_alert::resume_data)
        ;

    class_<file_renamed_alert, bases<torrent_alert>, noncopyable>(
        "file_renamed_alert", no_init
    )
        .def_readonly("index", &file_renamed_alert::index)
        .def_readonly("name", &file_renamed_alert::name)
        ;

    class_<file_rename_failed_alert, bases<torrent_alert>, noncopyable>(
        "file_rename_failed_alert", no_init
    )
        .def_readonly("index", &file_rename_failed_alert::index)
        .def_readonly("error", &file_rename_failed_alert::error)
        ;

    class_<torrent_resumed_alert, bases<torrent_alert>, noncopyable>(
        "torrent_resumed_alert", no_init
	);

	class_<state_changed_alert, bases<torrent_alert>, noncopyable>(
	    "state_changed_alert", no_init
	)
	    .def_readonly("state", &state_changed_alert::state)
	    ;

	class_<dht_reply_alert, bases<tracker_alert>, noncopyable>(
	    "dht_reply_alert", no_init
	)
	    .def_readonly("num_peers", &dht_reply_alert::num_peers)
	    ;

	class_<peer_unsnubbed_alert, bases<peer_alert>, noncopyable>(
	    "peer_unsnubbed_alert", no_init
	);

	class_<peer_snubbed_alert, bases<peer_alert>, noncopyable>(
	    "peer_snubbed_alert", no_init
	);

    class_<peer_connect_alert, bases<peer_alert>, noncopyable>(
        "peer_connect_alert", no_init
    );

    class_<peer_disconnected_alert, bases<peer_alert>, noncopyable>(
        "peer_disconnected_alert", no_init
    );

    class_<request_dropped_alert, bases<peer_alert>, noncopyable>(
        "request_dropped_alert", no_init
    )
        .def_readonly("block_index", &request_dropped_alert::block_index)
        .def_readonly("piece_index", &request_dropped_alert::piece_index)
    ;

    class_<block_timeout_alert, bases<peer_alert>, noncopyable>(
        "block_timeout_alert", no_init
    )
        .def_readonly("block_index", &block_timeout_alert::block_index)
        .def_readonly("piece_index", &block_timeout_alert::piece_index)
    ;

    class_<unwanted_block_alert, bases<peer_alert>, noncopyable>(
        "unwanted_block_alert", no_init
    )
        .def_readonly("block_index", &unwanted_block_alert::block_index)
        .def_readonly("piece_index", &unwanted_block_alert::piece_index)
    ;

    class_<torrent_delete_failed_alert, bases<torrent_alert>, noncopyable>(
        "torrent_delete_failed_alert", no_init
    );

    class_<save_resume_data_failed_alert, bases<torrent_alert>, noncopyable>(
        "save_resume_data_failed_alert", no_init
    );

    class_<performance_alert, bases<torrent_alert>, noncopyable>(
        "performance_alert", no_init
    )
        .def_readonly("warning_code", &performance_alert::warning_code)
    ;
    enum_<performance_alert::performance_warning_t>("performance_warning_t")
        .value("outstanding_disk_buffer_limit_reached", performance_alert::outstanding_disk_buffer_limit_reached)
        .value("outstanding_request_limit_reached", performance_alert::outstanding_request_limit_reached)
    ;

}
<commit_msg>Add some missing alerts and properties<commit_after>// Copyright Daniel Wallin 2006. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#include <boost/python.hpp>
#include <libtorrent/alert.hpp>
#include <libtorrent/alert_types.hpp>

using namespace boost::python;
using namespace libtorrent;

std::string get_buffer(read_piece_alert const& rpa)
{
    return rpa.buffer ? std::string(rpa.buffer.get(), rpa.size)
       : std::string();
}

void bind_alert()
{
    using boost::noncopyable;

    {
        scope alert_scope = class_<alert, noncopyable>("alert", no_init)
            .def("message", &alert::message)
            .def("what", &alert::what)
            .def("category", &alert::category)
#ifndef TORRENT_NO_DEPRECATE
            .def("severity", &alert::severity)
#endif
            .def("__str__", &alert::message)
            ;

#ifndef TORRENT_NO_DEPRECATE
        enum_<alert::severity_t>("severity_levels")
            .value("debug", alert::debug)
            .value("info", alert::info)
            .value("warning", alert::warning)
            .value("critical", alert::critical)
            .value("fatal", alert::fatal)
            .value("none", alert::none)
            ;
#endif

        enum_<alert::category_t>("category_t")
            .value("error_notification", alert::error_notification)
            .value("peer_notification", alert::peer_notification)
            .value("port_mapping_notification", alert::port_mapping_notification)
            .value("storage_notification", alert::storage_notification)
            .value("tracker_notification", alert::tracker_notification)
            .value("debug_notification", alert::debug_notification)
            .value("status_notification", alert::status_notification)
            .value("progress_notification", alert::progress_notification)
            .value("ip_block_notification", alert::ip_block_notification)
            .value("performance_warning", alert::performance_warning)
            .value("all_categories", alert::all_categories)
            ;

    }

    class_<torrent_alert, bases<alert>, noncopyable>(
        "torrent_alert", no_init
    )
        .def_readonly("handle", &torrent_alert::handle)
        ;

    class_<tracker_alert, bases<torrent_alert>, noncopyable>(
        "tracker_alert", no_init
    )
        .def_readonly("url", &tracker_alert::url)
        ;

    class_<read_piece_alert, bases<torrent_alert>, noncopyable>(
        "read_piece_alert", 0, no_init
    )
        .add_property("buffer", get_buffer)
        .def_readonly("piece", &read_piece_alert::piece)
        .def_readonly("size", &read_piece_alert::size)
        ;

    class_<peer_alert, bases<torrent_alert>, noncopyable>(
        "peer_alert", no_init
    )
        .def_readonly("ip", &peer_alert::ip)
        .def_readonly("pid", &peer_alert::pid)
    ;
    class_<tracker_error_alert, bases<tracker_alert>, noncopyable>(
        "tracker_error_alert", no_init
    )
        .def_readonly("msg", &tracker_error_alert::msg)
        .def_readonly("times_in_row", &tracker_error_alert::times_in_row)
        .def_readonly("status_code", &tracker_error_alert::status_code)
        ;

    class_<tracker_warning_alert, bases<tracker_alert>, noncopyable>(
        "tracker_warning_alert", no_init
    );

    class_<tracker_reply_alert, bases<tracker_alert>, noncopyable>(
        "tracker_reply_alert", no_init
    )
        .def_readonly("num_peers", &tracker_reply_alert::num_peers)
        ;

    class_<tracker_announce_alert, bases<tracker_alert>, noncopyable>(
        "tracker_announce_alert", no_init
    )
        .def_readonly("event", &tracker_reply_alert::event)
        ;

    class_<hash_failed_alert, bases<torrent_alert>, noncopyable>(
        "hash_failed_alert", no_init
    )
        .def_readonly("piece_index", &hash_failed_alert::piece_index)
        ;

    class_<peer_ban_alert, bases<peer_alert>, noncopyable>(
        "peer_ban_alert", no_init
    );

    class_<peer_error_alert, bases<peer_alert>, noncopyable>(
        "peer_error_alert", no_init
    );

    class_<invalid_request_alert, bases<peer_alert>, noncopyable>(
        "invalid_request_alert", no_init
    )
        .def_readonly("request", &invalid_request_alert::request)
        ;

    class_<peer_request>("peer_request")
        .def_readonly("piece", &peer_request::piece)
        .def_readonly("start", &peer_request::start)
        .def_readonly("length", &peer_request::length)
        .def(self == self)
        ;

    class_<torrent_finished_alert, bases<torrent_alert>, noncopyable>(
        "torrent_finished_alert", no_init
    );

    class_<piece_finished_alert, bases<torrent_alert>, noncopyable>(
        "piece_finished_alert", no_init
    )
        .def_readonly("piece_index", &piece_finished_alert::piece_index)
        ;

    class_<block_finished_alert, bases<peer_alert>, noncopyable>(
        "block_finished_alert", no_init
    )
        .def_readonly("block_index", &block_finished_alert::block_index)
        .def_readonly("piece_index", &block_finished_alert::piece_index)
        ;

    class_<block_downloading_alert, bases<peer_alert>, noncopyable>(
        "block_downloading_alert", no_init
    )
        .def_readonly("peer_speedmsg", &block_downloading_alert::peer_speedmsg)
        .def_readonly("block_index", &block_downloading_alert::block_index)
        .def_readonly("piece_index", &block_downloading_alert::piece_index)
        ;

    class_<storage_moved_alert, bases<torrent_alert>, noncopyable>(
        "storage_moved_alert", no_init
    )
        .def_readonly("path", &storaged_moved_alert::path)
        ;

    class_<storage_moved_failed_alert, bases<torrent_alert>, noncopyable>(
        "storage_moved_failed_alert", no_init
    )
        .def_readonly("error", &storage_moved_failed_alert::error)
        ;

    class_<torrent_deleted_alert, bases<torrent_alert>, noncopyable>(
        "torrent_deleted_alert", no_init
    );

    class_<torrent_paused_alert, bases<torrent_alert>, noncopyable>(
        "torrent_paused_alert", no_init
    );

    class_<torrent_checked_alert, bases<torrent_alert>, noncopyable>(
        "torrent_checked_alert", no_init
    );

    class_<url_seed_alert, bases<torrent_alert>, noncopyable>(
        "url_seed_alert", no_init
    )
        .def_readonly("url", &url_seed_alert::url)
        .def_readonly("msg", &url_seed_alert::msg)
        ;

    class_<file_error_alert, bases<torrent_alert>, noncopyable>(
        "file_error_alert", no_init
    )
        .def_readonly("file", &file_error_alert::file)
        .def_readonly("msg", &file_error_alert::msg)
        ;

    class_<metadata_failed_alert, bases<torrent_alert>, noncopyable>(
        "metadata_failed_alert", no_init
    );

    class_<metadata_received_alert, bases<torrent_alert>, noncopyable>(
        "metadata_received_alert", no_init
    );

    class_<listen_failed_alert, bases<alert>, noncopyable>(
        "listen_failed_alert", no_init
    )
        .def_readonly("endpoint", &listen_failed_alert::endpoint)
        .def_readonly("error", &listen_failed_alert::error)
        ;

    class_<listen_succeeded_alert, bases<alert>, noncopyable>(
        "listen_succeeded_alert", no_init
    )
        .def_readonly("endpoint", &listen_succeeded_alert::endpoint)
        ;

    class_<portmap_error_alert, bases<alert>, noncopyable>(
        "portmap_error_alert", no_init
    )
        .def_readonly("mapping", &portmap_error_alert::mapping)
        .def_readonly("type", &portmap_error_alert::type)
        .def_readonly("msg", &portmap_error_alert::msg)
        ;

    class_<portmap_alert, bases<alert>, noncopyable>(
        "portmap_alert", no_init
    )
        .def_readonly("mapping", &portmap_alert::mapping)
        .def_readonly("external_port", &portmap_alert::external_port)
        .def_readonly("type", &portmap_alert::type)
        ;

    class_<portmap_log_alert, bases<alert>, noncopyable>(
        "portmap_log_alert", no_init
    )
        .def_readonly("type", &portmap_log_alert::type)
        .def_readonly("msg", &portmap_log_alert::msg)
        ;

    class_<fastresume_rejected_alert, bases<torrent_alert>, noncopyable>(
        "fastresume_rejected_alert", no_init
    )
        .def_readonly("msg", &fastresume_rejected_alert::msg)
        ;

    class_<peer_blocked_alert, bases<alert>, noncopyable>(
        "peer_blocked_alert", no_init
    )
        .def_readonly("ip", &peer_blocked_alert::ip)
        ;

    class_<scrape_reply_alert, bases<tracker_alert>, noncopyable>(
        "scrape_reply_alert", no_init
    )
        .def_readonly("incomplete", &scrape_reply_alert::incomplete)
        .def_readonly("complete", &scrape_reply_alert::complete)
        ;

    class_<scrape_failed_alert, bases<tracker_alert>, noncopyable>(
        "scrape_failed_alert", no_init
    );

    class_<udp_error_alert, bases<alert>, noncopyable>(
        "udp_error_alert", no_init
    )
        .def_readonly("endpoint", &udp_error_alert::endpoint)
        .def_readonly("error", &udp_error_alert::error)
        ;

    class_<external_ip_alert, bases<alert>, noncopyable>(
        "external_ip_alert", no_init
    )
        .def_readonly("external_address", &external_ip_alert::external_address)
        ;

    class_<save_resume_data_alert, bases<torrent_alert>, noncopyable>(
        "save_resume_data_alert", no_init
    )
        .def_readonly("resume_data", &save_resume_data_alert::resume_data)
        ;

    class_<file_renamed_alert, bases<torrent_alert>, noncopyable>(
        "file_renamed_alert", no_init
    )
        .def_readonly("index", &file_renamed_alert::index)
        .def_readonly("name", &file_renamed_alert::name)
        ;

    class_<file_rename_failed_alert, bases<torrent_alert>, noncopyable>(
        "file_rename_failed_alert", no_init
    )
        .def_readonly("index", &file_rename_failed_alert::index)
        .def_readonly("error", &file_rename_failed_alert::error)
        ;

    class_<torrent_resumed_alert, bases<torrent_alert>, noncopyable>(
        "torrent_resumed_alert", no_init
	);

	class_<state_changed_alert, bases<torrent_alert>, noncopyable>(
	    "state_changed_alert", no_init
	)
	    .def_readonly("state", &state_changed_alert::state)
	    .def_readonly("prev_state", &state_changed_alert::prev_state)
	    ;

	class_<dht_reply_alert, bases<tracker_alert>, noncopyable>(
	    "dht_reply_alert", no_init
	)
	    .def_readonly("num_peers", &dht_reply_alert::num_peers)
	    ;

    class_<dht_announce_alert, bases<alert>, noncopyable>(
        "dht_announce_alert", no_init
    )
        .def_readonly("ip" &dht_announce_alert::ip)
        .def_readonly("port", &dht_announce_alert::port)
        .def_readonly("info_hash", &dht_announce_alert::info_hash)
    ;

    class_<dht_get_peers_alert, bases<alert>, noncopyable>(
        "dht_get_peers_alert", no_init
    )
        .def_readonly("info_hash", &dht_get_peers_alert::info_hash)
    ;

	class_<peer_unsnubbed_alert, bases<peer_alert>, noncopyable>(
	    "peer_unsnubbed_alert", no_init
	);

	class_<peer_snubbed_alert, bases<peer_alert>, noncopyable>(
	    "peer_snubbed_alert", no_init
	);

    class_<peer_connect_alert, bases<peer_alert>, noncopyable>(
        "peer_connect_alert", no_init
    );

    class_<peer_disconnected_alert, bases<peer_alert>, noncopyable>(
        "peer_disconnected_alert", no_init
    )
        .def_readonly("msg", &peer_disconnected_alert::msg)
        ;

    class_<request_dropped_alert, bases<peer_alert>, noncopyable>(
        "request_dropped_alert", no_init
    )
        .def_readonly("block_index", &request_dropped_alert::block_index)
        .def_readonly("piece_index", &request_dropped_alert::piece_index)
    ;

    class_<block_timeout_alert, bases<peer_alert>, noncopyable>(
        "block_timeout_alert", no_init
    )
        .def_readonly("block_index", &block_timeout_alert::block_index)
        .def_readonly("piece_index", &block_timeout_alert::piece_index)
    ;

    class_<unwanted_block_alert, bases<peer_alert>, noncopyable>(
        "unwanted_block_alert", no_init
    )
        .def_readonly("block_index", &unwanted_block_alert::block_index)
        .def_readonly("piece_index", &unwanted_block_alert::piece_index)
    ;

    class_<torrent_delete_failed_alert, bases<torrent_alert>, noncopyable>(
        "torrent_delete_failed_alert", no_init
    )
        .def_readonly("msg", &torrent_delete_failed_alert::msg)
        ;

    class_<save_resume_data_failed_alert, bases<torrent_alert>, noncopyable>(
        "save_resume_data_failed_alert", no_init
    )
        .def_readonly("msg", &save_resume_data_failed_alert::msg)
        ;

    class_<performance_alert, bases<torrent_alert>, noncopyable>(
        "performance_alert", no_init
    )
        .def_readonly("warning_code", &performance_alert::warning_code)
    ;
    enum_<performance_alert::performance_warning_t>("performance_warning_t")
        .value("outstanding_disk_buffer_limit_reached", performance_alert::outstanding_disk_buffer_limit_reached)
        .value("outstanding_request_limit_reached", performance_alert::outstanding_request_limit_reached)
        .value("upload_limit_too_low", performance_alert::upload_limit_too_low)
        .value("download_limit_too_low", performance_alert::download_limit_too_low)
    ;

}
<|endoftext|>


<commit_before><commit_msg>BUG: fix QByteArray to std::string conversion in monteverdi<commit_after><|endoftext|>