<commit_before>#include <command/command.hpp>
#include <chat/chat.hpp>

static const Word priority=1;
static const String name("Whisper Support");
static const String identifier("w");
static const String summary("Sends a private message to another player.");
static const String help(
	"Syntax: /w <player name> <message>\n"
	"Sends a private message to <player name>.\n"
	"Note that this message will still be logged, so don't send anything you wouldn't want server administrators to read."
);
static const Regex whitespace("\\s");
static const Regex parse("^([^\\s]+)\\s+(.+)$");

class Whisper : public Module, public Command {

	public:

		virtual const String & Name () const noexcept override {

			return name;

		}

		virtual Word Priority () const noexcept override {

			return priority;

		}

		virtual void Install () override {

			Commands->Add(this);

		}

		virtual const String & Summary () const noexcept override {

			return summary;

		}

		virtual const String & Help () const noexcept override {

			return help;

		}

		virtual const String & Identifier () const noexcept override {

			return identifier;

		}

		virtual bool Check (SmartPointer<Client> client) const override {

			//	Everyone can send whispers
			return true;

		}

		virtual Vector<String> AutoComplete (const String & args) const override {

			Vector<String> retr;

			//	Is there whitespace in the args
			//	listing?
			//
			//	If so a username has been specified
			//	and there's nothing we can do
			if (whitespace.IsMatch(args)) return retr;

			//	Create a regex to match only users
			//	whose username begins with the
			//	string we were passed
			Regex regex(
				String::Format(
					"^{0}",
					Regex::Escape(
						args
					)
				),
				//	Usernames are not case sensitive
				RegexOptions().SetIgnoreCase()
			);

			RunningServer->Clients.Scan([&] (const SmartPointer<Client> & client) {

				//	Only authenticated users are valid
				//	chat targets
				if (
					(client->GetState()==ClientState::Authenticated) &&
					regex.IsMatch(client->GetUsername())
				) {

					retr.Add(
						//	Normalize to lower case
						client->GetUsername().ToLower()
					);

				}

			});

			return retr;

		}

		virtual bool Execute (SmartPointer<Client> client, const String & args, ChatMessage & message) override {

			//	Attempt to parse args
			auto match=parse.Match(args);

			if (!match.Success()) return false;

			//	Prepare a message
			ChatMessage whisper;
			whisper.To.Add(match[1].Value());
			whisper.From=std::move(client);
			whisper << match[2].Value();

			//	Attempt to send
			if (Chat->Send(whisper).Count()==0) {

				//	Delivery success -- could not be
				//	delivered to zero recipients (meaning
				//	intended recipient exists)

				//	Send it back to original sender
				whisper.Echo=true;

				message=std::move(whisper);

			} else {

				//	Delivery failure -- could not be
				//	delivered to at least one recipient
				//	(meaning intended recipient does not
				//	exist).

				//	Transmit error to caller
				message	<< ChatStyle::Red
						<< ChatStyle::Bold
						<< "User \""
						<< match[1].Value()
						<< "\" does not exist";

			}

			return true;

		}

};

static Nullable<Whisper> module;

extern "C" {

	Module * Load () {

		if (module.IsNull()) module.Construct();

		return &(*module);

	}

	void Unload () {

		module.Destroy();

	}

}
<commit_msg>Whisper Bugfix<commit_after>#include <command/command.hpp>
#include <chat/chat.hpp>

static const Word priority=1;
static const String name("Whisper Support");
static const String identifier("w");
static const String summary("Sends a private message to another player.");
static const String help(
	"Syntax: /w <player name> <message>\n"
	"Sends a private message to <player name>.\n"
	"Note that this message will still be logged."
);
static const Regex whitespace("\\s");
static const Regex parse("^([^\\s]+)\\s+(.+)$");

class Whisper : public Module, public Command {

	public:

		virtual const String & Name () const noexcept override {

			return name;

		}

		virtual Word Priority () const noexcept override {

			return priority;

		}

		virtual void Install () override {

			Commands->Add(this);

		}

		virtual const String & Summary () const noexcept override {

			return summary;

		}

		virtual const String & Help () const noexcept override {

			return help;

		}

		virtual const String & Identifier () const noexcept override {

			return identifier;

		}

		virtual bool Check (SmartPointer<Client> client) const override {

			//	Everyone can send whispers
			return true;

		}

		virtual Vector<String> AutoComplete (const String & args) const override {

			Vector<String> retr;

			//	Is there whitespace in the args
			//	listing?
			//
			//	If so a username has been specified
			//	and there's nothing we can do
			if (whitespace.IsMatch(args)) return retr;

			//	Create a regex to match only users
			//	whose username begins with the
			//	string we were passed
			Regex regex(
				String::Format(
					"^{0}",
					Regex::Escape(
						args
					)
				),
				//	Usernames are not case sensitive
				RegexOptions().SetIgnoreCase()
			);

			RunningServer->Clients.Scan([&] (const SmartPointer<Client> & client) {

				//	Only authenticated users are valid
				//	chat targets
				if (
					(client->GetState()==ClientState::Authenticated) &&
					regex.IsMatch(client->GetUsername())
				) {

					retr.Add(
						//	Normalize to lower case
						client->GetUsername().ToLower()
					);

				}

			});

			return retr;

		}

		virtual bool Execute (SmartPointer<Client> client, const String & args, ChatMessage & message) override {

			//	Attempt to parse args
			auto match=parse.Match(args);

			if (!match.Success()) return false;

			//	Prepare a message
			ChatMessage whisper(
				std::move(client),
				match[1].Value(),
				match[2].Value()
			);

			//	Attempt to send
			if (Chat->Send(whisper).Count()==0) {

				//	Delivery success -- could not be
				//	delivered to zero recipients (meaning
				//	intended recipient exists)

				//	Send it back to original sender
				whisper.Echo=true;

				message=std::move(whisper);

			} else {

				//	Delivery failure -- could not be
				//	delivered to at least one recipient
				//	(meaning intended recipient does not
				//	exist).

				//	Transmit error to caller
				message	<< ChatStyle::Red
						<< ChatStyle::Bold
						<< "User \""
						<< match[1].Value()
						<< "\" does not exist";

			}

			return true;

		}

};

static Nullable<Whisper> module;

extern "C" {

	Module * Load () {

		if (module.IsNull()) module.Construct();

		return &(*module);

	}

	void Unload () {

		module.Destroy();

	}

}
<|endoftext|>


<commit_before>/*******************************************************************************
 * libproxy - A library for proxy configuration
 * Copyright (C) 2006 Nathaniel McCallum <nathaniel@natemccallum.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
 ******************************************************************************/

#include "../extension_pacrunner.hpp"
using namespace libproxy;

#define I_ACKNOWLEDGE_THAT_NATUS_IS_NOT_STABLE
#include <natus/natus.h>
#include "pacutils.h"

#ifndef INET_ADDRSTRLEN
#define INET_ADDRSTRLEN 16
#endif

#ifndef INET6_ADDRSTRLEN
#define INET6_ADDRSTRLEN 46
#endif

using namespace natus;

static Value dnsResolve(Value& ths, Value& fnc, vector<Value>& arg) {
	Value exc = checkArguments(ths, arg, "s");
	if (exc.isException()) return exc;

	// Look it up
	struct addrinfo *info;
	if (getaddrinfo(arg[0].toString().c_str(), NULL, NULL, &info))
		return NULL;

	// Try for IPv4
	char* tmp = new char[INET6_ADDRSTRLEN+1];
	if (getnameinfo(info->ai_addr, info->ai_addrlen,
					tmp, INET6_ADDRSTRLEN+1,
					NULL, 0,
					NI_NUMERICHOST)) {
			freeaddrinfo(info);
			delete tmp;
			return NULL;
		}
	freeaddrinfo(info);

	// Create the return value
	Value ret = ths.newString(tmp);
	delete tmp;
	return ret;
}

static Value myIpAddress(Value& ths, Value& fnc, vector<Value>& arg) {
	char hostname[1024];
	if (!gethostname(hostname, 1023)) {
		vector<Value> dnsargs;
		dnsargs.push_back(ths.newString(hostname));
		return dnsResolve(ths, fnc, dnsargs);
	}
	return ths.newString("Unable to find hostname!").toException();
}

class webkit_pacrunner : public pacrunner {
public:
	webkit_pacrunner(string pac, const url& pacurl) throw (bad_alloc) : pacrunner(pac, pacurl) {
		Value exc;

		// Create the basic context
		if (!eng.initialize()) goto error;
		glb = this->eng.newGlobal();
		if (glb.isException()) goto error;

		// Add dnsResolve into the context
		if (!glb.set("dnsResolve", glb.newFunction(dnsResolve))) goto error;

		// Add myIpAddress into the context
		if (!glb.set("myIpAddress", glb.newFunction(myIpAddress))) goto error;

		// Add all other routines into the context
		exc = glb.evaluate(JAVASCRIPT_ROUTINES);
		if (exc.isException()) goto error;

		// Add the PAC into the context
		exc = glb.evaluate(pac.c_str(), pacurl.to_string());
		if (exc.isException()) goto error;
		return;

	error:
		throw bad_alloc();
	}

	string run(const url& url_) throw (bad_alloc) {
		vector<Value> args;
		args.push_back(glb.newString(url_.to_string()));
		args.push_back(glb.newString(url_.get_host()));

		Value res = glb.call("FindProxyForURL", args);
		if (res.isString() && !res.isException())
			return res.toString();
		return "";
	}

private:
	Engine eng;
	Value  glb;
};

PX_PACRUNNER_MODULE_EZ(webkit, "JSObjectMakeFunctionWithCallback", "webkit");
<commit_msg>cleanup natus pacrunner<commit_after>/*******************************************************************************
 * libproxy - A library for proxy configuration
 * Copyright (C) 2006 Nathaniel McCallum <nathaniel@natemccallum.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
 ******************************************************************************/

#include "../extension_pacrunner.hpp"
using namespace libproxy;

#define I_ACKNOWLEDGE_THAT_NATUS_IS_NOT_STABLE
#include <natus/natus.h>
#include "pacutils.h"

using namespace natus;

static Value dnsResolve(Value& ths, Value& fnc, vector<Value>& arg) {
	Value exc = checkArguments(ths, arg, "s");
	if (exc.isException()) return exc;

	// Look it up
	struct addrinfo *info;
	if (getaddrinfo(arg[0].toString().c_str(), NULL, NULL, &info))
		return NULL;

	// Try for IPv4
	char* tmp = new char[INET6_ADDRSTRLEN+1];
	if (getnameinfo(info->ai_addr, info->ai_addrlen,
					tmp, INET6_ADDRSTRLEN+1,
					NULL, 0,
					NI_NUMERICHOST)) {
			freeaddrinfo(info);
			delete tmp;
			return NULL;
		}
	freeaddrinfo(info);

	// Create the return value
	Value ret = ths.newString(tmp);
	delete tmp;
	return ret;
}

static Value myIpAddress(Value& ths, Value& fnc, vector<Value>& arg) {
	char hostname[1024];
	if (!gethostname(hostname, 1023)) {
		vector<Value> dnsargs;
		dnsargs.push_back(ths.newString(hostname));
		return dnsResolve(ths, fnc, dnsargs);
	}
	return ths.newString("Unable to find hostname!").toException();
}

class natus_pacrunner : public pacrunner {
public:
	natus_pacrunner(string pac, const url& pacurl) throw (bad_alloc) : pacrunner(pac, pacurl) {
		Value exc;

		// Create the basic context
		if (!eng.initialize()) goto error;
		glb = this->eng.newGlobal();
		if (glb.isException()) goto error;

		// Add dnsResolve into the context
		if (!glb.set("dnsResolve", glb.newFunction(dnsResolve))) goto error;

		// Add myIpAddress into the context
		if (!glb.set("myIpAddress", glb.newFunction(myIpAddress))) goto error;

		// Add all other routines into the context
		exc = glb.evaluate(JAVASCRIPT_ROUTINES);
		if (exc.isException()) goto error;

		// Add the PAC into the context
		exc = glb.evaluate(pac.c_str(), pacurl.to_string());
		if (exc.isException()) goto error;
		return;

	error:
		throw bad_alloc();
	}

	string run(const url& url_) throw (bad_alloc) {
		vector<Value> args;
		args.push_back(glb.newString(url_.to_string()));
		args.push_back(glb.newString(url_.get_host()));

		Value res = glb.call("FindProxyForURL", args);
		if (res.isString() && !res.isException())
			return res.toString();
		return "";
	}

private:
	Engine eng;
	Value  glb;
};

PX_PACRUNNER_MODULE_EZ(natus, "nt_engine_init", "natus");
<|endoftext|>


<commit_before>#include "player.hxx"
#include "stb_vorbis.h"
#include <iostream>

Player::Player(std::string const &filename) {
  // Load a vorbis file
  int channels, len, sampleRate;
  int16_t *buffer;
  len = stb_vorbis_decode_filename(filename.c_str(), &channels, &sampleRate,
      &buffer);

  // Initialize an SDL audio device
  SDL_AudioSpec want, have;

  want.freq = sampleRate;
  want.format = AUDIO_S16LSB;
  want.channels = 2;
  want.samples = 4096;
  want.callback = playerCallback;
  want.userdata = (void*)this;

  audioDevice = SDL_OpenAudioDevice(NULL, 0, &want, &have,
      SDL_AUDIO_ALLOW_FORMAT_CHANGE);

  if (want.format != have.format) {
    std::cout << "Player failed to get required audio format!" << std::endl;
  }

  // Prep player class members to play from previously loaded audio buffer
  currentLen = len * sizeof(uint16_t);
  audioPos = audioData = (uint8_t*)buffer;
}

Player::~Player() {
  delete[] audioData;
}

void Player::start() {
  SDL_PauseAudioDevice(audioDevice, 0);
}

void Player::playerCallback(void *userData, uint8_t *stream, int len) {
  Player *player = (Player*)userData;

  // Don't play if empty
  if (player->currentLen == 0) {
    return;
  }

  // Limit reading to buffer bounds
  len = (len > player->currentLen ? player->currentLen : len);

  // Copy audio buffer to player
  SDL_memcpy(stream, player->audioPos, len);

  // Move to next block
  player->audioPos += len;

  // Keep track of data left in the buffer
  player->currentLen -= len;
}
<commit_msg>Fixed some audio player bugs.<commit_after>#include "player.hxx"
#include "stb_vorbis.h"
#include <iostream>

Player::Player(std::string const &filename) {
  // Load a vorbis file
  int channels, len, sampleRate;
  int16_t *buffer;
  len = stb_vorbis_decode_filename(filename.c_str(), &channels, &sampleRate,
      &buffer);

  // Initialize an SDL audio device
  SDL_AudioSpec want, have;

  want.freq = sampleRate;
  want.format = AUDIO_S16LSB;
  want.channels = channels;
  want.samples = 4096;
  want.callback = playerCallback;
  want.userdata = (void*)this;

  audioDevice = SDL_OpenAudioDevice(NULL, 0, &want, &have,
      SDL_AUDIO_ALLOW_FORMAT_CHANGE);

  if (want.format != have.format) {
    std::cout << "Player failed to get required audio format!" << std::endl;
  }

  // Prep player class members to play from previously loaded audio buffer
  currentLen = len * sizeof(uint16_t) * channels;
  audioPos = audioData = (uint8_t*)buffer;
}

Player::~Player() {
  delete[] audioData;
}

void Player::start() {
  SDL_PauseAudioDevice(audioDevice, 0);
}

void Player::playerCallback(void *userData, uint8_t *stream, int len) {
  Player *player = (Player*)userData;

  // Don't play if empty
  if (player->currentLen == 0) {
    SDL_memset(stream, 0, len);
    return;
  }

  // Limit reading to buffer bounds
  len = (len > player->currentLen ? player->currentLen : len);

  // Copy audio buffer to player
  SDL_memcpy(stream, player->audioPos, len);

  // Move to next block
  player->audioPos += len;

  // Keep track of data left in the buffer
  player->currentLen -= len;
}
<|endoftext|>


<commit_before>#include "RTimer.h"
#include "RTimerEvent.h"
#include "RCoreApplication.h"
#include "RScopedPointer.h"
#include "RIsr.h"
#include "RThread.h"

static const int32_t sMaxDelayMS = static_cast<int32_t>(portMAX_DELAY) *
                                   portTICK_PERIOD_MS;

RTimer::RTimer()
  : mHandle(NULL)
  , mIsSingleShot(false)
  , mExtended(0)
#if (configUSE_16_BIT_TICKS == 1)
  , mExtendedCounter(0)
#endif
{
  // NOTE: Set timer run as idle task by default, but we can't set interval to
  // zero, otherwise the created timer will return to NULL, so we give value 1 .
  mHandle = xTimerCreate(
    "",
    1,
    pdFALSE,                           // one-shot timer
    reinterpret_cast<void *>(0),
    onTimeout
    );

  vTimerSetTimerID(mHandle, this);
}

RTimer::~RTimer()
{
  while(pdPASS != xTimerDelete(mHandle, portMAX_DELAY))
  {
    RThread::yieldCurrentThread();
  }
}

int32_t
RTimer::interval() const
{
  return static_cast<int32_t>(xTimerGetPeriod(mHandle)) * portTICK_PERIOD_MS
#if (configUSE_16_BIT_TICKS == 1)
         * (mExtended + 1)
#endif
  ;
}

bool
RTimer::isActive() const
{
  return xTimerIsTimerActive(mHandle);
}

bool
RTimer::isSingleShot() const
{
  return mIsSingleShot;
}

void
RTimer::setInterval(int32_t msec)
{
#if (configUSE_16_BIT_TICKS == 1)
  mExtended = static_cast<uint8_t>(msec / sMaxDelayMS);

  // A little trick to generate a fixed delay value, so that we needs not to
  // store the remainder
  msec /= (mExtended + 1);
#endif

  msec /= portTICK_PERIOD_MS;

  if(msec <= 0)
  {
    msec = 1;
  }

  if(_rIsrExecuting())
  {
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    xTimerChangePeriodFromISR(mHandle, static_cast<rtime>(msec),
                              &xHigherPriorityTaskWoken);

    // xTimerChangePeriod will cause timer start, so we need to stop it
    // immediately
    xHigherPriorityTaskWoken = pdFALSE;
    xTimerStopFromISR(mHandle, &xHigherPriorityTaskWoken);
  }
  else
  {
    taskENTER_CRITICAL();

    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    xTimerChangePeriodFromISR(mHandle, static_cast<rtime>(msec),
                              &xHigherPriorityTaskWoken);

    // xTimerChangePeriod will cause timer start, so we need to stop it
    // immediately
    xHigherPriorityTaskWoken = pdFALSE;
    xTimerStopFromISR(mHandle, &xHigherPriorityTaskWoken);

    taskEXIT_CRITICAL();
  }
}

void
RTimer::setSingleShot(bool singleShot)
{
  mIsSingleShot = singleShot;
}

int
RTimer::timerId() const
{
  // WARNING: We shorten handle to id value, but it may lead duplicate id values.
  return rShortenPtr(pvTimerGetTimerID(mHandle));
}

void
RTimer::start()
{
#if (configUSE_16_BIT_TICKS == 1)
  mExtendedCounter.store(mExtended);
#endif

  if(_rIsrExecuting())
  {
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    xTimerStartFromISR(mHandle, &xHigherPriorityTaskWoken);
  }
  else
  {
    taskENTER_CRITICAL();

    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    xTimerStartFromISR(mHandle, &xHigherPriorityTaskWoken);

    taskEXIT_CRITICAL();
  }
}

void
RTimer::start(int32_t msec)
{
  setInterval(msec);
  start();
}

void
RTimer::stop()
{
  if(_rIsrExecuting())
  {
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    xTimerStopFromISR(mHandle, &xHigherPriorityTaskWoken);
  }
  else
  {
    taskENTER_CRITICAL();

    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    xTimerStopFromISR(mHandle, &xHigherPriorityTaskWoken);

    taskEXIT_CRITICAL();
  }
}

bool
RTimer::event(REvent *e)
{
  if(e->type() == RTimerEvent::staticType())
  {
    // FIXME: Here may be generate a potential crash
    auto timerEvent = static_cast<RTimerEvent *>(e);

    timeout.emit();

    if(!mIsSingleShot)
    {
      start(); // Restart timer for next round
    }

    timerEvent->accept();
    return true;
  }

  return RObject::event(e);
}

void
RTimer::onTimeout(TimerHandle_t handle)
{
  auto self = static_cast<RTimer *>(pvTimerGetTimerID(handle));

#if (configUSE_16_BIT_TICKS == 1)

  if(self->mExtendedCounter.addIfLargeThan(0, -1))
  {
    if(_rIsrExecuting())
    {
      BaseType_t xHigherPriorityTaskWoken = pdFALSE;

      xTimerStartFromISR(
        self->mHandle, &xHigherPriorityTaskWoken);
    }
    else
    {
      taskENTER_CRITICAL();

      BaseType_t xHigherPriorityTaskWoken = pdFALSE;

      xTimerStartFromISR(self->mHandle, &xHigherPriorityTaskWoken);

      taskEXIT_CRITICAL();
    }

    return;
  }

#endif

  // NOTE: Event will be deleted in REventLoop after they handled that event.
  RScopedPointer<RTimerEvent> event(new RTimerEvent(self->timerId()));

  RCoreApplication::postEvent(self, event.take());
}
<commit_msg>Fixed task CRITICAL related functions will lead some timer not working<commit_after>#include "RTimer.h"
#include "RTimerEvent.h"
#include "RCoreApplication.h"
#include "RScopedPointer.h"
#include "RIsr.h"
#include "RThread.h"

#define RTIMER_WAIT_PASS(code) \
  while(pdPASS != (code)) \
  { \
    RThread::yieldCurrentThread(); \
  }

static const int32_t sMaxDelayMS = static_cast<int32_t>(portMAX_DELAY) *
                                   portTICK_PERIOD_MS;

RTimer::RTimer()
  : mHandle(NULL)
  , mIsSingleShot(false)
  , mExtended(0)
#if (configUSE_16_BIT_TICKS == 1)
  , mExtendedCounter(0)
#endif
{
  // NOTE: Set timer run as idle task by default, but we can't set interval to
  // zero, otherwise the created timer will return to NULL, so we give value 1 .
  mHandle = xTimerCreate(
    "",
    1,
    pdFALSE,                           // one-shot timer
    reinterpret_cast<void *>(0),
    onTimeout
    );

  vTimerSetTimerID(mHandle, this);
}

RTimer::~RTimer()
{
  RTIMER_WAIT_PASS(xTimerDelete(mHandle, portMAX_DELAY));
}

int32_t
RTimer::interval() const
{
  return static_cast<int32_t>(xTimerGetPeriod(mHandle)) * portTICK_PERIOD_MS
#if (configUSE_16_BIT_TICKS == 1)
         * (mExtended + 1)
#endif
  ;
}

bool
RTimer::isActive() const
{
  return xTimerIsTimerActive(mHandle);
}

bool
RTimer::isSingleShot() const
{
  return mIsSingleShot;
}

void
RTimer::setInterval(int32_t msec)
{
#if (configUSE_16_BIT_TICKS == 1)
  mExtended = static_cast<uint8_t>(msec / sMaxDelayMS);

  // A little trick to generate a fixed delay value, so that we needs not to
  // store the remainder
  msec /= (mExtended + 1);
#endif

  msec /= portTICK_PERIOD_MS;

  if(msec <= 0)
  {
    msec = 1;
  }

  if(_rIsrExecuting())
  {
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    xTimerChangePeriodFromISR(mHandle, static_cast<rtime>(msec),
                              &xHigherPriorityTaskWoken);

    // xTimerChangePeriod will cause timer start, so we need to stop it
    // immediately
    xHigherPriorityTaskWoken = pdFALSE;
    xTimerStopFromISR(mHandle, &xHigherPriorityTaskWoken);
  }
  else
  {
    RTIMER_WAIT_PASS(xTimerChangePeriod(
                       mHandle, static_cast<rtime>(msec), portMAX_DELAY));
    RTIMER_WAIT_PASS(xTimerStop(mHandle, portMAX_DELAY));
  }
}

void
RTimer::setSingleShot(bool singleShot)
{
  mIsSingleShot = singleShot;
}

int
RTimer::timerId() const
{
  // WARNING: We shorten handle to id value, but it may lead duplicate id values.
  return rShortenPtr(pvTimerGetTimerID(mHandle));
}

void
RTimer::start()
{
#if (configUSE_16_BIT_TICKS == 1)
  mExtendedCounter.store(mExtended);
#endif

  if(_rIsrExecuting())
  {
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    xTimerStartFromISR(mHandle, &xHigherPriorityTaskWoken);
  }
  else
  {
    RTIMER_WAIT_PASS(xTimerStart(mHandle, portMAX_DELAY));
  }
}

void
RTimer::start(int32_t msec)
{
  setInterval(msec);
  start();
}

void
RTimer::stop()
{
  if(_rIsrExecuting())
  {
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    xTimerStopFromISR(mHandle, &xHigherPriorityTaskWoken);
  }
  else
  {
    RTIMER_WAIT_PASS(xTimerStop(mHandle, portMAX_DELAY));
  }
}

bool
RTimer::event(REvent *e)
{
  if(e->type() == RTimerEvent::staticType())
  {
    // FIXME: Here may be generate a potential crash
    auto timerEvent = static_cast<RTimerEvent *>(e);

    timeout.emit();

    if(!mIsSingleShot)
    {
      start(); // Restart timer for next round
    }

    timerEvent->accept();
    return true;
  }

  return RObject::event(e);
}

void
RTimer::onTimeout(TimerHandle_t handle)
{
  auto self = static_cast<RTimer *>(pvTimerGetTimerID(handle));

#if (configUSE_16_BIT_TICKS == 1)

  if(self->mExtendedCounter.addIfLargeThan(0, -1))
  {
    if(_rIsrExecuting())
    {
      BaseType_t xHigherPriorityTaskWoken = pdFALSE;

      xTimerStartFromISR(
        self->mHandle, &xHigherPriorityTaskWoken);
    }
    else
    {
      RTIMER_WAIT_PASS(xTimerStart(self->mHandle, portMAX_DELAY));
    }

    return;
  }

#endif

  // NOTE: Event will be deleted in REventLoop after they handled that event.
  RScopedPointer<RTimerEvent> event(new RTimerEvent(self->timerId()));

  RCoreApplication::postEvent(self, event.take());
}
<|endoftext|>


<commit_before>#include "hit.hpp"
#include <cmath>

Hit::Hit():
  hit_ {false},
  t_ {INFINITY},
  intersection_{glm::vec3{INFINITY}},
  normal_{glm::vec3{INFINITY}},
  shape_{nullptr} {}

Hit::Hit(bool hit, float t, glm::vec3 const& intersect,
      glm::vec3 const& normal, std::shared_ptr<Shape> shape):
  hit_{hit},
  t_{t},
  intersection_{intersect},
  normal_{normal},
  shape_{shape} {}<commit_msg>added hit_copy_const<commit_after>#include "hit.hpp"
#include <cmath>

Hit::Hit():
  hit_ {false},
  t_ {INFINITY},
  intersection_{glm::vec3{INFINITY}},
  normal_{glm::vec3{INFINITY}},
  shape_{nullptr} {}

Hit::Hit(bool hit, float t, glm::vec3 const& intersect,
      glm::vec3 const& normal, std::shared_ptr<Shape> shape):
  hit_{hit},
  t_{t},
  intersection_{intersect},
  normal_{normal},
  shape_{shape} {}

Hit::Hit(Hit const& hit_copy):
  hit_{hit_copy.hit_},
  t_{hit_copy.t_},
  intersection_{hit_copy.intersection_},
  normal_{hit_copy.normal_},
  shape_{hit_copy.shape_} {}<|endoftext|>


<commit_before>#ifndef GEN_INPUT_PROCESSOR_H
#define GEN_INPUT_PROCESSOR_H

#include <SDL2/SDL.h>
#include <set>
#include <algorithm>

template <class states_enum>
class binding {
    public:
        SDL_Keycode k;
        states_enum s;

    friend bool operator== (const binding &a, SDL_Keycode ck) {
            if (a.k == ck) {
                return true;
            }
            return false;
    }

    friend bool operator< (const binding &a, const binding &b)
    {
        if (a.k == b.k && a.s == b.s) {
            return false;
        }

        if (a.k <= b.k) {
            return true;
        }

        return false;
    }
};

template <class states_enum> class GenInputProcessor {
    public:
        void test_meth(states_enum s);
        void add_key_binding(SDL_Keycode k, states_enum s);
        void rm_key_binding(SDL_Keycode k, states_enum s);
        void process_input(SDL_Event *event);
        bool is_state_active(states_enum s);

    private:
        std::set<binding<states_enum> > bindings;
        std::set<states_enum> active_states;
};

template <class states_enum>
void GenInputProcessor<states_enum>::test_meth(
    states_enum s)
{
    binding<states_enum> b = { .s = s};
    bindings.insert(b);
}

template <class states_enum>
void GenInputProcessor<states_enum>::add_key_binding(
    SDL_Keycode k,
    states_enum s)
{
    binding<states_enum> b = {.k = k, .s = s};
    bindings.insert(b);
}

template <class states_enum>
void GenInputProcessor<states_enum>::rm_key_binding(
    SDL_Keycode k,
    states_enum s)
{
    binding<states_enum> b = {.k = k, .s = s};
    bindings.erase(b);
}

template <class states_enum>
void GenInputProcessor<states_enum>::process_input(SDL_Event *event)
{
    SDL_Keycode key = event->key.keysym.sym;

    typename std::set<binding<states_enum> >::iterator res = \
        std::find_if(bindings.begin(), bindings.end(), key);

    if (res != bindings.end()) {
        active_states.insert(res->s);
    }
}

template <class states_enum>
bool GenInputProcessor<states_enum>::is_state_active(states_enum s)
{
    if (active_states.find(s) != active_states.end()) {
        return true;
    }
    return false;
}

#endif
<commit_msg>Really finished general input processor<commit_after>#ifndef GEN_INPUT_PROCESSOR_H
#define GEN_INPUT_PROCESSOR_H

#include <SDL2/SDL.h>
#include <set>
#include <algorithm>

template <class states_enum>
class binding {
    public:
        SDL_Keycode k;
        states_enum s;

        friend bool operator== (const binding &a, SDL_Keycode ck) {
            if (a.k == ck) {
                return true;
            }
            return false;
        }

        friend bool operator< (const binding &a, const binding &b)
        {
            if (a.k == b.k && a.s == b.s) {
                return false;
            }

            if (a.k <= b.k) {
                return true;
            }

            return false;
        }
};

template <class states_enum> class GenInputProcessor {
    public:
        void test_meth(states_enum s);
        void add_key_binding(SDL_Keycode k, states_enum s);
        void rm_key_binding(SDL_Keycode k, states_enum s);
        void process_input(SDL_Event *event);
        bool is_state_active(states_enum s);

    private:
        std::set<binding<states_enum> > bindings;
        std::set<states_enum> active_states;
};

template <class states_enum>
void GenInputProcessor<states_enum>::test_meth(
    states_enum s)
{
    binding<states_enum> b = { .s = s};
    bindings.insert(b);
}

template <class states_enum>
void GenInputProcessor<states_enum>::add_key_binding(
    SDL_Keycode k,
    states_enum s)
{
    binding<states_enum> b = {.k = k, .s = s};
    bindings.insert(b);
}

template <class states_enum>
void GenInputProcessor<states_enum>::rm_key_binding(
    SDL_Keycode k,
    states_enum s)
{
    binding<states_enum> b = {.k = k, .s = s};
    bindings.erase(b);
}

template <class states_enum>
void GenInputProcessor<states_enum>::process_input(SDL_Event *event)
{
    SDL_Keycode key = event->key.keysym.sym;

    typename std::set<binding<states_enum> >::iterator res = \
        std::find(bindings.begin(), bindings.end(), key);

    if (res != bindings.end()) {
        if (event->key.type == SDL_KEYDOWN) {
            active_states.insert(res->s);
        } else {
            active_states.erase(res->s);
        }
    }
}

template <class states_enum>
bool GenInputProcessor<states_enum>::is_state_active(states_enum s)
{
    if (active_states.find(s) != active_states.end()) {
        return true;
    }
    return false;
}

#endif
<|endoftext|>


<commit_before>/*
    Copyright (C) 2013  Martin Klapetek <mklapetek@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) 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 Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "kpeopletranslationproxy.h"

#include <KPeople/PersonsModel>

#include <kpeople/personpluginmanager.h>
#include <kpeople/global.h>

#include "KTp/im-persons-data-source.h"
#include "KTp/types.h"

#include <KDebug>
#include <KIconLoader>
#include <KABC/Addressee>

#include <QPixmapCache>

using namespace KPeople;

KPeopleTranslationProxy::KPeopleTranslationProxy(QObject *parent)
    : QIdentityProxyModel(parent)
{
}

KPeopleTranslationProxy::~KPeopleTranslationProxy()
{
}

QVariant KPeopleTranslationProxy::data(const QModelIndex &proxyIndex, int role) const
{
    if (!proxyIndex.isValid()) {
        return QVariant();
    }

//     IMPersonsDataSource *imPlugin = qobject_cast<IMPersonsDataSource*>(PersonPluginManager::presencePlugin());
//
//     if (!imPlugin) {
//         kWarning() << "No imPlugin";
//         return QVariant();
//     }
//
    KABC::Addressee contact = mapToSource(proxyIndex).data(KPeople::PersonsModel::PersonVCardRole).value<KABC::Addressee>();

    switch (role) {
        case KTp::ContactPresenceTypeRole:
            return translatePresence(contact.custom(QLatin1String("telepathy"), QLatin1String("presence")));
        case KTp::ContactPresenceIconRole:
            return KPeople::iconForPresenceString(contact.custom(QLatin1String("telepathy"), QLatin1String("presence")));
//         case KTp::ContactPresenceNameRole:
//             return mapToSource(proxyIndex).data(PersonsModel::PresenceDisplayRole);
        case Qt::DisplayRole:
            return mapToSource(proxyIndex).data(KPeople::PersonsModel::FormattedNameRole);
        case KTp::RowTypeRole:
            if (mapToSource(proxyIndex).data(KPeople::PersonsModel::PersonIdRole)
                        .toString().startsWith((QLatin1String("kpeople://")))) {
                return KTp::PersonRowType;
            } else {
                return KTp::ContactRowType;
            }
//             //if the person has max 1 child, it's a fake person, so treat it as contact row
//             if (mapToSource(proxyIndex).parent().isValid() || sourceModel()->rowCount(mapToSource(proxyIndex)) <= 1) {
//                 return KTp::ContactRowType;
//             } else {
//                 return KTp::PersonRowType;
//             }
//         case KTp::ContactAvatarPathRole:
//             return mapToSource(proxyIndex).data(PersonsModel::PhotosRole);
        case KTp::ContactAvatarPixmapRole:
            return mapToSource(proxyIndex).data(KPeople::PersonsModel::PhotoRole);
        case KTp::IdRole:
            return contact.custom(QLatin1String("telepathy"), QLatin1String("contactId"));
//         case KTp::HeaderTotalUsersRole:
//             return sourceModel()->rowCount(mapToSource(proxyIndex));
//         case KTp::ContactGroupsRole:
//             return mapToSource(proxyIndex).data(PersonsModel::GroupsRole);
//         case KTp::NepomukUriRole:
//             return mapToSource(proxyIndex).data(PersonsModel::UriRole);
    }
//
//     int j = sourceModel()->rowCount(mapToSource(proxyIndex));
//
//
//     KTp::ContactPtr contact;
//
//     if (j > 0) {
//         KTp::ContactPtr mostOnlineContact;
//
//         Q_FOREACH(const QVariant &v, mapToSource(proxyIndex).data(PersonsModel::IMsRole).toList()) {
//             KTp::ContactPtr c = imPlugin->contactForContactId(v.toString());
//             if (mostOnlineContact.isNull() && !c.isNull()) {
//                 mostOnlineContact = c;
//                 continue;
//             }
//             if (!c.isNull()) {
//                 if (c->presence() < mostOnlineContact->presence()) {
//                     mostOnlineContact = c;
//                 }
//             }
//         }
//         contact = mostOnlineContact;
//     } else if (j == 0) {
//         contact = imPlugin->contactForContactId(mapToSource(proxyIndex).data(PersonsModel::IMsRole).toString());
//     }
//
//     if (!contact.isNull()) {
//         switch (role) {
//             case KTp::AccountRole:
//                 return QVariant::fromValue<Tp::AccountPtr>(imPlugin->accountForContact(contact));
//                 break;
//             case KTp::ContactRole:
//                 return QVariant::fromValue<KTp::ContactPtr>(contact);
//                 break;
//             case KTp::ContactPresenceMessageRole:
//                 return contact->presence().statusMessage();
//                 break;
//             case KTp::ContactIsBlockedRole:
//                 return contact->isBlocked();
//                 break;
//             case KTp::ContactCanTextChatRole:
//                 return true;
//                 break;
//             case KTp::ContactCanAudioCallRole:
//                 return contact->audioCallCapability();
//                 break;
//             case KTp::ContactCanVideoCallRole:
//                 return contact->videoCallCapability();
//                 break;
//             case KTp::ContactCanFileTransferRole:
//                 return contact->fileTransferCapability();
//                 break;
//             case KTp::ContactClientTypesRole:
//                 return contact->clientTypes();
//                 break;
//         }
//     } else if (contact.isNull() && role == KTp::AccountRole) {
//         QVariant accountPath = mapToSource(proxyIndex).data(PersonsModel::UserRole);
//         if (accountPath.type() == QVariant::List) {
//             return QVariant::fromValue<Tp::AccountPtr>(imPlugin->accountManager()->accountForObjectPath(accountPath.toList().first().toString()));
//         } else {
//             return QVariant::fromValue<Tp::AccountPtr>(imPlugin->accountManager()->accountForObjectPath(accountPath.toString()));
//         }
//     }
// //     }

    return mapToSource(proxyIndex).data(role);
}

QVariant KPeopleTranslationProxy::translatePresence(const QVariant &presenceName) const
{
    if (presenceName == QLatin1String("available")) {
        return Tp::ConnectionPresenceTypeAvailable;
    }

    if (presenceName == QLatin1String("away")) {
        return Tp::ConnectionPresenceTypeAway;
    }

    if (presenceName == QLatin1String("busy") || presenceName == QLatin1String("dnd")) {
        return Tp::ConnectionPresenceTypeBusy;
    }

    if (presenceName == QLatin1String("xa")) {
        return Tp::ConnectionPresenceTypeExtendedAway;
    }

    if (presenceName == QLatin1String("hidden")) {
        return Tp::ConnectionPresenceTypeHidden;
    }

    return Tp::ConnectionPresenceTypeOffline;
}

QPixmap KPeopleTranslationProxy::contactPixmap(const QModelIndex &index) const
{
    QPixmap avatar;

    int presenceType = index.data(KTp::ContactPresenceTypeRole).toInt();
    //we need some ID to generate proper cache key for this contact
    //so we'll use the contact's uri
    const QString id = index.data(KTp::IdRole).toString();

    //key for the pixmap cache, so we can look up the avatar
    const QString keyCache = id + (presenceType == Tp::ConnectionPresenceTypeOffline ? QLatin1String("-offline") : QLatin1String("-online"));

    //check pixmap cache for the avatar, if not present, load the avatar
    if (!QPixmapCache::find(keyCache, avatar)){
        const QVariantList files = index.data(KTp::ContactAvatarPathRole).toList();
        QString file;
        if (!files.isEmpty()) {
            file = files.first().toUrl().toLocalFile();
        }

        //QPixmap::load() checks for empty path
        avatar.load(file);

        //if the above didn't succeed, we need to load the generic icon
        if (avatar.isNull()) {
            avatar = KIconLoader::global()->loadIcon(QLatin1String("im-user"), KIconLoader::NoGroup, 96);
        }

        //if the contact is offline, gray it out
        if (presenceType == Tp::ConnectionPresenceTypeOffline) {
            QImage image = avatar.toImage();
            const QPixmap alpha = avatar.alphaChannel();
            for (int i = 0; i < image.width(); ++i) {
                for (int j = 0; j < image.height(); ++j) {
                    int colour = qGray(image.pixel(i, j));
                    image.setPixel(i, j, qRgb(colour, colour, colour));
                }
            }
            avatar = avatar.fromImage(image);
            avatar.setAlphaChannel(alpha);
        }

        //insert the contact into pixmap cache for faster lookup
        QPixmapCache::insert(keyCache, avatar);
    }

    return avatar;
}
<commit_msg>Add missing const &<commit_after>/*
    Copyright (C) 2013  Martin Klapetek <mklapetek@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) 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 Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "kpeopletranslationproxy.h"

#include <KPeople/PersonsModel>

#include <kpeople/personpluginmanager.h>
#include <kpeople/global.h>

#include "KTp/im-persons-data-source.h"
#include "KTp/types.h"

#include <KDebug>
#include <KIconLoader>
#include <KABC/Addressee>

#include <QPixmapCache>

using namespace KPeople;

KPeopleTranslationProxy::KPeopleTranslationProxy(QObject *parent)
    : QIdentityProxyModel(parent)
{
}

KPeopleTranslationProxy::~KPeopleTranslationProxy()
{
}

QVariant KPeopleTranslationProxy::data(const QModelIndex &proxyIndex, int role) const
{
    if (!proxyIndex.isValid()) {
        return QVariant();
    }

//     IMPersonsDataSource *imPlugin = qobject_cast<IMPersonsDataSource*>(PersonPluginManager::presencePlugin());
//
//     if (!imPlugin) {
//         kWarning() << "No imPlugin";
//         return QVariant();
//     }
//
    const KABC::Addressee &contact = mapToSource(proxyIndex).data(KPeople::PersonsModel::PersonVCardRole).value<KABC::Addressee>();

    switch (role) {
        case KTp::ContactPresenceTypeRole:
            return translatePresence(contact.custom(QLatin1String("telepathy"), QLatin1String("presence")));
        case KTp::ContactPresenceIconRole:
            return KPeople::iconForPresenceString(contact.custom(QLatin1String("telepathy"), QLatin1String("presence")));
//         case KTp::ContactPresenceNameRole:
//             return mapToSource(proxyIndex).data(PersonsModel::PresenceDisplayRole);
        case Qt::DisplayRole:
            return mapToSource(proxyIndex).data(KPeople::PersonsModel::FormattedNameRole);
        case KTp::RowTypeRole:
            if (mapToSource(proxyIndex).data(KPeople::PersonsModel::PersonIdRole)
                        .toString().startsWith((QLatin1String("kpeople://")))) {

                return KTp::PersonRowType;
            } else {
                return KTp::ContactRowType;
            }
//             //if the person has max 1 child, it's a fake person, so treat it as contact row
//             if (mapToSource(proxyIndex).parent().isValid() || sourceModel()->rowCount(mapToSource(proxyIndex)) <= 1) {
//                 return KTp::ContactRowType;
//             } else {
//                 return KTp::PersonRowType;
//             }
//         case KTp::ContactAvatarPathRole:
//             return mapToSource(proxyIndex).data(PersonsModel::PhotosRole);
        case KTp::ContactAvatarPixmapRole:
            return mapToSource(proxyIndex).data(KPeople::PersonsModel::PhotoRole);
        case KTp::IdRole:
            return contact.custom(QLatin1String("telepathy"), QLatin1String("contactId"));
//         case KTp::HeaderTotalUsersRole:
//             return sourceModel()->rowCount(mapToSource(proxyIndex));
//         case KTp::ContactGroupsRole:
//             return mapToSource(proxyIndex).data(PersonsModel::GroupsRole);
//         case KTp::NepomukUriRole:
//             return mapToSource(proxyIndex).data(PersonsModel::UriRole);
    }
//
//     int j = sourceModel()->rowCount(mapToSource(proxyIndex));
//
//
//     KTp::ContactPtr contact;
//
//     if (j > 0) {
//         KTp::ContactPtr mostOnlineContact;
//
//         Q_FOREACH(const QVariant &v, mapToSource(proxyIndex).data(PersonsModel::IMsRole).toList()) {
//             KTp::ContactPtr c = imPlugin->contactForContactId(v.toString());
//             if (mostOnlineContact.isNull() && !c.isNull()) {
//                 mostOnlineContact = c;
//                 continue;
//             }
//             if (!c.isNull()) {
//                 if (c->presence() < mostOnlineContact->presence()) {
//                     mostOnlineContact = c;
//                 }
//             }
//         }
//         contact = mostOnlineContact;
//     } else if (j == 0) {
//         contact = imPlugin->contactForContactId(mapToSource(proxyIndex).data(PersonsModel::IMsRole).toString());
//     }
//
//     if (!contact.isNull()) {
//         switch (role) {
//             case KTp::AccountRole:
//                 return QVariant::fromValue<Tp::AccountPtr>(imPlugin->accountForContact(contact));
//                 break;
//             case KTp::ContactRole:
//                 return QVariant::fromValue<KTp::ContactPtr>(contact);
//                 break;
//             case KTp::ContactPresenceMessageRole:
//                 return contact->presence().statusMessage();
//                 break;
//             case KTp::ContactIsBlockedRole:
//                 return contact->isBlocked();
//                 break;
//             case KTp::ContactCanTextChatRole:
//                 return true;
//                 break;
//             case KTp::ContactCanAudioCallRole:
//                 return contact->audioCallCapability();
//                 break;
//             case KTp::ContactCanVideoCallRole:
//                 return contact->videoCallCapability();
//                 break;
//             case KTp::ContactCanFileTransferRole:
//                 return contact->fileTransferCapability();
//                 break;
//             case KTp::ContactClientTypesRole:
//                 return contact->clientTypes();
//                 break;
//         }
//     } else if (contact.isNull() && role == KTp::AccountRole) {
//         QVariant accountPath = mapToSource(proxyIndex).data(PersonsModel::UserRole);
//         if (accountPath.type() == QVariant::List) {
//             return QVariant::fromValue<Tp::AccountPtr>(imPlugin->accountManager()->accountForObjectPath(accountPath.toList().first().toString()));
//         } else {
//             return QVariant::fromValue<Tp::AccountPtr>(imPlugin->accountManager()->accountForObjectPath(accountPath.toString()));
//         }
//     }
// //     }

    return mapToSource(proxyIndex).data(role);
}

QVariant KPeopleTranslationProxy::translatePresence(const QVariant &presenceName) const
{
    if (presenceName == QLatin1String("available")) {
        return Tp::ConnectionPresenceTypeAvailable;
    }

    if (presenceName == QLatin1String("away")) {
        return Tp::ConnectionPresenceTypeAway;
    }

    if (presenceName == QLatin1String("busy") || presenceName == QLatin1String("dnd")) {
        return Tp::ConnectionPresenceTypeBusy;
    }

    if (presenceName == QLatin1String("xa")) {
        return Tp::ConnectionPresenceTypeExtendedAway;
    }

    if (presenceName == QLatin1String("hidden")) {
        return Tp::ConnectionPresenceTypeHidden;
    }

    return Tp::ConnectionPresenceTypeOffline;
}

QPixmap KPeopleTranslationProxy::contactPixmap(const QModelIndex &index) const
{
    QPixmap avatar;

    int presenceType = index.data(KTp::ContactPresenceTypeRole).toInt();
    //we need some ID to generate proper cache key for this contact
    //so we'll use the contact's uri
    const QString id = index.data(KTp::IdRole).toString();

    //key for the pixmap cache, so we can look up the avatar
    const QString keyCache = id + (presenceType == Tp::ConnectionPresenceTypeOffline ? QLatin1String("-offline") : QLatin1String("-online"));

    //check pixmap cache for the avatar, if not present, load the avatar
    if (!QPixmapCache::find(keyCache, avatar)){
        const QVariantList files = index.data(KTp::ContactAvatarPathRole).toList();
        QString file;
        if (!files.isEmpty()) {
            file = files.first().toUrl().toLocalFile();
        }

        //QPixmap::load() checks for empty path
        avatar.load(file);

        //if the above didn't succeed, we need to load the generic icon
        if (avatar.isNull()) {
            avatar = KIconLoader::global()->loadIcon(QLatin1String("im-user"), KIconLoader::NoGroup, 96);
        }

        //if the contact is offline, gray it out
        if (presenceType == Tp::ConnectionPresenceTypeOffline) {
            QImage image = avatar.toImage();
            const QPixmap alpha = avatar.alphaChannel();
            for (int i = 0; i < image.width(); ++i) {
                for (int j = 0; j < image.height(); ++j) {
                    int colour = qGray(image.pixel(i, j));
                    image.setPixel(i, j, qRgb(colour, colour, colour));
                }
            }
            avatar = avatar.fromImage(image);
            avatar.setAlphaChannel(alpha);
        }

        //insert the contact into pixmap cache for faster lookup
        QPixmapCache::insert(keyCache, avatar);
    }

    return avatar;
}
<|endoftext|>


<commit_before>#include "SQLite.h"

#include <cstring>
#include <cassert>
#include <iostream>
#include <vector>

#include "SQLException.h"

using namespace std;
using namespace sqldb;

class SQLiteStatement : public SQLStatement {
public:
  SQLiteStatement(sqlite3 * db, sqlite3_stmt * stmt)
    : db_(db), stmt_(stmt) {
    assert(db_);
    assert(stmt_);

    for (int i = 0, n = sqlite3_column_count(stmt_); i < n; i++) {
      column_names_.push_back(sqlite3_column_name(stmt_, i));
    }
  }
  ~SQLiteStatement() {
    if (stmt_) sqlite3_finalize(stmt_);
  }

  size_t execute() override {
    step();
    return getAffectedRows();
  }
  bool next() override {
    step();
    return results_available;
  }
  void reset() override {
    SQLStatement::reset();

    int r = sqlite3_reset(stmt_);

    switch (r) {
    case SQLITE_OK: return;

    case SQLITE_SCHEMA:
      throw SQLException(SQLException::SCHEMA_CHANGED, sqlite3_errmsg(db_));
      return;

    default:
      cerr << "unknown error: " << r << endl;
      assert(0);
      return;
    }
  }

  void set(int column_idx, std::string_view value, bool is_defined) override {
    int r;
    if (is_defined) r = sqlite3_bind_text(stmt_, column_idx, value.data(), static_cast<int>(value.size()), SQLITE_TRANSIENT);
    else r = sqlite3_bind_null(stmt_, column_idx);
    if (r != SQLITE_OK) {
      throw SQLException(SQLException::BIND_FAILED, sqlite3_errmsg(db_));
    }
  }

  void set(int column_idx, int value, bool is_defined) override {
    int r;
    if (is_defined) r = sqlite3_bind_int(stmt_, column_idx, value);
    else r = sqlite3_bind_null(stmt_, column_idx);
    if (r != SQLITE_OK) {
      throw SQLException(SQLException::BIND_FAILED, sqlite3_errmsg(db_));
    }
  }

  void set(int column_idx, double value, bool is_defined) override {
    int r;
    if (is_defined) r = sqlite3_bind_double(stmt_, column_idx, value);
    else r = sqlite3_bind_null(stmt_, column_idx);
    if (r != SQLITE_OK) {
      throw SQLException(SQLException::BIND_FAILED, sqlite3_errmsg(db_));
    }
  }

  void set(int column_idx, long long value, bool is_defined) override {
    int r;
    if (is_defined) r = sqlite3_bind_int64(stmt_, column_idx, (sqlite_int64)value);
    else r = sqlite3_bind_null(stmt_, column_idx);
    if (r != SQLITE_OK) {
      throw SQLException(SQLException::BIND_FAILED, sqlite3_errmsg(db_));
    }
  }

  void set(int column_idx, const void * data, size_t len, bool is_defined) {
    int r;
    if (is_defined) r = sqlite3_bind_blob(stmt_, column_idx, data, len, SQLITE_TRANSIENT);
    else r = sqlite3_bind_null(stmt_, column_idx);
    if (r != SQLITE_OK) {
      throw SQLException(SQLException::BIND_FAILED, sqlite3_errmsg(db_));
    }
  }

  SQLiteStatement & bind(int value, bool is_defined) override {
    set(getNextBindIndex(), value, is_defined);
    return *this;
  }
  SQLiteStatement & bind(long long value, bool is_defined) override {
    set(getNextBindIndex(), value, is_defined);
    return *this;
  }
  SQLiteStatement & bind(double value, bool is_defined) override {
    set(getNextBindIndex(), value, is_defined);
    return *this;
  }
  SQLiteStatement & bind(std::string_view value, bool is_defined) override {
    set(getNextBindIndex(), std::move(value), is_defined);
    return *this;
  }
  SQLiteStatement & bind(const void * data, size_t len, bool is_defined) override {
    set(getNextBindIndex(), data, len, is_defined);
    return *this;
  }

  int getInt(int column_index, int default_value = 0) override {
    if (!isNull(column_index)) {
      return sqlite3_column_int(stmt_, column_index);
    }
    return default_value;
  }
  double getDouble(int column_index, double default_value = 0.0) override {
    if (!isNull(column_index)) {
      return sqlite3_column_double(stmt_, column_index);
    }
    return default_value;
  }
  float getFloat(int column_index, float default_value) override {
    if (!isNull(column_index)) {
      return static_cast<float>(sqlite3_column_double(stmt_, column_index));
    }
    return default_value;
  }
  long long getLongLong(int column_index, long long default_value = 0) override {
    if (!isNull(column_index)) {
      return sqlite3_column_int64(stmt_, column_index);
    }
    return default_value;
  }
  std::string getText(int column_index, std::string default_value) override {
    if (!isNull(column_index)) {
      const char * s = (const char *)sqlite3_column_text(stmt_, column_index);
      if (s) {
	return string(s);
      }
    }
    return move(default_value);
  }
  std::vector<uint8_t> getBlob(int column_index) override {
    std::vector<uint8_t> r;
    if (!isNull(column_index)) {
      auto data = reinterpret_cast<const uint8_t*>(sqlite3_column_blob(stmt_, column_index));
      auto len = sqlite3_column_bytes(stmt_, column_index);
      r.reserve(len);
      for (int i = 0; i < len; i++) r.push_back(data[i]);
    }
    return r;
  }

  bool isNull(int column_index) const override {
    if (!results_available) {
      return true;
    } else {
      return stmt_ ? sqlite3_column_type(stmt_, column_index) == SQLITE_NULL : true;
    }
  }

  int getNumFields() const override {
    return static_cast<int>(column_names_.size());
  }

  long long getLastInsertId() const override {
    return sqlite3_last_insert_rowid(db_);
  }
  size_t getAffectedRows() const override {
    return sqlite3_changes(db_);
  }

  std::string getColumnName(int column_index) const override {
    if (column_index >= 0 && column_index < static_cast<int>(column_names_.size())) {
      return column_names_[column_index];
    } else {
      return "";
    }
  }

protected:
  void step();

private:
  sqlite3 * db_;
  sqlite3_stmt * stmt_;
  vector<const char *> column_names_;
};

SQLite::SQLite(const string & db_file, bool read_only) : db_file_(db_file), read_only_(read_only)
{
  open();
}

SQLite::SQLite(const SQLite & other) : db_file_(other.db_file_), read_only_(other.read_only_)
{
  open();
}

SQLite::SQLite(SQLite && other)
  : db_file_(std::move(other.db_file_)), db_(std::exchange(other.db_, nullptr)), read_only_(other.read_only_) { }

SQLite::~SQLite() {
  if (db_) {
    int r = sqlite3_close(db_);
    if (r) {
      cerr << "error while closing, r = " << r << endl;
    }
  }
}

static int latin1_order(unsigned char c) {
  if (c >= 'A' && c <= 'Z') return 1 + c - 'A';
  else if (c >= 'a' && c <= 'z') return 1 + c - 'a';
  else if (c == 0xc5 || c == 0xe5) return 27;
  else if (c == 0xc4 || c == 0xe4) return 28;
  else if (c == 0xd6 || c == 0xf6) return 29;
  else return c;
}

static int latin1_compare(void * arg, int len1, const void * ptr1, int len2, const void * ptr2) {
  const unsigned char * s1 = (const unsigned char *)ptr1;
  const unsigned char * s2 = (const unsigned char *)ptr2;
  for (int i = 0; i < len1 && i < len2; i++) {
    int o1 = latin1_order(s1[i]), o2 = latin1_order(s2[i]);
    if (o1 < o2) return -1;
    else if (o1 > o2) return +1;
  }
  if (len1 < len2) return -1;
  else if (len1 > len2) return +1;
  else return 0;
}

bool
SQLite::open() {
  int flags = 0;
  if (db_file_.empty()) {
    flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
  } else if (read_only_) {
    flags = SQLITE_OPEN_READONLY;
  } else {
    flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
  }
  int r = sqlite3_open_v2(db_file_.c_str(), &db_, flags, 0);
  if (r) {
    db_ = 0;
    throw SQLException(SQLException::OPEN_FAILED, sqlite3_errmsg(db_));
  }

  if (db_) {
    sqlite3_busy_timeout(db_, 1000);

    r = sqlite3_create_collation( db_,
				  "NOCASE", // "latin1",
				  SQLITE_UTF8,
				  0, // this,
				  latin1_compare
				  );
    if (r) {
      cerr << "failed to create NOCASE collation\n";
    }
  }

  return true;
}

std::unique_ptr<sqldb::SQLStatement>
SQLite::prepare(string_view query) {
  if (!db_) {
    throw SQLException(SQLException::PREPARE_FAILED);
  }
  sqlite3_stmt * stmt = 0;
  int r = sqlite3_prepare_v2(db_, query.data(), query.size(), &stmt, 0);
  if (r != SQLITE_OK) {
    throw SQLException(SQLException::PREPARE_FAILED, sqlite3_errmsg(db_));
  }
  assert(stmt);
  return std::make_unique<SQLiteStatement>(db_, stmt);
}

void
SQLiteStatement::step() {
  results_available = false;

  while ( 1 ) {
    int r = sqlite3_step(stmt_);
    switch (r) {
    case SQLITE_ROW:
      results_available = true;
      return;

    case SQLITE_DONE:
      return;

    case SQLITE_BUSY:
      cerr << "database is busy\n";
      break;

    case SQLITE_ERROR: throw SQLException(SQLException::DATABASE_ERROR, sqlite3_errmsg(db_));
    case SQLITE_MISUSE: throw SQLException(SQLException::DATABASE_MISUSE, sqlite3_errmsg(db_));
    case SQLITE_CONSTRAINT: throw SQLException(SQLException::CONSTRAINT_VIOLATION, sqlite3_errmsg(db_));
    case SQLITE_MISMATCH: throw SQLException(SQLException::MISMATCH, sqlite3_errmsg(db_));

    default:
      cerr << "unknown error: " << r << endl;
      assert(0);
      return;
    }
  }

  throw SQLException(SQLException::QUERY_TIMED_OUT);
}
<commit_msg>refactor<commit_after>#include "SQLite.h"

#include <cstring>
#include <cassert>
#include <iostream>
#include <vector>

#include "SQLException.h"

using namespace std;
using namespace sqldb;

class SQLiteStatement : public SQLStatement {
public:
  SQLiteStatement(sqlite3 * db, sqlite3_stmt * stmt)
    : db_(db), stmt_(stmt) {
    assert(db_);
    assert(stmt_);

    for (int i = 0, n = sqlite3_column_count(stmt_); i < n; i++) {
      column_names_.push_back(sqlite3_column_name(stmt_, i));
    }
  }
  ~SQLiteStatement() {
    if (stmt_) sqlite3_finalize(stmt_);
  }

  size_t execute() override {
    step();
    return getAffectedRows();
  }
  bool next() override {
    SQLStatement::reset();
    step();
    return results_available_;
  }
  void reset() override {
    SQLStatement::reset();

    int r = sqlite3_reset(stmt_);

    switch (r) {
    case SQLITE_OK: return;

    case SQLITE_SCHEMA:
      throw SQLException(SQLException::SCHEMA_CHANGED, sqlite3_errmsg(db_));
      return;

    default:
      cerr << "unknown error: " << r << endl;
      assert(0);
      return;
    }
  }

  void set(int column_idx, std::string_view value, bool is_defined) override {
    int r;
    if (is_defined) r = sqlite3_bind_text(stmt_, column_idx + 1, value.data(), static_cast<int>(value.size()), SQLITE_TRANSIENT);
    else r = sqlite3_bind_null(stmt_, column_idx + 1);
    if (r != SQLITE_OK) {
      throw SQLException(SQLException::BIND_FAILED, sqlite3_errmsg(db_));
    }
  }

  void set(int column_idx, int value, bool is_defined) override {
    int r;
    if (is_defined) r = sqlite3_bind_int(stmt_, column_idx + 1, value);
    else r = sqlite3_bind_null(stmt_, column_idx + 1);
    if (r != SQLITE_OK) {
      throw SQLException(SQLException::BIND_FAILED, sqlite3_errmsg(db_));
    }
  }

  void set(int column_idx, double value, bool is_defined) override {
    int r;
    if (is_defined) r = sqlite3_bind_double(stmt_, column_idx + 1, value);
    else r = sqlite3_bind_null(stmt_, column_idx + 1);
    if (r != SQLITE_OK) {
      throw SQLException(SQLException::BIND_FAILED, sqlite3_errmsg(db_));
    }
  }

  void set(int column_idx, long long value, bool is_defined) override {
    int r;
    if (is_defined) r = sqlite3_bind_int64(stmt_, column_idx + 1, (sqlite_int64)value);
    else r = sqlite3_bind_null(stmt_, column_idx + 1);
    if (r != SQLITE_OK) {
      throw SQLException(SQLException::BIND_FAILED, sqlite3_errmsg(db_));
    }
  }

  void set(int column_idx, const void * data, size_t len, bool is_defined) {
    int r;
    if (is_defined) r = sqlite3_bind_blob(stmt_, column_idx + 1, data, len, SQLITE_TRANSIENT);
    else r = sqlite3_bind_null(stmt_, column_idx + 1);
    if (r != SQLITE_OK) {
      throw SQLException(SQLException::BIND_FAILED, sqlite3_errmsg(db_));
    }
  }

  int getInt(int column_index, int default_value = 0) override {
    if (!isNull(column_index)) {
      return sqlite3_column_int(stmt_, column_index);
    }
    return default_value;
  }
  double getDouble(int column_index, double default_value = 0.0) override {
    if (!isNull(column_index)) {
      return sqlite3_column_double(stmt_, column_index);
    }
    return default_value;
  }
  float getFloat(int column_index, float default_value) override {
    if (!isNull(column_index)) {
      return static_cast<float>(sqlite3_column_double(stmt_, column_index));
    }
    return default_value;
  }
  long long getLongLong(int column_index, long long default_value = 0) override {
    if (!isNull(column_index)) {
      return sqlite3_column_int64(stmt_, column_index);
    }
    return default_value;
  }
  std::string getText(int column_index, std::string default_value) override {
    if (!isNull(column_index)) {
      const char * s = (const char *)sqlite3_column_text(stmt_, column_index);
      if (s) {
	return string(s);
      }
    }
    return move(default_value);
  }
  std::vector<uint8_t> getBlob(int column_index) override {
    std::vector<uint8_t> r;
    if (!isNull(column_index)) {
      auto data = reinterpret_cast<const uint8_t*>(sqlite3_column_blob(stmt_, column_index));
      auto len = sqlite3_column_bytes(stmt_, column_index);
      r.reserve(len);
      for (int i = 0; i < len; i++) r.push_back(data[i]);
    }
    return r;
  }

  bool isNull(int column_index) const override {
    if (!results_available_) {
      return true;
    } else {
      return stmt_ ? sqlite3_column_type(stmt_, column_index) == SQLITE_NULL : true;
    }
  }

  int getNumFields() const override {
    return static_cast<int>(column_names_.size());
  }

  long long getLastInsertId() const override {
    return sqlite3_last_insert_rowid(db_);
  }
  size_t getAffectedRows() const override {
    return sqlite3_changes(db_);
  }

  std::string getColumnName(int column_index) const override {
    if (column_index >= 0 && column_index < static_cast<int>(column_names_.size())) {
      return column_names_[column_index];
    } else {
      return "";
    }
  }

protected:
  void step();

private:
  sqlite3 * db_;
  sqlite3_stmt * stmt_;
  vector<const char *> column_names_;
};

SQLite::SQLite(const string & db_file, bool read_only) : db_file_(db_file), read_only_(read_only)
{
  open();
}

SQLite::SQLite(const SQLite & other) : db_file_(other.db_file_), read_only_(other.read_only_)
{
  open();
}

SQLite::SQLite(SQLite && other)
  : db_file_(std::move(other.db_file_)), db_(std::exchange(other.db_, nullptr)), read_only_(other.read_only_) { }

SQLite::~SQLite() {
  if (db_) {
    int r = sqlite3_close(db_);
    if (r) {
      cerr << "error while closing, r = " << r << endl;
    }
  }
}

static int latin1_order(unsigned char c) {
  if (c >= 'A' && c <= 'Z') return 1 + c - 'A';
  else if (c >= 'a' && c <= 'z') return 1 + c - 'a';
  else if (c == 0xc5 || c == 0xe5) return 27;
  else if (c == 0xc4 || c == 0xe4) return 28;
  else if (c == 0xd6 || c == 0xf6) return 29;
  else return c;
}

static int latin1_compare(void * arg, int len1, const void * ptr1, int len2, const void * ptr2) {
  const unsigned char * s1 = (const unsigned char *)ptr1;
  const unsigned char * s2 = (const unsigned char *)ptr2;
  for (int i = 0; i < len1 && i < len2; i++) {
    int o1 = latin1_order(s1[i]), o2 = latin1_order(s2[i]);
    if (o1 < o2) return -1;
    else if (o1 > o2) return +1;
  }
  if (len1 < len2) return -1;
  else if (len1 > len2) return +1;
  else return 0;
}

bool
SQLite::open() {
  int flags = 0;
  if (db_file_.empty()) {
    flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
  } else if (read_only_) {
    flags = SQLITE_OPEN_READONLY;
  } else {
    flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
  }
  int r = sqlite3_open_v2(db_file_.c_str(), &db_, flags, 0);
  if (r) {
    db_ = 0;
    throw SQLException(SQLException::OPEN_FAILED, sqlite3_errmsg(db_));
  }

  if (db_) {
    sqlite3_busy_timeout(db_, 1000);

    r = sqlite3_create_collation( db_,
				  "NOCASE", // "latin1",
				  SQLITE_UTF8,
				  0, // this,
				  latin1_compare
				  );
    if (r) {
      cerr << "failed to create NOCASE collation\n";
    }
  }

  return true;
}

std::unique_ptr<sqldb::SQLStatement>
SQLite::prepare(string_view query) {
  if (!db_) {
    throw SQLException(SQLException::PREPARE_FAILED);
  }
  sqlite3_stmt * stmt = 0;
  int r = sqlite3_prepare_v2(db_, query.data(), query.size(), &stmt, 0);
  if (r != SQLITE_OK) {
    throw SQLException(SQLException::PREPARE_FAILED, sqlite3_errmsg(db_));
  }
  assert(stmt);
  return std::make_unique<SQLiteStatement>(db_, stmt);
}

void
SQLiteStatement::step() {
  results_available_ = false;

  while ( 1 ) {
    int r = sqlite3_step(stmt_);
    switch (r) {
    case SQLITE_ROW:
      results_available_ = true;
      return;

    case SQLITE_DONE:
      return;

    case SQLITE_BUSY:
      cerr << "database is busy\n";
      break;

    case SQLITE_ERROR: throw SQLException(SQLException::DATABASE_ERROR, sqlite3_errmsg(db_));
    case SQLITE_MISUSE: throw SQLException(SQLException::DATABASE_MISUSE, sqlite3_errmsg(db_));
    case SQLITE_CONSTRAINT: throw SQLException(SQLException::CONSTRAINT_VIOLATION, sqlite3_errmsg(db_));
    case SQLITE_MISMATCH: throw SQLException(SQLException::MISMATCH, sqlite3_errmsg(db_));

    default:
      cerr << "unknown error: " << r << endl;
      assert(0);
      return;
    }
  }

  throw SQLException(SQLException::QUERY_TIMED_OUT);
}
<|endoftext|>


<commit_before>#include <utility>
#include <iterator>
#include <limits>
#include <cstring>
#include <stdexcept>
#include "puzzle.hpp"

/// We don't want to rely on C++14 yet.
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args)
{
	return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

namespace Puzzle {

// BEGIN Implementation of Expressions

Expression::~Expression() = default;

class BinaryExpr : public Expression
{
protected:
	BinaryExpr(std::unique_ptr<Expression> left,
	           std::unique_ptr<Expression> right)
		: left(std::move(left)), right(std::move(right)) {}

	std::unique_ptr<Expression> left, right;
};

class EqualsExpr : public BinaryExpr
{
public:
	EqualsExpr(std::unique_ptr<Expression> left,
	           std::unique_ptr<Expression> right)
		: BinaryExpr(std::move(left), std::move(right)) {}

	fraction<int64_t> eval(const int *assignment) const override
		{ return left->eval(assignment) == right->eval(assignment); }
};

class SumExpr : public BinaryExpr
{
public:
	SumExpr(std::unique_ptr<Expression> left,
	        std::unique_ptr<Expression> right)
		: BinaryExpr(std::move(left), std::move(right)) {}

	fraction<int64_t> eval(const int *assignment) const override
		{ return left->eval(assignment) + right->eval(assignment); }
};

class DifferenceExpr : public BinaryExpr
{
public:
	DifferenceExpr(std::unique_ptr<Expression> left,
	               std::unique_ptr<Expression> right)
		: BinaryExpr(std::move(left), std::move(right)) {}

	fraction<int64_t> eval(const int *assignment) const override
		{ return left->eval(assignment) - right->eval(assignment); }
};

class ProductExpr : public BinaryExpr
{
public:
	ProductExpr(std::unique_ptr<Expression> left,
	            std::unique_ptr<Expression> right)
		: BinaryExpr(std::move(left), std::move(right)) {}

	fraction<int64_t> eval(const int *assignment) const override
		{ return left->eval(assignment) * right->eval(assignment); }
};

class QuotientExpr : public BinaryExpr
{
public:
	QuotientExpr(std::unique_ptr<Expression> left,
	             std::unique_ptr<Expression> right)
		: BinaryExpr(std::move(left), std::move(right)) {}

	fraction<int64_t> eval(const int *assignment) const override
		{ return left->eval(assignment) / right->eval(assignment); }
};

class WordExpr : public Expression
{
public:
	WordExpr(const char *begin, const char *end,
	         const std::map<char, int> &letterToIndex, int radix)
		: word(new int[std::distance(begin, end) + 1]), radix(radix)
	{
		size_t len = std::distance(begin, end);
		for (size_t i = 0; i < len; ++i)
			word[i] = letterToIndex.at(begin[(len-1) - i]);
		word[len] = -1;
	}

	fraction<int64_t> eval(const int *assignment) const override
	{
		int64_t res = 0, val = 1;
		for (size_t i = 0; word[i] >= 0; ++i) {
			res += assignment[word[i]] * val;
			val *= radix;
		}
		return fraction<int64_t>(res);
	}

private:
	std::unique_ptr<int[]> word;
	int radix;
};

class NumberExpr : public Expression
{
public:
	NumberExpr(const char* begin, const char* end, int radix) : value(0)
	{
		for (const char *cur = begin; cur != end; ++cur) {
			value *= radix;
			value += *cur - '0';
		}
	}

	fraction<int64_t> eval(const int*) const override
	{
		return fraction<int64_t>(value);
	}

private:
	int64_t value;
};

// END Implementation of Expressions

// BEGIN Implementation of ExpressionParser

/**
 * Parser data
 */
enum class NodeType {
	EQUAL = 0,          // should occur exactly once - at root
	PLUS,
	MINUS,
	MULTIPLY,
	DIVIDE,
	// FACTORIAL,
	// BINOMIAL,   etc.
	WORD = 0x1000,      // "fixed-value"/number leaf
	NUMBER              // "variable-value"/word leaf
};

struct ExprType {
	char op;
	NodeType type;
	int priority;
};

static const ExprType ParseTable[] = {
	{'=', NodeType::EQUAL, 0},
	{'+', NodeType::PLUS, 1},
	{'-', NodeType::MINUS, 1},
	{'*', NodeType::MULTIPLY, 2},
	{'/', NodeType::DIVIDE, 2}
};

std::unique_ptr<Expression> ExpressionParser::parse(const char *expr)
{
	return parse(expr, expr + strlen(expr));
}

std::unique_ptr<Expression> ExpressionParser::parse(
	const char *begin, const char *end)
{
	NodeType type = NodeType::WORD;
	const char *split;
	int priority = std::numeric_limits<int>::max();

	// TODO: process parantheses
	// LOW: skip whitespace (well, maybe)
	for (const char *cur = begin; cur != end; ++cur)
		for (size_t op = 0; op < (sizeof(ParseTable)/sizeof(ExprType)); ++op)
			if (*cur == ParseTable[op].op && priority >= ParseTable[op].priority) {
				type = ParseTable[op].type;
				split = cur;
				priority = ParseTable[op].priority;
			}

	// split expression and process parts recursively
	if (type != NodeType::WORD) {
		auto left = parse(begin, split);
		auto right = parse(split+1, end);
		switch (type) {
			case NodeType::EQUAL:
				return make_unique<EqualsExpr>(std::move(left), std::move(right));
			case NodeType::PLUS:
				return make_unique<SumExpr>(std::move(left), std::move(right));
			case NodeType::MINUS:
				return make_unique<DifferenceExpr>(std::move(left), std::move(right));
			case NodeType::MULTIPLY:
				return make_unique<ProductExpr>(std::move(left), std::move(right));
			case NodeType::DIVIDE:
				return make_unique<QuotientExpr>(std::move(left), std::move(right));
			default:
				throw std::runtime_error("Unreachable code location");
		}
	}
	else {
		// Is it a word or number?
		const char *cur;
		for (cur = begin; cur != end; ++cur)
			if (*cur >= '0' && *cur <= '9')
				break;
		if (cur == end)
			return make_unique<WordExpr>(begin, end, letterToIndex, radix);
		else
			return make_unique<NumberExpr>(begin, end, radix);
	}
}

// END Implementation of ExpressionParser

//------------------------------
//  IMPLEMENTATION OF PUZZLES
//------------------------------

Puzzle::Puzzle(const char *puzzle, int rad) : radix(rad), indexToLetter(rad), leading(rad)
{
	// fill Map
	std::map<char, int> letterToIndex;
	for (int i = 0; puzzle[i]; ++i)
		if (puzzle[i] >= 'A' && puzzle[i] <= 'Z')   // what about nondecimal digits?
			letterToIndex.insert(std::pair<char, int>(puzzle[i], -1));

	// assign numbers to letters
	numLetters = 0;
	for (auto it = letterToIndex.begin(); it != letterToIndex.end(); ++it, ++numLetters) {
		indexToLetter[numLetters] = it->first;
		it->second = numLetters;
	}

	// make syntax tree
	ExpressionParser parser(letterToIndex, rad);
	root = parser.parse(puzzle);

	// leading digits aren't allowed to be zero
	if (puzzle[0] >= 'A' && puzzle[0] <= 'Z')
		leading[letterToIndex[puzzle[0]]] = true;
	for (int i = 1; puzzle[i]; ++i)
		if (puzzle[i-1] < 'A' && puzzle[i] >= 'A' && puzzle[i] <= 'Z')
			leading[letterToIndex[puzzle[i]]] = true;
}

bool Puzzle::eval(const int *assignment) const
{
	for (int i = 0; i < radix; ++i)
		if (!assignment[i] && leading[i])
			return false;
	return root->eval(assignment) != 0;
}

//------------------------------
// PERMUTATION GENERATOR IMPLEMENTATION
//------------------------------
MapGen::MapGen(int domainSize, int codomainSize)
	: n(codomainSize), m(domainSize)
{
	if (codomainSize < domainSize)
		throw std::domain_error("There are no injective maps if the codomain is smaller than the domain.");
	map = new int[domainSize];

	// M0
	for (int i = 0; i < domainSize; ++i)
		map[i] = i;
}

MapGen::~MapGen()
{
	delete[] map;
}

//---------------------------  ALGORITHM DESCRIPTION  -------------------------
// (The following algorithm is inspired by Donald E. Knuth: The Art of Computer Programming, Vol. 4, Fasc. 2, Algorithm L; but slightly modified)
// Algorithm M: Visit all injective maps f from {1, ..., m} to {1, ..., n}, given m<n.
// Idea: Run through all m-subsets of {1, ..., n} and visit all permutations of these subsets for each one.
//   Running through all m-subsets is done by a "combination-enumeration" algorithm which outputs all combinations in a canonical order.
//   Running through all permutations of these subsets is done by Alg. L.
// M0. start with map (a_1, ..., a_m) = (1, ..., m).
// M1. visit map (a_1, ..., a_m)
// M2. [Find j] j <- m-1; while (a_j >= a_{j+1}) --j;
//     if (j=0) goto M4;
// M3. [Next a_j] l <- n; while (a_j >= a_l) --l; a_j <-> a_l;
// M4. [Reverse a_{j+1}, ..., a_m] k<-j+1; l<-m; while (k<l) {a_k <-> a_l, k++, l--} if (j>0) goto M1.
// M5. [Next combination] j <- m; while (a_j == j+(n-m)) --j;
//     if (j=0) finished;
//     else {++a_j; while (j<m) a_{++j} <- a_{j-1}+1; goto M1}
bool MapGen::nextMap()
{
	int j, l, k;

	// M2
	j = m - 2;      // "j <- m-1"
	while (j >= 0 && (map[j] >= map[j+1]))
		--j;
	if (j >= 0) {
		// M3
		l = m - 1;  // "l <- m"
		while (map[j] >= map[l])
			--l;
		std::swap(map[j], map[l]);
	}

	// M4
	k = j + 1;      // "k <- j+1"
	l = m - 1;      // "l <- m"
	while (k < l) {
		std::swap(map[k], map[l]);
		++k; --l;
	}

	if (j < 0) {
		// M5
		j = m - 1;  // "j <- m"
		int diff = n-m;
		while (j >= 0 && (map[j] == j+diff))
			--j;
		if (j < 0)
			return false;
		else {
			l = map[j];
			while (j < m)
				map[j++] = ++l;
		}
	}

	return true;
}

//------------------------------
//        PUZZLE SOLVER
//------------------------------
PuzzleSolver::PuzzleSolver(const Puzzle &puzzle)
	: puzzle(puzzle) {}

int PuzzleSolver::print_solutions(std::ostream &out, bool terminal)
{
	int numSolutions = 0;

	try {
		MapGen mapGen(puzzle.getNumLetters(), puzzle.getRadix());

		if (terminal)
			out << "\e[1m";
		for (int i = 0; i < puzzle.getNumLetters(); ++i)
			out << puzzle[i] << ' ';
		if (terminal)
			out << "\e[0m";
		out << std::endl;

		do
			if (puzzle.eval(*mapGen)) {
				++numSolutions;
				for (int i = 0; i < puzzle.getNumLetters(); ++i)
					out << mapGen[i] << ' ';
				out << std::endl;
			}
		while (mapGen.nextMap());
	}
	catch (const std::domain_error &err) {
		out << "This alphametic has too many letters.\n\n";
	}

	return numSolutions;
}

}
<commit_msg>Revised implementation of Puzzle<commit_after>#include <utility>
#include <iterator>
#include <limits>
#include <cstring>
#include <stdexcept>
#include "puzzle.hpp"

/// We don't want to rely on C++14 yet.
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args)
{
	return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

namespace Puzzle {

// BEGIN Implementation of Expressions

Expression::~Expression() = default;

class BinaryExpr : public Expression
{
protected:
	BinaryExpr(std::unique_ptr<Expression> left,
	           std::unique_ptr<Expression> right)
		: left(std::move(left)), right(std::move(right)) {}

	std::unique_ptr<Expression> left, right;
};

class EqualsExpr : public BinaryExpr
{
public:
	EqualsExpr(std::unique_ptr<Expression> left,
	           std::unique_ptr<Expression> right)
		: BinaryExpr(std::move(left), std::move(right)) {}

	fraction<int64_t> eval(const int *assignment) const override
		{ return left->eval(assignment) == right->eval(assignment); }
};

class SumExpr : public BinaryExpr
{
public:
	SumExpr(std::unique_ptr<Expression> left,
	        std::unique_ptr<Expression> right)
		: BinaryExpr(std::move(left), std::move(right)) {}

	fraction<int64_t> eval(const int *assignment) const override
		{ return left->eval(assignment) + right->eval(assignment); }
};

class DifferenceExpr : public BinaryExpr
{
public:
	DifferenceExpr(std::unique_ptr<Expression> left,
	               std::unique_ptr<Expression> right)
		: BinaryExpr(std::move(left), std::move(right)) {}

	fraction<int64_t> eval(const int *assignment) const override
		{ return left->eval(assignment) - right->eval(assignment); }
};

class ProductExpr : public BinaryExpr
{
public:
	ProductExpr(std::unique_ptr<Expression> left,
	            std::unique_ptr<Expression> right)
		: BinaryExpr(std::move(left), std::move(right)) {}

	fraction<int64_t> eval(const int *assignment) const override
		{ return left->eval(assignment) * right->eval(assignment); }
};

class QuotientExpr : public BinaryExpr
{
public:
	QuotientExpr(std::unique_ptr<Expression> left,
	             std::unique_ptr<Expression> right)
		: BinaryExpr(std::move(left), std::move(right)) {}

	fraction<int64_t> eval(const int *assignment) const override
		{ return left->eval(assignment) / right->eval(assignment); }
};

class WordExpr : public Expression
{
public:
	WordExpr(const char *begin, const char *end,
	         const std::map<char, int> &letterToIndex, int radix)
		: word(new int[std::distance(begin, end) + 1]), radix(radix)
	{
		size_t len = std::distance(begin, end);
		for (size_t i = 0; i < len; ++i)
			word[i] = letterToIndex.at(begin[(len-1) - i]);
		word[len] = -1;
	}

	fraction<int64_t> eval(const int *assignment) const override
	{
		int64_t res = 0, val = 1;
		for (size_t i = 0; word[i] >= 0; ++i) {
			res += assignment[word[i]] * val;
			val *= radix;
		}
		return fraction<int64_t>(res);
	}

private:
	std::unique_ptr<int[]> word;
	int radix;
};

class NumberExpr : public Expression
{
public:
	NumberExpr(const char* begin, const char* end, int radix) : value(0)
	{
		for (const char *cur = begin; cur != end; ++cur) {
			value *= radix;
			value += *cur - '0';
		}
	}

	fraction<int64_t> eval(const int*) const override
	{
		return fraction<int64_t>(value);
	}

private:
	int64_t value;
};

// END Implementation of Expressions

// BEGIN Implementation of ExpressionParser

/**
 * Parser data
 */
enum class NodeType {
	EQUAL = 0,          // should occur exactly once - at root
	PLUS,
	MINUS,
	MULTIPLY,
	DIVIDE,
	// FACTORIAL,
	// BINOMIAL,   etc.
	WORD = 0x1000,      // "fixed-value"/number leaf
	NUMBER              // "variable-value"/word leaf
};

struct ExprType {
	char op;
	NodeType type;
	int priority;
};

static const ExprType ParseTable[] = {
	{'=', NodeType::EQUAL, 0},
	{'+', NodeType::PLUS, 1},
	{'-', NodeType::MINUS, 1},
	{'*', NodeType::MULTIPLY, 2},
	{'/', NodeType::DIVIDE, 2}
};

std::unique_ptr<Expression> ExpressionParser::parse(const char *expr)
{
	return parse(expr, expr + strlen(expr));
}

std::unique_ptr<Expression> ExpressionParser::parse(
	const char *begin, const char *end)
{
	NodeType type = NodeType::WORD;
	const char *split;
	int priority = std::numeric_limits<int>::max();

	// TODO: process parantheses
	// LOW: skip whitespace (well, maybe)
	for (const char *cur = begin; cur != end; ++cur)
		for (size_t op = 0; op < (sizeof(ParseTable)/sizeof(ExprType)); ++op)
			if (*cur == ParseTable[op].op && priority >= ParseTable[op].priority) {
				type = ParseTable[op].type;
				split = cur;
				priority = ParseTable[op].priority;
			}

	// split expression and process parts recursively
	if (type != NodeType::WORD) {
		auto left = parse(begin, split);
		auto right = parse(split+1, end);
		switch (type) {
			case NodeType::EQUAL:
				return make_unique<EqualsExpr>(std::move(left), std::move(right));
			case NodeType::PLUS:
				return make_unique<SumExpr>(std::move(left), std::move(right));
			case NodeType::MINUS:
				return make_unique<DifferenceExpr>(std::move(left), std::move(right));
			case NodeType::MULTIPLY:
				return make_unique<ProductExpr>(std::move(left), std::move(right));
			case NodeType::DIVIDE:
				return make_unique<QuotientExpr>(std::move(left), std::move(right));
			default:
				throw std::runtime_error("Unreachable code location");
		}
	}
	else {
		// Is it a word or number?
		const char *cur;
		for (cur = begin; cur != end; ++cur)
			if (*cur >= '0' && *cur <= '9')
				break;
		if (cur == end)
			return make_unique<WordExpr>(begin, end, letterToIndex, radix);
		else
			return make_unique<NumberExpr>(begin, end, radix);
	}
}

// END Implementation of ExpressionParser

// BEGIN Implementation of Puzzle

Puzzle::Puzzle(const char *puzzle, int rad)
	: radix(rad), numLetters(0), indexToLetter(rad), leading(rad)
{
	// Collect letters.
	std::map<char, int> letterToIndex;
	for (const char *cur = puzzle; *cur; ++cur)
		if (*cur >= 'A' && *cur <= 'Z')
			letterToIndex[*cur];

	// Assign numbers to letters.
	for (auto &pair : letterToIndex) {
		indexToLetter[numLetters] = pair.first;
		pair.second = numLetters++;
	}

	// Make syntax tree.
	ExpressionParser parser(letterToIndex, rad);
	root = parser.parse(puzzle);

	// Leading digits aren't allowed to be zero.
	if (puzzle[0] >= 'A' && puzzle[0] <= 'Z')
		leading[letterToIndex[puzzle[0]]] = true;
	for (int i = 1; puzzle[i]; ++i)
		if (puzzle[i-1] < 'A' && puzzle[i] >= 'A' && puzzle[i] <= 'Z')
			leading[letterToIndex[puzzle[i]]] = true;
}

bool Puzzle::eval(const int *assignment) const
{
	for (int i = 0; i < radix; ++i)
		if (!assignment[i] && leading[i])
			return false;
	return root->eval(assignment) != 0;
}

// END Implementation of Puzzle

//------------------------------
// PERMUTATION GENERATOR IMPLEMENTATION
//------------------------------
MapGen::MapGen(int domainSize, int codomainSize)
	: n(codomainSize), m(domainSize)
{
	if (codomainSize < domainSize)
		throw std::domain_error("There are no injective maps if the codomain is smaller than the domain.");
	map = new int[domainSize];

	// M0
	for (int i = 0; i < domainSize; ++i)
		map[i] = i;
}

MapGen::~MapGen()
{
	delete[] map;
}

//---------------------------  ALGORITHM DESCRIPTION  -------------------------
// (The following algorithm is inspired by Donald E. Knuth: The Art of Computer Programming, Vol. 4, Fasc. 2, Algorithm L; but slightly modified)
// Algorithm M: Visit all injective maps f from {1, ..., m} to {1, ..., n}, given m<n.
// Idea: Run through all m-subsets of {1, ..., n} and visit all permutations of these subsets for each one.
//   Running through all m-subsets is done by a "combination-enumeration" algorithm which outputs all combinations in a canonical order.
//   Running through all permutations of these subsets is done by Alg. L.
// M0. start with map (a_1, ..., a_m) = (1, ..., m).
// M1. visit map (a_1, ..., a_m)
// M2. [Find j] j <- m-1; while (a_j >= a_{j+1}) --j;
//     if (j=0) goto M4;
// M3. [Next a_j] l <- n; while (a_j >= a_l) --l; a_j <-> a_l;
// M4. [Reverse a_{j+1}, ..., a_m] k<-j+1; l<-m; while (k<l) {a_k <-> a_l, k++, l--} if (j>0) goto M1.
// M5. [Next combination] j <- m; while (a_j == j+(n-m)) --j;
//     if (j=0) finished;
//     else {++a_j; while (j<m) a_{++j} <- a_{j-1}+1; goto M1}
bool MapGen::nextMap()
{
	int j, l, k;

	// M2
	j = m - 2;      // "j <- m-1"
	while (j >= 0 && (map[j] >= map[j+1]))
		--j;
	if (j >= 0) {
		// M3
		l = m - 1;  // "l <- m"
		while (map[j] >= map[l])
			--l;
		std::swap(map[j], map[l]);
	}

	// M4
	k = j + 1;      // "k <- j+1"
	l = m - 1;      // "l <- m"
	while (k < l) {
		std::swap(map[k], map[l]);
		++k; --l;
	}

	if (j < 0) {
		// M5
		j = m - 1;  // "j <- m"
		int diff = n-m;
		while (j >= 0 && (map[j] == j+diff))
			--j;
		if (j < 0)
			return false;
		else {
			l = map[j];
			while (j < m)
				map[j++] = ++l;
		}
	}

	return true;
}

//------------------------------
//        PUZZLE SOLVER
//------------------------------
PuzzleSolver::PuzzleSolver(const Puzzle &puzzle)
	: puzzle(puzzle) {}

int PuzzleSolver::print_solutions(std::ostream &out, bool terminal)
{
	int numSolutions = 0;

	try {
		MapGen mapGen(puzzle.getNumLetters(), puzzle.getRadix());

		if (terminal)
			out << "\e[1m";
		for (int i = 0; i < puzzle.getNumLetters(); ++i)
			out << puzzle[i] << ' ';
		if (terminal)
			out << "\e[0m";
		out << std::endl;

		do
			if (puzzle.eval(*mapGen)) {
				++numSolutions;
				for (int i = 0; i < puzzle.getNumLetters(); ++i)
					out << mapGen[i] << ' ';
				out << std::endl;
			}
		while (mapGen.nextMap());
	}
	catch (const std::domain_error &err) {
		out << "This alphametic has too many letters.\n\n";
	}

	return numSolutions;
}

}
<|endoftext|>


<commit_before>#include <cassert>
#include <climits>
#include <sstream>
#include <stdexcept>
#include <typeinfo>

#include <set>
#include <tuple>
#include <vector>

#include <Python.h>

namespace dubzzz {
namespace Py2Cpp {

template <class T>
struct CppBuilder
{
  T operator() (PyObject* pyo)
  {
    assert(pyo);

    std::ostringstream oss;
    oss << "No conversion implemented to convert PyObject* into " << typeid(T).name();

    throw std::invalid_argument(oss.str());
    return T {};
  }
};

template <>
struct CppBuilder<PyObject*>
{
  PyObject* operator() (PyObject* pyo)
  {
    assert(pyo);
    return pyo;
  }
};

template <>
struct CppBuilder<bool>
{
  bool operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyBool_Check(pyo))
    {
      return pyo == Py_True;
    }
    throw std::invalid_argument("Not a PyBool instance");
  }
};

template <>
struct CppBuilder<int>
{
  int operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyLong_Check(pyo))
    {
      long v { PyLong_AsLong(pyo) };
      if (v < INT_MIN || v > INT_MAX)
      {
        throw std::overflow_error("Out of <int> boundaries");
      }
      return static_cast<int>(v);
    }
    else if (PyInt_Check(pyo))
    {
      long v { PyInt_AS_LONG(pyo) };
      if (v < INT_MIN || v > INT_MAX)
      {
        throw std::overflow_error("Out of <int> boundaries");
      }
      return static_cast<int>(v);
    }
    throw std::invalid_argument("Not a PyLong instance");
  }
};

template <>
struct CppBuilder<unsigned int>
{
  unsigned int operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyLong_Check(pyo))
    {
      unsigned long v { PyLong_AsUnsignedLongMask(pyo) };
      if (v > UINT_MAX)
      {
        throw std::overflow_error("Out of <unsigned int> boundaries");
      }
      return static_cast<unsigned int>(v);
    }
    else if (PyInt_Check(pyo))
    {
      unsigned long v { PyInt_AsUnsignedLongMask(pyo) };
      if (v > UINT_MAX)
      {
        throw std::overflow_error("Out of <unsigned int> boundaries");
      }
      return static_cast<int>(v);
    }
    throw std::invalid_argument("Not a PyLong instance");
  }
};

template <>
struct CppBuilder<long>
{
  long operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyLong_Check(pyo))
    {
      return PyLong_AsLong(pyo);
    }
    else if (PyInt_Check(pyo))
    {
      return PyInt_AS_LONG(pyo);
    }
    throw std::invalid_argument("Not a PyLong instance");
  }
};

template <>
struct CppBuilder<unsigned long>
{
  unsigned long operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyLong_Check(pyo))
    {
      return PyLong_AsUnsignedLong(pyo);
    }
    else if (PyInt_Check(pyo))
    {
      return PyInt_AsUnsignedLongMask(pyo);
    }
    throw std::invalid_argument("Not a PyLong instance");
  }
};

template <>
struct CppBuilder<long long>
{
  long long operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyLong_Check(pyo))
    {
      return PyLong_AsLongLong(pyo);
    }
    else if (PyInt_Check(pyo))
    {
      return PyInt_AS_LONG(pyo);
    }
    throw std::invalid_argument("Not a PyLong instance");
  }
};

template <>
struct CppBuilder<unsigned long long>
{
  unsigned long long operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyLong_Check(pyo))
    {
      return PyLong_AsUnsignedLongLong(pyo);
    }
    else if (PyInt_Check(pyo))
    {
      return PyInt_AsUnsignedLongLongMask(pyo);
    }
    throw std::invalid_argument("Not a PyLong instance");
  }
};

template <>
struct CppBuilder<double>
{
  double operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyFloat_Check(pyo))
    {
      return PyFloat_AS_DOUBLE(pyo);
    }
    else if (PyLong_Check(pyo))
    {
      return PyLong_AsDouble(pyo);
    }
    else if (PyInt_Check(pyo))
    {
      return PyInt_AS_LONG(pyo);
    }
    throw std::invalid_argument("Neither a PyDouble nor a PyLong instance");
  }
};

template <class TUPLE, std::size_t pos>
void _feedCppTuple(TUPLE& tuple, PyObject* root)
{}

template <class TUPLE, std::size_t pos, class T, class... Args>
void _feedCppTuple(TUPLE& tuple, PyObject* root)
{

  std::get<pos>(tuple) = CppBuilder<T>()(PyTuple_GetItem(root, pos));
  _feedCppTuple<TUPLE, pos +1, Args...>(tuple, root);
}

template <class... Args>
struct CppBuilder<std::tuple<Args...>>
{
  std::tuple<Args...> operator() (PyObject* pyo)
  {
    if (PyTuple_Check(pyo))
    {
      if (PyTuple_Size(pyo) == sizeof...(Args))
      {
        std::tuple<Args...> tuple { std::make_tuple(Args()...) };
        _feedCppTuple<std::tuple<Args...>, 0, Args...>(tuple, pyo);
        return tuple;
      }
      else
      {
        std::ostringstream oss;
        oss << "PyTuple length differs from asked one: "
            << "PyTuple(" << PyTuple_Size(pyo) << ") "
            << "and std::tuple<...>(" << sizeof...(Args) << ")";
        throw std::length_error(oss.str());
      }
    }
    throw std::invalid_argument("Not a PyTuple instance");
  }
};

template <class T>
struct CppBuilder<std::vector<T>>
{
  std::vector<T> operator() (PyObject* pyo)
  {
    if (PyList_Check(pyo))
    {
      long size { PyList_Size(pyo) };
      std::vector<T> v(size);
      for (long i { 0 } ; i != size ; ++i)
      {
        v[i] = CppBuilder<T>()(PyList_GetItem(pyo, i));
      }
      return v;
    }
    throw std::invalid_argument("Not a PyList instance");
  }
};

template <class T>
struct CppBuilder<std::set<T>>
{
  std::set<T> operator() (PyObject* pyo)
  {
    if (PySet_Check(pyo))
    {
      long size { PySet_Size(pyo) };
      std::vector<PyObject*> backup(size);
      std::set<T> s;
      for (long i { 0 } ; i != size ; ++i)
      {
        PyObject* popped { PySet_Pop(pyo) };
        backup[i] = popped;
        s.insert(CppBuilder<T>()(popped));
      }
      for (PyObject* popped : backup)
      {
        PySet_Add(pyo, popped);
      }
      return s;
    }
    throw std::invalid_argument("Not a PyList instance");
  }
};

}
}

<commit_msg>[Mem Leaks] Add call to Py_DECREF during the creation of std::set<commit_after>#include <cassert>
#include <climits>
#include <sstream>
#include <stdexcept>
#include <typeinfo>

#include <set>
#include <tuple>
#include <vector>

#include <Python.h>

namespace dubzzz {
namespace Py2Cpp {

template <class T>
struct CppBuilder
{
  T operator() (PyObject* pyo)
  {
    assert(pyo);

    std::ostringstream oss;
    oss << "No conversion implemented to convert PyObject* into " << typeid(T).name();

    throw std::invalid_argument(oss.str());
    return T {};
  }
};

template <>
struct CppBuilder<PyObject*>
{
  PyObject* operator() (PyObject* pyo)
  {
    assert(pyo);
    return pyo;
  }
};

template <>
struct CppBuilder<bool>
{
  bool operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyBool_Check(pyo))
    {
      return pyo == Py_True;
    }
    throw std::invalid_argument("Not a PyBool instance");
  }
};

template <>
struct CppBuilder<int>
{
  int operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyLong_Check(pyo))
    {
      long v { PyLong_AsLong(pyo) };
      if (v < INT_MIN || v > INT_MAX)
      {
        throw std::overflow_error("Out of <int> boundaries");
      }
      return static_cast<int>(v);
    }
    else if (PyInt_Check(pyo))
    {
      long v { PyInt_AS_LONG(pyo) };
      if (v < INT_MIN || v > INT_MAX)
      {
        throw std::overflow_error("Out of <int> boundaries");
      }
      return static_cast<int>(v);
    }
    throw std::invalid_argument("Not a PyLong instance");
  }
};

template <>
struct CppBuilder<unsigned int>
{
  unsigned int operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyLong_Check(pyo))
    {
      unsigned long v { PyLong_AsUnsignedLongMask(pyo) };
      if (v > UINT_MAX)
      {
        throw std::overflow_error("Out of <unsigned int> boundaries");
      }
      return static_cast<unsigned int>(v);
    }
    else if (PyInt_Check(pyo))
    {
      unsigned long v { PyInt_AsUnsignedLongMask(pyo) };
      if (v > UINT_MAX)
      {
        throw std::overflow_error("Out of <unsigned int> boundaries");
      }
      return static_cast<int>(v);
    }
    throw std::invalid_argument("Not a PyLong instance");
  }
};

template <>
struct CppBuilder<long>
{
  long operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyLong_Check(pyo))
    {
      return PyLong_AsLong(pyo);
    }
    else if (PyInt_Check(pyo))
    {
      return PyInt_AS_LONG(pyo);
    }
    throw std::invalid_argument("Not a PyLong instance");
  }
};

template <>
struct CppBuilder<unsigned long>
{
  unsigned long operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyLong_Check(pyo))
    {
      return PyLong_AsUnsignedLong(pyo);
    }
    else if (PyInt_Check(pyo))
    {
      return PyInt_AsUnsignedLongMask(pyo);
    }
    throw std::invalid_argument("Not a PyLong instance");
  }
};

template <>
struct CppBuilder<long long>
{
  long long operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyLong_Check(pyo))
    {
      return PyLong_AsLongLong(pyo);
    }
    else if (PyInt_Check(pyo))
    {
      return PyInt_AS_LONG(pyo);
    }
    throw std::invalid_argument("Not a PyLong instance");
  }
};

template <>
struct CppBuilder<unsigned long long>
{
  unsigned long long operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyLong_Check(pyo))
    {
      return PyLong_AsUnsignedLongLong(pyo);
    }
    else if (PyInt_Check(pyo))
    {
      return PyInt_AsUnsignedLongLongMask(pyo);
    }
    throw std::invalid_argument("Not a PyLong instance");
  }
};

template <>
struct CppBuilder<double>
{
  double operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyFloat_Check(pyo))
    {
      return PyFloat_AS_DOUBLE(pyo);
    }
    else if (PyLong_Check(pyo))
    {
      return PyLong_AsDouble(pyo);
    }
    else if (PyInt_Check(pyo))
    {
      return PyInt_AS_LONG(pyo);
    }
    throw std::invalid_argument("Neither a PyDouble nor a PyLong instance");
  }
};

template <class TUPLE, std::size_t pos>
void _feedCppTuple(TUPLE& tuple, PyObject* root)
{}

template <class TUPLE, std::size_t pos, class T, class... Args>
void _feedCppTuple(TUPLE& tuple, PyObject* root)
{

  std::get<pos>(tuple) = CppBuilder<T>()(PyTuple_GetItem(root, pos));
  _feedCppTuple<TUPLE, pos +1, Args...>(tuple, root);
}

template <class... Args>
struct CppBuilder<std::tuple<Args...>>
{
  std::tuple<Args...> operator() (PyObject* pyo)
  {
    if (PyTuple_Check(pyo))
    {
      if (PyTuple_Size(pyo) == sizeof...(Args))
      {
        std::tuple<Args...> tuple { std::make_tuple(Args()...) };
        _feedCppTuple<std::tuple<Args...>, 0, Args...>(tuple, pyo);
        return tuple;
      }
      else
      {
        std::ostringstream oss;
        oss << "PyTuple length differs from asked one: "
            << "PyTuple(" << PyTuple_Size(pyo) << ") "
            << "and std::tuple<...>(" << sizeof...(Args) << ")";
        throw std::length_error(oss.str());
      }
    }
    throw std::invalid_argument("Not a PyTuple instance");
  }
};

template <class T>
struct CppBuilder<std::vector<T>>
{
  std::vector<T> operator() (PyObject* pyo)
  {
    if (PyList_Check(pyo))
    {
      long size { PyList_Size(pyo) };
      std::vector<T> v(size);
      for (long i { 0 } ; i != size ; ++i)
      {
        v[i] = CppBuilder<T>()(PyList_GetItem(pyo, i));
      }
      return v;
    }
    throw std::invalid_argument("Not a PyList instance");
  }
};

template <class T>
struct CppBuilder<std::set<T>>
{
  std::set<T> operator() (PyObject* pyo)
  {
    if (PySet_Check(pyo))
    {
      long size { PySet_Size(pyo) };
      std::vector<PyObject*> backup(size);
      std::set<T> s;
      for (long i { 0 } ; i != size ; ++i)
      {
        PyObject* popped { PySet_Pop(pyo) };
        backup[i] = popped;
        s.insert(CppBuilder<T>()(popped));
      }
      for (PyObject* popped : backup)
      {
        PySet_Add(pyo, popped);
        Py_DECREF(popped);
      }
      return s;
    }
    throw std::invalid_argument("Not a PyList instance");
  }
};

}
}

<|endoftext|>


<commit_before>#include "libtorrent/random.hpp"

namespace libtorrent
{

	namespace
	{
		uint32_t x = 123456789;
	}

	void random_seed(boost::uint32_t v)
	{
		x = v;
	}

	// this is an xorshift random number generator
	// see: http://en.wikipedia.org/wiki/Xorshift
	boost::uint32_t random()
	{
		static uint32_t y = 362436069;
		static uint32_t z = 521288629;
		static uint32_t w = 88675123;
		uint32_t t;

		t = x ^ (x << 11);
		x = y; y = z; z = w;
		return w = w ^ (w >> 19) ^ (t ^ (t >> 8));
	}
}

<commit_msg>fix random.cpp build errors on non C99 compilers<commit_after>#include "libtorrent/random.hpp"

namespace libtorrent
{

	namespace
	{
		boost::uint32_t x = 123456789;
	}

	void random_seed(boost::uint32_t v)
	{
		x = v;
	}

	// this is an xorshift random number generator
	// see: http://en.wikipedia.org/wiki/Xorshift
	boost::uint32_t random()
	{
		static boost::uint32_t y = 362436069;
		static boost::uint32_t z = 521288629;
		static boost::uint32_t w = 88675123;
		boost::uint32_t t;

		t = x ^ (x << 11);
		x = y; y = z; z = w;
		return w = w ^ (w >> 19) ^ (t ^ (t >> 8));
	}
}

<|endoftext|>