<commit_before>// SciTE - Scintilla based Text Editor
/** @file DirectorExtension.cxx
 ** Extension for communicating with a director program.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

#define _WIN32_WINNT  0x0400
#include <windows.h>
#include <commctrl.h>

#include "Platform.h"

#include "PropSet.h"

#include "Scintilla.h"
#include "Accessor.h"
#include "Extender.h"
#include "DirectorExtension.h"
#include "SciTE.h"
#include "SciTEBase.h"

static ExtensionAPI *host = 0;
static DirectorExtension *pde = 0;
static HWND wDirector = 0;
static HWND wCorrespondent = 0;
static HWND wReceiver = 0;
static bool startedByDirector = false;
static bool shuttingDown = false;
unsigned int SDI = 0;

static void SendDirector(const char *verb, const char *arg = 0) {
	if ((wDirector != 0) || (wCorrespondent != 0)) {
		HWND wDestination = wCorrespondent;
		SString addressedMessage;
		if (wDestination) {
			addressedMessage += ":";
			SString address(reinterpret_cast<int>(wDestination));
			addressedMessage += address;
			addressedMessage += ":";
		} else {
			wDestination = wDirector;
		}
		addressedMessage += verb;
		addressedMessage += ":";
		if (arg)
			addressedMessage += arg;
		char *slashedMessage = Slash(addressedMessage.c_str());
		if (slashedMessage) {
			COPYDATASTRUCT cds;
			cds.dwData = 0;
			cds.cbData = strlen(slashedMessage);
			cds.lpData = reinterpret_cast<void *>(
			                 const_cast<char *>(slashedMessage));
			::SendMessage(wDestination, WM_COPYDATA,
			              reinterpret_cast<WPARAM>(wReceiver),
			              reinterpret_cast<LPARAM>(&cds));
			delete []slashedMessage;
		}
	}
}

static void SendDirector(const char *verb, sptr_t arg) {
	SString s(arg);
	::SendDirector(verb, s.c_str());
}

static void CheckEnvironment(ExtensionAPI *host) {
	if (host && !shuttingDown) {
		if (!wDirector) {
			char *director = host->Property("director.hwnd");
			if (director && *director) {
				startedByDirector = true;
				wDirector = reinterpret_cast<HWND>(atoi(director));
				// Director is just seen so identify this to it
				::SendDirector("identity", reinterpret_cast<sptr_t>(wReceiver));
			}
			delete []director;
		}
		char number[32];
		sprintf(number, "%0d", reinterpret_cast<int>(wReceiver));
		host->SetProperty("WindowID", number);
	}
}

static char DirectorExtension_ClassName[] = "DirectorExtension";

static LRESULT HandleCopyData(LPARAM lParam) {
	COPYDATASTRUCT *pcds = reinterpret_cast<COPYDATASTRUCT *>(lParam);
	// Copy into an temporary buffer to ensure \0 terminated
	if (pde && pcds->lpData) {
		char *dataCopy = new char[pcds->cbData + 1];
		if (dataCopy) {
			strncpy(dataCopy, reinterpret_cast<char *>(pcds->lpData), pcds->cbData);
			dataCopy[pcds->cbData] = '\0';
			pde->HandleStringMessage(dataCopy);
			delete []dataCopy;
		}
	}
	return 0;
}

LRESULT PASCAL DirectorExtension_WndProc(
    HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) {
	if (iMessage == WM_COPYDATA) {
		return HandleCopyData(lParam);
	} else if (iMessage == SDI) {
		return SDI;
	}
	return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
}

static void DirectorExtension_Register(HINSTANCE hInstance) {
	WNDCLASS wndclass;
	wndclass.style = 0;
	wndclass.lpfnWndProc = DirectorExtension_WndProc;
	wndclass.cbClsExtra = 0;
	wndclass.cbWndExtra = 0;
	wndclass.hInstance = hInstance;
	wndclass.hIcon = 0;
	wndclass.hCursor = NULL;
	wndclass.hbrBackground = NULL;
	wndclass.lpszMenuName = 0;
	wndclass.lpszClassName = DirectorExtension_ClassName;
	if (!::RegisterClass(&wndclass))
		::exit(FALSE);
}

DirectorExtension::DirectorExtension() {
	pde = this;
}

DirectorExtension::~DirectorExtension() {
	pde = 0;
}

bool DirectorExtension::Initialise(ExtensionAPI *host_) {
	host = host_;
	SDI = ::RegisterWindowMessage("SciTEDirectorInterface");
	HINSTANCE hInstance = reinterpret_cast<HINSTANCE>(
	                          host->GetInstance());
	DirectorExtension_Register(hInstance);
	wReceiver = ::CreateWindow(
	                DirectorExtension_ClassName,
	                DirectorExtension_ClassName,
	                0,
	                0, 0, 0, 0,
	                0,
	                0,
	                hInstance,
	                0);
	if (!wReceiver)
		::exit(FALSE);
	// Make the frame window handle available so the director can activate it.
	::SetWindowLong(wReceiver, GWL_USERDATA,
		reinterpret_cast<LONG>(((SciTEBase*)host)->GetID()));
	CheckEnvironment(host);
	return true;
}

bool DirectorExtension::Finalise() {
	::SendDirector("closing");
	if (wReceiver)
		::DestroyWindow(wReceiver);
	wReceiver = 0;
	return true;
}

bool DirectorExtension::Clear() {
	return true;
}

bool DirectorExtension::Load(const char *) {
	return true;
}

bool DirectorExtension::OnOpen(const char *path) {
	CheckEnvironment(host);
	if (*path) {
		::SendDirector("opened", path);
	}
	return true;
}

bool DirectorExtension::OnSwitchFile(const char *path) {
	CheckEnvironment(host);
	if (*path) {
		::SendDirector("switched", path);
	}
	return true;
};

bool DirectorExtension::OnSave(const char *path) {
	CheckEnvironment(host);
	if (*path) {
		::SendDirector("saved", path);
	}
	return true;
}

bool DirectorExtension::OnChar(char) {
	return false;
}

bool DirectorExtension::OnExecute(const char *) {
	return false;
}

bool DirectorExtension::OnSavePointReached() {
	return false;
}

bool DirectorExtension::OnSavePointLeft() {
	return false;
}

bool DirectorExtension::OnStyle(unsigned int, int, int, Accessor *) {
	return false;
}

// These should probably have arguments

bool DirectorExtension::OnDoubleClick() {
	return false;
}

bool DirectorExtension::OnUpdateUI() {
	return false;
}

bool DirectorExtension::OnMarginClick() {
	return false;
}

bool DirectorExtension::OnMacro(const char *command, const char *params) {
	SendDirector(command, params);
	return true;
}

bool DirectorExtension::SendProperty(const char *prop) {
	CheckEnvironment(host);
	if (*prop) {
		::SendDirector("property", prop);
	}
	return true;
}

void DirectorExtension::HandleStringMessage(const char *message) {
	// Message may contain multiple commands separated by '\n'
	// Reentrance trouble - if this function is reentered, the wCorrespondent may
	// be set to zero before time.
	WordList wlMessage(true);
	wlMessage.Set(message);
	for (int i = 0; i < wlMessage.len; i++) {
		// Message format is [:return address:]command:argument
		char *cmd = wlMessage[i];
		if (*cmd == ':') {
			// There is a return address
			char *colon = strchr(cmd + 1, ':');
			if (colon) {
				*colon = '\0';
				wCorrespondent = reinterpret_cast<HWND>(atoi(cmd + 1));
				cmd = colon + 1;
			}
		}
		if (isprefix(cmd, "identity:")) {
			char *arg = strchr(cmd, ':');
			if (arg)
				wDirector = reinterpret_cast<HWND>(atoi(arg + 1));
		} else if (isprefix(cmd, "closing:")) {
			wDirector = 0;
			if (startedByDirector) {
				shuttingDown = true;
				host->ShutDown();
				shuttingDown = false;
			}
		} else if (host) {
			host->Perform(cmd);
		}
		wCorrespondent = 0;
	}
}

#ifdef _MSC_VER
// Unreferenced inline functions are OK
#pragma warning(disable: 4514)
#endif
<commit_msg>Execute sends macro:run command to director.<commit_after>// SciTE - Scintilla based Text Editor
/** @file DirectorExtension.cxx
 ** Extension for communicating with a director program.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

#define _WIN32_WINNT  0x0400
#include <windows.h>
#include <commctrl.h>

#include "Platform.h"

#include "PropSet.h"

#include "Scintilla.h"
#include "Accessor.h"
#include "Extender.h"
#include "DirectorExtension.h"
#include "SciTE.h"
#include "SciTEBase.h"

static ExtensionAPI *host = 0;
static DirectorExtension *pde = 0;
static HWND wDirector = 0;
static HWND wCorrespondent = 0;
static HWND wReceiver = 0;
static bool startedByDirector = false;
static bool shuttingDown = false;
unsigned int SDI = 0;

static void SendDirector(const char *verb, const char *arg = 0) {
	if ((wDirector != 0) || (wCorrespondent != 0)) {
		HWND wDestination = wCorrespondent;
		SString addressedMessage;
		if (wDestination) {
			addressedMessage += ":";
			SString address(reinterpret_cast<int>(wDestination));
			addressedMessage += address;
			addressedMessage += ":";
		} else {
			wDestination = wDirector;
		}
		addressedMessage += verb;
		addressedMessage += ":";
		if (arg)
			addressedMessage += arg;
		char *slashedMessage = Slash(addressedMessage.c_str());
		if (slashedMessage) {
			COPYDATASTRUCT cds;
			cds.dwData = 0;
			cds.cbData = strlen(slashedMessage);
			cds.lpData = reinterpret_cast<void *>(
			                 const_cast<char *>(slashedMessage));
			::SendMessage(wDestination, WM_COPYDATA,
			              reinterpret_cast<WPARAM>(wReceiver),
			              reinterpret_cast<LPARAM>(&cds));
			delete []slashedMessage;
		}
	}
}

static void SendDirector(const char *verb, sptr_t arg) {
	SString s(arg);
	::SendDirector(verb, s.c_str());
}

static void CheckEnvironment(ExtensionAPI *host) {
	if (host && !shuttingDown) {
		if (!wDirector) {
			char *director = host->Property("director.hwnd");
			if (director && *director) {
				startedByDirector = true;
				wDirector = reinterpret_cast<HWND>(atoi(director));
				// Director is just seen so identify this to it
				::SendDirector("identity", reinterpret_cast<sptr_t>(wReceiver));
			}
			delete []director;
		}
		char number[32];
		sprintf(number, "%0d", reinterpret_cast<int>(wReceiver));
		host->SetProperty("WindowID", number);
	}
}

static char DirectorExtension_ClassName[] = "DirectorExtension";

static LRESULT HandleCopyData(LPARAM lParam) {
	COPYDATASTRUCT *pcds = reinterpret_cast<COPYDATASTRUCT *>(lParam);
	// Copy into an temporary buffer to ensure \0 terminated
	if (pde && pcds->lpData) {
		char *dataCopy = new char[pcds->cbData + 1];
		if (dataCopy) {
			strncpy(dataCopy, reinterpret_cast<char *>(pcds->lpData), pcds->cbData);
			dataCopy[pcds->cbData] = '\0';
			pde->HandleStringMessage(dataCopy);
			delete []dataCopy;
		}
	}
	return 0;
}

LRESULT PASCAL DirectorExtension_WndProc(
    HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) {
	if (iMessage == WM_COPYDATA) {
		return HandleCopyData(lParam);
	} else if (iMessage == SDI) {
		return SDI;
	}
	return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
}

static void DirectorExtension_Register(HINSTANCE hInstance) {
	WNDCLASS wndclass;
	wndclass.style = 0;
	wndclass.lpfnWndProc = DirectorExtension_WndProc;
	wndclass.cbClsExtra = 0;
	wndclass.cbWndExtra = 0;
	wndclass.hInstance = hInstance;
	wndclass.hIcon = 0;
	wndclass.hCursor = NULL;
	wndclass.hbrBackground = NULL;
	wndclass.lpszMenuName = 0;
	wndclass.lpszClassName = DirectorExtension_ClassName;
	if (!::RegisterClass(&wndclass))
		::exit(FALSE);
}

DirectorExtension::DirectorExtension() {
	pde = this;
}

DirectorExtension::~DirectorExtension() {
	pde = 0;
}

bool DirectorExtension::Initialise(ExtensionAPI *host_) {
	host = host_;
	SDI = ::RegisterWindowMessage("SciTEDirectorInterface");
	HINSTANCE hInstance = reinterpret_cast<HINSTANCE>(
	                          host->GetInstance());
	DirectorExtension_Register(hInstance);
	wReceiver = ::CreateWindow(
	                DirectorExtension_ClassName,
	                DirectorExtension_ClassName,
	                0,
	                0, 0, 0, 0,
	                0,
	                0,
	                hInstance,
	                0);
	if (!wReceiver)
		::exit(FALSE);
	// Make the frame window handle available so the director can activate it.
	::SetWindowLong(wReceiver, GWL_USERDATA,
		reinterpret_cast<LONG>(((SciTEBase*)host)->GetID()));
	CheckEnvironment(host);
	return true;
}

bool DirectorExtension::Finalise() {
	::SendDirector("closing");
	if (wReceiver)
		::DestroyWindow(wReceiver);
	wReceiver = 0;
	return true;
}

bool DirectorExtension::Clear() {
	return true;
}

bool DirectorExtension::Load(const char *) {
	return true;
}

bool DirectorExtension::OnOpen(const char *path) {
	CheckEnvironment(host);
	if (*path) {
		::SendDirector("opened", path);
	}
	return true;
}

bool DirectorExtension::OnSwitchFile(const char *path) {
	CheckEnvironment(host);
	if (*path) {
		::SendDirector("switched", path);
	}
	return true;
};

bool DirectorExtension::OnSave(const char *path) {
	CheckEnvironment(host);
	if (*path) {
		::SendDirector("saved", path);
	}
	return true;
}

bool DirectorExtension::OnChar(char) {
	return false;
}

bool DirectorExtension::OnExecute(const char *cmd) {
	CheckEnvironment(host);
	::SendDirector("macro:run", cmd);
	return true;
}

bool DirectorExtension::OnSavePointReached() {
	return false;
}

bool DirectorExtension::OnSavePointLeft() {
	return false;
}

bool DirectorExtension::OnStyle(unsigned int, int, int, Accessor *) {
	return false;
}

// These should probably have arguments

bool DirectorExtension::OnDoubleClick() {
	return false;
}

bool DirectorExtension::OnUpdateUI() {
	return false;
}

bool DirectorExtension::OnMarginClick() {
	return false;
}

bool DirectorExtension::OnMacro(const char *command, const char *params) {
	SendDirector(command, params);
	return true;
}

bool DirectorExtension::SendProperty(const char *prop) {
	CheckEnvironment(host);
	if (*prop) {
		::SendDirector("property", prop);
	}
	return true;
}

void DirectorExtension::HandleStringMessage(const char *message) {
	// Message may contain multiple commands separated by '\n'
	// Reentrance trouble - if this function is reentered, the wCorrespondent may
	// be set to zero before time.
	WordList wlMessage(true);
	wlMessage.Set(message);
	for (int i = 0; i < wlMessage.len; i++) {
		// Message format is [:return address:]command:argument
		char *cmd = wlMessage[i];
		if (*cmd == ':') {
			// There is a return address
			char *colon = strchr(cmd + 1, ':');
			if (colon) {
				*colon = '\0';
				wCorrespondent = reinterpret_cast<HWND>(atoi(cmd + 1));
				cmd = colon + 1;
			}
		}
		if (isprefix(cmd, "identity:")) {
			char *arg = strchr(cmd, ':');
			if (arg)
				wDirector = reinterpret_cast<HWND>(atoi(arg + 1));
		} else if (isprefix(cmd, "closing:")) {
			wDirector = 0;
			if (startedByDirector) {
				shuttingDown = true;
				host->ShutDown();
				shuttingDown = false;
			}
		} else if (host) {
			host->Perform(cmd);
		}
		wCorrespondent = 0;
	}
}

#ifdef _MSC_VER
// Unreferenced inline functions are OK
#pragma warning(disable: 4514)
#endif
<|endoftext|>


<commit_before>/**
 * \file
 * \brief      PySceneManager class implementation.
 * \author     Thomas Moeller
 * \details
 *
 * Copyright (C) the PyInventor contributors. All rights reserved.
 * This file is part of PyInventor, distributed under the BSD 3-Clause
 * License. For full terms see the included COPYING file.
 */

#include <Inventor/SoSceneManager.h>
#include <Inventor/events/SoLocation2Event.h>
#include <Inventor/events/SoMouseButtonEvent.h>
#include <Inventor/events/SoKeyboardEvent.h>
#include <Inventor/nodes/SoNode.h>
#include <Inventor/engines/SoEngine.h>
#include <Inventor/elements/SoGLLazyElement.h> // for GL.h, whose location is distribution specific under system/ or sys/
#include <Inventor/SoDB.h>

#ifdef TGS_VERSION
#include <Inventor/events/SoMouseWheelEvent.h>
#endif

#include "PySceneManager.h"

#pragma warning ( disable : 4127 ) // conditional expression is constant in Py_DECREF
#pragma warning ( disable : 4244 ) // possible loss of data when converting int to short in SbVec2s

PyTypeObject *PySceneManager::getType()
{
	static PyMemberDef members[] =
	{
		{"scene", T_OBJECT_EX, offsetof(Object, scene), 0, "scene graph"},
		{"redisplay", T_OBJECT_EX, offsetof(Object, renderCallback), 0, "render callback"},
		{NULL}  /* Sentinel */
	};

	static PyMethodDef methods[] =
	{
		{"render", (PyCFunction) render, METH_NOARGS, "Renders the scene into an OpenGL context" },
		{"resize", (PyCFunction) resize, METH_VARARGS, "Sets the window size" },
		{"mouse_button", (PyCFunction) mouse_button, METH_VARARGS, "Sends mouse button event into the scene for processing" },
		{"mouse_move", (PyCFunction) mouse_move, METH_VARARGS, "Sends mouse move event into the scene for processing" },
		{"key", (PyCFunction) key, METH_VARARGS, "Sends keyboard event into the scene for processing" },
		{NULL}  /* Sentinel */
	};

	static PyTypeObject managerType =
	{
		PyVarObject_HEAD_INIT(NULL, 0)
		"SceneManager",            /* tp_name */
		sizeof(Object),            /* tp_basicsize */
		0,                         /* tp_itemsize */
		(destructor) tp_dealloc,   /* tp_dealloc */
		0,                         /* tp_print */
		0,                         /* tp_getattr */
		0,                         /* tp_setattr */
		0,                         /* tp_reserved */
		0,                         /* tp_repr */
		0,                         /* tp_as_number */
		0,                         /* tp_as_sequence */
		0,                         /* tp_as_mapping */
		0,                         /* tp_hash  */
		0,                         /* tp_call */
		0,                         /* tp_str */
		0,                         /* tp_getattro */
		(setattrofunc)tp_setattro, /* tp_setattro */
		0,                         /* tp_as_buffer */
		Py_TPFLAGS_DEFAULT |
			Py_TPFLAGS_BASETYPE,   /* tp_flags */
		"Scene manager object",    /* tp_doc */
		0,                         /* tp_traverse */
		0,                         /* tp_clear */
		0,                         /* tp_richcompare */
		0,                         /* tp_weaklistoffset */
		0,                         /* tp_iter */
		0,                         /* tp_iternext */
		methods,                   /* tp_methods */
		members,                   /* tp_members */
		0,                         /* tp_getset */
		0,                         /* tp_base */
		0,                         /* tp_dict */
		0,                         /* tp_descr_get */
		0,                         /* tp_descr_set */
		0,                         /* tp_dictoffset */
		(initproc) tp_init,        /* tp_init */
		0,                         /* tp_alloc */
		tp_new,                    /* tp_new */
	};

	return &managerType;
}

void PySceneManager::tp_dealloc(Object* self)
{
	if (self->sceneManager)
	{
		delete self->sceneManager;
	}

	Py_XDECREF(self->scene);
	Py_XDECREF(self->renderCallback);

    Py_TYPE(self)->tp_free((PyObject*)self);
}

PyObject* PySceneManager::tp_new(PyTypeObject *type, PyObject* /*args*/, PyObject* /*kwds*/)
{
	PySceneObject::initSoDB();

    Object *self = (Object *)type->tp_alloc(type, 0);
    if (self != NULL)
	{
		self->scene = 0;
		self->renderCallback = 0;
		self->sceneManager = 0;
	}

    return (PyObject *) self;
}

int PySceneManager::tp_init(Object *self, PyObject * /*args*/, PyObject * /*kwds*/)
{
	self->scene = PySceneObject::createWrapper("Separator");
	self->sceneManager = new SoSceneManager();
	if (self->scene && self->sceneManager)
	{
		self->sceneManager->setSceneGraph((SoNode*) ((PySceneObject::Object*) self->scene)->inventorObject);
	}
	self->sceneManager->setRenderCallback(renderCBFunc, self);
	self->sceneManager->activate();

	Py_INCREF(Py_None);
	self->renderCallback = Py_None;

	return 0;
}

int PySceneManager::tp_setattro(Object* self, PyObject *attrname, PyObject *value)
{
	int result = 0;

	result = PyObject_GenericSetAttr((PyObject*) self, attrname, value);

	const char *attr = PyUnicode_AsUTF8(attrname);
	if (attr && (strcmp(attr, "scene") == 0))
	{
		if (PyNode_Check(self->scene))
		{
			SoFieldContainer *fc = ((PySceneObject::Object*) self->scene)->inventorObject;
			if (fc && fc->isOfType(SoNode::getClassTypeId()))
			{
				self->sceneManager->setSceneGraph((SoNode*) fc);
				self->sceneManager->scheduleRedraw();
			}
			else
			{
				PyErr_SetString(PyExc_IndexError, "Scene object must be of type SoNode");
			}
		}
		else
		{
			PyErr_SetString(PyExc_IndexError, "Scene must be of type Node");
		}
	}

	return result;
}

void PySceneManager::renderCBFunc(void *userdata, SoSceneManager * /*mgr*/)
{
	Object *self = (Object *) userdata;
	if ((self != NULL) && (self->renderCallback != NULL) && PyCallable_Check(self->renderCallback))
	{
		PyObject *value = PyObject_CallObject(self->renderCallback, NULL);
		if (value != NULL)
		{
			Py_DECREF(value);
		}
	}
}

PyObject* PySceneManager::render(Object *self)
{
	self->sceneManager->render();

    // need to flush or nothing will be shown on OS X
    glFlush();

    Py_INCREF(Py_None);
    return Py_None;
}

PyObject* PySceneManager::resize(Object *self, PyObject *args)
{
    int width = 0, height = 0;
    if (PyArg_ParseTuple(args, "ii", &width, &height))
	{
        // for Coin both setWindowSize() and setSize() must be called
        // in order to get correct rendering and event handling
		self->sceneManager->setWindowSize(SbVec2s(width, height));
        self->sceneManager->setSize(SbVec2s(width, height));
	}

    Py_INCREF(Py_None);
    return Py_None;
}

PyObject* PySceneManager::mouse_button(Object *self, PyObject *args)
{
    int button = 0, state = 0, x = 0, y = 0;
    if (PyArg_ParseTuple(args, "iiii", &button, &state, &x, &y))
	{
		y = self->sceneManager->getWindowSize()[1] - y;

        #ifdef TGS_VERSION
		// Coin does not have wheel event (yet)
        if (button > 2)
		{
			// wheel
			SoMouseWheelEvent ev;
			ev.setTime(SbTime::getTimeOfDay());
			ev.setDelta(state ? -120 : 120);
			if (self->sceneManager->processEvent(&ev))
			{
				SoDB::getSensorManager()->processDelayQueue(FALSE);
			}
		}
		else
        #endif
		{
			SoMouseButtonEvent ev;
			ev.setTime(SbTime::getTimeOfDay());
			ev.setPosition(SbVec2s(x, y));
			ev.setButton((SoMouseButtonEvent::Button) (button + 1));
			ev.setState(state ? SoMouseButtonEvent::UP : SoMouseButtonEvent::DOWN);
			if (self->sceneManager->processEvent(&ev))
			{
				SoDB::getSensorManager()->processDelayQueue(FALSE);
			}
		}
	}

    Py_INCREF(Py_None);
    return Py_None;
}

PyObject* PySceneManager::mouse_move(Object *self, PyObject *args)
{
    int x = 0, y = 0;
    if (PyArg_ParseTuple(args, "ii", &x, &y))
	{
		y = self->sceneManager->getWindowSize()[1] - y;

		SoLocation2Event ev;
		ev.setTime(SbTime::getTimeOfDay());
		ev.setPosition(SbVec2s(x, y));
		if (self->sceneManager->processEvent(&ev))
		{
			SoDB::getSensorManager()->processDelayQueue(FALSE);
		}
	}

    Py_INCREF(Py_None);
    return Py_None;
}

PyObject* PySceneManager::key(Object *self, PyObject *args)
{
    char key;
    if (PyArg_ParseTuple(args, "c", &key))
	{
		bool mapped = true;
		SoKeyboardEvent ev;
		ev.setTime(SbTime::getTimeOfDay());

		if ((key >= 'a') && (key <= 'z'))
		{
			ev.setKey(SoKeyboardEvent::Key(SoKeyboardEvent::A + (key - 'a')));
		}
		else if ((key >= 'A') && (key <= 'Z'))
		{
			ev.setKey(SoKeyboardEvent::Key(SoKeyboardEvent::A + (key - 'Z')));
			ev.setShiftDown(TRUE);
		}
		else switch (key)
		{
		case '\n':
		case '\r':		ev.setKey(SoKeyboardEvent::RETURN); break;
		case '\t':		ev.setKey(SoKeyboardEvent::TAB); break;
		case ' ':		ev.setKey(SoKeyboardEvent::SPACE); break;
		case ',':		ev.setKey(SoKeyboardEvent::COMMA); break;
		case '.':		ev.setKey(SoKeyboardEvent::PERIOD); break;
		case '=':		ev.setKey(SoKeyboardEvent::EQUAL); break;
		case '-':		ev.setKey(SoKeyboardEvent::PAD_SUBTRACT); break;
		case '+':		ev.setKey(SoKeyboardEvent::PAD_ADD); break;
		case '/':		ev.setKey(SoKeyboardEvent::PAD_DIVIDE); break;
		case '*':		ev.setKey(SoKeyboardEvent::PAD_MULTIPLY); break;
		case '\x1b':	ev.setKey(SoKeyboardEvent::ESCAPE); break;
		case '\x08':	ev.setKey(SoKeyboardEvent::BACKSPACE); break;
		default:
			mapped = false;
		}

		if (mapped)
		{
			ev.setState(SoButtonEvent::DOWN);
			SbBool processed = self->sceneManager->processEvent(&ev);
			ev.setState(SoButtonEvent::UP);
			processed |= self->sceneManager->processEvent(&ev);
			if (processed)
			{
				SoDB::getSensorManager()->processDelayQueue(FALSE);
			}
		}
	}

    Py_INCREF(Py_None);
    return Py_None;
}

<commit_msg>Added setting background color via scene manager init.<commit_after>/**
 * \file
 * \brief      PySceneManager class implementation.
 * \author     Thomas Moeller
 * \details
 *
 * Copyright (C) the PyInventor contributors. All rights reserved.
 * This file is part of PyInventor, distributed under the BSD 3-Clause
 * License. For full terms see the included COPYING file.
 */

#include <Inventor/SoSceneManager.h>
#include <Inventor/events/SoLocation2Event.h>
#include <Inventor/events/SoMouseButtonEvent.h>
#include <Inventor/events/SoKeyboardEvent.h>
#include <Inventor/nodes/SoNode.h>
#include <Inventor/engines/SoEngine.h>
#include <Inventor/elements/SoGLLazyElement.h> // for GL.h, whose location is distribution specific under system/ or sys/
#include <Inventor/SoDB.h>

#ifdef TGS_VERSION
#include <Inventor/events/SoMouseWheelEvent.h>
#endif

#include "PySceneManager.h"

#pragma warning ( disable : 4127 ) // conditional expression is constant in Py_DECREF
#pragma warning ( disable : 4244 ) // possible loss of data when converting int to short in SbVec2s

PyTypeObject *PySceneManager::getType()
{
	static PyMemberDef members[] =
	{
		{"scene", T_OBJECT_EX, offsetof(Object, scene), 0, "scene graph"},
		{"redisplay", T_OBJECT_EX, offsetof(Object, renderCallback), 0, "render callback"},
		{NULL}  /* Sentinel */
	};

	static PyMethodDef methods[] =
	{
		{"render", (PyCFunction) render, METH_NOARGS, "Renders the scene into an OpenGL context" },
		{"resize", (PyCFunction) resize, METH_VARARGS, "Sets the window size" },
		{"mouse_button", (PyCFunction) mouse_button, METH_VARARGS, "Sends mouse button event into the scene for processing" },
		{"mouse_move", (PyCFunction) mouse_move, METH_VARARGS, "Sends mouse move event into the scene for processing" },
		{"key", (PyCFunction) key, METH_VARARGS, "Sends keyboard event into the scene for processing" },
		{NULL}  /* Sentinel */
	};

	static PyTypeObject managerType =
	{
		PyVarObject_HEAD_INIT(NULL, 0)
		"SceneManager",            /* tp_name */
		sizeof(Object),            /* tp_basicsize */
		0,                         /* tp_itemsize */
		(destructor) tp_dealloc,   /* tp_dealloc */
		0,                         /* tp_print */
		0,                         /* tp_getattr */
		0,                         /* tp_setattr */
		0,                         /* tp_reserved */
		0,                         /* tp_repr */
		0,                         /* tp_as_number */
		0,                         /* tp_as_sequence */
		0,                         /* tp_as_mapping */
		0,                         /* tp_hash  */
		0,                         /* tp_call */
		0,                         /* tp_str */
		0,                         /* tp_getattro */
		(setattrofunc)tp_setattro, /* tp_setattro */
		0,                         /* tp_as_buffer */
		Py_TPFLAGS_DEFAULT |
			Py_TPFLAGS_BASETYPE,   /* tp_flags */
		"Scene manager object",    /* tp_doc */
		0,                         /* tp_traverse */
		0,                         /* tp_clear */
		0,                         /* tp_richcompare */
		0,                         /* tp_weaklistoffset */
		0,                         /* tp_iter */
		0,                         /* tp_iternext */
		methods,                   /* tp_methods */
		members,                   /* tp_members */
		0,                         /* tp_getset */
		0,                         /* tp_base */
		0,                         /* tp_dict */
		0,                         /* tp_descr_get */
		0,                         /* tp_descr_set */
		0,                         /* tp_dictoffset */
		(initproc) tp_init,        /* tp_init */
		0,                         /* tp_alloc */
		tp_new,                    /* tp_new */
	};

	return &managerType;
}

void PySceneManager::tp_dealloc(Object* self)
{
	if (self->sceneManager)
	{
		delete self->sceneManager;
	}

	Py_XDECREF(self->scene);
	Py_XDECREF(self->renderCallback);

    Py_TYPE(self)->tp_free((PyObject*)self);
}

PyObject* PySceneManager::tp_new(PyTypeObject *type, PyObject* /*args*/, PyObject* /*kwds*/)
{
	PySceneObject::initSoDB();

    Object *self = (Object *)type->tp_alloc(type, 0);
    if (self != NULL)
	{
		self->scene = 0;
		self->renderCallback = 0;
		self->sceneManager = 0;
	}

    return (PyObject *) self;
}

int PySceneManager::tp_init(Object *self, PyObject *args, PyObject *kwds)
{
	PyObject *background = 0;
	static char *kwlist[] = { "background", NULL};

	if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &background))
        return -1;

	self->scene = PySceneObject::createWrapper("Separator");
	self->sceneManager = new SoSceneManager();
	if (self->scene && self->sceneManager)
	{
		self->sceneManager->setSceneGraph((SoNode*) ((PySceneObject::Object*) self->scene)->inventorObject);
	}
	self->sceneManager->setRenderCallback(renderCBFunc, self);
	self->sceneManager->activate();

	Py_INCREF(Py_None);
	self->renderCallback = Py_None;

    // configure background color
	if (background && PySequence_Check(background))
	{
		PyObject *seq = PySequence_Fast(background, "expected a sequence");
		size_t n = PySequence_Size(seq);
        if (n == 3)
        {
            SbColor color(0, 0, 0);
            for (int i = 0; i < 3; ++i)
            {
                PyObject *seqItem = PySequence_GetItem(seq, i);
                if (seqItem)
                {
                    if (PyFloat_Check(seqItem))
                        color[i] = (float) PyFloat_AsDouble(seqItem);
                    else if (PyLong_Check(seqItem))
                        color[i] = (float) PyLong_AsDouble(seqItem);
                }
            }
            if (self->sceneManager)
                self->sceneManager->setBackgroundColor(color);
        }

		Py_XDECREF(seq);
	}

	return 0;
}

int PySceneManager::tp_setattro(Object* self, PyObject *attrname, PyObject *value)
{
	int result = 0;

	result = PyObject_GenericSetAttr((PyObject*) self, attrname, value);

	const char *attr = PyUnicode_AsUTF8(attrname);
	if (attr && (strcmp(attr, "scene") == 0))
	{
		if (PyNode_Check(self->scene))
		{
			SoFieldContainer *fc = ((PySceneObject::Object*) self->scene)->inventorObject;
			if (fc && fc->isOfType(SoNode::getClassTypeId()))
			{
				self->sceneManager->setSceneGraph((SoNode*) fc);
				self->sceneManager->scheduleRedraw();
			}
			else
			{
				PyErr_SetString(PyExc_IndexError, "Scene object must be of type SoNode");
			}
		}
		else
		{
			PyErr_SetString(PyExc_IndexError, "Scene must be of type Node");
		}
	}

	return result;
}

void PySceneManager::renderCBFunc(void *userdata, SoSceneManager * /*mgr*/)
{
	Object *self = (Object *) userdata;
	if ((self != NULL) && (self->renderCallback != NULL) && PyCallable_Check(self->renderCallback))
	{
		PyObject *value = PyObject_CallObject(self->renderCallback, NULL);
		if (value != NULL)
		{
			Py_DECREF(value);
		}
	}
}

PyObject* PySceneManager::render(Object *self)
{
	self->sceneManager->render();

    // need to flush or nothing will be shown on OS X
    glFlush();

    Py_INCREF(Py_None);
    return Py_None;
}

PyObject* PySceneManager::resize(Object *self, PyObject *args)
{
    int width = 0, height = 0;
    if (PyArg_ParseTuple(args, "ii", &width, &height))
	{
        // for Coin both setWindowSize() and setSize() must be called
        // in order to get correct rendering and event handling
		self->sceneManager->setWindowSize(SbVec2s(width, height));
        self->sceneManager->setSize(SbVec2s(width, height));
	}

    Py_INCREF(Py_None);
    return Py_None;
}

PyObject* PySceneManager::mouse_button(Object *self, PyObject *args)
{
    int button = 0, state = 0, x = 0, y = 0;
    if (PyArg_ParseTuple(args, "iiii", &button, &state, &x, &y))
	{
		y = self->sceneManager->getWindowSize()[1] - y;

        #ifdef TGS_VERSION
		// Coin does not have wheel event (yet)
        if (button > 2)
		{
			// wheel
			SoMouseWheelEvent ev;
			ev.setTime(SbTime::getTimeOfDay());
			ev.setDelta(state ? -120 : 120);
			if (self->sceneManager->processEvent(&ev))
			{
				SoDB::getSensorManager()->processDelayQueue(FALSE);
			}
		}
		else
        #endif
		{
			SoMouseButtonEvent ev;
			ev.setTime(SbTime::getTimeOfDay());
			ev.setPosition(SbVec2s(x, y));
			ev.setButton((SoMouseButtonEvent::Button) (button + 1));
			ev.setState(state ? SoMouseButtonEvent::UP : SoMouseButtonEvent::DOWN);
			if (self->sceneManager->processEvent(&ev))
			{
				SoDB::getSensorManager()->processDelayQueue(FALSE);
			}
		}
	}

    Py_INCREF(Py_None);
    return Py_None;
}

PyObject* PySceneManager::mouse_move(Object *self, PyObject *args)
{
    int x = 0, y = 0;
    if (PyArg_ParseTuple(args, "ii", &x, &y))
	{
		y = self->sceneManager->getWindowSize()[1] - y;

		SoLocation2Event ev;
		ev.setTime(SbTime::getTimeOfDay());
		ev.setPosition(SbVec2s(x, y));
		if (self->sceneManager->processEvent(&ev))
		{
			SoDB::getSensorManager()->processDelayQueue(FALSE);
		}
	}

    Py_INCREF(Py_None);
    return Py_None;
}

PyObject* PySceneManager::key(Object *self, PyObject *args)
{
    char key;
    if (PyArg_ParseTuple(args, "c", &key))
	{
		bool mapped = true;
		SoKeyboardEvent ev;
		ev.setTime(SbTime::getTimeOfDay());

		if ((key >= 'a') && (key <= 'z'))
		{
			ev.setKey(SoKeyboardEvent::Key(SoKeyboardEvent::A + (key - 'a')));
		}
		else if ((key >= 'A') && (key <= 'Z'))
		{
			ev.setKey(SoKeyboardEvent::Key(SoKeyboardEvent::A + (key - 'Z')));
			ev.setShiftDown(TRUE);
		}
		else switch (key)
		{
		case '\n':
		case '\r':		ev.setKey(SoKeyboardEvent::RETURN); break;
		case '\t':		ev.setKey(SoKeyboardEvent::TAB); break;
		case ' ':		ev.setKey(SoKeyboardEvent::SPACE); break;
		case ',':		ev.setKey(SoKeyboardEvent::COMMA); break;
		case '.':		ev.setKey(SoKeyboardEvent::PERIOD); break;
		case '=':		ev.setKey(SoKeyboardEvent::EQUAL); break;
		case '-':		ev.setKey(SoKeyboardEvent::PAD_SUBTRACT); break;
		case '+':		ev.setKey(SoKeyboardEvent::PAD_ADD); break;
		case '/':		ev.setKey(SoKeyboardEvent::PAD_DIVIDE); break;
		case '*':		ev.setKey(SoKeyboardEvent::PAD_MULTIPLY); break;
		case '\x1b':	ev.setKey(SoKeyboardEvent::ESCAPE); break;
		case '\x08':	ev.setKey(SoKeyboardEvent::BACKSPACE); break;
		default:
			mapped = false;
		}

		if (mapped)
		{
			ev.setState(SoButtonEvent::DOWN);
			SbBool processed = self->sceneManager->processEvent(&ev);
			ev.setState(SoButtonEvent::UP);
			processed |= self->sceneManager->processEvent(&ev);
			if (processed)
			{
				SoDB::getSensorManager()->processDelayQueue(FALSE);
			}
		}
	}

    Py_INCREF(Py_None);
    return Py_None;
}

<|endoftext|>


<commit_before>//
// Copyright(c) 2016-2017 benikabocha.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//

#include "File.h"
#include "UnicodeUtil.h"

#include <streambuf>

namespace saba
{
	saba::File::File()
		: m_fp(nullptr)
		, m_fileSize(0)
		, m_badFlag(false)
	{
	}

	File::~File()
	{
		Close();
	}

	bool File::OpenFile(const char * filepath, const char * mode)
	{
		if (m_fp != nullptr)
		{
			Close();
		}
#if _WIN32
		std::wstring wFilepath;
		if (!TryToWString(filepath, wFilepath))
		{
			return false;
		}
		std::wstring wMode = ToWString(mode);
		auto err = _wfopen_s(&m_fp, wFilepath.c_str(), wMode.c_str());
		if (err != 0)
		{
			return false;
		}
#else
		m_fp = fopen(filepath, mode);
		if (m_fp == nullptr)
		{
			return false;
		}
#endif

		ClearBadFlag();

		Seek(0, SeekDir::End);
		m_fileSize = Tell();
		Seek(0, SeekDir::Begin);
		if (IsBad())
		{
			Close();
			return false;
		}
		return true;
	}

	bool File::Open(const char * filepath)
	{
		return OpenFile(filepath, "rb");
	}

	bool File::OpenText(const char * filepath)
	{
		return OpenFile(filepath, "r");
	}

	bool File::Create(const char * filepath)
	{
		return OpenFile(filepath, "wb");
	}

	bool File::CreateText(const char * filepath)
	{
		return OpenFile(filepath, "w");
	}

	void saba::File::Close()
	{
		if (m_fp != nullptr)
		{
			fclose(m_fp);
			m_fp = nullptr;
			m_fileSize = 0;
			m_badFlag = false;
		}
	}

	bool saba::File::IsOpen()
	{
		return m_fp != nullptr;
	}

	File::Offset File::GetSize() const
	{
		return m_fileSize;
	}

	bool File::IsBad() const
	{
		return m_badFlag;
	}

	void File::ClearBadFlag()
	{
		m_badFlag = false;
	}

	FILE * saba::File::GetFilePointer() const
	{
		return m_fp;
	}

	bool saba::File::ReadAll(std::vector<char>* buffer)
	{
		if (buffer == nullptr)
		{
			return false;
		}

		buffer->resize(m_fileSize);
		Seek(0, SeekDir::Begin);
		if (!Read(&(*buffer)[0], m_fileSize))
		{
			return false;
		}

		return true;
	}

	bool saba::File::Seek(Offset offset, SeekDir origin)
	{
		if (m_fp == nullptr)
		{
			return false;
		}
		int cOrigin = 0;
		switch (origin)
		{
		case SeekDir::Begin:
			cOrigin = SEEK_SET;
			break;
		case SeekDir::Current:
			cOrigin = SEEK_CUR;
			break;
		case SeekDir::End:
			cOrigin = SEEK_END;
			break;
		default:
			return false;
		}
#if _WIN32
		if (_fseeki64(m_fp, offset, cOrigin) != 0)
		{
			m_badFlag = true;
			return false;
		}
#else // _WIN32
		if (fseek(m_fp, offset, cOrigin) != 0)
		{
			m_badFlag = true;
			return false;
		}
#endif // _WIN32
		return true;
	}

	File::Offset File::Tell()
	{
		if (m_fp == nullptr)
		{
			return -1;
		}
#if _WIN32
		return (Offset)_ftelli64(m_fp);
#else // _WIN32
		return (Offset)ftell(m_fp);
#endif // _WIN32
	}

	TextFileReader::TextFileReader(const char * filepath)
	{
		Open(filepath);
	}

	TextFileReader::TextFileReader(const std::string & filepath)
	{
		Open(filepath);
	}

	bool TextFileReader::Open(const char * filepath)
	{
#if _WIN32
		std::wstring wFilepath;
		if (!TryToWString(filepath, wFilepath))
		{
			return false;
		}
		m_ifs.open(wFilepath);
#else
		m_ifs.open(filepath, std::ios::binary);
#endif
		return m_ifs.is_open();
	}

	bool TextFileReader::Open(const std::string & filepath)
	{
		return Open(filepath.c_str());
	}

	void TextFileReader::Close()
	{
		m_ifs.close();
	}

	bool TextFileReader::IsOpen()
	{
		return m_ifs.is_open();
	}

	std::string TextFileReader::ReadLine()
	{
		if (!IsOpen() || IsEof())
		{
			return "";
		}
		std::istreambuf_iterator<char> it(m_ifs);
		std::istreambuf_iterator<char> end;
		std::string line;
		auto outputIt = std::back_inserter(line);
		while (it != end && (*it) != '\r' && (*it) != '\n')
		{
			(*outputIt) = (*it);
			++outputIt;
			++it;
		}
		if (it != end)
		{
			auto ch = *it;
			++it;
			if (it != end && ch == '\r' && (*it) == '\n')
			{
				++it;
			}
		}

		return line;
	}

	void TextFileReader::ReadAllLines(std::vector<std::string>& lines)
	{
		lines.clear();
		if (!IsOpen() || IsEof())
		{
			return;
		}
		while (!IsEof())
		{
			lines.emplace_back(ReadLine());
		}
	}

	std::string TextFileReader::ReadAll()
	{
		std::istreambuf_iterator<char> begin(m_ifs);
		std::istreambuf_iterator<char> end;
		return std::string(begin, end);
	}

	bool TextFileReader::IsEof()
	{
		if (!m_ifs.is_open())
		{
			return m_ifs.eof();
		}

		if (m_ifs.eof())
		{
			return true;
		}
		int ch = m_ifs.peek();
		if (ch == std::ifstream::traits_type::eof())
		{
			return true;
		}

		return false;
	}

	bool OpenFromUtf8Path(const std::string & filepath, std::ifstream & ifs, std::ios_base::openmode mode)
	{
#if _WIN32
		std::wstring wFilepath;
		if (!TryToWString(filepath, wFilepath))
		{
			return false;
		}
		ifs.open(wFilepath, mode);
#else
		ifs.open(filepath, mode);
#endif
		return ifs.is_open();
	}
}

<commit_msg>fix vs2015 build error<commit_after>//
// Copyright(c) 2016-2017 benikabocha.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//

#include "File.h"
#include "UnicodeUtil.h"

#include <streambuf>
#include <iterator>

namespace saba
{
	saba::File::File()
		: m_fp(nullptr)
		, m_fileSize(0)
		, m_badFlag(false)
	{
	}

	File::~File()
	{
		Close();
	}

	bool File::OpenFile(const char * filepath, const char * mode)
	{
		if (m_fp != nullptr)
		{
			Close();
		}
#if _WIN32
		std::wstring wFilepath;
		if (!TryToWString(filepath, wFilepath))
		{
			return false;
		}
		std::wstring wMode = ToWString(mode);
		auto err = _wfopen_s(&m_fp, wFilepath.c_str(), wMode.c_str());
		if (err != 0)
		{
			return false;
		}
#else
		m_fp = fopen(filepath, mode);
		if (m_fp == nullptr)
		{
			return false;
		}
#endif

		ClearBadFlag();

		Seek(0, SeekDir::End);
		m_fileSize = Tell();
		Seek(0, SeekDir::Begin);
		if (IsBad())
		{
			Close();
			return false;
		}
		return true;
	}

	bool File::Open(const char * filepath)
	{
		return OpenFile(filepath, "rb");
	}

	bool File::OpenText(const char * filepath)
	{
		return OpenFile(filepath, "r");
	}

	bool File::Create(const char * filepath)
	{
		return OpenFile(filepath, "wb");
	}

	bool File::CreateText(const char * filepath)
	{
		return OpenFile(filepath, "w");
	}

	void saba::File::Close()
	{
		if (m_fp != nullptr)
		{
			fclose(m_fp);
			m_fp = nullptr;
			m_fileSize = 0;
			m_badFlag = false;
		}
	}

	bool saba::File::IsOpen()
	{
		return m_fp != nullptr;
	}

	File::Offset File::GetSize() const
	{
		return m_fileSize;
	}

	bool File::IsBad() const
	{
		return m_badFlag;
	}

	void File::ClearBadFlag()
	{
		m_badFlag = false;
	}

	FILE * saba::File::GetFilePointer() const
	{
		return m_fp;
	}

	bool saba::File::ReadAll(std::vector<char>* buffer)
	{
		if (buffer == nullptr)
		{
			return false;
		}

		buffer->resize(m_fileSize);
		Seek(0, SeekDir::Begin);
		if (!Read(&(*buffer)[0], m_fileSize))
		{
			return false;
		}

		return true;
	}

	bool saba::File::Seek(Offset offset, SeekDir origin)
	{
		if (m_fp == nullptr)
		{
			return false;
		}
		int cOrigin = 0;
		switch (origin)
		{
		case SeekDir::Begin:
			cOrigin = SEEK_SET;
			break;
		case SeekDir::Current:
			cOrigin = SEEK_CUR;
			break;
		case SeekDir::End:
			cOrigin = SEEK_END;
			break;
		default:
			return false;
		}
#if _WIN32
		if (_fseeki64(m_fp, offset, cOrigin) != 0)
		{
			m_badFlag = true;
			return false;
		}
#else // _WIN32
		if (fseek(m_fp, offset, cOrigin) != 0)
		{
			m_badFlag = true;
			return false;
		}
#endif // _WIN32
		return true;
	}

	File::Offset File::Tell()
	{
		if (m_fp == nullptr)
		{
			return -1;
		}
#if _WIN32
		return (Offset)_ftelli64(m_fp);
#else // _WIN32
		return (Offset)ftell(m_fp);
#endif // _WIN32
	}

	TextFileReader::TextFileReader(const char * filepath)
	{
		Open(filepath);
	}

	TextFileReader::TextFileReader(const std::string & filepath)
	{
		Open(filepath);
	}

	bool TextFileReader::Open(const char * filepath)
	{
#if _WIN32
		std::wstring wFilepath;
		if (!TryToWString(filepath, wFilepath))
		{
			return false;
		}
		m_ifs.open(wFilepath);
#else
		m_ifs.open(filepath, std::ios::binary);
#endif
		return m_ifs.is_open();
	}

	bool TextFileReader::Open(const std::string & filepath)
	{
		return Open(filepath.c_str());
	}

	void TextFileReader::Close()
	{
		m_ifs.close();
	}

	bool TextFileReader::IsOpen()
	{
		return m_ifs.is_open();
	}

	std::string TextFileReader::ReadLine()
	{
		if (!IsOpen() || IsEof())
		{
			return "";
		}
		std::istreambuf_iterator<char> it(m_ifs);
		std::istreambuf_iterator<char> end;
		std::string line;
		auto outputIt = std::back_inserter(line);
		while (it != end && (*it) != '\r' && (*it) != '\n')
		{
			(*outputIt) = (*it);
			++outputIt;
			++it;
		}
		if (it != end)
		{
			auto ch = *it;
			++it;
			if (it != end && ch == '\r' && (*it) == '\n')
			{
				++it;
			}
		}

		return line;
	}

	void TextFileReader::ReadAllLines(std::vector<std::string>& lines)
	{
		lines.clear();
		if (!IsOpen() || IsEof())
		{
			return;
		}
		while (!IsEof())
		{
			lines.emplace_back(ReadLine());
		}
	}

	std::string TextFileReader::ReadAll()
	{
		std::istreambuf_iterator<char> begin(m_ifs);
		std::istreambuf_iterator<char> end;
		return std::string(begin, end);
	}

	bool TextFileReader::IsEof()
	{
		if (!m_ifs.is_open())
		{
			return m_ifs.eof();
		}

		if (m_ifs.eof())
		{
			return true;
		}
		int ch = m_ifs.peek();
		if (ch == std::ifstream::traits_type::eof())
		{
			return true;
		}

		return false;
	}

	bool OpenFromUtf8Path(const std::string & filepath, std::ifstream & ifs, std::ios_base::openmode mode)
	{
#if _WIN32
		std::wstring wFilepath;
		if (!TryToWString(filepath, wFilepath))
		{
			return false;
		}
		ifs.open(wFilepath, mode);
#else
		ifs.open(filepath, mode);
#endif
		return ifs.is_open();
	}
}

<|endoftext|>


<commit_before>#include <string>
#include <sampgdk/core.h>
#include <sampgdk/a_samp.h>

#include <mono/jit/jit.h>
#include <mono/metadata/assembly.h>
#include <mono/metadata/mono-debug.h>
#include <mono/metadata/debug-helpers.h>

#include "SampSharp.h"
#include "ConfigReader.h"
#include "StringUtil.h"
#include "MonoUtil.h"
#include "PathUtil.h"
#include "Benchmark.h"
#include "amxplugin.cpp"

using sampgdk::logprintf;

extern void *pAMXFunctions;

PLUGIN_EXPORT unsigned int PLUGIN_CALL
Supports() {
	return sampgdk::Supports() | SUPPORTS_PROCESS_TICK;
}

PLUGIN_EXPORT bool PLUGIN_CALL
Load(void **ppData) {
	pAMXFunctions = ppData[PLUGIN_DATA_AMX_EXPORTS];

	if (!sampgdk::Load(ppData)) {
		return false;
	}

	//read config
	ConfigReader server_cfg("server.cfg");
    std::string gamemode = "gamemode/Default.GameMode.dll Default.GameMode:GameMode";
    std::string path, name_space, klass, symbols;

    server_cfg.GetOptionAsString("gamemode", gamemode);
	server_cfg.GetOptionAsString("symbols", symbols);

    std::stringstream gamemode_stream(gamemode);
	std::getline(gamemode_stream, path, ' ');
    std::getline(gamemode_stream, name_space, ':');
    std::getline(gamemode_stream, klass, '\n');

    StringUtil::TrimString(path);
    StringUtil::TrimString(name_space);
    StringUtil::TrimString(klass);

    //init mono
    #ifdef _WIN32
	mono_set_dirs(PathUtil::GetLibDirectory().c_str(),
        PathUtil::GetConfigDirectory().c_str());
	#endif

	mono_debug_init(MONO_DEBUG_FORMAT_MONO);
	MonoDomain *root = mono_jit_init(PathUtil::GetPathInBin(path).c_str());

    //generate symbol files
    #ifdef _WIN32
    if(symbols.length() > 0) {
	    logprintf("[SampSharp] Generating symbol files");

        std::stringstream symbols_stream(symbols);
	    std::string file;
	    while (std::getline(symbols_stream, file, ' ')) {
            if(file.length() > 0) {
                logprintf("[SampSharp] Processing \"%s\"...", file.c_str());
                MonoUtil::GenerateSymbols(file.c_str());
            }
	    }
        sampgdk::logprintf("[SampSharp] Done!\n");
    }
	#endif

    //load gamemode
	logprintf("[SampSharp] Loading gamemode: %s::%s from \"%s\".",
		(char *)name_space.c_str(),
		(char *)klass.c_str(),
		(char *)path.c_str());

    MonoImage *image = mono_assembly_get_image(
        mono_assembly_open(PathUtil::GetPathInBin(path).c_str(), NULL));

	auto class_from_name = mono_class_from_name(image, name_space.c_str(), klass.c_str());

	if (class_from_name == NULL)
	{
		logprintf("[SampShart] %s::%s is not a valid Namespace:Class combination inside \"%s\".",
			(char *)name_space.c_str(),
			(char *)klass.c_str(),
			(char *)path.c_str());

		return true;
	}

	SampSharp::Load(root, image, class_from_name);

	logprintf("[SampSharp] SampSharp is ready!\n");
	return true;
}

PLUGIN_EXPORT void PLUGIN_CALL
Unload() {
	SampSharp::Unload();
	sampgdk::Unload();
}

PLUGIN_EXPORT void PLUGIN_CALL
ProcessTick() {
    SampSharp::ProcessTick();
	sampgdk::ProcessTick();
}

PLUGIN_EXPORT bool PLUGIN_CALL
OnPublicCall(AMX *amx, const char *name, cell *params, cell *retval) {
    #ifdef DO_BENCHMARK
    if(!strcmp(name, "OnGameModeInit")) {
        Benchmark();
    }
    #endif
	return SampSharp::ProcessPublicCall(amx, name, params, retval);
}
<commit_msg>Improved code to avoid duplicate calls to c_str for namespace/class/path strings<commit_after>#include <string>
#include <sampgdk/core.h>
#include <sampgdk/a_samp.h>

#include <mono/jit/jit.h>
#include <mono/metadata/assembly.h>
#include <mono/metadata/mono-debug.h>
#include <mono/metadata/debug-helpers.h>

#include "SampSharp.h"
#include "ConfigReader.h"
#include "StringUtil.h"
#include "MonoUtil.h"
#include "PathUtil.h"
#include "Benchmark.h"
#include "amxplugin.cpp"

using sampgdk::logprintf;

extern void *pAMXFunctions;

PLUGIN_EXPORT unsigned int PLUGIN_CALL
Supports() {
	return sampgdk::Supports() | SUPPORTS_PROCESS_TICK;
}

PLUGIN_EXPORT bool PLUGIN_CALL
Load(void **ppData) {
	pAMXFunctions = ppData[PLUGIN_DATA_AMX_EXPORTS];

	if (!sampgdk::Load(ppData)) {
		return false;
	}

	//read config
	ConfigReader server_cfg("server.cfg");
    std::string gamemode = "gamemode/Default.GameMode.dll Default.GameMode:GameMode";
    std::string path, name_space, klass, symbols;

    server_cfg.GetOptionAsString("gamemode", gamemode);
	server_cfg.GetOptionAsString("symbols", symbols);

    std::stringstream gamemode_stream(gamemode);
	std::getline(gamemode_stream, path, ' ');
    std::getline(gamemode_stream, name_space, ':');
    std::getline(gamemode_stream, klass, '\n');

    StringUtil::TrimString(path);
    StringUtil::TrimString(name_space);
    StringUtil::TrimString(klass);

    //init mono
    #ifdef _WIN32
	mono_set_dirs(PathUtil::GetLibDirectory().c_str(),
        PathUtil::GetConfigDirectory().c_str());
	#endif

	mono_debug_init(MONO_DEBUG_FORMAT_MONO);
	MonoDomain *root = mono_jit_init(PathUtil::GetPathInBin(path).c_str());

    //generate symbol files
    #ifdef _WIN32
    if(symbols.length() > 0) {
	    logprintf("[SampSharp] Generating symbol files");

        std::stringstream symbols_stream(symbols);
	    std::string file;
	    while (std::getline(symbols_stream, file, ' ')) {
            if(file.length() > 0) {
                logprintf("[SampSharp] Processing \"%s\"...", file.c_str());
                MonoUtil::GenerateSymbols(file.c_str());
            }
	    }
        sampgdk::logprintf("[SampSharp] Done!\n");
    }
	#endif

    //load gamemode
	auto namespace_ctr = (char *)name_space.c_str();
	auto klass_ctr = (char *)klass.c_str();
	auto path_ctr = (char *)path.c_str();

	logprintf("[SampSharp] Loading gamemode: %s::%s from \"%s\".",
		namespace_ctr,
		klass_ctr,
		path_ctr);

    MonoImage *image = mono_assembly_get_image(
        mono_assembly_open(PathUtil::GetPathInBin(path).c_str(), NULL));

	auto class_from_name = mono_class_from_name(image, namespace_ctr, klass_ctr);

	if (class_from_name == NULL)
	{
		logprintf("[SampShart] %s::%s is not a valid Namespace:Class combination inside \"%s\".",
			namespace_ctr,
			klass_ctr,
			path_ctr);

		return true;
	}

	SampSharp::Load(root, image, class_from_name);

	logprintf("[SampSharp] SampSharp is ready!\n");
	return true;
}

PLUGIN_EXPORT void PLUGIN_CALL
Unload() {
	SampSharp::Unload();
	sampgdk::Unload();
}

PLUGIN_EXPORT void PLUGIN_CALL
ProcessTick() {
    SampSharp::ProcessTick();
	sampgdk::ProcessTick();
}

PLUGIN_EXPORT bool PLUGIN_CALL
OnPublicCall(AMX *amx, const char *name, cell *params, cell *retval) {
    #ifdef DO_BENCHMARK
    if(!strcmp(name, "OnGameModeInit")) {
        Benchmark();
    }
    #endif
	return SampSharp::ProcessPublicCall(amx, name, params, retval);
}
<|endoftext|>


<commit_before>//===-- llvm/CallingConvLower.cpp - Calling Conventions -------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the CCState class, used for lowering and implementing
// calling conventions.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;

CCState::CCState(unsigned CC, bool isVarArg, const TargetMachine &tm,
                 SmallVector<CCValAssign, 16> &locs)
  : CallingConv(CC), IsVarArg(isVarArg), TM(tm),
    TRI(*TM.getRegisterInfo()), Locs(locs) {
  // No stack is used.
  StackOffset = 0;

  UsedRegs.resize(TRI.getNumRegs());
}

// HandleByVal - Allocate a stack slot large enough to pass an argument by
// value. The size and alignment information of the argument is encoded in its
// parameter attribute.
void CCState::HandleByVal(unsigned ValNo, MVT ValVT,
                          MVT LocVT, CCValAssign::LocInfo LocInfo,
                          int MinSize, int MinAlign,
                          ISD::ArgFlagsTy ArgFlags) {
  unsigned Align = ArgFlags.getByValAlign();
  unsigned Size  = ArgFlags.getByValSize();
  if (MinSize > (int)Size)
    Size = MinSize;
  if (MinAlign > (int)Align)
    Align = MinAlign;
  unsigned Offset = AllocateStack(Size, Align);

  addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
}

/// MarkAllocated - Mark a register and all of its aliases as allocated.
void CCState::MarkAllocated(unsigned Reg) {
  UsedRegs[Reg/32] |= 1 << (Reg&31);

  if (const unsigned *RegAliases = TRI.getAliasSet(Reg))
    for (; (Reg = *RegAliases); ++RegAliases)
      UsedRegs[Reg/32] |= 1 << (Reg&31);
}

/// AnalyzeFormalArguments - Analyze an ISD::FORMAL_ARGUMENTS node,
/// incorporating info about the formals into this state.
void CCState::AnalyzeFormalArguments(SDNode *TheArgs, CCAssignFn Fn) {
  unsigned NumArgs = TheArgs->getNumValues()-1;

  for (unsigned i = 0; i != NumArgs; ++i) {
    MVT ArgVT = TheArgs->getValueType(i);
    ISD::ArgFlagsTy ArgFlags =
      cast<ARG_FLAGSSDNode>(TheArgs->getOperand(3+i))->getArgFlags();
    if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this)) {
      cerr << "Formal argument #" << i << " has unhandled type "
           << ArgVT.getMVTString() << "\n";
      abort();
    }
  }
}

/// AnalyzeReturn - Analyze the returned values of an ISD::RET node,
/// incorporating info about the result values into this state.
void CCState::AnalyzeReturn(SDNode *TheRet, CCAssignFn Fn) {
  // Determine which register each value should be copied into.
  for (unsigned i = 0, e = TheRet->getNumOperands() / 2; i != e; ++i) {
    MVT VT = TheRet->getOperand(i*2+1).getValueType();
    ISD::ArgFlagsTy ArgFlags =
      cast<ARG_FLAGSSDNode>(TheRet->getOperand(i*2+2))->getArgFlags();
    if (Fn(i, VT, VT, CCValAssign::Full, ArgFlags, *this)){
      cerr << "Return operand #" << i << " has unhandled type "
           << VT.getMVTString() << "\n";
      abort();
    }
  }
}

/// AnalyzeCallOperands - Analyze an ISD::CALL node, incorporating info
/// about the passed values into this state.
void CCState::AnalyzeCallOperands(SDNode *TheCall, CCAssignFn Fn) {
  unsigned NumOps = (TheCall->getNumOperands() - 5) / 2;
  for (unsigned i = 0; i != NumOps; ++i) {
    MVT ArgVT = TheCall->getOperand(5+2*i).getValueType();
    ISD::ArgFlagsTy ArgFlags =
      cast<ARG_FLAGSSDNode>(TheCall->getOperand(5+2*i+1))->getArgFlags();
    if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this)) {
      cerr << "Call operand #" << i << " has unhandled type "
           << ArgVT.getMVTString() << "\n";
      abort();
    }
  }
}

/// AnalyzeCallResult - Analyze the return values of an ISD::CALL node,
/// incorporating info about the passed values into this state.
void CCState::AnalyzeCallResult(SDNode *TheCall, CCAssignFn Fn) {
  for (unsigned i = 0, e = TheCall->getNumValues() - 1; i != e; ++i) {
    MVT VT = TheCall->getValueType(i);
    if (Fn(i, VT, VT, CCValAssign::Full, ISD::ArgFlagsTy(), *this)) {
      cerr << "Call result #" << i << " has unhandled type "
           << VT.getMVTString() << "\n";
      abort();
    }
  }
}
<commit_msg>Correct the allocation size for CCState's UsedRegs member, which only needs one bit for each register. UsedRegs is a SmallVector sized at 16, so this eliminates a heap allocation/free for every call and return processed by Legalize on most targets.<commit_after>//===-- llvm/CallingConvLower.cpp - Calling Conventions -------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the CCState class, used for lowering and implementing
// calling conventions.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;

CCState::CCState(unsigned CC, bool isVarArg, const TargetMachine &tm,
                 SmallVector<CCValAssign, 16> &locs)
  : CallingConv(CC), IsVarArg(isVarArg), TM(tm),
    TRI(*TM.getRegisterInfo()), Locs(locs) {
  // No stack is used.
  StackOffset = 0;

  UsedRegs.resize((TRI.getNumRegs()+31)/32);
}

// HandleByVal - Allocate a stack slot large enough to pass an argument by
// value. The size and alignment information of the argument is encoded in its
// parameter attribute.
void CCState::HandleByVal(unsigned ValNo, MVT ValVT,
                          MVT LocVT, CCValAssign::LocInfo LocInfo,
                          int MinSize, int MinAlign,
                          ISD::ArgFlagsTy ArgFlags) {
  unsigned Align = ArgFlags.getByValAlign();
  unsigned Size  = ArgFlags.getByValSize();
  if (MinSize > (int)Size)
    Size = MinSize;
  if (MinAlign > (int)Align)
    Align = MinAlign;
  unsigned Offset = AllocateStack(Size, Align);

  addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
}

/// MarkAllocated - Mark a register and all of its aliases as allocated.
void CCState::MarkAllocated(unsigned Reg) {
  UsedRegs[Reg/32] |= 1 << (Reg&31);

  if (const unsigned *RegAliases = TRI.getAliasSet(Reg))
    for (; (Reg = *RegAliases); ++RegAliases)
      UsedRegs[Reg/32] |= 1 << (Reg&31);
}

/// AnalyzeFormalArguments - Analyze an ISD::FORMAL_ARGUMENTS node,
/// incorporating info about the formals into this state.
void CCState::AnalyzeFormalArguments(SDNode *TheArgs, CCAssignFn Fn) {
  unsigned NumArgs = TheArgs->getNumValues()-1;

  for (unsigned i = 0; i != NumArgs; ++i) {
    MVT ArgVT = TheArgs->getValueType(i);
    ISD::ArgFlagsTy ArgFlags =
      cast<ARG_FLAGSSDNode>(TheArgs->getOperand(3+i))->getArgFlags();
    if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this)) {
      cerr << "Formal argument #" << i << " has unhandled type "
           << ArgVT.getMVTString() << "\n";
      abort();
    }
  }
}

/// AnalyzeReturn - Analyze the returned values of an ISD::RET node,
/// incorporating info about the result values into this state.
void CCState::AnalyzeReturn(SDNode *TheRet, CCAssignFn Fn) {
  // Determine which register each value should be copied into.
  for (unsigned i = 0, e = TheRet->getNumOperands() / 2; i != e; ++i) {
    MVT VT = TheRet->getOperand(i*2+1).getValueType();
    ISD::ArgFlagsTy ArgFlags =
      cast<ARG_FLAGSSDNode>(TheRet->getOperand(i*2+2))->getArgFlags();
    if (Fn(i, VT, VT, CCValAssign::Full, ArgFlags, *this)){
      cerr << "Return operand #" << i << " has unhandled type "
           << VT.getMVTString() << "\n";
      abort();
    }
  }
}

/// AnalyzeCallOperands - Analyze an ISD::CALL node, incorporating info
/// about the passed values into this state.
void CCState::AnalyzeCallOperands(SDNode *TheCall, CCAssignFn Fn) {
  unsigned NumOps = (TheCall->getNumOperands() - 5) / 2;
  for (unsigned i = 0; i != NumOps; ++i) {
    MVT ArgVT = TheCall->getOperand(5+2*i).getValueType();
    ISD::ArgFlagsTy ArgFlags =
      cast<ARG_FLAGSSDNode>(TheCall->getOperand(5+2*i+1))->getArgFlags();
    if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this)) {
      cerr << "Call operand #" << i << " has unhandled type "
           << ArgVT.getMVTString() << "\n";
      abort();
    }
  }
}

/// AnalyzeCallResult - Analyze the return values of an ISD::CALL node,
/// incorporating info about the passed values into this state.
void CCState::AnalyzeCallResult(SDNode *TheCall, CCAssignFn Fn) {
  for (unsigned i = 0, e = TheCall->getNumValues() - 1; i != e; ++i) {
    MVT VT = TheCall->getValueType(i);
    if (Fn(i, VT, VT, CCValAssign::Full, ISD::ArgFlagsTy(), *this)) {
      cerr << "Call result #" << i << " has unhandled type "
           << VT.getMVTString() << "\n";
      abort();
    }
  }
}
<|endoftext|>


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

#include <mapnik/geometry/envelope.hpp>
#include <mapnik/geometry/envelope_impl.hpp>
#include <mapnik/text/symbolizer_helpers.hpp>

namespace mapnik { namespace geometry {

template MAPNIK_DECL mapnik::box2d<double> envelope(geometry<double> const& geom);
// single
template MAPNIK_DECL mapnik::box2d<double> envelope(point<double> const& geom);
template MAPNIK_DECL mapnik::box2d<double> envelope(line_string<double> const& geom);
template MAPNIK_DECL mapnik::box2d<double> envelope(polygon<double> const& geom);
template MAPNIK_DECL mapnik::box2d<double> envelope(linear_ring<double> const& geom);
// multi
template MAPNIK_DECL mapnik::box2d<double> envelope(multi_point<double> const& geom);
template MAPNIK_DECL mapnik::box2d<double> envelope(multi_line_string<double> const& geom);
template MAPNIK_DECL mapnik::box2d<double> envelope(multi_polygon<double> const& geom);
// collection
template MAPNIK_DECL mapnik::box2d<double> envelope(geometry_collection<double> const& geom);

} // end ns geometry
} // end ns mapnik
<commit_msg>remove unused include directive<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#include <mapnik/geometry/envelope.hpp>
#include <mapnik/geometry/envelope_impl.hpp>

namespace mapnik { namespace geometry {

template MAPNIK_DECL mapnik::box2d<double> envelope(geometry<double> const& geom);
// single
template MAPNIK_DECL mapnik::box2d<double> envelope(point<double> const& geom);
template MAPNIK_DECL mapnik::box2d<double> envelope(line_string<double> const& geom);
template MAPNIK_DECL mapnik::box2d<double> envelope(polygon<double> const& geom);
template MAPNIK_DECL mapnik::box2d<double> envelope(linear_ring<double> const& geom);
// multi
template MAPNIK_DECL mapnik::box2d<double> envelope(multi_point<double> const& geom);
template MAPNIK_DECL mapnik::box2d<double> envelope(multi_line_string<double> const& geom);
template MAPNIK_DECL mapnik::box2d<double> envelope(multi_polygon<double> const& geom);
// collection
template MAPNIK_DECL mapnik::box2d<double> envelope(geometry_collection<double> const& geom);

} // end ns geometry
} // end ns mapnik
<|endoftext|>


<commit_before>//===-- AMDGPUTargetTransformInfo.cpp - AMDGPU specific TTI pass ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// \file
// This file implements a TargetTransformInfo analysis pass specific to the
// AMDGPU target machine. It uses the target's detailed information to provide
// more precise answers to certain TTI queries, while letting the target
// independent and default TTI implementations handle the rest.
//
//===----------------------------------------------------------------------===//

#include "AMDGPU.h"
#include "AMDGPUTargetMachine.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Support/Debug.h"
#include "llvm/Target/CostTable.h"
#include "llvm/Target/TargetLowering.h"
using namespace llvm;

#define DEBUG_TYPE "AMDGPUtti"

// Declare the pass initialization routine locally as target-specific passes
// don't have a target-wide initialization entry point, and so we rely on the
// pass constructor initialization.
namespace llvm {
void initializeAMDGPUTTIPass(PassRegistry &);
}

namespace {

class AMDGPUTTI final : public ImmutablePass, public TargetTransformInfo {
  const AMDGPUTargetMachine *TM;
  const AMDGPUSubtarget *ST;
  const AMDGPUTargetLowering *TLI;

  /// Estimate the overhead of scalarizing an instruction. Insert and Extract
  /// are set if the result needs to be inserted and/or extracted from vectors.
  unsigned getScalarizationOverhead(Type *Ty, bool Insert, bool Extract) const;

public:
  AMDGPUTTI() : ImmutablePass(ID), TM(nullptr), ST(nullptr), TLI(nullptr) {
    llvm_unreachable("This pass cannot be directly constructed");
  }

  AMDGPUTTI(const AMDGPUTargetMachine *TM)
      : ImmutablePass(ID), TM(TM), ST(TM->getSubtargetImpl()),
        TLI(TM->getTargetLowering()) {
    initializeAMDGPUTTIPass(*PassRegistry::getPassRegistry());
  }

  void initializePass() override { pushTTIStack(this); }

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    TargetTransformInfo::getAnalysisUsage(AU);
  }

  /// Pass identification.
  static char ID;

  /// Provide necessary pointer adjustments for the two base classes.
  void *getAdjustedAnalysisPointer(const void *ID) override {
    if (ID == &TargetTransformInfo::ID)
      return (TargetTransformInfo *)this;
    return this;
  }

  bool hasBranchDivergence() const override;

  void getUnrollingPreferences(Loop *L,
                               UnrollingPreferences &UP) const override;

  PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) const override;

  unsigned getNumberOfRegisters(bool Vector) const override;
  unsigned getRegisterBitWidth(bool Vector) const override;
  unsigned getMaximumUnrollFactor() const override;

  /// @}
};

} // end anonymous namespace

INITIALIZE_AG_PASS(AMDGPUTTI, TargetTransformInfo, "AMDGPUtti",
                   "AMDGPU Target Transform Info", true, true, false)
char AMDGPUTTI::ID = 0;

ImmutablePass *
llvm::createAMDGPUTargetTransformInfoPass(const AMDGPUTargetMachine *TM) {
  return new AMDGPUTTI(TM);
}

bool AMDGPUTTI::hasBranchDivergence() const { return true; }

void AMDGPUTTI::getUnrollingPreferences(Loop *L,
                                        UnrollingPreferences &UP) const {
  for (const BasicBlock *BB : L->getBlocks()) {
    for (const Instruction &I : *BB) {
      const GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(&I);
      if (!GEP || GEP->getAddressSpace() != AMDGPUAS::PRIVATE_ADDRESS)
        continue;

      const Value *Ptr = GEP->getPointerOperand();
      const AllocaInst *Alloca = dyn_cast<AllocaInst>(GetUnderlyingObject(Ptr));
      if (Alloca) {
        // We want to do whatever we can to limit the number of alloca
        // instructions that make it through to the code generator.  allocas
        // require us to use indirect addressing, which is slow and prone to
        // compiler bugs.  If this loop does an address calculation on an
        // alloca ptr, then we want to use a higher than normal loop unroll
        // threshold. This will give SROA a better chance to eliminate these
        // allocas.
        //
        // Don't use the maximum allowed value here as it will make some
        // programs way too big.
        UP.Threshold = 500;
      }
    }
  }
}

AMDGPUTTI::PopcntSupportKind
AMDGPUTTI::getPopcntSupport(unsigned TyWidth) const {
  assert(isPowerOf2_32(TyWidth) && "Ty width must be power of 2");
  return ST->hasBCNT(TyWidth) ? PSK_FastHardware : PSK_Software;
}

unsigned AMDGPUTTI::getNumberOfRegisters(bool Vec) const {
  if (Vec)
    return 0;

  // Number of VGPRs on SI.
  if (ST->getGeneration() >= AMDGPUSubtarget::SOUTHERN_ISLANDS)
    return 256;

  return 4 * 128; // XXX - 4 channels. Should these count as vector instead?
}

unsigned AMDGPUTTI::getRegisterBitWidth(bool) const {
  return 32;
}

unsigned AMDGPUTTI::getMaximumUnrollFactor() const {
  // Semi-arbitrary large amount.
  return 64;
}
<commit_msg>R600/SI: Allow partial unrolling and increase thresholds.<commit_after>//===-- AMDGPUTargetTransformInfo.cpp - AMDGPU specific TTI pass ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// \file
// This file implements a TargetTransformInfo analysis pass specific to the
// AMDGPU target machine. It uses the target's detailed information to provide
// more precise answers to certain TTI queries, while letting the target
// independent and default TTI implementations handle the rest.
//
//===----------------------------------------------------------------------===//

#include "AMDGPU.h"
#include "AMDGPUTargetMachine.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Support/Debug.h"
#include "llvm/Target/CostTable.h"
#include "llvm/Target/TargetLowering.h"
using namespace llvm;

#define DEBUG_TYPE "AMDGPUtti"

// Declare the pass initialization routine locally as target-specific passes
// don't have a target-wide initialization entry point, and so we rely on the
// pass constructor initialization.
namespace llvm {
void initializeAMDGPUTTIPass(PassRegistry &);
}

namespace {

class AMDGPUTTI final : public ImmutablePass, public TargetTransformInfo {
  const AMDGPUTargetMachine *TM;
  const AMDGPUSubtarget *ST;
  const AMDGPUTargetLowering *TLI;

  /// Estimate the overhead of scalarizing an instruction. Insert and Extract
  /// are set if the result needs to be inserted and/or extracted from vectors.
  unsigned getScalarizationOverhead(Type *Ty, bool Insert, bool Extract) const;

public:
  AMDGPUTTI() : ImmutablePass(ID), TM(nullptr), ST(nullptr), TLI(nullptr) {
    llvm_unreachable("This pass cannot be directly constructed");
  }

  AMDGPUTTI(const AMDGPUTargetMachine *TM)
      : ImmutablePass(ID), TM(TM), ST(TM->getSubtargetImpl()),
        TLI(TM->getTargetLowering()) {
    initializeAMDGPUTTIPass(*PassRegistry::getPassRegistry());
  }

  void initializePass() override { pushTTIStack(this); }

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    TargetTransformInfo::getAnalysisUsage(AU);
  }

  /// Pass identification.
  static char ID;

  /// Provide necessary pointer adjustments for the two base classes.
  void *getAdjustedAnalysisPointer(const void *ID) override {
    if (ID == &TargetTransformInfo::ID)
      return (TargetTransformInfo *)this;
    return this;
  }

  bool hasBranchDivergence() const override;

  void getUnrollingPreferences(Loop *L,
                               UnrollingPreferences &UP) const override;

  PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) const override;

  unsigned getNumberOfRegisters(bool Vector) const override;
  unsigned getRegisterBitWidth(bool Vector) const override;
  unsigned getMaximumUnrollFactor() const override;

  /// @}
};

} // end anonymous namespace

INITIALIZE_AG_PASS(AMDGPUTTI, TargetTransformInfo, "AMDGPUtti",
                   "AMDGPU Target Transform Info", true, true, false)
char AMDGPUTTI::ID = 0;

ImmutablePass *
llvm::createAMDGPUTargetTransformInfoPass(const AMDGPUTargetMachine *TM) {
  return new AMDGPUTTI(TM);
}

bool AMDGPUTTI::hasBranchDivergence() const { return true; }

void AMDGPUTTI::getUnrollingPreferences(Loop *L,
                                        UnrollingPreferences &UP) const {
  UP.Threshold = 300; // Twice the default.
  UP.Count = UINT_MAX;
  UP.Partial = true;

  // TODO: Do we want runtime unrolling?

  for (const BasicBlock *BB : L->getBlocks()) {
    for (const Instruction &I : *BB) {
      const GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(&I);
      if (!GEP || GEP->getAddressSpace() != AMDGPUAS::PRIVATE_ADDRESS)
        continue;

      const Value *Ptr = GEP->getPointerOperand();
      const AllocaInst *Alloca = dyn_cast<AllocaInst>(GetUnderlyingObject(Ptr));
      if (Alloca) {
        // We want to do whatever we can to limit the number of alloca
        // instructions that make it through to the code generator.  allocas
        // require us to use indirect addressing, which is slow and prone to
        // compiler bugs.  If this loop does an address calculation on an
        // alloca ptr, then we want to use a higher than normal loop unroll
        // threshold. This will give SROA a better chance to eliminate these
        // allocas.
        //
        // Don't use the maximum allowed value here as it will make some
        // programs way too big.
        UP.Threshold = 800;
      }
    }
  }
}

AMDGPUTTI::PopcntSupportKind
AMDGPUTTI::getPopcntSupport(unsigned TyWidth) const {
  assert(isPowerOf2_32(TyWidth) && "Ty width must be power of 2");
  return ST->hasBCNT(TyWidth) ? PSK_FastHardware : PSK_Software;
}

unsigned AMDGPUTTI::getNumberOfRegisters(bool Vec) const {
  if (Vec)
    return 0;

  // Number of VGPRs on SI.
  if (ST->getGeneration() >= AMDGPUSubtarget::SOUTHERN_ISLANDS)
    return 256;

  return 4 * 128; // XXX - 4 channels. Should these count as vector instead?
}

unsigned AMDGPUTTI::getRegisterBitWidth(bool) const {
  return 32;
}

unsigned AMDGPUTTI::getMaximumUnrollFactor() const {
  // Semi-arbitrary large amount.
  return 64;
}
<|endoftext|>


<commit_before>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You may
 * obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/

#include "condor_common.h"
#include "string_list.h"
#include "read_multiple_logs.h"
#include "check_events.h"

MULTI_LOG_HASH_INSTANCE; // For the multi-log-file code...
CHECK_EVENTS_HASH_INSTANCE; // For the event checking code...

int main(int argc, char **argv)
{
	int		result = 0;

	if ( argc <= 1 || (argc >= 2 && !strcmp("-usage", argv[1])) ) {
		printf("Usage: condor_check_userlogs <log file 1> "
				"[log file 2] ... [log file n]\n");
		exit(0);
	}

		// Set up dprintf.
	Termlog = true;
	dprintf_config("condor_check_userlogs");
	DebugFlags = D_ALWAYS;

	StringList	logFiles;
	for ( int argnum = 1; argnum < argc; ++argnum ) {
		logFiles.append(argv[argnum]);
	}
	logFiles.rewind();

	ReadMultipleUserLogs	ru;
	char *filename;
	while ( (filename = logFiles.next()) ) {
		MyString filestring( filename );
		CondorError errstack;
		if ( !ru.monitorLogFile( filestring, false, errstack ) ) {
			fprintf( stderr, "Error monitoring log file %s: %s\n", filename,
						errstack.getFullText() );
			result = 1;
		}
	}

	bool logsMissing = false;

	CheckEvents		ce;
	int totalSubmitted = 0;
	int netSubmitted = 0;
	bool done = false;
	while( !done ) {

    	ULogEvent* e = NULL;
		MyString errorMsg;

        ULogEventOutcome outcome = ru.readEvent( e );

        switch (outcome) {

        case ULOG_NO_EVENT:
        case ULOG_RD_ERROR:
        case ULOG_UNK_ERROR:

			printf( "Log outcome: %s\n", ULogEventOutcomeNames[outcome] );
			done = true;
			break;

        case ULOG_OK:

			printf( "Log event: %s (%d.%d.%d)",
						ULogEventNumberNames[e->eventNumber],
						e->cluster, e->proc, e->subproc );

			if ( ce.CheckAnEvent(e, errorMsg) != CheckEvents::EVENT_OKAY ) {
				fprintf(stderr, "%s\n", errorMsg.Value());
				result = 1;
			}

			if( e->eventNumber == ULOG_SUBMIT ) {
				SubmitEvent* ee = (SubmitEvent*) e;
				printf( " (\"%s\")", ee->submitEventLogNotes );
				++totalSubmitted;
				++netSubmitted;
				printf( "\n Total submitted: %d; net submitted: %d\n",
						totalSubmitted, netSubmitted );
			}

			if( e->eventNumber == ULOG_JOB_HELD ) {
				JobHeldEvent* ee = (JobHeldEvent*) e;
				printf( " (code=%d subcode=%d)", ee->getReasonCode(),
						ee->getReasonSubCode());
			}

			if( e->eventNumber == ULOG_JOB_TERMINATED ) {
				--netSubmitted;
				printf( "\n Total submitted: %d; net submitted: %d\n",
						totalSubmitted, netSubmitted );
			}

			if( e->eventNumber == ULOG_JOB_ABORTED ) {
				--netSubmitted;
				printf( "\n Total submitted: %d; net submitted: %d\n",
						totalSubmitted, netSubmitted );
			}

			if( e->eventNumber == ULOG_EXECUTABLE_ERROR ) {
				--netSubmitted;
				printf( "\n Total submitted: %d; net submitted: %d\n",
						totalSubmitted, netSubmitted );
			}

			printf( "\n" );
			break;

		default:

			fprintf(stderr, "Unexpected read event outcome!\n");
			result = 1;
			break;
        }
	}

	logFiles.rewind();
	while ( (filename = logFiles.next()) ) {
		MyString filestring( filename );
		CondorError errstack;
		if ( !ru.unmonitorLogFile( filestring, errstack ) ) {
			fprintf( stderr, "Error unmonitoring log file %s: %s\n", filename,
						errstack.getFullText() );
			result = 1;
		}
	}

	MyString errorMsg;
	CheckEvents::check_event_result_t checkAllResult =
				ce.CheckAllJobs(errorMsg);
	if ( checkAllResult != CheckEvents::EVENT_OKAY ) {
		fprintf(stderr, "%s\n", errorMsg.Value());
		fprintf(stderr, "CheckAllJobs() result: %s\n",
					CheckEvents::ResultToString(checkAllResult));
		result = 1;
	}

	if ( result == 0 ) {
		if ( !logsMissing ) {
			printf("Log(s) are okay\n");
		} else {
			printf("Log(s) may be okay\n");
			printf(  "Some logs cannot be read\n");
		}
	} else {
		printf("Log(s) have error(s)\n");
	}
	return result;
}
<commit_msg>Fixed coverity-found bug.<commit_after>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You may
 * obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/

#include "condor_common.h"
#include "string_list.h"
#include "read_multiple_logs.h"
#include "check_events.h"

MULTI_LOG_HASH_INSTANCE; // For the multi-log-file code...
CHECK_EVENTS_HASH_INSTANCE; // For the event checking code...

int main(int argc, char **argv)
{
	int		result = 0;

	if ( argc <= 1 || (argc >= 2 && !strcmp("-usage", argv[1])) ) {
		printf("Usage: condor_check_userlogs <log file 1> "
				"[log file 2] ... [log file n]\n");
		exit(0);
	}

		// Set up dprintf.
	Termlog = true;
	dprintf_config("condor_check_userlogs");
	DebugFlags = D_ALWAYS;

	StringList	logFiles;
	for ( int argnum = 1; argnum < argc; ++argnum ) {
		logFiles.append(argv[argnum]);
	}
	logFiles.rewind();

	ReadMultipleUserLogs	ru;
	char *filename;
	while ( (filename = logFiles.next()) ) {
		MyString filestring( filename );
		CondorError errstack;
		if ( !ru.monitorLogFile( filestring, false, errstack ) ) {
			fprintf( stderr, "Error monitoring log file %s: %s\n", filename,
						errstack.getFullText() );
			result = 1;
		}
	}

	bool logsMissing = false;

	CheckEvents		ce;
	int totalSubmitted = 0;
	int netSubmitted = 0;
	bool done = false;
	while( !done ) {

    	ULogEvent* e = NULL;
		MyString errorMsg;

        ULogEventOutcome outcome = ru.readEvent( e );

        switch (outcome) {

        case ULOG_RD_ERROR:
        case ULOG_UNK_ERROR:
			logsMissing = true;
        case ULOG_NO_EVENT:

			printf( "Log outcome: %s\n", ULogEventOutcomeNames[outcome] );
			done = true;
			break;

        case ULOG_OK:

			printf( "Log event: %s (%d.%d.%d)",
						ULogEventNumberNames[e->eventNumber],
						e->cluster, e->proc, e->subproc );

			if ( ce.CheckAnEvent(e, errorMsg) != CheckEvents::EVENT_OKAY ) {
				fprintf(stderr, "%s\n", errorMsg.Value());
				result = 1;
			}

			if( e->eventNumber == ULOG_SUBMIT ) {
				SubmitEvent* ee = (SubmitEvent*) e;
				printf( " (\"%s\")", ee->submitEventLogNotes );
				++totalSubmitted;
				++netSubmitted;
				printf( "\n Total submitted: %d; net submitted: %d\n",
						totalSubmitted, netSubmitted );
			}

			if( e->eventNumber == ULOG_JOB_HELD ) {
				JobHeldEvent* ee = (JobHeldEvent*) e;
				printf( " (code=%d subcode=%d)", ee->getReasonCode(),
						ee->getReasonSubCode());
			}

			if( e->eventNumber == ULOG_JOB_TERMINATED ) {
				--netSubmitted;
				printf( "\n Total submitted: %d; net submitted: %d\n",
						totalSubmitted, netSubmitted );
			}

			if( e->eventNumber == ULOG_JOB_ABORTED ) {
				--netSubmitted;
				printf( "\n Total submitted: %d; net submitted: %d\n",
						totalSubmitted, netSubmitted );
			}

			if( e->eventNumber == ULOG_EXECUTABLE_ERROR ) {
				--netSubmitted;
				printf( "\n Total submitted: %d; net submitted: %d\n",
						totalSubmitted, netSubmitted );
			}

			printf( "\n" );
			break;

		default:

			fprintf(stderr, "Unexpected read event outcome!\n");
			result = 1;
			break;
        }
	}

	logFiles.rewind();
	while ( (filename = logFiles.next()) ) {
		MyString filestring( filename );
		CondorError errstack;
		if ( !ru.unmonitorLogFile( filestring, errstack ) ) {
			fprintf( stderr, "Error unmonitoring log file %s: %s\n", filename,
						errstack.getFullText() );
			result = 1;
		}
	}

	MyString errorMsg;
	CheckEvents::check_event_result_t checkAllResult =
				ce.CheckAllJobs(errorMsg);
	if ( checkAllResult != CheckEvents::EVENT_OKAY ) {
		fprintf(stderr, "%s\n", errorMsg.Value());
		fprintf(stderr, "CheckAllJobs() result: %s\n",
					CheckEvents::ResultToString(checkAllResult));
		result = 1;
	}

	if ( result == 0 ) {
		if ( !logsMissing ) {
			printf("Log(s) are okay\n");
		} else {
			printf("Log(s) may be okay\n");
			printf(  "Some logs cannot be read\n");
		}
	} else {
		printf("Log(s) have error(s)\n");
	}
	return result;
}
<|endoftext|>


<commit_before>#ifndef ITERTOOLS_SAMPLE_CLASSES_HPP
#define ITERTOOLS_SAMPLE_CLASSES_HPP

#include <iostream>
#include <utility>
#include <cstddef>

namespace itertest {
    class MoveOnly {
        private:
            int i; // not an aggregate
        public:
            MoveOnly(int v)
                : i{v}
            { }

            MoveOnly(const MoveOnly&) = delete;
            MoveOnly& operator=(const MoveOnly&) = delete;

            MoveOnly(MoveOnly&& other) noexcept
                : i{other.i}
            { }

            MoveOnly& operator=(MoveOnly&& other) noexcept {
                this->i = other.i;
                return *this;
            }

            // for std::next_permutation compatibility
            friend bool operator<(const MoveOnly& lhs, const MoveOnly& rhs) {
                return lhs.i < rhs.i;
            }

            friend std::ostream& operator<<(
                    std::ostream& out, const MoveOnly& self) {
                return out << self.i;
            }

    };

    class DerefByValue {
        private:
            static constexpr std::size_t N = 3;
            int array[N] = {0};
        public:
            DerefByValue() = default;

            class Iterator {
                private:
                    int *current;
                public:
                    Iterator() = default;
                    Iterator(int *p)
                        : current{p}
                    { }

                    bool operator!=(const Iterator& other) const {
                        return this->current != other.current;
                    }

                    // for testing, iterator derefences to an int instead of
                    // an int&
                    int operator*() {
                        return *this->current;
                    }

                    Iterator& operator++() {
                        ++this->current;
                        return *this;
                    }
            };

            Iterator begin() {
                return {this->array};
            }

            Iterator end() {
                return {this->array + N};
            }
    };
}
#endif // #ifndef ITERTOOLS_SAMPLE_CLASSES_HPP
<commit_msg>adds DerefByValueFancy with random access iterator<commit_after>#ifndef ITERTOOLS_SAMPLE_CLASSES_HPP
#define ITERTOOLS_SAMPLE_CLASSES_HPP

#include <iostream>
#include <utility>
#include <cstddef>

namespace itertest {
    class MoveOnly {
        private:
            int i; // not an aggregate
        public:
            MoveOnly(int v)
                : i{v}
            { }

            MoveOnly(const MoveOnly&) = delete;
            MoveOnly& operator=(const MoveOnly&) = delete;

            MoveOnly(MoveOnly&& other) noexcept
                : i{other.i}
            { }

            MoveOnly& operator=(MoveOnly&& other) noexcept {
                this->i = other.i;
                return *this;
            }

            // for std::next_permutation compatibility
            friend bool operator<(const MoveOnly& lhs, const MoveOnly& rhs) {
                return lhs.i < rhs.i;
            }

            friend std::ostream& operator<<(
                    std::ostream& out, const MoveOnly& self) {
                return out << self.i;
            }

    };

    class DerefByValue {
        private:
            static constexpr std::size_t N = 3;
            int array[N] = {0, 1, 2};
        public:
            DerefByValue() = default;

            class Iterator {
                private:
                    int *current;
                public:
                    Iterator() = default;
                    Iterator(int *p)
                        : current{p}
                    { }

                    bool operator!=(const Iterator& other) const {
                        return this->current != other.current;
                    }

                    // for testing, iterator derefences to an int instead of
                    // an int&
                    int operator*() {
                        return *this->current;
                    }

                    Iterator& operator++() {
                        ++this->current;
                        return *this;
                    }
            };

            Iterator begin() {
                return {this->array};
            }

            Iterator end() {
                return {this->array + N};
            }
    };

    class DerefByValueFancy {
        private:
            static constexpr std::size_t N = 3;
            int array[N] = {0, 1, 2};
        public:
            DerefByValueFancy() = default;

            int *begin() {
                return this->array;
            }

            int *end() {
                return this->array + N;
            }
    };
}
#endif // #ifndef ITERTOOLS_SAMPLE_CLASSES_HPP
<|endoftext|>