<commit_before>//================ Copyright (c) 2017, PG, All rights reserved. =================//
//
// Purpose:		macOS
//
// $NoKeywords: $macenv
//===============================================================================//

#ifdef __APPLE__

#include "MacOSEnvironment.h"
#include "main_OSX_cpp.h"
#include "Engine.h"

#include "NullContextMenu.h"
#include "MacOSGLLegacyInterface.h"

#include <dirent.h>
#include <libgen.h> // for dirname
#include <sys/stat.h>
#include <unistd.h> // for access()

extern bool g_bRunning;

std::vector<McRect> MacOSEnvironment::m_vMonitors;

MacOSEnvironment::MacOSEnvironment(MacOSWrapper *wrapper) : Environment()
{
	m_wrapper = wrapper;

	m_bFullScreen = false;
	m_bResizable = true;

	m_bCursorClipped = false;
	m_bCursorRequest = false;
	m_bCursorReset = false;
	m_iCursorVisibleCounter = 0;
	m_iCursorInvisibleCounter = 0;
	m_bCursorVisible = true;
	m_bCursorVisibleInternalOverride = m_bCursorVisible;
	m_bIsCursorInsideWindow = false;
	m_cursorType = CURSORTYPE::CURSOR_NORMAL;

	// TODO: init monitors
	if (m_vMonitors.size() < 1)
	{
		///debugLog("WARNING: No monitors found! Adding default monitor ...\n");

		const Vector2 windowSize = getWindowSize();
		m_vMonitors.push_back(McRect(0, 0, windowSize.x, windowSize.y));
	}
}

MacOSEnvironment::~MacOSEnvironment()
{
}

void MacOSEnvironment::update()
{
	// handle cursor changes
	if (!m_bCursorRequest)
	{
		if (m_bCursorReset)
		{
			m_bCursorReset = false;
			setCursor(CURSOR_NORMAL);
		}
	}
	m_bCursorRequest = false;

	// check if cursor is inside the engine window
	m_bIsCursorInsideWindow = McRect(0, 0, engine->getScreenWidth(), engine->getScreenHeight()).contains(getMousePos());

	// imitate windows logic, the cursor visibility setting only applies if the cursor is within the engine window
	if (!m_bIsCursorInsideWindow && !m_bCursorVisible && !m_bCursorVisibleInternalOverride)
		setCursorVisible(true, true);
	else if (m_bIsCursorInsideWindow && !m_bCursorVisible && m_bCursorVisibleInternalOverride)
		setCursorVisible(false, true);
}

Graphics *MacOSEnvironment::createRenderer()
{
	return new MacOSGLLegacyInterface();
}

ContextMenu *MacOSEnvironment::createContextMenu()
{
	return new NullContextMenu();
}

Environment::OS MacOSEnvironment::getOS()
{
	return Environment::OS::OS_MACOS;
}

void MacOSEnvironment::shutdown()
{
	g_bRunning = false;
}

void MacOSEnvironment::restart()
{
	// TODO
	shutdown();
}

void MacOSEnvironment::sleep(unsigned int us)
{
	MacOSWrapper::microSleep(us);
}

UString MacOSEnvironment::getExecutablePath()
{
	// TODO
	return UString("");
}

void MacOSEnvironment::openURLInDefaultBrowser(UString url)
{
	MacOSWrapper::openURLInDefaultBrowser(url.toUtf8());
}

UString MacOSEnvironment::getUsername()
{
	return UString(MacOSWrapper::getUsername());
}

UString MacOSEnvironment::getUserDataPath()
{
	UString path = "/Users/";
	path.append(getUsername());
	return path;
}

bool MacOSEnvironment::fileExists(UString filename)
{
	///return std::ifstream(filename.toUtf8()).good();
	return (access(filename.toUtf8(), R_OK) >= 0);
}

bool MacOSEnvironment::directoryExists(UString directoryName)
{
	DIR *dir = opendir(directoryName.toUtf8());
	if (dir)
	{
		closedir(dir);
		return true;
	}
	else if (ENOENT == errno) // not a directory
	{
	}
	else // something else broke
	{
	}
	return false;
}

bool MacOSEnvironment::createDirectory(UString directoryName)
{
	return mkdir(directoryName.toUtf8(), DEFFILEMODE) != -1;
}

bool MacOSEnvironment::renameFile(UString oldFileName, UString newFileName)
{
	return rename(oldFileName.toUtf8(), newFileName.toUtf8()) != -1;
}

bool MacOSEnvironment::deleteFile(UString filePath)
{
	return remove(filePath.toUtf8()) == 0;
}

std::vector<UString> MacOSEnvironment::getFilesInFolder(UString folder)
{
	std::vector<UString> files;

	struct dirent **namelist;
	int n = scandir(folder.toUtf8(), &namelist, getFilesInFolderFilter, alphasort);
	if (n < 0)
	{
		///debugLog("LinuxEnvironment::getFilesInFolder() error, scandir() returned %i!\n", n);
		return files;
	}

	while (n--)
	{
		const char *name = namelist[n]->d_name;
		UString uName = UString(name);
		UString fullName = folder;
		fullName.append(uName);
		free(namelist[n]);

		struct stat stDirInfo;
		int lstatret = lstat(fullName.toUtf8(), &stDirInfo);
		if (lstatret < 0)
		{
			//perror (name);
			//debugLog("LinuxEnvironment::getFilesInFolder() error, lstat() returned %i!\n", lstatret);
			continue;
		}

		if (!S_ISDIR(stDirInfo.st_mode))
			files.push_back(uName);
	}
	free(namelist);

	return files;
}

std::vector<UString> MacOSEnvironment::getFoldersInFolder(UString folder)
{
	std::vector<UString> folders;

	struct dirent **namelist;
	int n = scandir(folder.toUtf8(), &namelist, getFoldersInFolderFilter, alphasort);
	if (n < 0)
	{
		///debugLog("LinuxEnvironment::getFilesInFolder() error, scandir() returned %i!\n", n);
		return folders;
	}

	while (n--)
	{
		const char *name = namelist[n]->d_name;
		UString uName = UString(name);
		UString fullName = folder;
		fullName.append(uName);
		free(namelist[n]);

		struct stat stDirInfo;
		int lstatret = lstat(fullName.toUtf8(), &stDirInfo);
		if (lstatret < 0)
		{
			///perror (name);
			///debugLog("LinuxEnvironment::getFilesInFolder() error, lstat() returned %i!\n", lstatret);
			continue;
		}

		if (S_ISDIR(stDirInfo.st_mode))
			folders.push_back(uName);
	}
	free(namelist);

	return folders;
}

std::vector<UString> MacOSEnvironment::getLogicalDrives()
{
	std::vector<UString> drives;
	drives.push_back(UString("/"));
	return drives;
}

UString MacOSEnvironment::getFolderFromFilePath(UString filepath)
{
	if (directoryExists(filepath)) // indirect check if this is already a valid directory (and not a file)
		return filepath;
	else
		return UString(dirname((char*)filepath.toUtf8()));
}

UString MacOSEnvironment::getFileExtensionFromFilePath(UString filepath, bool includeDot)
{
	int idx = filepath.findLast(".");
	if (idx != -1)
		return filepath.substr(idx+1);
	else
		return UString("");
}

UString MacOSEnvironment::getClipBoardText()
{
	const char *text = MacOSWrapper::getClipboardText();
	return (text != NULL ? UString(text) : "");
}

void MacOSEnvironment::setClipBoardText(UString text)
{
	MacOSWrapper::setClipboardText(text.toUtf8());
}

void MacOSEnvironment::showMessageInfo(UString title, UString message)
{
	MacOSWrapper::showMessageInfo(title.toUtf8(), message.toUtf8());
}

void MacOSEnvironment::showMessageWarning(UString title, UString message)
{
	MacOSWrapper::showMessageWarning(title.toUtf8(), message.toUtf8());
}

void MacOSEnvironment::showMessageError(UString title, UString message)
{
	MacOSWrapper::showMessageError(title.toUtf8(), message.toUtf8());
}

void MacOSEnvironment::showMessageErrorFatal(UString title, UString message)
{
	MacOSWrapper::showMessageErrorFatal(title.toUtf8(), message.toUtf8());
}

UString MacOSEnvironment::openFileWindow(const char *filetypefilters, UString title, UString initialpath)
{
	// TODO
	return UString("");
}

UString MacOSEnvironment::openFolderWindow(UString title, UString initialpath)
{
	// TODO
	return UString("");
}

void MacOSEnvironment::focus()
{
	MacOSWrapper::focus();
}

void MacOSEnvironment::center()
{
	MacOSWrapper::center();
}

void MacOSEnvironment::minimize()
{
	MacOSWrapper::minimize();
}

void MacOSEnvironment::maximize()
{
	MacOSWrapper::maximize();
}

void MacOSEnvironment::enableFullscreen()
{
	if (m_bFullScreen) return;

	MacOSWrapper::enableFullscreen();
	focus();

	m_bFullScreen = true;
}

void MacOSEnvironment::disableFullscreen()
{
	if (!m_bFullScreen) return;

	MacOSWrapper::disableFullscreen();
	focus();

	m_bFullScreen = false;
}

void MacOSEnvironment::setWindowTitle(UString title)
{
	MacOSWrapper::setWindowTitle(title.toUtf8());
}

void MacOSEnvironment::setWindowPos(int x, int y)
{
	MacOSWrapper::setWindowPos(x, y);
}

void MacOSEnvironment::setWindowSize(int width, int height)
{
	MacOSWrapper::setWindowSize(width, height);
}

void MacOSEnvironment::setWindowResizable(bool resizable)
{
	MacOSWrapper::setWindowResizable(resizable);
}

void MacOSEnvironment::setWindowGhostCorporeal(bool corporeal)
{
	// TODO
}

void MacOSEnvironment::setMonitor(int monitor)
{
	// TODO:
	center();
}

Vector2 MacOSEnvironment::getWindowPos()
{
	const MacOSWrapper::VECTOR2 pos = MacOSWrapper::getWindowPos();
	return Vector2(pos.x, pos.y);
}

Vector2 MacOSEnvironment::getWindowSize()
{
	const MacOSWrapper::VECTOR2 windowSize = MacOSWrapper::getWindowSize();
	return Vector2(windowSize.x, windowSize.y);
}

int MacOSEnvironment::getMonitor()
{
	return MacOSWrapper::getMonitor();
}

std::vector<McRect> MacOSEnvironment::getMonitors()
{
	return m_vMonitors;
}

Vector2 MacOSEnvironment::getNativeScreenSize()
{
	const MacOSWrapper::VECTOR2 size = MacOSWrapper::getNativeScreenSize();
	return Vector2(size.x, size.y);
}

McRect MacOSEnvironment::getVirtualScreenRect()
{
	// TODO
	return McRect(0, 0, 1, 1);
}

McRect MacOSEnvironment::getDesktopRect()
{
	// TODO
	const Vector2 screen = getNativeScreenSize();
	return McRect(0, 0, screen.x, screen.y);
}

int MacOSEnvironment::getDPI()
{
	// TODO
	return 96;
}

bool MacOSEnvironment::isCursorInWindow()
{
	return m_bIsCursorInsideWindow;
}

bool MacOSEnvironment::isCursorVisible()
{
	return m_bCursorVisible;
}

Vector2 MacOSEnvironment::getMousePos()
{
	MacOSWrapper::VECTOR2 mousePos = MacOSWrapper::getMousePos();
	return Vector2(mousePos.x, -mousePos.y + engine->getScreenHeight() - 1); // wtf apple: "The y coordinate in the returned point starts from a base of 1, not 0."
}

McRect MacOSEnvironment::getCursorClip()
{
	return m_cursorClip;
}

CURSORTYPE MacOSEnvironment::getCursor()
{
	return m_cursorType;
}

void MacOSEnvironment::setCursor(CURSORTYPE cur)
{
	m_cursorType = cur;

	// TODO: finish other cursor types
	switch (cur)
	{
	case CURSORTYPE::CURSOR_TEXT:
		MacOSWrapper::setCursor(1);
		break;
	default:
		MacOSWrapper::setCursor(0);
		break;
	}

	m_bCursorReset = true;
	m_bCursorRequest = true;
}

void MacOSEnvironment::setCursorVisible(bool visible)
{
	setCursorVisible(visible, false);
}

void MacOSEnvironment::setCursorVisible(bool visible, bool internalOverride)
{
	MacOSWrapper::setCursorVisible(visible);

	if (visible)
		m_iCursorVisibleCounter++;
	else
		m_iCursorInvisibleCounter++;

	if (visible)
	{
		for (int i=0; i<m_iCursorInvisibleCounter-1; i++)
		{
			MacOSWrapper::setCursorVisible(visible);
		}
		m_iCursorInvisibleCounter = 0;
	}
	else
	{
		for (int i=0; i<m_iCursorVisibleCounter-1; i++)
		{
			MacOSWrapper::setCursorVisible(visible);
		}
		m_iCursorVisibleCounter = 0;
	}

	if (!internalOverride)
		m_bCursorVisible = visible;

	m_bCursorVisibleInternalOverride = visible;
}

void MacOSEnvironment::setMousePos(int x, int y)
{
	MacOSWrapper::setMousePos(x, y);
}

void MacOSEnvironment::setCursorClip(bool clip, McRect rect)
{
	m_bCursorClipped = clip;
	m_cursorClip = rect;

	if (clip)
	{
		if (rect.getWidth() == 0 && rect.getHeight() == 0)
		{
			m_cursorClip = McRect(0, 0, engine->getScreenWidth(), engine->getScreenHeight());
		}

		// TODO: custom rect (only fullscreen works atm)
	}

	MacOSWrapper::setCursorClip(clip); // TODO
}

UString MacOSEnvironment::keyCodeToString(KEYCODE keyCode)
{
	// TODO
	return UString::format("%lu", keyCode);
}

// helper functions

int MacOSEnvironment::getFilesInFolderFilter(const struct dirent *entry)
{
	return 1;
}

int MacOSEnvironment::getFoldersInFolderFilter(const struct dirent *entry)
{
	return 1;
}

#endif
<commit_msg>Fixed refactoring breakage (2)<commit_after>//================ Copyright (c) 2017, PG, All rights reserved. =================//
//
// Purpose:		macOS
//
// $NoKeywords: $macenv
//===============================================================================//

#ifdef __APPLE__

#include "MacOSEnvironment.h"
#include "main_OSX_cpp.h"
#include "Engine.h"

#include "NullContextMenu.h"
#include "MacOSGLLegacyInterface.h"

#include <dirent.h>
#include <libgen.h> // for dirname
#include <sys/stat.h>
#include <unistd.h> // for access()

extern bool g_bRunning;

std::vector<McRect> MacOSEnvironment::m_vMonitors;

MacOSEnvironment::MacOSEnvironment(MacOSWrapper *wrapper) : Environment()
{
	m_wrapper = wrapper;

	m_bFullScreen = false;
	m_bResizable = true;

	m_bCursorClipped = false;
	m_bCursorRequest = false;
	m_bCursorReset = false;
	m_iCursorVisibleCounter = 0;
	m_iCursorInvisibleCounter = 0;
	m_bCursorVisible = true;
	m_bCursorVisibleInternalOverride = m_bCursorVisible;
	m_bIsCursorInsideWindow = false;
	m_cursorType = CURSORTYPE::CURSOR_NORMAL;

	// TODO: init monitors
	if (m_vMonitors.size() < 1)
	{
		///debugLog("WARNING: No monitors found! Adding default monitor ...\n");

		const Vector2 windowSize = getWindowSize();
		m_vMonitors.push_back(McRect(0, 0, windowSize.x, windowSize.y));
	}
}

MacOSEnvironment::~MacOSEnvironment()
{
}

void MacOSEnvironment::update()
{
	// handle cursor changes
	if (!m_bCursorRequest)
	{
		if (m_bCursorReset)
		{
			m_bCursorReset = false;
			setCursor(CURSORTYPE::CURSOR_NORMAL);
		}
	}
	m_bCursorRequest = false;

	// check if cursor is inside the engine window
	m_bIsCursorInsideWindow = McRect(0, 0, engine->getScreenWidth(), engine->getScreenHeight()).contains(getMousePos());

	// imitate windows logic, the cursor visibility setting only applies if the cursor is within the engine window
	if (!m_bIsCursorInsideWindow && !m_bCursorVisible && !m_bCursorVisibleInternalOverride)
		setCursorVisible(true, true);
	else if (m_bIsCursorInsideWindow && !m_bCursorVisible && m_bCursorVisibleInternalOverride)
		setCursorVisible(false, true);
}

Graphics *MacOSEnvironment::createRenderer()
{
	return new MacOSGLLegacyInterface();
}

ContextMenu *MacOSEnvironment::createContextMenu()
{
	return new NullContextMenu();
}

Environment::OS MacOSEnvironment::getOS()
{
	return Environment::OS::OS_MACOS;
}

void MacOSEnvironment::shutdown()
{
	g_bRunning = false;
}

void MacOSEnvironment::restart()
{
	// TODO
	shutdown();
}

void MacOSEnvironment::sleep(unsigned int us)
{
	MacOSWrapper::microSleep(us);
}

UString MacOSEnvironment::getExecutablePath()
{
	// TODO
	return UString("");
}

void MacOSEnvironment::openURLInDefaultBrowser(UString url)
{
	MacOSWrapper::openURLInDefaultBrowser(url.toUtf8());
}

UString MacOSEnvironment::getUsername()
{
	return UString(MacOSWrapper::getUsername());
}

UString MacOSEnvironment::getUserDataPath()
{
	UString path = "/Users/";
	path.append(getUsername());
	return path;
}

bool MacOSEnvironment::fileExists(UString filename)
{
	///return std::ifstream(filename.toUtf8()).good();
	return (access(filename.toUtf8(), R_OK) >= 0);
}

bool MacOSEnvironment::directoryExists(UString directoryName)
{
	DIR *dir = opendir(directoryName.toUtf8());
	if (dir)
	{
		closedir(dir);
		return true;
	}
	else if (ENOENT == errno) // not a directory
	{
	}
	else // something else broke
	{
	}
	return false;
}

bool MacOSEnvironment::createDirectory(UString directoryName)
{
	return mkdir(directoryName.toUtf8(), DEFFILEMODE) != -1;
}

bool MacOSEnvironment::renameFile(UString oldFileName, UString newFileName)
{
	return rename(oldFileName.toUtf8(), newFileName.toUtf8()) != -1;
}

bool MacOSEnvironment::deleteFile(UString filePath)
{
	return remove(filePath.toUtf8()) == 0;
}

std::vector<UString> MacOSEnvironment::getFilesInFolder(UString folder)
{
	std::vector<UString> files;

	struct dirent **namelist;
	int n = scandir(folder.toUtf8(), &namelist, getFilesInFolderFilter, alphasort);
	if (n < 0)
	{
		///debugLog("LinuxEnvironment::getFilesInFolder() error, scandir() returned %i!\n", n);
		return files;
	}

	while (n--)
	{
		const char *name = namelist[n]->d_name;
		UString uName = UString(name);
		UString fullName = folder;
		fullName.append(uName);
		free(namelist[n]);

		struct stat stDirInfo;
		int lstatret = lstat(fullName.toUtf8(), &stDirInfo);
		if (lstatret < 0)
		{
			//perror (name);
			//debugLog("LinuxEnvironment::getFilesInFolder() error, lstat() returned %i!\n", lstatret);
			continue;
		}

		if (!S_ISDIR(stDirInfo.st_mode))
			files.push_back(uName);
	}
	free(namelist);

	return files;
}

std::vector<UString> MacOSEnvironment::getFoldersInFolder(UString folder)
{
	std::vector<UString> folders;

	struct dirent **namelist;
	int n = scandir(folder.toUtf8(), &namelist, getFoldersInFolderFilter, alphasort);
	if (n < 0)
	{
		///debugLog("LinuxEnvironment::getFilesInFolder() error, scandir() returned %i!\n", n);
		return folders;
	}

	while (n--)
	{
		const char *name = namelist[n]->d_name;
		UString uName = UString(name);
		UString fullName = folder;
		fullName.append(uName);
		free(namelist[n]);

		struct stat stDirInfo;
		int lstatret = lstat(fullName.toUtf8(), &stDirInfo);
		if (lstatret < 0)
		{
			///perror (name);
			///debugLog("LinuxEnvironment::getFilesInFolder() error, lstat() returned %i!\n", lstatret);
			continue;
		}

		if (S_ISDIR(stDirInfo.st_mode))
			folders.push_back(uName);
	}
	free(namelist);

	return folders;
}

std::vector<UString> MacOSEnvironment::getLogicalDrives()
{
	std::vector<UString> drives;
	drives.push_back(UString("/"));
	return drives;
}

UString MacOSEnvironment::getFolderFromFilePath(UString filepath)
{
	if (directoryExists(filepath)) // indirect check if this is already a valid directory (and not a file)
		return filepath;
	else
		return UString(dirname((char*)filepath.toUtf8()));
}

UString MacOSEnvironment::getFileExtensionFromFilePath(UString filepath, bool includeDot)
{
	int idx = filepath.findLast(".");
	if (idx != -1)
		return filepath.substr(idx+1);
	else
		return UString("");
}

UString MacOSEnvironment::getClipBoardText()
{
	const char *text = MacOSWrapper::getClipboardText();
	return (text != NULL ? UString(text) : "");
}

void MacOSEnvironment::setClipBoardText(UString text)
{
	MacOSWrapper::setClipboardText(text.toUtf8());
}

void MacOSEnvironment::showMessageInfo(UString title, UString message)
{
	MacOSWrapper::showMessageInfo(title.toUtf8(), message.toUtf8());
}

void MacOSEnvironment::showMessageWarning(UString title, UString message)
{
	MacOSWrapper::showMessageWarning(title.toUtf8(), message.toUtf8());
}

void MacOSEnvironment::showMessageError(UString title, UString message)
{
	MacOSWrapper::showMessageError(title.toUtf8(), message.toUtf8());
}

void MacOSEnvironment::showMessageErrorFatal(UString title, UString message)
{
	MacOSWrapper::showMessageErrorFatal(title.toUtf8(), message.toUtf8());
}

UString MacOSEnvironment::openFileWindow(const char *filetypefilters, UString title, UString initialpath)
{
	// TODO
	return UString("");
}

UString MacOSEnvironment::openFolderWindow(UString title, UString initialpath)
{
	// TODO
	return UString("");
}

void MacOSEnvironment::focus()
{
	MacOSWrapper::focus();
}

void MacOSEnvironment::center()
{
	MacOSWrapper::center();
}

void MacOSEnvironment::minimize()
{
	MacOSWrapper::minimize();
}

void MacOSEnvironment::maximize()
{
	MacOSWrapper::maximize();
}

void MacOSEnvironment::enableFullscreen()
{
	if (m_bFullScreen) return;

	MacOSWrapper::enableFullscreen();
	focus();

	m_bFullScreen = true;
}

void MacOSEnvironment::disableFullscreen()
{
	if (!m_bFullScreen) return;

	MacOSWrapper::disableFullscreen();
	focus();

	m_bFullScreen = false;
}

void MacOSEnvironment::setWindowTitle(UString title)
{
	MacOSWrapper::setWindowTitle(title.toUtf8());
}

void MacOSEnvironment::setWindowPos(int x, int y)
{
	MacOSWrapper::setWindowPos(x, y);
}

void MacOSEnvironment::setWindowSize(int width, int height)
{
	MacOSWrapper::setWindowSize(width, height);
}

void MacOSEnvironment::setWindowResizable(bool resizable)
{
	MacOSWrapper::setWindowResizable(resizable);
}

void MacOSEnvironment::setWindowGhostCorporeal(bool corporeal)
{
	// TODO
}

void MacOSEnvironment::setMonitor(int monitor)
{
	// TODO:
	center();
}

Vector2 MacOSEnvironment::getWindowPos()
{
	const MacOSWrapper::VECTOR2 pos = MacOSWrapper::getWindowPos();
	return Vector2(pos.x, pos.y);
}

Vector2 MacOSEnvironment::getWindowSize()
{
	const MacOSWrapper::VECTOR2 windowSize = MacOSWrapper::getWindowSize();
	return Vector2(windowSize.x, windowSize.y);
}

int MacOSEnvironment::getMonitor()
{
	return MacOSWrapper::getMonitor();
}

std::vector<McRect> MacOSEnvironment::getMonitors()
{
	return m_vMonitors;
}

Vector2 MacOSEnvironment::getNativeScreenSize()
{
	const MacOSWrapper::VECTOR2 size = MacOSWrapper::getNativeScreenSize();
	return Vector2(size.x, size.y);
}

McRect MacOSEnvironment::getVirtualScreenRect()
{
	// TODO
	return McRect(0, 0, 1, 1);
}

McRect MacOSEnvironment::getDesktopRect()
{
	// TODO
	const Vector2 screen = getNativeScreenSize();
	return McRect(0, 0, screen.x, screen.y);
}

int MacOSEnvironment::getDPI()
{
	// TODO
	return 96;
}

bool MacOSEnvironment::isCursorInWindow()
{
	return m_bIsCursorInsideWindow;
}

bool MacOSEnvironment::isCursorVisible()
{
	return m_bCursorVisible;
}

Vector2 MacOSEnvironment::getMousePos()
{
	MacOSWrapper::VECTOR2 mousePos = MacOSWrapper::getMousePos();
	return Vector2(mousePos.x, -mousePos.y + engine->getScreenHeight() - 1); // wtf apple: "The y coordinate in the returned point starts from a base of 1, not 0."
}

McRect MacOSEnvironment::getCursorClip()
{
	return m_cursorClip;
}

CURSORTYPE MacOSEnvironment::getCursor()
{
	return m_cursorType;
}

void MacOSEnvironment::setCursor(CURSORTYPE cur)
{
	m_cursorType = cur;

	// TODO: finish other cursor types
	switch (cur)
	{
	case CURSORTYPE::CURSOR_TEXT:
		MacOSWrapper::setCursor(1);
		break;
	default:
		MacOSWrapper::setCursor(0);
		break;
	}

	m_bCursorReset = true;
	m_bCursorRequest = true;
}

void MacOSEnvironment::setCursorVisible(bool visible)
{
	setCursorVisible(visible, false);
}

void MacOSEnvironment::setCursorVisible(bool visible, bool internalOverride)
{
	MacOSWrapper::setCursorVisible(visible);

	if (visible)
		m_iCursorVisibleCounter++;
	else
		m_iCursorInvisibleCounter++;

	if (visible)
	{
		for (int i=0; i<m_iCursorInvisibleCounter-1; i++)
		{
			MacOSWrapper::setCursorVisible(visible);
		}
		m_iCursorInvisibleCounter = 0;
	}
	else
	{
		for (int i=0; i<m_iCursorVisibleCounter-1; i++)
		{
			MacOSWrapper::setCursorVisible(visible);
		}
		m_iCursorVisibleCounter = 0;
	}

	if (!internalOverride)
		m_bCursorVisible = visible;

	m_bCursorVisibleInternalOverride = visible;
}

void MacOSEnvironment::setMousePos(int x, int y)
{
	MacOSWrapper::setMousePos(x, y);
}

void MacOSEnvironment::setCursorClip(bool clip, McRect rect)
{
	m_bCursorClipped = clip;
	m_cursorClip = rect;

	if (clip)
	{
		if (rect.getWidth() == 0 && rect.getHeight() == 0)
		{
			m_cursorClip = McRect(0, 0, engine->getScreenWidth(), engine->getScreenHeight());
		}

		// TODO: custom rect (only fullscreen works atm)
	}

	MacOSWrapper::setCursorClip(clip); // TODO
}

UString MacOSEnvironment::keyCodeToString(KEYCODE keyCode)
{
	// TODO
	return UString::format("%lu", keyCode);
}

// helper functions

int MacOSEnvironment::getFilesInFolderFilter(const struct dirent *entry)
{
	return 1;
}

int MacOSEnvironment::getFoldersInFolderFilter(const struct dirent *entry)
{
	return 1;
}

#endif
<|endoftext|>


<commit_before>
#include <QtTest/QtTest>
#include <QtGui>
#include <QDBusArgument>
#include <QDBusConnection>
#include <QDBusMessage>
#include <QDBusInterface>

#include "../src/dbusconnection.h"
#include "../src/struct_marshallers.h"

class AccessibleTestWindow: public QWidget
{
    Q_OBJECT
public:
    AccessibleTestWindow() {
        DBusConnection c;
        m_address = c.connection().baseService().toLatin1().data();
        m_layout = new QHBoxLayout;
        setLayout(m_layout);
    }
    QString dbusAddress() const {return m_address;}

    void addChild(QWidget* c)
    {
        m_layout->addWidget(c);
    }

    void clearChildren()
    {
        qDeleteAll(children());
    }

private:
    QString m_address;
    QString m_bus;
    QHBoxLayout* m_layout;
};

class tst_QtAtSpi :public QObject
{
    Q_OBJECT

private slots:
    void initTestCase();

    void testLabel();

    void cleanupTestCase();
//     void rootObject();
//     void navigateChildren();
//     void menu();
//
//     void cache();

private:
    void registerDbus();
    static QString getParent(QDBusInterface* interface);
    static QStringList getChildren(QDBusInterface* interface);
    QDBusInterface* getInterface(const QString& path, const QString& interfaceName);

    AccessibleTestWindow* m_window;

    QString bus;
    QString address;
    QDBusInterface* root; // the root object on dbus (for the app)
    QDBusInterface* rootApplication;
    QDBusInterface* mainWindow;

    DBusConnection dbus;
};

// helper to find children of a dbus object
QStringList tst_QtAtSpi::getChildren(QDBusInterface* interface)
{
    QSpiObjectReferenceArray list;
    interface->call(QDBus::Block, "GetChildren").arguments().first().value<QDBusArgument>() >> list;

    Q_ASSERT(interface->property("ChildCount").toInt() == list.count());

    QStringList children;
    foreach(const QSpiObjectReference& ref, list) {
        children << ref.path.path();
    }
    return children;
}

QString tst_QtAtSpi::getParent(QDBusInterface* interface)
{
    interface->property("Parent");
    QSpiObjectReference parent;
    const QDBusArgument a = interface->property("Parent").value<QDBusArgument>();
    a >> parent;
    return parent.path.path();
}

// helper to get dbus object
QDBusInterface* tst_QtAtSpi::getInterface(const QString& path, const QString& interfaceName)
{
    return new QDBusInterface(address, path, interfaceName, dbus.connection(), this);
}

void tst_QtAtSpi::initTestCase()
{
    QCOMPARE(qgetenv("QT_ACCESSIBILITY"), QByteArray("1"));

    dbus = DBusConnection();

    m_window = new AccessibleTestWindow();
    m_window->show();
    QTest::qWaitForWindowShown(m_window);
    QTest::qWait(1000); // Seems like we need to give dbus some time

    address = m_window->dbusAddress();
    registerDbus();

    QStringList appChildren = getChildren(root);
    QString window = appChildren.at(0);
    mainWindow = getInterface(window, "org.a11y.atspi.Accessible");
}

void tst_QtAtSpi::cleanupTestCase()
{
    delete mainWindow;
    delete rootApplication;
    delete root;
    delete m_window;
}

void tst_QtAtSpi::registerDbus()
{
    QVERIFY(dbus.connection().isConnected());

    root = getInterface("/org/a11y/atspi/accessible/root",
                        "org.a11y.atspi.Accessible");

    rootApplication = getInterface("/org/a11y/atspi/accessible/root",
                        "org.a11y.atspi.Application");
    QVERIFY(root->isValid());
    QVERIFY(rootApplication->isValid());

    QStringList appChildren = getChildren(root);
    QString window = appChildren.at(0);
    mainWindow = getInterface(window, "org.a11y.atspi.Accessible");
}

#define ROOTPATH "/org/a11y/atspi/accessible"

void tst_QtAtSpi::testLabel()
{
    QLabel* l = new QLabel(m_window);
    l->setText("Hello A11y");
    m_window->addChild(l);

    QStringList children = getChildren(mainWindow);

    QDBusInterface* labelInterface = getInterface(children.at(0), "org.a11y.atspi.Accessible");
    QCOMPARE(labelInterface->property("Name").toString(), QLatin1String("Hello A11y"));
}

// void tst_QtAtSpi::rootObject()
// {
//     QCOMPARE(root->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("application"));
//     QCOMPARE(root->call(QDBus::Block, "GetRole").arguments().first().toUInt(), 75u);
//     QCOMPARE(root->property("ChildCount").toInt(), 1);
//     QCOMPARE(root->property("Name").toString(), QLatin1String("Simple A11y Test App"));
//     QCOMPARE(root->call(QDBus::Block, "GetChildren").arguments().first().toString(), QString());
//
//     QStringList children = getChildren(root);
//     QCOMPARE(children.length(), 1);
// //    QCOMPARE(children.at(0), QLatin1String(ROOTPATH "/1"));
//
//     qDebug() << "Toolkit Name: " << rootApplication->property("ToolkitName");
//     qDebug() << "Version: " << rootApplication->property("Version");
//

//     QCOMPARE(mainWindow->property("Name").toString(), QLatin1String("MainWindow"));
//     QCOMPARE(mainWindow->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("window"));
// }
//
//
// void tst_QtAtSpi::navigateChildren()
// {
//
//     // FIXME
// //    QCOMPARE(getParent(mainWindow), QLatin1String("/org/a11y/atspi/accessible/0"));
// //    mainWindow->property("Parent");
//
//     QStringList mainWinChildren = getChildren(mainWindow);
//     QCOMPARE(mainWinChildren.count(), 3);
// //    QCOMPARE(mainWinChildren, QStringList() << ROOTPATH "/2" << ROOTPATH "/3" << ROOTPATH "/4");
//
//     // first child: central widget. the others are menu+statusbar
//     QDBusInterface* centralWidget = getInterface(mainWinChildren.first(), "org.a11y.atspi.Accessible");
//     QCOMPARE(centralWidget->property("Name").toString(), QString());
//     QStringList centralWidgetChildren = getChildren(centralWidget);
//     QCOMPARE(centralWidgetChildren.count(), 7);
//
//     QDBusInterface* label = getInterface(centralWidgetChildren.at(0), "org.a11y.atspi.Accessible");
//     QVERIFY(label->isValid());
//     QCOMPARE(label->property("Name").toString(), QLatin1String("Some Text"));
//     QCOMPARE(getChildren(label).count(), 0);
//
//     QDBusInterface* button = getInterface(centralWidgetChildren.at(1), "org.a11y.atspi.Accessible");
//     QVERIFY(button->isValid());
//     QCOMPARE(button->property("Name").toString(), QLatin1String("Create More Buttons"));
//     QCOMPARE(getChildren(button).count(), 0);
//
//     QDBusInterface* label2 = getInterface(centralWidgetChildren.at(2), "org.a11y.atspi.Accessible");
//     QCOMPARE(label2->property("Name").toString(), QLatin1String("Enter your name:"));
//     QCOMPARE(getChildren(label2).count(), 0);
//
//     QDBusInterface* lineEdit = getInterface(centralWidgetChildren.at(3), "org.a11y.atspi.Accessible");
//     QCOMPARE(lineEdit->property("Name").toString(), QLatin1String("Name line edit"));
//     QCOMPARE(getChildren(lineEdit).count(), 0);
//
//     QDBusInterface* text = getInterface(centralWidgetChildren.at(4), "org.a11y.atspi.Accessible");
//     // QCOMPARE(text->property("Name").toString().left(6), QString());
//     QCOMPARE(getChildren(text).count(), 7);
//     // FIXME: why does this guy have so many kids?
//
//     // tabbar and stackwidget
//     QDBusInterface* tabWidget = getInterface(centralWidgetChildren.at(5), "org.a11y.atspi.Accessible");
//     QCOMPARE(tabWidget->property("Name").toString(), QString());
//     QStringList tabWidgetChildren = getChildren(tabWidget);
//     QCOMPARE(tabWidgetChildren.count(), 2);
//
//     QDBusInterface* stackWidget = getInterface(tabWidgetChildren.at(0), "org.a11y.atspi.Accessible");
//     QCOMPARE(stackWidget->property("Name").toString(), QString());
//     QCOMPARE(stackWidget->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("layered pane"));
//     QStringList stackChildren = getChildren(stackWidget);
//     QCOMPARE(stackChildren.count(), 2);
//
//     QDBusInterface* stackWidget1 = getInterface(stackChildren.at(0), "org.a11y.atspi.Accessible");
//     QCOMPARE(stackWidget1->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("filler"));
//     QStringList stackWidget1Children = getChildren(stackWidget1);
//
//     // radiobuttons
//     QDBusInterface* radio1 = getInterface(stackWidget1Children.at(0), "org.a11y.atspi.Accessible");
//     QCOMPARE(radio1->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("radio button"));
//     QCOMPARE(radio1->property("ChildCount").toInt(), 0);
//     QCOMPARE(getChildren(radio1), QStringList());
// //    QCOMPARE(radio1->property("Name").toString(), QLatin1String("Apple"));
//
//     QDBusInterface* stackWidget2 = getInterface(stackChildren.at(1), "org.a11y.atspi.Accessible");
//     QCOMPARE(stackWidget2->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("filler"));
//
//     // second tab?
//
//     delete radio1;
//     delete stackWidget1;
//     delete stackWidget2;
//
//     QDBusInterface* tabBar = getInterface(tabWidgetChildren.at(1), "org.a11y.atspi.Accessible");
//     // FIXME: is that good? we get the child's name here...
//     QCOMPARE(tabBar->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("page tab list"));
//     QCOMPARE(tabBar->property("ChildCount").toInt(), 4);
//     QStringList tabBarChildren = getChildren(tabWidget);
//     QCOMPARE(tabBarChildren.count(), 2);
//
//     QDBusInterface* tabButton1 = getInterface(tabBarChildren.at(0), "org.a11y.atspi.Accessible");
//     QCOMPARE(tabButton1->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("page tab"));
//     QCOMPARE(tabButton1->property("Name").toString(), QLatin1String("Fruits"));
//     QStringList tabButton1Children = getChildren(tabButton1);
//     QVERIFY(tabBarChildren.first() != tabButton1Children.first());
//     QCOMPARE(getChildren(tabButton1).count(), 4);
//     QCOMPARE(tabButton1->property("ChildCount").toInt(), 4);
//
//     QDBusInterface* tabButton2 = getInterface(tabBarChildren.at(1), "org.a11y.atspi.Accessible");
//     QCOMPARE(tabButton2->property("Name").toString(), QLatin1String("Other"));
//     QCOMPARE(tabButton2->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("page tab"));
//     QStringList tabButton2Children = getChildren(tabButton1);
//     QVERIFY(tabBarChildren.first() != tabButton2Children.first());
//     QCOMPARE(getChildren(tabButton2).count(), 4);
//     QCOMPARE(tabButton2->property("ChildCount").toInt(), 4);
//
//
// //    QDBusInterface* tabButton2 = getInterface(tabBarChildren.at(1), "org.a11y.atspi.Accessible");
// //    QCOMPARE(tabButton2->property("Name").toString(), QLatin1String("Fruits"));
// //    QCOMPARE(tabButton2->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("page tab"));
// //    QCOMPARE(getChildren(tabButton1).count(), 0);
//
//     delete tabButton1;
//     delete tabButton2;
//
//     delete stackWidget;
//     delete tabBar;
//
//
//     // combobox
//     QDBusInterface* combobox = getInterface(centralWidgetChildren.at(6), "org.a11y.atspi.Accessible");
//     QCOMPARE(combobox->property("Name").toString(), QLatin1String("Comboboxes are fun!"));
//     QCOMPARE(getChildren(combobox).count(), 3);
//
//
//
//     delete combobox;
//     delete tabWidget;
//     delete text;
//     delete lineEdit;
//     delete label2;
//     delete button;
//     delete label;
//
//     delete centralWidget;
//     delete mainWindow;
// }
//
// void tst_QtAtSpi::menu()
// {
//     QStringList c = getChildren(mainWindow);
//     QDBusInterface* menuRoot = getInterface(c.at(1), "org.a11y.atspi.Accessible");
//     QCOMPARE(menuRoot->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("menu bar"));
//     QCOMPARE(menuRoot->property("Name").toString(), QLatin1String("aN:menubar"));
//     QStringList menus = getChildren(menuRoot);
//     QCOMPARE(menus.count(), 2); // File, Edit
//
//     QDBusInterface* fileMenu = getInterface(menus.at(0), "org.a11y.atspi.Accessible");
//     QCOMPARE(fileMenu->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("menu item"));
//     QCOMPARE(fileMenu->property("Name").toString(), QLatin1String("File"));
//
//     QDBusInterface* editMenu = getInterface(menus.at(1), "org.a11y.atspi.Accessible");
//     QCOMPARE(editMenu->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("menu item"));
//     QCOMPARE(editMenu->property("Name").toString(), QLatin1String("Edit"));
// }
//
// void tst_QtAtSpi::cache()
// {
//     QDBusInterface* cache = getInterface("/org/a11y/atspi/cache", "org.a11y.atspi.Cache");
//     //qDebug() << cache->call(QDBus::Block, "GetItems");
//     delete cache;
// }

QTEST_MAIN(tst_QtAtSpi)

#include "tst_qt-atspi.moc"
<commit_msg>Fixed memory leak in tst_qt-atspi.cpp<commit_after>
#include <QtTest/QtTest>
#include <QtGui>
#include <QDBusArgument>
#include <QDBusConnection>
#include <QDBusMessage>
#include <QDBusInterface>

#include "../src/dbusconnection.h"
#include "../src/struct_marshallers.h"

class AccessibleTestWindow: public QWidget
{
    Q_OBJECT
public:
    AccessibleTestWindow() {
        DBusConnection c;
        m_address = c.connection().baseService().toLatin1().data();
        m_layout = new QHBoxLayout;
        setLayout(m_layout);
    }
    QString dbusAddress() const {return m_address;}

    void addChild(QWidget* c)
    {
        m_layout->addWidget(c);
    }

    void clearChildren()
    {
        qDeleteAll(children());
    }

private:
    QString m_address;
    QString m_bus;
    QHBoxLayout* m_layout;
};

class tst_QtAtSpi :public QObject
{
    Q_OBJECT

private slots:
    void initTestCase();

    void testLabel();

    void cleanupTestCase();
//     void rootObject();
//     void navigateChildren();
//     void menu();
//
//     void cache();

private:
    void registerDbus();
    static QString getParent(QDBusInterface* interface);
    static QStringList getChildren(QDBusInterface* interface);
    QDBusInterface* getInterface(const QString& path, const QString& interfaceName);

    AccessibleTestWindow* m_window;

    QString bus;
    QString address;
    QDBusInterface* root; // the root object on dbus (for the app)
    QDBusInterface* rootApplication;
    QDBusInterface* mainWindow;

    DBusConnection dbus;
};

// helper to find children of a dbus object
QStringList tst_QtAtSpi::getChildren(QDBusInterface* interface)
{
    QSpiObjectReferenceArray list;
    interface->call(QDBus::Block, "GetChildren").arguments().first().value<QDBusArgument>() >> list;

    Q_ASSERT(interface->property("ChildCount").toInt() == list.count());

    QStringList children;
    foreach(const QSpiObjectReference& ref, list) {
        children << ref.path.path();
    }
    return children;
}

QString tst_QtAtSpi::getParent(QDBusInterface* interface)
{
    interface->property("Parent");
    QSpiObjectReference parent;
    const QDBusArgument a = interface->property("Parent").value<QDBusArgument>();
    a >> parent;
    return parent.path.path();
}

// helper to get dbus object
QDBusInterface* tst_QtAtSpi::getInterface(const QString& path, const QString& interfaceName)
{
    return new QDBusInterface(address, path, interfaceName, dbus.connection(), this);
}

void tst_QtAtSpi::initTestCase()
{
    QCOMPARE(qgetenv("QT_ACCESSIBILITY"), QByteArray("1"));

    dbus = DBusConnection();

    m_window = new AccessibleTestWindow();
    m_window->show();
    QTest::qWaitForWindowShown(m_window);
    QTest::qWait(1000); // Seems like we need to give dbus some time

    address = m_window->dbusAddress();
    registerDbus();

    QStringList appChildren = getChildren(root);
    QString window = appChildren.at(0);
    mainWindow = getInterface(window, "org.a11y.atspi.Accessible");
}

void tst_QtAtSpi::cleanupTestCase()
{
    delete mainWindow;
    delete rootApplication;
    delete root;
    delete m_window;
}

void tst_QtAtSpi::registerDbus()
{
    QVERIFY(dbus.connection().isConnected());

    root = getInterface("/org/a11y/atspi/accessible/root",
                        "org.a11y.atspi.Accessible");

    rootApplication = getInterface("/org/a11y/atspi/accessible/root",
                        "org.a11y.atspi.Application");
    QVERIFY(root->isValid());
    QVERIFY(rootApplication->isValid());

    QStringList appChildren = getChildren(root);
    QString window = appChildren.at(0);
    mainWindow = getInterface(window, "org.a11y.atspi.Accessible");
}

#define ROOTPATH "/org/a11y/atspi/accessible"

void tst_QtAtSpi::testLabel()
{
    QLabel* l = new QLabel(m_window);
    l->setText("Hello A11y");
    m_window->addChild(l);

    QStringList children = getChildren(mainWindow);

    QDBusInterface* labelInterface = getInterface(children.at(0), "org.a11y.atspi.Accessible");
    QCOMPARE(labelInterface->property("Name").toString(), QLatin1String("Hello A11y"));

    m_window->clearChildren();
    delete labelInterface;
}

// void tst_QtAtSpi::rootObject()
// {
//     QCOMPARE(root->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("application"));
//     QCOMPARE(root->call(QDBus::Block, "GetRole").arguments().first().toUInt(), 75u);
//     QCOMPARE(root->property("ChildCount").toInt(), 1);
//     QCOMPARE(root->property("Name").toString(), QLatin1String("Simple A11y Test App"));
//     QCOMPARE(root->call(QDBus::Block, "GetChildren").arguments().first().toString(), QString());
//
//     QStringList children = getChildren(root);
//     QCOMPARE(children.length(), 1);
// //    QCOMPARE(children.at(0), QLatin1String(ROOTPATH "/1"));
//
//     qDebug() << "Toolkit Name: " << rootApplication->property("ToolkitName");
//     qDebug() << "Version: " << rootApplication->property("Version");
//

//     QCOMPARE(mainWindow->property("Name").toString(), QLatin1String("MainWindow"));
//     QCOMPARE(mainWindow->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("window"));
// }
//
//
// void tst_QtAtSpi::navigateChildren()
// {
//
//     // FIXME
// //    QCOMPARE(getParent(mainWindow), QLatin1String("/org/a11y/atspi/accessible/0"));
// //    mainWindow->property("Parent");
//
//     QStringList mainWinChildren = getChildren(mainWindow);
//     QCOMPARE(mainWinChildren.count(), 3);
// //    QCOMPARE(mainWinChildren, QStringList() << ROOTPATH "/2" << ROOTPATH "/3" << ROOTPATH "/4");
//
//     // first child: central widget. the others are menu+statusbar
//     QDBusInterface* centralWidget = getInterface(mainWinChildren.first(), "org.a11y.atspi.Accessible");
//     QCOMPARE(centralWidget->property("Name").toString(), QString());
//     QStringList centralWidgetChildren = getChildren(centralWidget);
//     QCOMPARE(centralWidgetChildren.count(), 7);
//
//     QDBusInterface* label = getInterface(centralWidgetChildren.at(0), "org.a11y.atspi.Accessible");
//     QVERIFY(label->isValid());
//     QCOMPARE(label->property("Name").toString(), QLatin1String("Some Text"));
//     QCOMPARE(getChildren(label).count(), 0);
//
//     QDBusInterface* button = getInterface(centralWidgetChildren.at(1), "org.a11y.atspi.Accessible");
//     QVERIFY(button->isValid());
//     QCOMPARE(button->property("Name").toString(), QLatin1String("Create More Buttons"));
//     QCOMPARE(getChildren(button).count(), 0);
//
//     QDBusInterface* label2 = getInterface(centralWidgetChildren.at(2), "org.a11y.atspi.Accessible");
//     QCOMPARE(label2->property("Name").toString(), QLatin1String("Enter your name:"));
//     QCOMPARE(getChildren(label2).count(), 0);
//
//     QDBusInterface* lineEdit = getInterface(centralWidgetChildren.at(3), "org.a11y.atspi.Accessible");
//     QCOMPARE(lineEdit->property("Name").toString(), QLatin1String("Name line edit"));
//     QCOMPARE(getChildren(lineEdit).count(), 0);
//
//     QDBusInterface* text = getInterface(centralWidgetChildren.at(4), "org.a11y.atspi.Accessible");
//     // QCOMPARE(text->property("Name").toString().left(6), QString());
//     QCOMPARE(getChildren(text).count(), 7);
//     // FIXME: why does this guy have so many kids?
//
//     // tabbar and stackwidget
//     QDBusInterface* tabWidget = getInterface(centralWidgetChildren.at(5), "org.a11y.atspi.Accessible");
//     QCOMPARE(tabWidget->property("Name").toString(), QString());
//     QStringList tabWidgetChildren = getChildren(tabWidget);
//     QCOMPARE(tabWidgetChildren.count(), 2);
//
//     QDBusInterface* stackWidget = getInterface(tabWidgetChildren.at(0), "org.a11y.atspi.Accessible");
//     QCOMPARE(stackWidget->property("Name").toString(), QString());
//     QCOMPARE(stackWidget->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("layered pane"));
//     QStringList stackChildren = getChildren(stackWidget);
//     QCOMPARE(stackChildren.count(), 2);
//
//     QDBusInterface* stackWidget1 = getInterface(stackChildren.at(0), "org.a11y.atspi.Accessible");
//     QCOMPARE(stackWidget1->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("filler"));
//     QStringList stackWidget1Children = getChildren(stackWidget1);
//
//     // radiobuttons
//     QDBusInterface* radio1 = getInterface(stackWidget1Children.at(0), "org.a11y.atspi.Accessible");
//     QCOMPARE(radio1->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("radio button"));
//     QCOMPARE(radio1->property("ChildCount").toInt(), 0);
//     QCOMPARE(getChildren(radio1), QStringList());
// //    QCOMPARE(radio1->property("Name").toString(), QLatin1String("Apple"));
//
//     QDBusInterface* stackWidget2 = getInterface(stackChildren.at(1), "org.a11y.atspi.Accessible");
//     QCOMPARE(stackWidget2->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("filler"));
//
//     // second tab?
//
//     delete radio1;
//     delete stackWidget1;
//     delete stackWidget2;
//
//     QDBusInterface* tabBar = getInterface(tabWidgetChildren.at(1), "org.a11y.atspi.Accessible");
//     // FIXME: is that good? we get the child's name here...
//     QCOMPARE(tabBar->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("page tab list"));
//     QCOMPARE(tabBar->property("ChildCount").toInt(), 4);
//     QStringList tabBarChildren = getChildren(tabWidget);
//     QCOMPARE(tabBarChildren.count(), 2);
//
//     QDBusInterface* tabButton1 = getInterface(tabBarChildren.at(0), "org.a11y.atspi.Accessible");
//     QCOMPARE(tabButton1->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("page tab"));
//     QCOMPARE(tabButton1->property("Name").toString(), QLatin1String("Fruits"));
//     QStringList tabButton1Children = getChildren(tabButton1);
//     QVERIFY(tabBarChildren.first() != tabButton1Children.first());
//     QCOMPARE(getChildren(tabButton1).count(), 4);
//     QCOMPARE(tabButton1->property("ChildCount").toInt(), 4);
//
//     QDBusInterface* tabButton2 = getInterface(tabBarChildren.at(1), "org.a11y.atspi.Accessible");
//     QCOMPARE(tabButton2->property("Name").toString(), QLatin1String("Other"));
//     QCOMPARE(tabButton2->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("page tab"));
//     QStringList tabButton2Children = getChildren(tabButton1);
//     QVERIFY(tabBarChildren.first() != tabButton2Children.first());
//     QCOMPARE(getChildren(tabButton2).count(), 4);
//     QCOMPARE(tabButton2->property("ChildCount").toInt(), 4);
//
//
// //    QDBusInterface* tabButton2 = getInterface(tabBarChildren.at(1), "org.a11y.atspi.Accessible");
// //    QCOMPARE(tabButton2->property("Name").toString(), QLatin1String("Fruits"));
// //    QCOMPARE(tabButton2->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("page tab"));
// //    QCOMPARE(getChildren(tabButton1).count(), 0);
//
//     delete tabButton1;
//     delete tabButton2;
//
//     delete stackWidget;
//     delete tabBar;
//
//
//     // combobox
//     QDBusInterface* combobox = getInterface(centralWidgetChildren.at(6), "org.a11y.atspi.Accessible");
//     QCOMPARE(combobox->property("Name").toString(), QLatin1String("Comboboxes are fun!"));
//     QCOMPARE(getChildren(combobox).count(), 3);
//
//
//
//     delete combobox;
//     delete tabWidget;
//     delete text;
//     delete lineEdit;
//     delete label2;
//     delete button;
//     delete label;
//
//     delete centralWidget;
//     delete mainWindow;
// }
//
// void tst_QtAtSpi::menu()
// {
//     QStringList c = getChildren(mainWindow);
//     QDBusInterface* menuRoot = getInterface(c.at(1), "org.a11y.atspi.Accessible");
//     QCOMPARE(menuRoot->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("menu bar"));
//     QCOMPARE(menuRoot->property("Name").toString(), QLatin1String("aN:menubar"));
//     QStringList menus = getChildren(menuRoot);
//     QCOMPARE(menus.count(), 2); // File, Edit
//
//     QDBusInterface* fileMenu = getInterface(menus.at(0), "org.a11y.atspi.Accessible");
//     QCOMPARE(fileMenu->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("menu item"));
//     QCOMPARE(fileMenu->property("Name").toString(), QLatin1String("File"));
//
//     QDBusInterface* editMenu = getInterface(menus.at(1), "org.a11y.atspi.Accessible");
//     QCOMPARE(editMenu->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("menu item"));
//     QCOMPARE(editMenu->property("Name").toString(), QLatin1String("Edit"));
// }
//
// void tst_QtAtSpi::cache()
// {
//     QDBusInterface* cache = getInterface("/org/a11y/atspi/cache", "org.a11y.atspi.Cache");
//     //qDebug() << cache->call(QDBus::Block, "GetItems");
//     delete cache;
// }

QTEST_MAIN(tst_QtAtSpi)

#include "tst_qt-atspi.moc"
<|endoftext|>


<commit_before>// libMesh includes
#include <libmesh/libmesh.h>
#include <libmesh/distributed_mesh.h>
#include <libmesh/replicated_mesh.h>
#include <libmesh/mesh_generation.h>
#include <libmesh/edge_edge2.h>

// cppunit includes
#include "test_comm.h"
#include "libmesh_cppunit.h"

using namespace libMesh;

class AllSecondOrderTest : public CppUnit::TestCase
{
public:
  LIBMESH_CPPUNIT_TEST_SUITE( AllSecondOrderTest );

  CPPUNIT_TEST( allSecondOrder );
  CPPUNIT_TEST( allSecondOrderRange );

  CPPUNIT_TEST_SUITE_END();

public:
  void setUp() {}

  void tearDown() {}

  void allSecondOrder()
  {
    LOG_UNIT_TEST;

    DistributedMesh mesh(*TestCommWorld, /*dim=*/2);

    mesh.allow_remote_element_removal(false);

    MeshTools::Generation::build_square(mesh, 2, 2);

    mesh.all_second_order();
  }

  void allSecondOrderRange()
  {
    ReplicatedMesh mesh(*TestCommWorld);

    // Construct a single-element Quad4 mesh
    MeshTools::Generation::build_square(mesh, /*nx=*/1, /*ny=*/1);

    // Add extra nodes above the four original nodes
    Point z_trans(0,0,1);
    for (dof_id_type n=0; n<4; ++n)
      mesh.add_point(mesh.point(n) + z_trans, /*id=*/4+n, /*proc_id=*/0);

    // Construct Edge2 elements attached to Quad4 at individual points
    // and in subdomain 1.
    for (dof_id_type n=0; n<4; ++n)
      {
        Elem * elem = mesh.add_elem(new Edge2);
        elem->set_node(0) = mesh.node_ptr(n);
        elem->set_node(1) = mesh.node_ptr(n+4);
        elem->subdomain_id() = 1;
      }

    // Convert only Edge2 elements (all elements in subdomain 1) to
    // SECOND-order.
    mesh.all_second_order_range(mesh.active_subdomain_elements_ptr_range(1),
                                /*full_ordered=*/true);
  }
};

CPPUNIT_TEST_SUITE_REGISTRATION( AllSecondOrderTest );
<commit_msg>Add checks to unit test<commit_after>// libMesh includes
#include <libmesh/libmesh.h>
#include <libmesh/distributed_mesh.h>
#include <libmesh/replicated_mesh.h>
#include <libmesh/mesh_generation.h>
#include <libmesh/edge_edge2.h>

// cppunit includes
#include "test_comm.h"
#include "libmesh_cppunit.h"

using namespace libMesh;

class AllSecondOrderTest : public CppUnit::TestCase
{
public:
  LIBMESH_CPPUNIT_TEST_SUITE( AllSecondOrderTest );

  CPPUNIT_TEST( allSecondOrder );
  CPPUNIT_TEST( allSecondOrderRange );

  CPPUNIT_TEST_SUITE_END();

public:
  void setUp() {}

  void tearDown() {}

  void allSecondOrder()
  {
    LOG_UNIT_TEST;

    DistributedMesh mesh(*TestCommWorld, /*dim=*/2);

    mesh.allow_remote_element_removal(false);

    MeshTools::Generation::build_square(mesh, 2, 2);

    mesh.all_second_order();
  }

  void allSecondOrderRange()
  {
    ReplicatedMesh mesh(*TestCommWorld);

    // Construct a single-element Quad4 mesh
    MeshTools::Generation::build_square(mesh, /*nx=*/1, /*ny=*/1);

    // Add extra nodes above the four original nodes
    Point z_trans(0,0,1);
    for (dof_id_type n=0; n<4; ++n)
      mesh.add_point(mesh.point(n) + z_trans, /*id=*/4+n, /*proc_id=*/0);

    // Construct Edge2 elements attached to Quad4 at individual points
    // and in subdomain 1.
    for (dof_id_type n=0; n<4; ++n)
      {
        Elem * elem = mesh.add_elem(new Edge2);
        elem->set_node(0) = mesh.node_ptr(n);
        elem->set_node(1) = mesh.node_ptr(n+4);
        elem->subdomain_id() = 1;
      }

    // Convert only Edge2 elements (all elements in subdomain 1) to
    // SECOND-order.
    mesh.all_second_order_range(mesh.active_subdomain_elements_ptr_range(1),
                                /*full_ordered=*/true);

    // Make sure we still have the expected total number of elements
    CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(5), mesh.n_elem());

    // Make sure we added the right number of nodes
    CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(12), mesh.n_nodes());

    // Make sure that the type of the Quad4 is unchanged
    CPPUNIT_ASSERT_EQUAL(QUAD4, mesh.elem_ptr(0)->type());

    // Make sure that the other elements are now Edge3s
    for (dof_id_type e=1; e<5; ++e)
      CPPUNIT_ASSERT_EQUAL(EDGE3, mesh.elem_ptr(e)->type());
  }
};

CPPUNIT_TEST_SUITE_REGISTRATION( AllSecondOrderTest );
<|endoftext|>


<commit_before>// Copyright 2018 Google LLC. All Rights Reserved.
/*
  Copyright (C) 2005-2018 Steven L. Scott

  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 "Models/Glm/PosteriorSamplers/SpikeSlabSampler.hpp"
#include "cpputil/math_utils.hpp"
#include "cpputil/seq.hpp"
#include "distributions.hpp"

namespace BOOM {

  namespace {
    typedef SpikeSlabSampler SSS;
  }

  SSS::SpikeSlabSampler(GlmModel *model, const Ptr<MvnBase> &slab_prior,
                        const Ptr<VariableSelectionPrior> &spike_prior)
      : model_(model),
        slab_prior_(slab_prior),
        spike_prior_(spike_prior),
        max_flips_(-1),
        allow_model_selection_(true) {}

  // Performs one MCMC sweep along the provided set of inclusion indicators.
  void SSS::draw_inclusion_indicators(
      RNG &rng,
      Selector &inclusion_indicators,
      const WeightedRegSuf &suf,
      double sigsq) const {
    if (!allow_model_selection_) return;
    std::vector<int> indx =
        seq<int>(0, inclusion_indicators.nvars_possible() - 1);
    // I'd like to rely on std::random_shuffle for this, but I want
    // control over the random number generator.
    for (int i = indx.size() - 1; i > 0; --i) {
      int j = random_int_mt(rng, 0, i);
      if (j != i) {
        std::swap(indx[i], indx[j]);
      }
    }

    double logp = log_model_prob(inclusion_indicators, suf, sigsq);

    if (!std::isfinite(logp)) {
      spike_prior_->make_valid(inclusion_indicators);
      logp = log_model_prob(inclusion_indicators, suf, sigsq);
    }
    if (!std::isfinite(logp)) {
      ostringstream err;
      err << "SpikeSlabSampler did not start with a "
          << "legal configuration." << endl
          << "Selector vector:  " << inclusion_indicators << endl;
      if (model_) {
        err << "beta: " << model_->included_coefficients() << endl;
      }
      report_error(err.str());
    }

    uint n = inclusion_indicators.nvars_possible();
    if (max_flips_ > 0) n = std::min<int>(n, max_flips_);
    for (int i = 0; i < n; ++i) {
      logp = mcmc_one_flip(
          rng, inclusion_indicators, indx[i], logp, suf, sigsq);
    }
  }

  // Performs one MCMC sweep along the inclusion indicators for the
  // managed GlmModel.
  void SSS::draw_model_indicators(
      RNG &rng, const WeightedRegSuf &suf, double sigsq) {
    if (!allow_model_selection_) return;
    if (!model_) {
      report_error("No model was set.");
    }
    Selector inclusion_indicators = model_->coef().inc();
    draw_inclusion_indicators(rng, inclusion_indicators, suf, sigsq);
    model_->coef().set_inc(inclusion_indicators);
  }

  void SSS::draw_beta(RNG &rng, const WeightedRegSuf &suf, double sigsq) {
    if (!model_) {
      report_error("No model was set.");
    }
    Selector inclusion_indicators = model_->coef().inc();
    if (inclusion_indicators.nvars() == 0) {
      model_->drop_all();
      return;
    }
    Vector coefficients = model_->included_coefficients();
    draw_coefficients_given_inclusion(rng, coefficients, inclusion_indicators,
                                      suf, sigsq, false);
    // If model selection is turned off and some elements of beta
    // happen to be zero (because, e.inclusion_indicators., of a
    // failed MH step) we don't want the dimension of beta to change.
    model_->set_included_coefficients(coefficients);
  }

  void SSS::draw_coefficients_given_inclusion(
      RNG &rng, Vector &coefficients, const Selector &inclusion_indicators,
      const WeightedRegSuf &suf, double sigsq, bool full_set) const {
    if (inclusion_indicators.nvars() == 0) {
      if (full_set) {
        coefficients = 0.0;
      } else {
        coefficients.clear();
      }
      return;
    }
    SpdMatrix precision = inclusion_indicators.select(slab_prior_->siginv());
    Vector precision_mu =
        precision * inclusion_indicators.select(slab_prior_->mu());
    precision += inclusion_indicators.select(suf.xtx()) / sigsq;
    precision_mu += inclusion_indicators.select(suf.xty()) / sigsq;
    Vector mean = precision.solve(precision_mu);
    Vector draw = rmvn_ivar_mt(rng, mean, precision);
    if (full_set) {
      coefficients = inclusion_indicators.expand(draw);
    } else {
      coefficients = draw;
    }
  }

  double SSS::logpri() const {
    if (!model_) {
      report_error("No model was set.");
    }
    const Selector &inclusion_indicators(model_->coef().inc());
    double ans = spike_prior_->logp(inclusion_indicators);  // p(gamma)
    if (ans == BOOM::negative_infinity()) return ans;
    if (inclusion_indicators.nvars() > 0) {
      ans += dmvn(model_->included_coefficients(),
                  inclusion_indicators.select(slab_prior_->mu()),
                  inclusion_indicators.select(slab_prior_->siginv()), true);
    }
    return ans;
  }

  void SSS::allow_model_selection(bool tf) { allow_model_selection_ = tf; }

  void SSS::limit_model_selection(int max_flips) { max_flips_ = max_flips; }

  double SSS::log_model_prob(const Selector &inclusion_indicators,
                             const WeightedRegSuf &suf, double sigsq) const {
    double numerator = spike_prior_->logp(inclusion_indicators);
    if (numerator == BOOM::negative_infinity() ||
        inclusion_indicators.nvars() == 0) {
      // If numerator == -infinity then it is in a zero support point
      // in the prior.  If inclusion_indicators.nvars()==0 then all
      // coefficients are zero because of the point mass.  The only
      // entries remaining in the likelihood are sums of squares of
      // y[i] that are independent of inclusion_indicators.  They need
      // to be omitted here because they are omitted in the non-empty
      // case below.
      return numerator;
    }
    SpdMatrix precision = inclusion_indicators.select(slab_prior_->siginv());
    numerator += .5 * precision.logdet();
    if (numerator == BOOM::negative_infinity()) return numerator;

    Vector mu = inclusion_indicators.select(slab_prior_->mu());
    Vector precision_mu = precision * mu;
    numerator -= .5 * mu.dot(precision_mu);

    bool ok = true;
    precision += inclusion_indicators.select(suf.xtx()) / sigsq;
    Matrix L = precision.chol(ok);
    if (!ok) return BOOM::negative_infinity();
    double denominator = sum(log(L.diag()));  // = .5 log |precision|
    Vector S = inclusion_indicators.select(suf.xty()) / sigsq + precision_mu;
    Lsolve_inplace(L, S);
    denominator -= .5 * S.normsq();
    // S.normsq =  beta_tilde ^T V_tilde beta_tilde
    return numerator - denominator;
  }

  double SSS::mcmc_one_flip(RNG &rng, Selector &mod, int which_var,
                            double logp_old, const WeightedRegSuf &suf,
                            double sigsq) const {
    mod.flip(which_var);
    double logp_new = log_model_prob(mod, suf, sigsq);
    double u = runif_mt(rng, 0, 1);
    if (log(u) > logp_new - logp_old) {
      mod.flip(which_var);  // reject draw
      return logp_old;
    }
    return logp_new;
  }

}  // namespace BOOM
<commit_msg>add a comment<commit_after>// Copyright 2018 Google LLC. All Rights Reserved.
/*
  Copyright (C) 2005-2018 Steven L. Scott

  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 "Models/Glm/PosteriorSamplers/SpikeSlabSampler.hpp"
#include "cpputil/math_utils.hpp"
#include "cpputil/seq.hpp"
#include "distributions.hpp"

namespace BOOM {

  namespace {
    typedef SpikeSlabSampler SSS;
  }

  SSS::SpikeSlabSampler(GlmModel *model, const Ptr<MvnBase> &slab_prior,
                        const Ptr<VariableSelectionPrior> &spike_prior)
      : model_(model),
        slab_prior_(slab_prior),
        spike_prior_(spike_prior),
        max_flips_(-1),
        allow_model_selection_(true) {}

  // Performs one MCMC sweep along the provided set of inclusion indicators.
  void SSS::draw_inclusion_indicators(
      RNG &rng,
      Selector &inclusion_indicators,
      const WeightedRegSuf &suf,
      double sigsq) const {
    if (!allow_model_selection_) return;

    // Randomize the order in which the inclusion indicators are to be drawn.
    std::vector<int> indx =
        seq<int>(0, inclusion_indicators.nvars_possible() - 1);
    // I'd like to rely on std::random_shuffle for this, but I want
    // control over the random number generator.
    for (int i = indx.size() - 1; i > 0; --i) {
      int j = random_int_mt(rng, 0, i);
      if (j != i) {
        std::swap(indx[i], indx[j]);
      }
    }

    double logp = log_model_prob(inclusion_indicators, suf, sigsq);

    if (!std::isfinite(logp)) {
      spike_prior_->make_valid(inclusion_indicators);
      logp = log_model_prob(inclusion_indicators, suf, sigsq);
    }
    if (!std::isfinite(logp)) {
      ostringstream err;
      err << "SpikeSlabSampler did not start with a "
          << "legal configuration." << endl
          << "Selector vector:  " << inclusion_indicators << endl;
      if (model_) {
        err << "beta: " << model_->included_coefficients() << endl;
      }
      report_error(err.str());
    }

    uint n = inclusion_indicators.nvars_possible();
    if (max_flips_ > 0) n = std::min<int>(n, max_flips_);
    for (int i = 0; i < n; ++i) {
      logp = mcmc_one_flip(
          rng, inclusion_indicators, indx[i], logp, suf, sigsq);
    }
  }

  // Performs one MCMC sweep along the inclusion indicators for the
  // managed GlmModel.
  void SSS::draw_model_indicators(
      RNG &rng, const WeightedRegSuf &suf, double sigsq) {
    if (!allow_model_selection_) return;
    if (!model_) {
      report_error("No model was set.");
    }
    Selector inclusion_indicators = model_->coef().inc();
    draw_inclusion_indicators(rng, inclusion_indicators, suf, sigsq);
    model_->coef().set_inc(inclusion_indicators);
  }

  void SSS::draw_beta(RNG &rng, const WeightedRegSuf &suf, double sigsq) {
    if (!model_) {
      report_error("No model was set.");
    }
    Selector inclusion_indicators = model_->coef().inc();
    if (inclusion_indicators.nvars() == 0) {
      model_->drop_all();
      return;
    }
    Vector coefficients = model_->included_coefficients();
    draw_coefficients_given_inclusion(rng, coefficients, inclusion_indicators,
                                      suf, sigsq, false);
    // If model selection is turned off and some elements of beta
    // happen to be zero (because, e.inclusion_indicators., of a
    // failed MH step) we don't want the dimension of beta to change.
    model_->set_included_coefficients(coefficients);
  }

  void SSS::draw_coefficients_given_inclusion(
      RNG &rng, Vector &coefficients, const Selector &inclusion_indicators,
      const WeightedRegSuf &suf, double sigsq, bool full_set) const {
    if (inclusion_indicators.nvars() == 0) {
      if (full_set) {
        coefficients = 0.0;
      } else {
        coefficients.clear();
      }
      return;
    }
    SpdMatrix precision = inclusion_indicators.select(slab_prior_->siginv());
    Vector precision_mu =
        precision * inclusion_indicators.select(slab_prior_->mu());
    precision += inclusion_indicators.select(suf.xtx()) / sigsq;
    precision_mu += inclusion_indicators.select(suf.xty()) / sigsq;
    Vector mean = precision.solve(precision_mu);
    Vector draw = rmvn_ivar_mt(rng, mean, precision);
    if (full_set) {
      coefficients = inclusion_indicators.expand(draw);
    } else {
      coefficients = draw;
    }
  }

  double SSS::logpri() const {
    if (!model_) {
      report_error("No model was set.");
    }
    const Selector &inclusion_indicators(model_->coef().inc());
    double ans = spike_prior_->logp(inclusion_indicators);  // p(gamma)
    if (ans == BOOM::negative_infinity()) return ans;
    if (inclusion_indicators.nvars() > 0) {
      ans += dmvn(model_->included_coefficients(),
                  inclusion_indicators.select(slab_prior_->mu()),
                  inclusion_indicators.select(slab_prior_->siginv()), true);
    }
    return ans;
  }

  void SSS::allow_model_selection(bool tf) { allow_model_selection_ = tf; }

  void SSS::limit_model_selection(int max_flips) { max_flips_ = max_flips; }

  double SSS::log_model_prob(const Selector &inclusion_indicators,
                             const WeightedRegSuf &suf, double sigsq) const {
    double numerator = spike_prior_->logp(inclusion_indicators);
    if (numerator == BOOM::negative_infinity() ||
        inclusion_indicators.nvars() == 0) {
      // If numerator == -infinity then it is in a zero support point
      // in the prior.  If inclusion_indicators.nvars()==0 then all
      // coefficients are zero because of the point mass.  The only
      // entries remaining in the likelihood are sums of squares of
      // y[i] that are independent of inclusion_indicators.  They need
      // to be omitted here because they are omitted in the non-empty
      // case below.
      return numerator;
    }
    SpdMatrix precision = inclusion_indicators.select(slab_prior_->siginv());
    numerator += .5 * precision.logdet();
    if (numerator == BOOM::negative_infinity()) return numerator;

    Vector mu = inclusion_indicators.select(slab_prior_->mu());
    Vector precision_mu = precision * mu;
    numerator -= .5 * mu.dot(precision_mu);

    bool ok = true;
    precision += inclusion_indicators.select(suf.xtx()) / sigsq;
    Matrix L = precision.chol(ok);
    if (!ok) return BOOM::negative_infinity();
    double denominator = sum(log(L.diag()));  // = .5 log |precision|
    Vector S = inclusion_indicators.select(suf.xty()) / sigsq + precision_mu;
    Lsolve_inplace(L, S);
    denominator -= .5 * S.normsq();
    // S.normsq =  beta_tilde ^T V_tilde beta_tilde
    return numerator - denominator;
  }

  double SSS::mcmc_one_flip(RNG &rng, Selector &mod, int which_var,
                            double logp_old, const WeightedRegSuf &suf,
                            double sigsq) const {
    mod.flip(which_var);
    double logp_new = log_model_prob(mod, suf, sigsq);
    double u = runif_mt(rng, 0, 1);
    if (log(u) > logp_new - logp_old) {
      mod.flip(which_var);  // reject draw
      return logp_old;
    }
    return logp_new;
  }

}  // namespace BOOM
<|endoftext|>


<commit_before>#define PUT(x) std::cout << #x "=" << (x) << std::endl;
#include <cybozu/test.hpp>
#include <cybozu/xorshift.hpp>
#include <cybozu/benchmark.hpp>

#if 1
#include <mcl/bn384.hpp>
using namespace mcl::bn384;
#else
#include <mcl/bn256.hpp>
using namespace mcl::bn256;
#endif

#define PUT(x) std::cout << #x "=" << (x) << std::endl;

/*
	Skew Frobenius Map and Efficient Scalar Multiplication for Pairing-Based Cryptography
	Y. Sakemi, Y. Nogami, K. Okeya, H. Kato, Y. Morikawa
*/
struct oldGLV {
	Fp w; // (-1 + sqrt(-3)) / 2
	mpz_class r;
	mpz_class v; // 6z^2 + 4z + 1 > 0
	mpz_class c; // 2z + 1
	void init(const mpz_class& r, const mpz_class& z)
	{
		if (!Fp::squareRoot(w, -3)) throw cybozu::Exception("oldGLV:init");
		w = (w - 1) / 2;
		this->r = r;
		v = 1 + z * (4 + z * 6);
		c = 2 * z + 1;
	}
	/*
		(p^2 mod r) (x, y) = (wx, -y)
	*/
	void mulP2(G1& Q, const G1& P) const
	{
		Fp::mul(Q.x, P.x, w);
		Fp::neg(Q.y, P.y);
		Q.z = P.z;
	}
	/*
		x = ap^2 + b mod r
		assume(x < r);
	*/
	void split(mpz_class& a, mpz_class& b, const mpz_class& x) const
	{
		assert(0 < x && x < r);
		/*
			x = s1 * v + s2                  // s1 = x / v, s2 = x % v
			= s1 * c * p^2 + s2              // vP = cp^2 P
			= (s3 * v + s4) * p^2 + s2       // s3 = (s1 * c) / v, s4 = (s1 * c) % v
			= (s3 * c * p^2 + s4) * p^2 + s2
			= (s3 * c) * p^4 + s4 * p^2 + s2 // s5 = s3 * c, p^4 = p^2 - 1
			= s5 * (p^2 - 1) + s4 * p^2 + s2
			= (s4 + s5) * p^2 + (s2 - s5)
		*/
		mpz_class t;
		mcl::gmp::divmod(a, t, x, v); // a = t / v, t = t % v
		a *= c;
		mcl::gmp::divmod(b, a, a, v); // b = a / v, a = a % v
		b *= c;
		a += b;
		b = t - b;
	}
	template<class G1>
	void mul(G1& Q, const G1& P, const mpz_class& x) const
	{
		G1 A, B;
		mpz_class a, b;
		split(a, b, x);
		mulP2(A, P);
		G1::mul(A, A, a);
		G1::mul(B, P, b);
		G1::add(Q, A, B);
	}
};

template<class GLV1, class GLV2>
void compareLength(const GLV1& rhs, const GLV2& lhs)
{
	cybozu::XorShift rg;
	int Rc = 0;
	int Lc = 0;
	int eq = 0;
	mpz_class R0, R1, L0, L1, x;
	Fr r;
	for (int i = 1; i < 1000; i++) {
		r.setRand(rg);
		x = r.getMpz();
		rhs.split(R0, R1, x);
		lhs.split(L0, L1, x);

		size_t R0n = mcl::gmp::getBitSize(R0);
		size_t R1n = mcl::gmp::getBitSize(R1);
		size_t L0n = mcl::gmp::getBitSize(L0);
		size_t L1n = mcl::gmp::getBitSize(L1);
		size_t Rn = std::max(R0n, R1n);
		size_t Ln = std::max(L0n, L1n);
		if (Rn == Ln) {
			eq++;
		}
		if (Rn > Ln) {
			Rc++;
		}
		if (Rn < Ln) {
			Lc++;
		}
	}
	printf("eq=%d small is better rhs=%d, lhs=%d\n", eq, Rc, Lc);
}

void testGLV(const mcl::bn::CurveParam& cp)
{
	bn384init(cp);
	G1::setCompressedExpression(false);

	G1 P0, P1, P2;
	BN::mapToG1(P0, 1);
	cybozu::XorShift rg;

	oldGLV oldGlv;
	oldGlv.init(BN::param.r, BN::param.z);

	mcl::bn::GLV1<Fp> glv;
	glv.init(BN::param.r, BN::param.z);
	compareLength(glv, oldGlv);

	for (int i = 1; i < 100; i++) {
		BN::mapToG1(P0, i);
		Fr s;
		s.setRand(rg);
		mpz_class ss = s.getMpz();
		G1::mulBase(P1, P0, ss);
		glv.mul(P2, P0, ss);
		CYBOZU_TEST_EQUAL(P1, P2);
		glv.mul(P2, P0, ss, true);
		CYBOZU_TEST_EQUAL(P1, P2);
		oldGlv.mul(P2, P0, ss);
		CYBOZU_TEST_EQUAL(P1, P2);
	}
	for (int i = -100; i < 100; i++) {
		mpz_class ss = i;
		G1::mulBase(P1, P0, ss);
		glv.mul(P2, P0, ss);
		CYBOZU_TEST_EQUAL(P1, P2);
		glv.mul(P2, P0, ss, true);
		CYBOZU_TEST_EQUAL(P1, P2);
	}
	Fr s;
	BN::mapToG1(P0, 123);
	CYBOZU_BENCH_C("Ec::mul", 100, P1 = P0; s.setRand(rg); G1::mul, P2, P1, s.getMpz());
	CYBOZU_BENCH_C("Ec::glv", 100, P1 = P0; s.setRand(rg); glv.mul, P2, P1, s.getMpz());
}

template<class Fp2>
struct GLV2 {
	typedef mcl::EcT<Fp2> G2;
	size_t m;
	mpz_class B[4][4];
	mpz_class r;
	mpz_class v[4];
	void init(const mpz_class& r, const mpz_class& z)
	{
		this->r = r;
		m = mcl::gmp::getBitSize(r);
//		m = (m + mcl::fp::UnitBitSize - 1) & ~(mcl::fp::UnitBitSize - 1);// a little better size
		v[0] = ((1 + z * (3 + z * 2)) << m) / r;
		v[1] = ((z * (1 + z * (8 + z * 12))) << m) / r;
		v[2] = ((z * (1 + z * (4 + z * 6))) << m) / r;
		v[3] = -((z * (1 + z)) << m) / r;
		PUT(v[0]);
		PUT(v[1]);
		PUT(v[2]);
		PUT(v[3]);
		{
			const mpz_class z2p1 = z * 2 + 1;
			B[0][0] = z + 1;
			B[0][1] = z;
			B[0][2] = z;
			B[0][3] = -2 * z;
			B[1][0] = z2p1;
			B[1][1] = -z;
			B[1][2] = -(z + 1);
			B[1][3] = -z;
			B[2][0] = 2 * z;
			B[2][1] = z2p1;
			B[2][2] = z2p1;
			B[2][3] = z2p1;
			B[3][0] = z - 1;
			B[3][1] = 2 * z2p1;
			B[3][2] =  -2 * z + 1;
			B[3][3] = z - 1;
		}
	}
	void split(mpz_class u[4], const mpz_class& n) const
	{
		mpz_class t[4];
		for (int i = 0; i < 4; i++) {
			t[i] = (n * v[i]) >> m;
		}
		for (int i = 0; i < 4; i++) {
			u[i] = (i == 0) ? n : 0;
			for (int j = 0; j < 4; j++) {
				u[i] -= t[j] * B[j][i];
			}
		}
	}
};
/*
	lambda = 6 * z * z
	mul (lambda * 2) = FrobeniusOnTwist * 2
*/
void testGLV2(const mcl::bn::CurveParam& cp)
{
	bn384init(cp);
	G2::setCompressedExpression(false);
	G2 Q0, Q1, Q2;
	const mpz_class& z = BN::param.z;
	const mpz_class& r = BN::param.r;
	mpz_class lambda = 6 * z * z;
	GLV2<Fp2> glv2;
	glv2.init(r, z);
	mpz_class u[4];
	mpz_class n;
	cybozu::XorShift rg;
	for (int i = 0; i < 10; i++) {
		mcl::gmp::getRand(n, glv2.m, rg);
		n %= r;
		glv2.split(u, n);
		PUT(n);
		PUT(u[0]);
		PUT(u[1]);
		PUT(u[2]);
		PUT(u[3]);
		mpz_class v = u[0] + lambda * (u[1] + lambda * (u[2] + lambda * u[3]));
		PUT((n - v) % r);
	}
}

CYBOZU_TEST_AUTO(glv)
{
	testGLV2(mcl::bn::CurveFp254BNb);
return;
	testGLV(mcl::bn::CurveFp254BNb);
	testGLV(mcl::bn::CurveFp382_1);
	testGLV(mcl::bn::CurveFp382_2);
}
<commit_msg>test glv for g2<commit_after>#define PUT(x) std::cout << #x "=" << (x) << std::endl;
#include <cybozu/test.hpp>
#include <cybozu/xorshift.hpp>
#include <cybozu/benchmark.hpp>

#if 1
#include <mcl/bn384.hpp>
using namespace mcl::bn384;
#else
#include <mcl/bn256.hpp>
using namespace mcl::bn256;
#endif

#define PUT(x) std::cout << #x "=" << (x) << std::endl;

/*
	Skew Frobenius Map and Efficient Scalar Multiplication for Pairing-Based Cryptography
	Y. Sakemi, Y. Nogami, K. Okeya, H. Kato, Y. Morikawa
*/
struct oldGLV {
	Fp w; // (-1 + sqrt(-3)) / 2
	mpz_class r;
	mpz_class v; // 6z^2 + 4z + 1 > 0
	mpz_class c; // 2z + 1
	void init(const mpz_class& r, const mpz_class& z)
	{
		if (!Fp::squareRoot(w, -3)) throw cybozu::Exception("oldGLV:init");
		w = (w - 1) / 2;
		this->r = r;
		v = 1 + z * (4 + z * 6);
		c = 2 * z + 1;
	}
	/*
		(p^2 mod r) (x, y) = (wx, -y)
	*/
	void mulP2(G1& Q, const G1& P) const
	{
		Fp::mul(Q.x, P.x, w);
		Fp::neg(Q.y, P.y);
		Q.z = P.z;
	}
	/*
		x = ap^2 + b mod r
		assume(x < r);
	*/
	void split(mpz_class& a, mpz_class& b, const mpz_class& x) const
	{
		assert(0 < x && x < r);
		/*
			x = s1 * v + s2                  // s1 = x / v, s2 = x % v
			= s1 * c * p^2 + s2              // vP = cp^2 P
			= (s3 * v + s4) * p^2 + s2       // s3 = (s1 * c) / v, s4 = (s1 * c) % v
			= (s3 * c * p^2 + s4) * p^2 + s2
			= (s3 * c) * p^4 + s4 * p^2 + s2 // s5 = s3 * c, p^4 = p^2 - 1
			= s5 * (p^2 - 1) + s4 * p^2 + s2
			= (s4 + s5) * p^2 + (s2 - s5)
		*/
		mpz_class t;
		mcl::gmp::divmod(a, t, x, v); // a = t / v, t = t % v
		a *= c;
		mcl::gmp::divmod(b, a, a, v); // b = a / v, a = a % v
		b *= c;
		a += b;
		b = t - b;
	}
	template<class G1>
	void mul(G1& Q, const G1& P, const mpz_class& x) const
	{
		G1 A, B;
		mpz_class a, b;
		split(a, b, x);
		mulP2(A, P);
		G1::mul(A, A, a);
		G1::mul(B, P, b);
		G1::add(Q, A, B);
	}
};

template<class GLV1, class GLV2>
void compareLength(const GLV1& rhs, const GLV2& lhs)
{
	cybozu::XorShift rg;
	int Rc = 0;
	int Lc = 0;
	int eq = 0;
	mpz_class R0, R1, L0, L1, x;
	Fr r;
	for (int i = 1; i < 1000; i++) {
		r.setRand(rg);
		x = r.getMpz();
		rhs.split(R0, R1, x);
		lhs.split(L0, L1, x);

		size_t R0n = mcl::gmp::getBitSize(R0);
		size_t R1n = mcl::gmp::getBitSize(R1);
		size_t L0n = mcl::gmp::getBitSize(L0);
		size_t L1n = mcl::gmp::getBitSize(L1);
		size_t Rn = std::max(R0n, R1n);
		size_t Ln = std::max(L0n, L1n);
		if (Rn == Ln) {
			eq++;
		}
		if (Rn > Ln) {
			Rc++;
		}
		if (Rn < Ln) {
			Lc++;
		}
	}
	printf("eq=%d small is better rhs=%d, lhs=%d\n", eq, Rc, Lc);
}

void testGLV(const mcl::bn::CurveParam& cp)
{
	bn384init(cp);
	G1::setCompressedExpression(false);

	G1 P0, P1, P2;
	BN::mapToG1(P0, 1);
	cybozu::XorShift rg;

	oldGLV oldGlv;
	oldGlv.init(BN::param.r, BN::param.z);

	mcl::bn::GLV1<Fp> glv;
	glv.init(BN::param.r, BN::param.z);
	compareLength(glv, oldGlv);

	for (int i = 1; i < 100; i++) {
		BN::mapToG1(P0, i);
		Fr s;
		s.setRand(rg);
		mpz_class ss = s.getMpz();
		G1::mulBase(P1, P0, ss);
		glv.mul(P2, P0, ss);
		CYBOZU_TEST_EQUAL(P1, P2);
		glv.mul(P2, P0, ss, true);
		CYBOZU_TEST_EQUAL(P1, P2);
		oldGlv.mul(P2, P0, ss);
		CYBOZU_TEST_EQUAL(P1, P2);
	}
	for (int i = -100; i < 100; i++) {
		mpz_class ss = i;
		G1::mulBase(P1, P0, ss);
		glv.mul(P2, P0, ss);
		CYBOZU_TEST_EQUAL(P1, P2);
		glv.mul(P2, P0, ss, true);
		CYBOZU_TEST_EQUAL(P1, P2);
	}
	Fr s;
	BN::mapToG1(P0, 123);
	CYBOZU_BENCH_C("Ec::mul", 100, P1 = P0; s.setRand(rg); G1::mul, P2, P1, s.getMpz());
	CYBOZU_BENCH_C("Ec::glv", 100, P1 = P0; s.setRand(rg); glv.mul, P2, P1, s.getMpz());
}

template<class Fp2>
struct GLV2 {
	typedef mcl::EcT<Fp2> G2;
	size_t m;
	mpz_class B[4][4];
	mpz_class r;
	mpz_class v[4];
	void init(const mpz_class& r, const mpz_class& z)
	{
		this->r = r;
		m = mcl::gmp::getBitSize(r);
//		m = (m + mcl::fp::UnitBitSize - 1) & ~(mcl::fp::UnitBitSize - 1);// a little better size
#if 1
		v[0] = (1 + z * (3 + z * 2));
		v[1] = (z * (1 + z * (8 + z * 12)));
		v[2] = (z * (1 + z * (4 + z * 6)));
		v[3] = -(z * (1 + z * 2));
#else
		v[0] = ((1 + z * (3 + z * 2)) << m) / r;
		v[1] = ((z * (1 + z * (8 + z * 12))) << m) / r;
		v[2] = ((z * (1 + z * (4 + z * 6))) << m) / r;
		v[3] = -((z * (1 + z * 2)) << m) / r;
#endif
		PUT(v[0]);
		PUT(v[1]);
		PUT(v[2]);
		PUT(v[3]);
		{
			const mpz_class z2p1 = z * 2 + 1;
			B[0][0] = z + 1;
			B[0][1] = z;
			B[0][2] = z;
			B[0][3] = -2 * z;
			B[1][0] = z2p1;
			B[1][1] = -z;
			B[1][2] = -(z + 1);
			B[1][3] = -z;
			B[2][0] = 2 * z;
			B[2][1] = z2p1;
			B[2][2] = z2p1;
			B[2][3] = z2p1;
			B[3][0] = z - 1;
			B[3][1] = 2 * z2p1;
			B[3][2] =  -2 * z + 1;
			B[3][3] = z - 1;
		}
	}
	void split(mpz_class u[4], const mpz_class& n) const
	{
		mpz_class t[4];
		for (int i = 0; i < 4; i++) {
//			t[i] = (n * v[i]) >> m;
			t[i] = (n * v[i]) / r;
PUT(n * v[i]);
PUT(t[i]);
		}
		for (int i = 0; i < 4; i++) {
			u[i] = (i == 0) ? n : 0;
			for (int j = 0; j < 4; j++) {
				u[i] -= t[j] * B[j][i];
			}
		}
	}
};
/*
	lambda = 6 * z * z
	mul (lambda * 2) = FrobeniusOnTwist * 2
*/
void testGLV2(const mcl::bn::CurveParam& cp)
{
	bn384init(cp);
	G2::setCompressedExpression(false);
	G2 Q0, Q1, Q2;
	mpz_class z = BN::param.z;
	mpz_class r = BN::param.r;
//z = 10267;
r = 36*z*z*z*z+36*z*z*z+18*z*z+6*z+1;
	mpz_class lambda = 6 * z * z;
	GLV2<Fp2> glv2;
	glv2.init(r, z);
	mpz_class u[4];
	mpz_class n;
	cybozu::XorShift rg;
//	std::cout << std::hex;
	for (int i = 0; i < 3; i++) {
		mcl::gmp::getRand(n, glv2.m, rg);
		n %= r;
//n.set_str("123456789123456789", 10);
		glv2.split(u, n);
		PUT(n);
		PUT(u[0]); PUT(mcl::gmp::getBitSize(u[0]));
		PUT(u[1]);
		PUT(u[2]);
		PUT(u[3]);
		mpz_class v = u[0] + lambda * (u[1] + lambda * (u[2] + lambda * u[3]));
		PUT((n - v) % r);
	}
}

CYBOZU_TEST_AUTO(glv)
{
//	testGLV2(mcl::bn::CurveFp254BNb);
//return;
	testGLV(mcl::bn::CurveFp254BNb);
	testGLV(mcl::bn::CurveFp382_1);
	testGLV(mcl::bn::CurveFp382_2);
}
<|endoftext|>


<commit_before>/*=========================================================================
*
*  Copyright Insight Software Consortium
*
*  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.txt
*
*  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 "sitkImageSeriesWriter.h"

#include <itkImageIOBase.h>
#include <itkImageSeriesWriter.h>

namespace itk {
  namespace simple {

  void WriteImage ( const Image& inImage, const std::vector<std::string> &filenames, bool inUseCompression )
  {
    ImageSeriesWriter writer;
    writer.Execute( inImage, filenames, inUseCompression );
  }

  ImageSeriesWriter::ImageSeriesWriter()
  {

    this->m_UseCompression = false;

    // list of pixel types supported
    typedef NonLabelPixelIDTypeList PixelIDTypeList;

    this->m_MemberFactory.reset( new detail::MemberFunctionFactory<MemberFunctionType>( this ) );

    this->m_MemberFactory->RegisterMemberFunctions< PixelIDTypeList, 3 > ();
    //this->m_MemberFactory->RegisterMemberFunctions< PixelIDTypeList, 2 > ();
  }

  std::string ImageSeriesWriter::ToString() const
  {

    std::ostringstream out;
    out << "itk::simple::ImageSeriesWriter";
    out << std::endl;

    out << "  UseCompression: ";
    this->ToStringHelper(out, this->m_UseCompression);
    out << std::endl;

    out << "  FileNames:" << std::endl;
    std::vector<std::string>::const_iterator iter  = m_FileNames.begin();
    while( iter != m_FileNames.end() )
      {
      std::cout << "    \"" << *iter << "\"" << std::endl;
      ++iter;
      }

    return out.str();
  }

  ImageSeriesWriter::Self&
  ImageSeriesWriter::SetUseCompression( bool UseCompression )
  {
    this->m_UseCompression = UseCompression;
    return *this;
  }

  bool ImageSeriesWriter::GetUseCompression( void ) const
  {
    return this->m_UseCompression;
  }

  ImageSeriesWriter& ImageSeriesWriter::SetFileNames ( const std::vector<std::string> &filenames )
  {
    this->m_FileNames = filenames;
    return *this;
  }

  const std::vector<std::string> &ImageSeriesWriter::GetFileNames() const
  {
    return this->m_FileNames;
  }

  ImageSeriesWriter& ImageSeriesWriter::Execute ( const Image& image, const std::vector<std::string> &inFileNames, bool inUseCompression )
  {
    this->SetFileNames( inFileNames );
    this->SetUseCompression( inUseCompression );
    return this->Execute( image );
  }

  ImageSeriesWriter &ImageSeriesWriter::Execute ( const Image &image )
  {

    // check that the number of file names match the slice size
    PixelIDValueType type = image.GetPixelIDValue();
    unsigned int dimension = image.GetDimension();

    return this->m_MemberFactory->GetMemberFunction( type, dimension )( image );
  }

  template <class TImageType>
  ImageSeriesWriter &
  ImageSeriesWriter::ExecuteInternal( const Image& inImage )
  {
    // Define the input and output image types
    typedef TImageType     InputImageType;

    typename InputImageType::ConstPointer image = this->CastImageToITK<InputImageType>( inImage );

    typedef itk::ImageSeriesWriter<InputImageType,
                                   typename InputImageType::template Rebind<typename InputImageType::PixelType, InputImageType::ImageDimension-1>::Type> Writer;

    typename Writer::Pointer writer = Writer::New();
    writer->SetUseCompression( this->m_UseCompression );
    writer->SetFileNames( this->m_FileNames );
    writer->SetInput( image );

    this->PreUpdate( writer.GetPointer() );

    writer->Update();

    return *this;
  }

  }
}
<commit_msg>Suppress warning about sprintf warning in image series writer.<commit_after>/*=========================================================================
*
*  Copyright Insight Software Consortium
*
*  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.txt
*
*  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 "sitkImageSeriesWriter.h"

#include <itkImageIOBase.h>
// suppress warning about using sprintf
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <itkImageSeriesWriter.h>

namespace itk {
  namespace simple {

  void WriteImage ( const Image& inImage, const std::vector<std::string> &filenames, bool inUseCompression )
  {
    ImageSeriesWriter writer;
    writer.Execute( inImage, filenames, inUseCompression );
  }

  ImageSeriesWriter::ImageSeriesWriter()
  {

    this->m_UseCompression = false;

    // list of pixel types supported
    typedef NonLabelPixelIDTypeList PixelIDTypeList;

    this->m_MemberFactory.reset( new detail::MemberFunctionFactory<MemberFunctionType>( this ) );

    this->m_MemberFactory->RegisterMemberFunctions< PixelIDTypeList, 3 > ();
    //this->m_MemberFactory->RegisterMemberFunctions< PixelIDTypeList, 2 > ();
  }

  std::string ImageSeriesWriter::ToString() const
  {

    std::ostringstream out;
    out << "itk::simple::ImageSeriesWriter";
    out << std::endl;

    out << "  UseCompression: ";
    this->ToStringHelper(out, this->m_UseCompression);
    out << std::endl;

    out << "  FileNames:" << std::endl;
    std::vector<std::string>::const_iterator iter  = m_FileNames.begin();
    while( iter != m_FileNames.end() )
      {
      std::cout << "    \"" << *iter << "\"" << std::endl;
      ++iter;
      }

    return out.str();
  }

  ImageSeriesWriter::Self&
  ImageSeriesWriter::SetUseCompression( bool UseCompression )
  {
    this->m_UseCompression = UseCompression;
    return *this;
  }

  bool ImageSeriesWriter::GetUseCompression( void ) const
  {
    return this->m_UseCompression;
  }

  ImageSeriesWriter& ImageSeriesWriter::SetFileNames ( const std::vector<std::string> &filenames )
  {
    this->m_FileNames = filenames;
    return *this;
  }

  const std::vector<std::string> &ImageSeriesWriter::GetFileNames() const
  {
    return this->m_FileNames;
  }

  ImageSeriesWriter& ImageSeriesWriter::Execute ( const Image& image, const std::vector<std::string> &inFileNames, bool inUseCompression )
  {
    this->SetFileNames( inFileNames );
    this->SetUseCompression( inUseCompression );
    return this->Execute( image );
  }

  ImageSeriesWriter &ImageSeriesWriter::Execute ( const Image &image )
  {

    // check that the number of file names match the slice size
    PixelIDValueType type = image.GetPixelIDValue();
    unsigned int dimension = image.GetDimension();

    return this->m_MemberFactory->GetMemberFunction( type, dimension )( image );
  }

  template <class TImageType>
  ImageSeriesWriter &
  ImageSeriesWriter::ExecuteInternal( const Image& inImage )
  {
    // Define the input and output image types
    typedef TImageType     InputImageType;

    typename InputImageType::ConstPointer image = this->CastImageToITK<InputImageType>( inImage );

    typedef itk::ImageSeriesWriter<InputImageType,
                                   typename InputImageType::template Rebind<typename InputImageType::PixelType, InputImageType::ImageDimension-1>::Type> Writer;

    typename Writer::Pointer writer = Writer::New();
    writer->SetUseCompression( this->m_UseCompression );
    writer->SetFileNames( this->m_FileNames );
    writer->SetInput( image );

    this->PreUpdate( writer.GetPointer() );

    writer->Update();

    return *this;
  }

  }
}
<|endoftext|>


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

#include "U16InputStream.h"

#include <assert.h>
#include <string.h>

#include <unicode/ucnv.h>

#include <algorithm>

const char* U16InputStream::DefaultEncoding = "utf-8";

namespace {

struct Override
{
    const char* input;
    const char* replacement;
};

// cf. HTML Living Standard 13.2.2.2 Character encodings
// cf. http://bugs.icu-project.org/trac/browser/icu/trunk/source/data/mappings/convrtrs.txt
Override overrides[] = {
    { "euc-kr", "windows-949" },
    { "euc-jp", "windows-51932" },    // ucnv_open() may not understand 'CP51932'.
    { "gb2312", "GBK" },
    { "gb_2312-80", "GBK" },
    // { "iso-2022-jp", "CP50220" },  // ucnv_open() may not understand 'CP50220'; iso-2022-jp appears to be the same as CP50220 in ICU.
    { "iso-8859-1", "windows-1252" },
    { "iso-8859-9", "windows-1254" },
    { "iso-8859-11", "windows-874" },
    { "ks_c_5601-1987", "windows-949" },
    { "shift_jis", "Windows-31j" },
    { "tis-620", "windows-874" },
    { "us-ascii", "windows-1252" }
};

}  // namespace

U16InputStream::U16InputStream(std::istream& stream, const std::string& optionalEncoding) :
    confidence(Certain),
    encoding(optionalEncoding),
    stream(stream)
{
    initializeConverter();
    encoding = checkEncoding(encoding);
    if (encoding.empty())
        confidence = Tentative;
}

U16InputStream::~U16InputStream()
{
    if (converter)
        ucnv_close(converter);
}

const char* U16InputStream::skipSpace(const char* p)
{
    while (*p) {
        if (strchr(" \t\r\n\f", *p) == 0)
            return p;
        ++p;
    }
    return p;
};

const char* U16InputStream::skipOver(const char* p, const char* target, size_t length)
{
    while (*p) {
        if (strncmp(p, target, length) == 0)
            return p + length;
        ++p;
    }
    return p;
};

void U16InputStream::detect(const char* p)
{
    if (confidence != Tentative)
        return;
    if (strncmp(p, "\xfe\xff", 2) == 0) {
        encoding = "utf-16be";
        confidence = Irrelevant;
        return;
    }
    if (strncmp(p, "\xff\xfe", 2) == 0) {
        encoding = "utf-16le";
        confidence = Irrelevant;
        return;
    }
    if (strncmp(p, "\xef\xbb\xbf", 3) == 0) {
        encoding = "utf-8";
        confidence = Irrelevant;
        return;
    }
    encoding = "";
}

std::string U16InputStream::checkEncoding(std::string value)
{
    // Remove any leading or trailing space characters
    std::string::iterator i = value.begin();
    while (i < value.end() && strchr("\t\n\f\r ", *i))
        ++i;
    value.erase(value.begin(), i);
    int j;
    for (j = value.length(); 0 < j && strchr("\t\n\f\r ", value[j - 1]); --j)
        ;
    value.erase(j, value.length());

    if (value.empty())
        return "";

    // Override character encoding
    for (Override* override = overrides;
         override < &overrides[sizeof overrides / sizeof overrides[0]];
         ++override) {
        if (!strcasecmp(value.c_str(), override->input)) {
            value = override->replacement;
            break;
        }
    }
    return value;
}

void U16InputStream::setEncoding(std::string value)
{
    value = checkEncoding(value);
    if (value.empty())
        value = DefaultEncoding;

    // Re-check encoding with ICU for conversion
    UErrorCode error = U_ZERO_ERROR;
    converter = ucnv_open(value.c_str(), &error);
    if (!converter) {
        value = DefaultEncoding;
        converter = ucnv_open(value.c_str(), &error);
        if (!converter)
            eof = true;
    }
    encoding = value;
}

void U16InputStream::initializeConverter()
{
    flush = false;
    eof = !stream;
    converter = 0;
    source = sourceLimit = sourceBuffer;
    target = targetBuffer;
    nextChar = target;
    lastChar = 0;
}

void U16InputStream::updateSource()
{
    assert(!flush);
    size_t count = sourceLimit - source;
    if (0 < count && sourceBuffer != source)
        memmove(sourceBuffer, source, count);
    source = sourceBuffer;
    sourceLimit = sourceBuffer + count;
    count = ChunkSize - count;
    if (0 < count) {
        stream.read(sourceLimit, count);
        count = stream.gcount();
        if (!converter) {
            if (encoding.empty()) {
                sourceLimit[count] = '\0';
                detect(sourceLimit);
            }
            setEncoding(encoding);
        }
        sourceLimit += count;
        if (count == 0)
            flush = true;
    }
}

void U16InputStream::readChunk()
{
    nextChar = target = targetBuffer;
    updateSource();
    UErrorCode err = U_ZERO_ERROR;
    ucnv_toUnicode(converter,
                   reinterpret_cast<UChar**>(&target),
                   reinterpret_cast<UChar*>(targetBuffer) + ChunkSize,
                   const_cast<const char**>(&source),
                   sourceLimit, 0, flush, &err);
}

U16InputStream::operator std::u16string()
{
    std::u16string text;
    char16_t c;
    while (getChar(c))
        text += c;
    return text;
}<commit_msg>(U16InputStream::detect) : Support the utf-16 encodings without BOM; cf. at-charset-029.<commit_after>/*
 * Copyright 2010-2012 Esrille Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "U16InputStream.h"

#include <assert.h>
#include <string.h>

#include <unicode/ucnv.h>

#include <algorithm>

const char* U16InputStream::DefaultEncoding = "utf-8";

namespace {

struct Override
{
    const char* input;
    const char* replacement;
};

// cf. HTML Living Standard 13.2.2.2 Character encodings
// cf. http://bugs.icu-project.org/trac/browser/icu/trunk/source/data/mappings/convrtrs.txt
Override overrides[] = {
    { "euc-kr", "windows-949" },
    { "euc-jp", "windows-51932" },    // ucnv_open() may not understand 'CP51932'.
    { "gb2312", "GBK" },
    { "gb_2312-80", "GBK" },
    // { "iso-2022-jp", "CP50220" },  // ucnv_open() may not understand 'CP50220'; iso-2022-jp appears to be the same as CP50220 in ICU.
    { "iso-8859-1", "windows-1252" },
    { "iso-8859-9", "windows-1254" },
    { "iso-8859-11", "windows-874" },
    { "ks_c_5601-1987", "windows-949" },
    { "shift_jis", "Windows-31j" },
    { "tis-620", "windows-874" },
    { "us-ascii", "windows-1252" }
};

}  // namespace

U16InputStream::U16InputStream(std::istream& stream, const std::string& optionalEncoding) :
    confidence(Certain),
    encoding(optionalEncoding),
    stream(stream)
{
    initializeConverter();
    encoding = checkEncoding(encoding);
    if (encoding.empty())
        confidence = Tentative;
}

U16InputStream::~U16InputStream()
{
    if (converter)
        ucnv_close(converter);
}

const char* U16InputStream::skipSpace(const char* p)
{
    while (*p) {
        if (strchr(" \t\r\n\f", *p) == 0)
            return p;
        ++p;
    }
    return p;
};

const char* U16InputStream::skipOver(const char* p, const char* target, size_t length)
{
    while (*p) {
        if (strncmp(p, target, length) == 0)
            return p + length;
        ++p;
    }
    return p;
};

void U16InputStream::detect(const char* p)
{
    static char le[] = { 0x40, 0x00, 0x63, 0x00, 0x68, 0x00, 0x61, 0x00, 0x72, 0x00, 0x73, 0x00, 0x65, 0x00, 0x74, 0x00 };
    static char be[] = { 0x00, 0x40, 0x00, 0x63, 0x00, 0x68, 0x00, 0x61, 0x00, 0x72, 0x00, 0x73, 0x00, 0x65, 0x00, 0x74 };

    if (confidence != Tentative)
        return;
    if (strncmp(p, "\xfe\xff", 2) == 0 || strncmp(p, be, sizeof(be)) == 0) {
        encoding = "utf-16be";
        confidence = Irrelevant;
        return;
    }
    if (strncmp(p, "\xff\xfe", 2) == 0 || strncmp(p, le, sizeof(le)) == 0) {
        encoding = "utf-16le";
        confidence = Irrelevant;
        return;
    }
    if (strncmp(p, "\xef\xbb\xbf", 3) == 0) {
        encoding = "utf-8";
        confidence = Irrelevant;
        return;
    }
    encoding = "";
}

std::string U16InputStream::checkEncoding(std::string value)
{
    // Remove any leading or trailing space characters
    std::string::iterator i = value.begin();
    while (i < value.end() && strchr("\t\n\f\r ", *i))
        ++i;
    value.erase(value.begin(), i);
    int j;
    for (j = value.length(); 0 < j && strchr("\t\n\f\r ", value[j - 1]); --j)
        ;
    value.erase(j, value.length());

    if (value.empty())
        return "";

    // Override character encoding
    for (Override* override = overrides;
         override < &overrides[sizeof overrides / sizeof overrides[0]];
         ++override) {
        if (!strcasecmp(value.c_str(), override->input)) {
            value = override->replacement;
            break;
        }
    }
    return value;
}

void U16InputStream::setEncoding(std::string value)
{
    value = checkEncoding(value);
    if (value.empty())
        value = DefaultEncoding;

    // Re-check encoding with ICU for conversion
    UErrorCode error = U_ZERO_ERROR;
    converter = ucnv_open(value.c_str(), &error);
    if (!converter) {
        value = DefaultEncoding;
        converter = ucnv_open(value.c_str(), &error);
        if (!converter)
            eof = true;
    }
    encoding = value;
}

void U16InputStream::initializeConverter()
{
    flush = false;
    eof = !stream;
    converter = 0;
    source = sourceLimit = sourceBuffer;
    target = targetBuffer;
    nextChar = target;
    lastChar = 0;
}

void U16InputStream::updateSource()
{
    assert(!flush);
    size_t count = sourceLimit - source;
    if (0 < count && sourceBuffer != source)
        memmove(sourceBuffer, source, count);
    source = sourceBuffer;
    sourceLimit = sourceBuffer + count;
    count = ChunkSize - count;
    if (0 < count) {
        stream.read(sourceLimit, count);
        count = stream.gcount();
        if (!converter) {
            if (encoding.empty()) {
                sourceLimit[count] = '\0';
                detect(sourceLimit);
            }
            setEncoding(encoding);
        }
        sourceLimit += count;
        if (count == 0)
            flush = true;
    }
}

void U16InputStream::readChunk()
{
    nextChar = target = targetBuffer;
    updateSource();
    UErrorCode err = U_ZERO_ERROR;
    ucnv_toUnicode(converter,
                   reinterpret_cast<UChar**>(&target),
                   reinterpret_cast<UChar*>(targetBuffer) + ChunkSize,
                   const_cast<const char**>(&source),
                   sourceLimit, 0, flush, &err);
}

U16InputStream::operator std::u16string()
{
    std::u16string text;
    char16_t c;
    while (getChar(c))
        text += c;
    return text;
}<|endoftext|>