<commit_before>/***********************************************************************************************************************
*                                                                                *
* SPLASH build system v0.2                                                                                *
*                                                                                *
* Copyright (c) 2016 Andrew D. Zonenberg                                                                               *
* All rights reserved.                                                                                *
*                                                                                *
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the     *
* following conditions are met:                                                                                *
*                                                                                *
*    * Redistributions of source code must retain the above copyright notice, this list of conditions, and the         *
*      following disclaimer.                                                                                *
*                                                                                *
*    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the       *
*      following disclaimer in the documentation and/or other materials provided with the distribution.                *
*                                                                                *
*    * Neither the name of the author nor the names of any contributors may be used to endorse or promote products     *
*      derived from this software without specific prior written permission.                                           *
*                                                                                *
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL *
* THE AUTHORS BE HELD LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES        *
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR       *
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE       *
* POSSIBILITY OF SUCH DAMAGE.                                                                                *
*                                                                                *
***********************************************************************************************************************/

#include "splashcore.h"

using namespace std;

Cache* g_cache = NULL;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Construction / destruction

Cache::Cache(string cachename)
{
	LogVerbose("Initializing cache subsystem...\n");
	LogIndenter li;

	//TODO: get cache path from command line arg or something?
	//Hard-coding the path prevents more than one splashctl instance from running on a given server.
	//This may or may not be what we want. If we DO want to limit to one instance, we need a way for multiple distinct
	//projects to share the splashctl/splashbuild back end.
	string home = getenv("HOME");
	if(!DoesDirectoryExist(home))
		LogFatal("home dir does not exist\n");
	m_cachePath = home + "/.splash/cache-" + cachename;

	//If the cache directory does not exist, create it
	if(!DoesDirectoryExist(m_cachePath))
	{
		LogDebug("Cache directory does not exist, creating it\n");
		MakeDirectoryRecursive(m_cachePath, 0600);
	}

	//It exists, load existing entries
	else
	{
		LogDebug("Cache directory exists, loading items\n");
		for(unsigned int i=0; i<256; i++)
		{
			//If the cache isn't very full we might not have entries in every bucket
			char hex[3];
			snprintf(hex, sizeof(hex), "%02x", i);
			string dirname = m_cachePath + "/" + hex;
			if(!DoesDirectoryExist(dirname))
				continue;

			//It exists, load whatever is in it
			vector<string> subdirs;
			FindSubdirs(dirname, subdirs);
			for(auto dir : subdirs)
			{
				//The object ID is what goes in our table, not the file hash
				string oid = GetBasenameOfFile(dir);
				if(!ValidateCacheEntry(oid))
				{
					LogWarning("Cache entry %s is not valid\n", oid.c_str());
					continue;
				}

				//Cache entry is valid, add to the cache table
				m_cacheIndex.emplace(oid);
			}
		}

		LogVerbose("%d cache entries loaded\n", (int)m_cacheIndex.size());
	}
}

Cache::~Cache()
{
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Status queries

NodeInfo::NodeState Cache::GetState(string id)
{
	lock_guard<recursive_mutex> lock(m_mutex);

	if(IsCached(id))
		return NodeInfo::READY;

	//TODO: check if it's building

	else
		return NodeInfo::MISSING;
}

/**
	@brief Determine if a particular object is in the cache.

	@param id		Object ID hash
 */
bool Cache::IsCached(string id)
{
	lock_guard<recursive_mutex> lock(m_mutex);

	if(m_cacheIndex.find(id) != m_cacheIndex.end())
		return true;

	return false;
}

/**
	@brief Stronger form of IsCached(). Checks if the internal hash is consistent

	@param id		Object ID hash
 */
bool Cache::ValidateCacheEntry(string id)
{
	lock_guard<recursive_mutex> lock(m_mutex);

	//If the directory doesn't exist, obviously we have nothing useful there
	string dir = GetStoragePath(id);
	if(!DoesDirectoryExist(dir))
		return false;

	//If we're missing the file or hash, can't possibly be valid
	string fpath = dir + "/data";
	string hpath = dir + "/hash";
	if( !DoesFileExist(fpath) || !DoesFileExist(hpath) )
		return false;

	//Get the expected hash and compare to the real one
	//If it's invalid, just get rid of the junk
	string expected = GetFileContents(hpath);
	string found = sha256_file(fpath);
	if(expected != found)
	{
		LogWarning("Cache directory %s is corrupted (hash match failed)\n", id.c_str());
		ShellCommand(string("rm -I ") + dir + "/*");
		ShellCommand(string("rm -r ") + dir);
		return false;
	}

	return true;
}

/**
	@brief Gets the cache path used for storing a particular object
 */
string Cache::GetStoragePath(string id)
{
	return m_cachePath + "/" + id.substr(0, 2) + "/" + id;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Cache manipulation

/**
	@brief Reads a file from the cache
 */
string Cache::ReadCachedFile(string id)
{
	lock_guard<recursive_mutex> lock(m_mutex);

	//Sanity check
	if(m_cacheIndex.find(id) == m_cacheIndex.end())
	{
		LogError("Requested file %s is not in cache\n", id.c_str());
		return "";
	}

	//Read the file
	string ret = GetFileContents(GetStoragePath(id) + "/data");

	return ret;
}

/**
	@brief Adds a file to the cache

	@param basename			Name of the file without directory information
	@param id				Object ID hash
	@param hash				SHA-256 sum of the file
	@param data				Content of the file
	@param len				Length of the file
 */
void Cache::AddFile(string /*basename*/, string id, string hash, const char* data, uint64_t len)
{
	lock_guard<recursive_mutex> lock(m_mutex);

	//Create the directory. If it already exists, delete whatever junk was in there
	string dirname = GetStoragePath(id);
	if(DoesDirectoryExist(dirname))
	{
		LogWarning("Cache directory %s already exists but was not loaded, removing dead files\n", hash.c_str());
		ShellCommand(string("rm -I ") + dirname + "/*");
	}
	else
		MakeDirectoryRecursive(dirname, 0600);

	//Write the file data to it
	string fname = dirname + "/data";
	FILE* fp = fopen(fname.c_str(), "wb");
	if(!fp)
	{
		LogWarning("Couldn't create cache file %s\n", fname.c_str());
		return;
	}
	if(len != fwrite(data, 1, len, fp))
	{
		fclose(fp);
		LogWarning("Couldn't write cache file %s\n", fname.c_str());
		return;
	}
	fclose(fp);

	//Write the hash
	if(!PutFileContents(dirname + "/hash", hash))
		return;

	//TODO: write the atime file?

	//Remember that we have this file cached
	m_cacheIndex.emplace(hash);

	//TODO: add this file's size to the cache, if we went over the cap delete the LRU file
}
<commit_msg>splashcore: BUGFIX: Cache now uses ID, not hash, for cached hits<commit_after>/***********************************************************************************************************************
*                                                                                *
* SPLASH build system v0.2                                                                                *
*                                                                                *
* Copyright (c) 2016 Andrew D. Zonenberg                                                                               *
* All rights reserved.                                                                                *
*                                                                                *
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the     *
* following conditions are met:                                                                                *
*                                                                                *
*    * Redistributions of source code must retain the above copyright notice, this list of conditions, and the         *
*      following disclaimer.                                                                                *
*                                                                                *
*    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the       *
*      following disclaimer in the documentation and/or other materials provided with the distribution.                *
*                                                                                *
*    * Neither the name of the author nor the names of any contributors may be used to endorse or promote products     *
*      derived from this software without specific prior written permission.                                           *
*                                                                                *
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL *
* THE AUTHORS BE HELD LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES        *
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR       *
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE       *
* POSSIBILITY OF SUCH DAMAGE.                                                                                *
*                                                                                *
***********************************************************************************************************************/

#include "splashcore.h"

using namespace std;

Cache* g_cache = NULL;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Construction / destruction

Cache::Cache(string cachename)
{
	LogVerbose("Initializing cache subsystem...\n");
	LogIndenter li;

	//TODO: get cache path from command line arg or something?
	//Hard-coding the path prevents more than one splashctl instance from running on a given server.
	//This may or may not be what we want. If we DO want to limit to one instance, we need a way for multiple distinct
	//projects to share the splashctl/splashbuild back end.
	string home = getenv("HOME");
	if(!DoesDirectoryExist(home))
		LogFatal("home dir does not exist\n");
	m_cachePath = home + "/.splash/cache-" + cachename;

	//If the cache directory does not exist, create it
	if(!DoesDirectoryExist(m_cachePath))
	{
		LogDebug("Cache directory does not exist, creating it\n");
		MakeDirectoryRecursive(m_cachePath, 0600);
	}

	//It exists, load existing entries
	else
	{
		LogDebug("Cache directory exists, loading items\n");
		for(unsigned int i=0; i<256; i++)
		{
			//If the cache isn't very full we might not have entries in every bucket
			char hex[3];
			snprintf(hex, sizeof(hex), "%02x", i);
			string dirname = m_cachePath + "/" + hex;
			if(!DoesDirectoryExist(dirname))
				continue;

			//It exists, load whatever is in it
			vector<string> subdirs;
			FindSubdirs(dirname, subdirs);
			for(auto dir : subdirs)
			{
				//The object ID is what goes in our table, not the file hash
				string oid = GetBasenameOfFile(dir);
				if(!ValidateCacheEntry(oid))
				{
					LogWarning("Cache entry %s is not valid\n", oid.c_str());
					continue;
				}

				//Cache entry is valid, add to the cache table
				m_cacheIndex.emplace(oid);
			}
		}

		LogVerbose("%d cache entries loaded\n", (int)m_cacheIndex.size());
	}
}

Cache::~Cache()
{
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Status queries

NodeInfo::NodeState Cache::GetState(string id)
{
	lock_guard<recursive_mutex> lock(m_mutex);

	if(IsCached(id))
		return NodeInfo::READY;

	//TODO: check if it's building

	else
		return NodeInfo::MISSING;
}

/**
	@brief Determine if a particular object is in the cache.

	@param id		Object ID hash
 */
bool Cache::IsCached(string id)
{
	lock_guard<recursive_mutex> lock(m_mutex);

	if(m_cacheIndex.find(id) != m_cacheIndex.end())
		return true;

	return false;
}

/**
	@brief Stronger form of IsCached(). Checks if the internal hash is consistent

	@param id		Object ID hash
 */
bool Cache::ValidateCacheEntry(string id)
{
	lock_guard<recursive_mutex> lock(m_mutex);

	//If the directory doesn't exist, obviously we have nothing useful there
	string dir = GetStoragePath(id);
	if(!DoesDirectoryExist(dir))
		return false;

	//If we're missing the file or hash, can't possibly be valid
	string fpath = dir + "/data";
	string hpath = dir + "/hash";
	if( !DoesFileExist(fpath) || !DoesFileExist(hpath) )
		return false;

	//Get the expected hash and compare to the real one
	//If it's invalid, just get rid of the junk
	string expected = GetFileContents(hpath);
	string found = sha256_file(fpath);
	if(expected != found)
	{
		LogWarning("Cache directory %s is corrupted (hash match failed)\n", id.c_str());
		ShellCommand(string("rm -I ") + dir + "/*");
		ShellCommand(string("rm -r ") + dir);
		return false;
	}

	return true;
}

/**
	@brief Gets the cache path used for storing a particular object
 */
string Cache::GetStoragePath(string id)
{
	return m_cachePath + "/" + id.substr(0, 2) + "/" + id;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Cache manipulation

/**
	@brief Reads a file from the cache
 */
string Cache::ReadCachedFile(string id)
{
	lock_guard<recursive_mutex> lock(m_mutex);

	//Sanity check
	if(m_cacheIndex.find(id) == m_cacheIndex.end())
	{
		LogError("Requested file %s is not in cache\n", id.c_str());
		return "";
	}

	//Read the file
	string ret = GetFileContents(GetStoragePath(id) + "/data");

	return ret;
}

/**
	@brief Adds a file to the cache

	@param basename			Name of the file without directory information
	@param id				Object ID hash
	@param hash				SHA-256 sum of the file
	@param data				Content of the file
	@param len				Length of the file
 */
void Cache::AddFile(string /*basename*/, string id, string hash, const char* data, uint64_t len)
{
	lock_guard<recursive_mutex> lock(m_mutex);

	//Create the directory. If it already exists, delete whatever junk was in there
	string dirname = GetStoragePath(id);
	if(DoesDirectoryExist(dirname))
	{
		LogWarning("Cache directory %s already exists but was not loaded, removing dead files\n", hash.c_str());
		ShellCommand(string("rm -I ") + dirname + "/*");
	}
	else
		MakeDirectoryRecursive(dirname, 0600);

	//Write the file data to it
	string fname = dirname + "/data";
	FILE* fp = fopen(fname.c_str(), "wb");
	if(!fp)
	{
		LogWarning("Couldn't create cache file %s\n", fname.c_str());
		return;
	}
	if(len != fwrite(data, 1, len, fp))
	{
		fclose(fp);
		LogWarning("Couldn't write cache file %s\n", fname.c_str());
		return;
	}
	fclose(fp);

	//Write the hash
	if(!PutFileContents(dirname + "/hash", hash))
		return;

	//TODO: write the atime file?

	//Remember that we have this file cached
	m_cacheIndex.emplace(id);

	//TODO: add this file's size to the cache, if we went over the cap delete the LRU file
}
<|endoftext|>


<commit_before>// Copyright (c) 2011-2012, Zeex
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <cstdlib>

#include <Windows.h>
#include <DbgHelp.h>

#include "stacktrace.h"
#include "stacktrace-manual.h"

// MSDN says that CaptureStackBackTrace() can't handle more than 62 frames on
// Windows Server 2003 and Windows XP.
static const int kMaxFrames = 62;
static const int kMaxSymbolNameLength = 1024;

class DbgHelp {
public:
	DbgHelp(HANDLE process = NULL);
	~DbgHelp();

	bool HaveSymInitialize() const {
		return SymInitialize_ != NULL;
	}
	BOOL SymInitialize(HANDLE hProcess, PCSTR UserSearchPath, BOOL fInvadeProcess) const {
		return SymInitialize_(hProcess, UserSearchPath, fInvadeProcess);
	}

	bool HaveSymFromAddr() const {
		return SymFromAddr_ != NULL;
	}
	BOOL SymFromAddr(HANDLE hProcess, DWORD64 Address, PDWORD64 Displacement, PSYMBOL_INFO Symbol) const {
		return SymFromAddr_(hProcess, Address, Displacement, Symbol);
	}

	bool HaveSymCleanup() const {
		return SymCleanup_ != NULL;
	}
	BOOL SymCleanup(HANDLE hProcess) const {
		return SymCleanup_(hProcess);
	}

	bool HaveSymGetOptions() const {
		return SymGetOptions_ != NULL;
	}
	DWORD SymGetOptions() const {
		return SymGetOptions_();
	}

	bool HaveSymSetOptions() const {
		return SymSetOptions_ != NULL;
	}
	BOOL SymSetOptions(DWORD SymOptions) const {
		return SymSetOptions_(SymOptions);
	}

	bool HaveStackWalk64() const {
		return StackWalk64_ != NULL;
	}
	BOOL StackWalk64(
		DWORD MachineType,
		HANDLE hProcess,
		HANDLE hThread,
		LPSTACKFRAME64 StackFrame,
		LPVOID ContextRecord,
		PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
		PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
		PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
		PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress
	) {
		return StackWalk64_(MachineType, hProcess, hThread, StackFrame, ContextRecord,
		                    ReadMemoryRoutine, FunctionTableAccessRoutine, GetModuleBaseRoutine,
		                    TranslateAddress);
	}

	inline bool IsLoaded() const {
		return module_ != 0;
	}
	inline bool IsInitialized() const {
		return initialized_ != FALSE;
	}

private:
	typedef BOOL (WINAPI *SymInitializeType)(HANDLE, PCSTR, BOOL);
	SymInitializeType SymInitialize_;

	typedef BOOL (WINAPI *SymFromAddrType)(HANDLE, DWORD64, PDWORD64, PSYMBOL_INFO);
	SymFromAddrType SymFromAddr_;

	typedef BOOL (WINAPI *SymCleanupType)(HANDLE);
	SymCleanupType SymCleanup_;

	typedef DWORD (WINAPI *SymGetOptionsType)();
	SymGetOptionsType SymGetOptions_;

	typedef DWORD (WINAPI *SymSetOptionsType)(DWORD);
	SymSetOptionsType SymSetOptions_;

	typedef BOOL (WINAPI *StackWalk64Type)(DWORD, HANDLE, HANDLE, LPSTACKFRAME64, LPVOID ContextRecord,
	                                       PREAD_PROCESS_MEMORY_ROUTINE64, PFUNCTION_TABLE_ACCESS_ROUTINE64,
	                                       PGET_MODULE_BASE_ROUTINE64, PTRANSLATE_ADDRESS_ROUTINE64);
	StackWalk64Type StackWalk64_;

	HMODULE module_;
	HANDLE process_;
	BOOL initialized_;
};

DbgHelp::DbgHelp(HANDLE process)
	: module_(LoadLibrary("DbgHelp.dll"))
	, process_(process)
	, initialized_(FALSE)
{
	if (process_ == NULL) {
		process_ = GetCurrentProcess();
	}

	if (module_ != NULL) {
		SymInitialize_ = (SymInitializeType)GetProcAddress(module_, "SymInitialize");
		SymFromAddr_ = (SymFromAddrType)GetProcAddress(module_, "SymFromAddr");
		SymCleanup_ = (SymCleanupType)GetProcAddress(module_, "SymCleanup");
		SymGetOptions_ = (SymGetOptionsType)GetProcAddress(module_, "SymGetOptions");
		SymSetOptions_ = (SymSetOptionsType)GetProcAddress(module_, "SymSetOptions");
		StackWalk64_ = (StackWalk64Type)GetProcAddress(module_, "StackWalk64");
		if (SymInitialize_ != NULL) {
			initialized_ = SymInitialize_(process_, NULL, TRUE);
		}
	}
}

DbgHelp::~DbgHelp() {
	if (module_ != NULL) {
		if (initialized_ && SymCleanup_ != NULL) {
			SymCleanup_(process_);
		}
		FreeLibrary(module_);
	}
}

StackTrace::StackTrace(void *theirContext) {
	PCONTEXT context = reinterpret_cast<PCONTEXT>(theirContext);
	CONTEXT currentContext;
	if (theirContext == NULL) {
		RtlCaptureContext(&currentContext);
		context = &currentContext;
	}

	HANDLE process = GetCurrentProcess();
	DbgHelp dbghelp(process);
	if (!dbghelp.IsLoaded()) {
		goto fail;
	}

	STACKFRAME64 stackFrame;
	ZeroMemory(&stackFrame, sizeof(stackFrame));

	// http://stackoverflow.com/a/136942/249230
	stackFrame.AddrPC.Offset = context->Eip;
	stackFrame.AddrPC.Mode = AddrModeFlat;
	stackFrame.AddrFrame.Offset = context->Ebp;
	stackFrame.AddrFrame.Mode = AddrModeFlat;
	stackFrame.AddrStack.Offset = context->Esp;
	stackFrame.AddrStack.Mode = AddrModeFlat;

	if (!dbghelp.HaveStackWalk64()) {
		goto fail;
	}

	SYMBOL_INFO *symbol = NULL;

	if (dbghelp.IsInitialized()) {
		symbol = reinterpret_cast<SYMBOL_INFO*>(std::calloc(sizeof(*symbol) + kMaxSymbolNameLength, 1));
		symbol->SizeOfStruct = sizeof(*symbol);
		symbol->MaxNameLen = kMaxSymbolNameLength;

		if (dbghelp.HaveSymGetOptions() && dbghelp.HaveSymSetOptions()) {
			DWORD options = dbghelp.SymGetOptions();
			options |= SYMOPT_FAIL_CRITICAL_ERRORS;
			dbghelp.SymSetOptions(options);
		}
	}

	for (int i = 0; ; i++) {
		BOOL result = dbghelp.StackWalk64(IMAGE_FILE_MACHINE_I386, process, GetCurrentThread(), &stackFrame,
		                                  (PVOID)context, NULL, NULL, NULL, NULL);
		if (!result) {
			break;
		}

		DWORD64 address = stackFrame.AddrReturn.Offset;
		if (address == 0 || address == stackFrame.AddrPC.Offset) {
			break;
		}

		const char *name = "";
		if (dbghelp.IsInitialized() && dbghelp.HaveSymFromAddr() && symbol != NULL) {
			if (dbghelp.SymFromAddr(process, address, NULL, symbol)) {
				name = symbol->Name;
			}
		}

		frames_.push_back(StackFrame(reinterpret_cast<void*>(address), name));
	}

	if (symbol != NULL) {
		std::free(symbol);
	}

	return;

fail:
	StackTraceManual manualTrace(
		reinterpret_cast<void*>(context->Ebp),
		reinterpret_cast<void*>(context->Eip));

	frames_ = manualTrace.GetFrames();
}
<commit_msg>Make sure symbol table is loaded before calling to SymFromAddr()<commit_after>// Copyright (c) 2011-2012, Zeex
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <cstdlib>

#include <Windows.h>
#include <DbgHelp.h>

#include "stacktrace.h"
#include "stacktrace-manual.h"

// MSDN says that CaptureStackBackTrace() can't handle more than 62 frames on
// Windows Server 2003 and Windows XP.
static const int kMaxFrames = 62;
static const int kMaxSymbolNameLength = 1024;

class DbgHelp {
public:
	DbgHelp(HANDLE process = NULL);
	~DbgHelp();

	bool HaveSymInitialize() const {
		return SymInitialize_ != NULL;
	}
	BOOL SymInitialize(HANDLE hProcess, PCSTR UserSearchPath, BOOL fInvadeProcess) const {
		return SymInitialize_(hProcess, UserSearchPath, fInvadeProcess);
	}

	bool HaveSymFromAddr() const {
		return SymFromAddr_ != NULL;
	}
	BOOL SymFromAddr(HANDLE hProcess, DWORD64 Address, PDWORD64 Displacement, PSYMBOL_INFO Symbol) const {
		return SymFromAddr_(hProcess, Address, Displacement, Symbol);
	}

	bool HaveSymCleanup() const {
		return SymCleanup_ != NULL;
	}
	BOOL SymCleanup(HANDLE hProcess) const {
		return SymCleanup_(hProcess);
	}

	bool HaveSymGetOptions() const {
		return SymGetOptions_ != NULL;
	}
	DWORD SymGetOptions() const {
		return SymGetOptions_();
	}

	bool HaveSymSetOptions() const {
		return SymSetOptions_ != NULL;
	}
	BOOL SymSetOptions(DWORD SymOptions) const {
		return SymSetOptions_(SymOptions);
	}

	bool HaveSymGetModuleInfo64() const {
		return SymGetModuleInfo64_ != NULL;
	}
	BOOL SymGetModuleInfo64(HANDLE hProcess, DWORD64 dwAddr, PIMAGEHLP_MODULE64 ModuleInfo) const {
		return SymGetModuleInfo64_(hProcess, dwAddr, ModuleInfo);
	}

	bool HaveStackWalk64() const {
		return StackWalk64_ != NULL;
	}
	BOOL StackWalk64(DWORD MachineType, HANDLE hProcess, HANDLE hThread, LPSTACKFRAME64 StackFrame, LPVOID ContextRecord, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress) {
		return StackWalk64_(MachineType, hProcess, hThread, StackFrame, ContextRecord, ReadMemoryRoutine, FunctionTableAccessRoutine, GetModuleBaseRoutine, TranslateAddress);
	}

	inline bool IsLoaded() const {
		return module_ != 0;
	}
	inline bool IsInitialized() const {
		return initialized_ != FALSE;
	}

private:
	typedef BOOL (WINAPI *SymInitializeType)(HANDLE, PCSTR, BOOL);
	SymInitializeType SymInitialize_;

	typedef BOOL (WINAPI *SymFromAddrType)(HANDLE, DWORD64, PDWORD64, PSYMBOL_INFO);
	SymFromAddrType SymFromAddr_;

	typedef BOOL (WINAPI *SymCleanupType)(HANDLE);
	SymCleanupType SymCleanup_;

	typedef DWORD (WINAPI *SymGetOptionsType)();
	SymGetOptionsType SymGetOptions_;

	typedef DWORD (WINAPI *SymSetOptionsType)(DWORD);
	SymSetOptionsType SymSetOptions_;

	typedef BOOL (WINAPI *SymGetModuleInfo64Type)(HANDLE, DWORD64, PIMAGEHLP_MODULE64);
	SymGetModuleInfo64Type SymGetModuleInfo64_;

	typedef BOOL (WINAPI *StackWalk64Type)(DWORD, HANDLE, HANDLE, LPSTACKFRAME64, LPVOID ContextRecord,
	                                       PREAD_PROCESS_MEMORY_ROUTINE64, PFUNCTION_TABLE_ACCESS_ROUTINE64,
	                                       PGET_MODULE_BASE_ROUTINE64, PTRANSLATE_ADDRESS_ROUTINE64);
	StackWalk64Type StackWalk64_;

	HMODULE module_;
	HANDLE process_;
	BOOL initialized_;
};

DbgHelp::DbgHelp(HANDLE process)
	: module_(LoadLibrary("DbgHelp.dll"))
	, process_(process)
	, initialized_(FALSE)
{
	if (process_ == NULL) {
		process_ = GetCurrentProcess();
	}

	if (module_ != NULL) {
		SymInitialize_ = (SymInitializeType)GetProcAddress(module_, "SymInitialize");
		SymFromAddr_ = (SymFromAddrType)GetProcAddress(module_, "SymFromAddr");
		SymCleanup_ = (SymCleanupType)GetProcAddress(module_, "SymCleanup");
		SymGetOptions_ = (SymGetOptionsType)GetProcAddress(module_, "SymGetOptions");
		SymSetOptions_ = (SymSetOptionsType)GetProcAddress(module_, "SymSetOptions");
		SymGetModuleInfo64_ = (SymGetModuleInfo64Type)GetProcAddress(module_, "SymGetModuleInfo64");
		StackWalk64_ = (StackWalk64Type)GetProcAddress(module_, "StackWalk64");
		if (SymInitialize_ != NULL) {
			initialized_ = SymInitialize_(process_, NULL, TRUE);
		}
	}
}

DbgHelp::~DbgHelp() {
	if (module_ != NULL) {
		if (initialized_ && SymCleanup_ != NULL) {
			SymCleanup_(process_);
		}
		FreeLibrary(module_);
	}
}

StackTrace::StackTrace(void *theirContext) {
	PCONTEXT context = reinterpret_cast<PCONTEXT>(theirContext);
	CONTEXT currentContext;
	if (theirContext == NULL) {
		RtlCaptureContext(&currentContext);
		context = &currentContext;
	}

	HANDLE process = GetCurrentProcess();
	DbgHelp dbghelp(process);
	if (!dbghelp.IsLoaded()) {
		goto fail;
	}

	STACKFRAME64 stackFrame;
	ZeroMemory(&stackFrame, sizeof(stackFrame));

	// http://stackoverflow.com/a/136942/249230
	stackFrame.AddrPC.Offset = context->Eip;
	stackFrame.AddrPC.Mode = AddrModeFlat;
	stackFrame.AddrFrame.Offset = context->Ebp;
	stackFrame.AddrFrame.Mode = AddrModeFlat;
	stackFrame.AddrStack.Offset = context->Esp;
	stackFrame.AddrStack.Mode = AddrModeFlat;

	if (!dbghelp.HaveStackWalk64()) {
		goto fail;
	}

	SYMBOL_INFO *symbol = NULL;

	if (dbghelp.IsInitialized()) {
		symbol = reinterpret_cast<SYMBOL_INFO*>(std::calloc(sizeof(*symbol) + kMaxSymbolNameLength, 1));
		symbol->SizeOfStruct = sizeof(*symbol);
		symbol->MaxNameLen = kMaxSymbolNameLength;

		if (dbghelp.HaveSymGetOptions() && dbghelp.HaveSymSetOptions()) {
			DWORD options = dbghelp.SymGetOptions();
			options |= SYMOPT_FAIL_CRITICAL_ERRORS;
			dbghelp.SymSetOptions(options);
		}
	}

	for (int i = 0; ; i++) {
		BOOL result = dbghelp.StackWalk64(IMAGE_FILE_MACHINE_I386, process, GetCurrentThread(), &stackFrame,
		                                  (PVOID)context, NULL, NULL, NULL, NULL);
		if (!result) {
			break;
		}

		DWORD64 address = stackFrame.AddrReturn.Offset;
		if (address == 0 || address == stackFrame.AddrPC.Offset) {
			break;
		}

		bool haveSymbols = true;
		if (dbghelp.HaveSymGetModuleInfo64()) {
			IMAGEHLP_MODULE64 module;
			ZeroMemory(&module, sizeof(IMAGEHLP_MODULE64));
			module.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);
			if (dbghelp.SymGetModuleInfo64(process, address, &module)) {
				if (!module.GlobalSymbols) {
					haveSymbols = false;
				}
			}
		}

		const char *name = "";
		if (haveSymbols) {
			if (dbghelp.IsInitialized() && dbghelp.HaveSymFromAddr() && symbol != NULL) {
				if (dbghelp.SymFromAddr(process, address, NULL, symbol)) {
					name = symbol->Name;
				}
			}
		}

		frames_.push_back(StackFrame(reinterpret_cast<void*>(address), name));
	}

	if (symbol != NULL) {
		std::free(symbol);
	}

	return;

fail:
	StackTraceManual manualTrace(
		reinterpret_cast<void*>(context->Ebp),
		reinterpret_cast<void*>(context->Eip));

	frames_ = manualTrace.GetFrames();
}
<|endoftext|>


<commit_before>#include "game_state.hpp"

#include "start_game_state.hpp"
#include "imove.hpp"
#include "walk_move.hpp"
#include "wall_move.hpp"
#include "logger.hpp"
#include "exception.hpp"
#include "cegui_ext/dragged_window.hpp"

static boost::log::sources::severity_logger<boost::log::trivial::severity_level> lg;

namespace Quoridor {

static std::vector<std::string> colors = {"red", "green", "blue", "yellow"};
std::string GameState::name_("Start Game");

GameState::GameState(std::shared_ptr<StateManager> stm,
        const std::vector<std::string> &player_types) : stm_(stm), anim_(),
    board_(new Board(9)), pf_(), players_(), pawn_list_(), cur_pawn_(),
    dragging_pawn_node_(), pawn_path_(), added_wall_(0, 0, 0, 0), wall_idx_(0),
    status_(kWaitingForMove)
{
    CEGUI::ImageManager::getSingleton().loadImageset("pawn.imageset");
    CEGUI::ImageManager::getSingleton().loadImageset("board.imageset");
    CEGUI::ImageManager::getSingleton().loadImageset("wall.imageset");
    win_ = std::shared_ptr<CEGUI::Window>(
            CEGUI::WindowManager::getSingleton().
                    loadLayoutFromFile("game.layout"),
            [=](CEGUI::Window *w) {
                BOOST_LOG_SEV(lg, boost::log::trivial::debug) << "removing window " << w;
                CEGUI::WindowManager::getSingleton().destroyWindow(w);
            }
    );

    subscribe_for_events_();

    if ((player_types.size() != 2) && (player_types.size() != 4)) {
        throw Exception("Invalid number of players");
    }

    int i = 0;
    for (auto player_type : player_types) {
        BOOST_LOG_SEV(lg, boost::log::trivial::info) << "adding player "
            << player_type;
        std::shared_ptr<Pawn> pawn(new Pawn(colors[i]));
        board_->add_pawn(pawn);
        players_[pawn] = pf_.make_player(player_type, board_, pawn);
        pawn_list_.push_back(pawn);
        ++i;
    }

    anim_ = std::shared_ptr<CEGUI::Animation>(
            CEGUI::AnimationManager::getSingleton().
                    createAnimation("movePawn"),
            [=](CEGUI::Animation *anim) {
                CEGUI::AnimationManager::getSingleton().destroyAnimation(anim);
            }
    );
    anim_->setDuration(0.5);
    anim_->setReplayMode(CEGUI::Animation::RM_Once);

    set_pawns_();

    cur_pawn_ = pawn_list_[0];
}

GameState::~GameState()
{
}

void GameState::update()
{
    switch (status_) {
    case kWaitingForMove:
        make_move_();
        break;
    case kPerformedMove:
        status_ = kWaitingForMove;
        if (is_finished_()) {
            BOOST_LOG_SEV(lg, boost::log::trivial::info) << cur_pawn_->color()
                << " win";
            status_ = kFinished;
        }
        else {
            cur_pawn_ = next_pawn();
        }
        break;
    case kNeedPawnRedraw:
        redraw_pawn_();
        status_ = kWaitingForAnimationEnd;
        break;
    case kNeedDrawWall:
        draw_wall_();
        status_ = kPerformedMove;
        break;
    case kWaitingForAnimationEnd:
        break;
    case kFinished:
        break;
    default:
        break;
    }
}

std::shared_ptr<CEGUI::Window> GameState::window() const
{
    return win_;
}

const std::string &GameState::name() const
{
    return name_;
}

void GameState::set_pawns_()
{
    auto board_win = static_cast<CEGUI::DefaultWindow*>(win_->getChild("boardWindow"));

    board_win->subscribeEvent(
            CEGUI_Ext::DraggedWindow::EventDraggedWindowDropped,
            CEGUI::Event::Subscriber(&GameState::handle_pawn_dropped_, this));
    board_win->subscribeEvent(
            CEGUI_Ext::DraggedWindow::EventDraggedWindowStartDragging,
            CEGUI::Event::Subscriber(&GameState::handle_pawn_start_dragging_, this));

    CEGUI::Window *drag_win;
    for (auto pawn : pawn_list_) {
        if (players_[pawn]->is_interactive()) {
            drag_win = new CEGUI_Ext::DraggedWindow("DefaultWindow", pawn->color());
        }
        else {
            drag_win = CEGUI::WindowManager::getSingleton().createWindow("DefaultWindow", pawn->color());
            drag_win->subscribeEvent(CEGUI::AnimationInstance::EventAnimationEnded, CEGUI::Event::Subscriber(&GameState::handle_end_anim_, this));
        }

        drag_win->setSize(CEGUI::USize({0.1, 0}, {0.1, 0}));
        Pos pos = board_->pawn_node(pawn);
        float x_coord = 0.1111 * pos.col();
        float y_coord = 0.1111 * (8 - pos.row());
        drag_win->setPosition(CEGUI::UVector2({x_coord, 2}, {y_coord, 2}));

        auto pawn_win = CEGUI::WindowManager::getSingleton().loadLayoutFromFile("pawn_anim.layout");
        drag_win->addChild(pawn_win);
        board_win->addChild(drag_win);
    }
}

void GameState::redraw_pawn_()
{
    Pos old_pos = pawn_path_[0];
    Pos new_pos = pawn_path_[1];

    pawn_path_.clear();

    float old_x_coord = 0.1111 * old_pos.col();
    float old_y_coord = 0.1111 * (8 - old_pos.row());
    float new_x_coord = 0.1111 * new_pos.col();
    float new_y_coord = 0.1111 * (8 - new_pos.row());

    CEGUI::Affector *affector = anim_->createAffector("Position", "UVector2");
    affector->setApplicationMethod(CEGUI::Affector::AM_Absolute);
    affector->createKeyFrame(0.0, "{{" + std::to_string(old_x_coord)
            + ", 2.0}, { " + std::to_string(old_y_coord) + ", 2.0}}");
    affector->createKeyFrame(0.5, "{{" + std::to_string(new_x_coord)
            + ", 2.0}, { " + std::to_string(new_y_coord) + ", 2.0}}");

    auto pawn_win = win_->getChild("boardWindow/" + cur_pawn_->color());
    CEGUI::AnimationInstance *instance = CEGUI::AnimationManager::
            getSingleton().instantiateAnimation(anim_.get());
    instance->setTargetWindow(pawn_win);
    instance->start();
}

void GameState::draw_wall_()
{
    auto board_win = static_cast<CEGUI::DefaultWindow*>(win_->getChild("boardWindow"));

    if (added_wall_.orientation() == 0) {
        for (int i = 0; i < added_wall_.cnt(); ++i) {
            float x = 0.1111 * (added_wall_.start_pos() + i);
            float y = 0.1111 * ( 8 - added_wall_.line());
            auto wall_win = CEGUI::WindowManager::getSingleton().loadLayoutFromFile("horizontal_wall.layout");
            wall_win->setPosition(CEGUI::UVector2({x, 0}, {y, -2}));
            wall_win->setName("wallWindow" + std::to_string(wall_idx_));
            ++wall_idx_;
            board_win->addChild(wall_win);
            BOOST_LOG_SEV(lg, boost::log::trivial::info) << "added horizontal wall at "
                << x << ":" << y;
        }
    }
    else {
        for (int i = 0; i < added_wall_.cnt(); ++i) {
            float x = 0.1111 * (added_wall_.line());
            float y = 0.1111 * ( 8 - added_wall_.start_pos() - i);
            auto wall_win = CEGUI::WindowManager::getSingleton().loadLayoutFromFile("vertical_wall.layout");
            wall_win->setPosition(CEGUI::UVector2({x, -2}, {y, 0}));
            wall_win->setName("wallWindow" + std::to_string(wall_idx_));
            ++wall_idx_;
            board_win->addChild(wall_win);
            BOOST_LOG_SEV(lg, boost::log::trivial::info) << "added vertiacl wall at "
                << x << ":" << y;
        }
    }
}

std::shared_ptr<Pawn> GameState::next_pawn() const
{
    auto it = pawn_list_.begin();
    for (;it != pawn_list_.end(); ++it) {
        if (cur_pawn_ && (*it == cur_pawn_)) {
            break;
        }
    }
    if (++it == pawn_list_.end()) {
        return pawn_list_[0];
    }
    else {
        return *it;
    }
}

void GameState::make_move_()
{
    IMove *move = NULL;

    // bot's turn
    if (!players_[cur_pawn_]->is_interactive()) {
        move = players_[cur_pawn_]->get_move();
    }
    // human's turn, handle it in one of event handlers
    else {
        return;
    }

    if (move != NULL) {
        Pos cur_node = board_->pawn_node(cur_pawn_);
        int rc;

        if (WalkMove *walk_move = dynamic_cast<WalkMove*>(move)) {
            BOOST_LOG_SEV(lg, boost::log::trivial::info) << cur_pawn_->color()
                << " move: " << cur_node.row() << ":" << cur_node.col()
                << " -> " << walk_move->node().row() << ":"
                << walk_move->node().col();

            rc = board_->make_walking_move(cur_pawn_, walk_move->node());
            if (rc == 0) {
                pawn_path_.push_back(cur_node);
                pawn_path_.push_back(board_->pawn_node(cur_pawn_));
                status_ = kNeedPawnRedraw;
            }
        }
        else if (WallMove *wall_move = dynamic_cast<WallMove*>(move)) {
            const Wall &wall = wall_move->wall();
            rc = board_->add_wall(wall);
            if (rc == 0) {
                added_wall_ = wall;
                status_ = kNeedDrawWall;
            }
        }
    }
}

bool GameState::is_finished_() const
{
    return board_->is_at_goal_node(cur_pawn_);
}

void GameState::subscribe_for_events_()
{
    win_->getChild("back")->subscribeEvent(
            CEGUI::Window::EventMouseClick,
            CEGUI::Event::Subscriber(
                    &GameState::handle_back_, this
            )
    );
}

bool GameState::handle_back_(const CEGUI::EventArgs &/* e */)
{
    BOOST_LOG_SEV(lg, boost::log::trivial::info) << "returning to start game menu";
    stm_->change_state(std::shared_ptr<IState>(new StartGameState(stm_)));
    return true;
}

bool GameState::handle_end_anim_(const CEGUI::EventArgs &/* e */)
{
    status_ = kPerformedMove;
    return true;
}

bool GameState::handle_pawn_dropped_(const CEGUI::EventArgs &e)
{
    BOOST_LOG_SEV(lg, boost::log::trivial::info) << "pawn was dropped!";

    auto de = static_cast<const CEGUI_Ext::DragEvent &>(e);
    CEGUI::Vector2f rel_pos = CEGUI::CoordConverter::asRelative(
            de.window()->getPosition() + de.pos(),
            {468, 468}  // @fixme get parent size
    );
    Pos node = normalize_pawn_pos_(rel_pos);

    BOOST_LOG_SEV(lg, boost::log::trivial::info) << de.window() << " position "
        << node.row() << ":" << node.col();

    float x_coord;
    float y_coord;

    int rc = board_->make_walking_move(cur_pawn_, node);
    if (rc == 0) {
        x_coord = 0.1111 * node.col();
        y_coord = 0.1111 * (8 - node.row());
        status_ = kPerformedMove;
    }
    else {
        Pos cur_node = board_->pawn_node(cur_pawn_);
        x_coord = 0.1111 * cur_node.col();
        y_coord = 0.1111 * (8 - cur_node.row());
    }

    de.window()->setPosition(CEGUI::UVector2({x_coord, 2}, {y_coord, 2}));

    return true;
}

bool GameState::handle_pawn_start_dragging_(const CEGUI::EventArgs &e)
{
    BOOST_LOG_SEV(lg, boost::log::trivial::info) << "pawn is dragging";

    auto de = static_cast<const CEGUI_Ext::DragEvent &>(e);
    CEGUI::Vector2f rel_pos = CEGUI::CoordConverter::asRelative(
            de.window()->getPosition() + de.pos(),
            {468, 468}
    );
    dragging_pawn_node_ = normalize_pawn_pos_(rel_pos);
    BOOST_LOG_SEV(lg, boost::log::trivial::info) << "position is "
        << dragging_pawn_node_.row() << ":" << dragging_pawn_node_.col();
    return true;
}

Pos GameState::normalize_pawn_pos_(const CEGUI::Vector2f &rel_pos)
{
    return Pos(
            8 - static_cast<int>(rel_pos.d_y / 0.1111),
            static_cast<int>(rel_pos.d_x / 0.1111)
    );
}

}  /* namespace Quoridor */
<commit_msg>Check if dragging pawn is current<commit_after>#include "game_state.hpp"

#include "start_game_state.hpp"
#include "imove.hpp"
#include "walk_move.hpp"
#include "wall_move.hpp"
#include "logger.hpp"
#include "exception.hpp"
#include "cegui_ext/dragged_window.hpp"

static boost::log::sources::severity_logger<boost::log::trivial::severity_level> lg;

namespace Quoridor {

static std::vector<std::string> colors = {"red", "green", "blue", "yellow"};
std::string GameState::name_("Start Game");

GameState::GameState(std::shared_ptr<StateManager> stm,
        const std::vector<std::string> &player_types) : stm_(stm), anim_(),
    board_(new Board(9)), pf_(), players_(), pawn_list_(), cur_pawn_(),
    dragging_pawn_node_(), pawn_path_(), added_wall_(0, 0, 0, 0), wall_idx_(0),
    status_(kWaitingForMove)
{
    CEGUI::ImageManager::getSingleton().loadImageset("pawn.imageset");
    CEGUI::ImageManager::getSingleton().loadImageset("board.imageset");
    CEGUI::ImageManager::getSingleton().loadImageset("wall.imageset");
    win_ = std::shared_ptr<CEGUI::Window>(
            CEGUI::WindowManager::getSingleton().
                    loadLayoutFromFile("game.layout"),
            [=](CEGUI::Window *w) {
                BOOST_LOG_SEV(lg, boost::log::trivial::debug) << "removing window " << w;
                CEGUI::WindowManager::getSingleton().destroyWindow(w);
            }
    );

    subscribe_for_events_();

    if ((player_types.size() != 2) && (player_types.size() != 4)) {
        throw Exception("Invalid number of players");
    }

    int i = 0;
    for (auto player_type : player_types) {
        BOOST_LOG_SEV(lg, boost::log::trivial::info) << "adding player "
            << player_type;
        std::shared_ptr<Pawn> pawn(new Pawn(colors[i]));
        board_->add_pawn(pawn);
        players_[pawn] = pf_.make_player(player_type, board_, pawn);
        pawn_list_.push_back(pawn);
        ++i;
    }

    anim_ = std::shared_ptr<CEGUI::Animation>(
            CEGUI::AnimationManager::getSingleton().
                    createAnimation("movePawn"),
            [=](CEGUI::Animation *anim) {
                CEGUI::AnimationManager::getSingleton().destroyAnimation(anim);
            }
    );
    anim_->setDuration(0.5);
    anim_->setReplayMode(CEGUI::Animation::RM_Once);

    set_pawns_();

    cur_pawn_ = pawn_list_[0];
}

GameState::~GameState()
{
}

void GameState::update()
{
    switch (status_) {
    case kWaitingForMove:
        make_move_();
        break;
    case kPerformedMove:
        status_ = kWaitingForMove;
        if (is_finished_()) {
            BOOST_LOG_SEV(lg, boost::log::trivial::info) << cur_pawn_->color()
                << " win";
            status_ = kFinished;
        }
        else {
            cur_pawn_ = next_pawn();
        }
        break;
    case kNeedPawnRedraw:
        redraw_pawn_();
        status_ = kWaitingForAnimationEnd;
        break;
    case kNeedDrawWall:
        draw_wall_();
        status_ = kPerformedMove;
        break;
    case kWaitingForAnimationEnd:
        break;
    case kFinished:
        break;
    default:
        break;
    }
}

std::shared_ptr<CEGUI::Window> GameState::window() const
{
    return win_;
}

const std::string &GameState::name() const
{
    return name_;
}

void GameState::set_pawns_()
{
    auto board_win = static_cast<CEGUI::DefaultWindow*>(win_->getChild("boardWindow"));

    board_win->subscribeEvent(
            CEGUI_Ext::DraggedWindow::EventDraggedWindowDropped,
            CEGUI::Event::Subscriber(&GameState::handle_pawn_dropped_, this));
    board_win->subscribeEvent(
            CEGUI_Ext::DraggedWindow::EventDraggedWindowStartDragging,
            CEGUI::Event::Subscriber(&GameState::handle_pawn_start_dragging_, this));

    CEGUI::Window *drag_win;
    for (auto pawn : pawn_list_) {
        if (players_[pawn]->is_interactive()) {
            drag_win = new CEGUI_Ext::DraggedWindow("DefaultWindow", pawn->color());
        }
        else {
            drag_win = CEGUI::WindowManager::getSingleton().createWindow("DefaultWindow", pawn->color());
            drag_win->subscribeEvent(CEGUI::AnimationInstance::EventAnimationEnded, CEGUI::Event::Subscriber(&GameState::handle_end_anim_, this));
        }

        drag_win->setSize(CEGUI::USize({0.1, 0}, {0.1, 0}));
        Pos pos = board_->pawn_node(pawn);
        float x_coord = 0.1111 * pos.col();
        float y_coord = 0.1111 * (8 - pos.row());
        drag_win->setPosition(CEGUI::UVector2({x_coord, 2}, {y_coord, 2}));

        auto pawn_win = CEGUI::WindowManager::getSingleton().loadLayoutFromFile("pawn_anim.layout");
        drag_win->addChild(pawn_win);
        board_win->addChild(drag_win);
    }
}

void GameState::redraw_pawn_()
{
    Pos old_pos = pawn_path_[0];
    Pos new_pos = pawn_path_[1];

    pawn_path_.clear();

    float old_x_coord = 0.1111 * old_pos.col();
    float old_y_coord = 0.1111 * (8 - old_pos.row());
    float new_x_coord = 0.1111 * new_pos.col();
    float new_y_coord = 0.1111 * (8 - new_pos.row());

    CEGUI::Affector *affector = anim_->createAffector("Position", "UVector2");
    affector->setApplicationMethod(CEGUI::Affector::AM_Absolute);
    affector->createKeyFrame(0.0, "{{" + std::to_string(old_x_coord)
            + ", 2.0}, { " + std::to_string(old_y_coord) + ", 2.0}}");
    affector->createKeyFrame(0.5, "{{" + std::to_string(new_x_coord)
            + ", 2.0}, { " + std::to_string(new_y_coord) + ", 2.0}}");

    auto pawn_win = win_->getChild("boardWindow/" + cur_pawn_->color());
    CEGUI::AnimationInstance *instance = CEGUI::AnimationManager::
            getSingleton().instantiateAnimation(anim_.get());
    instance->setTargetWindow(pawn_win);
    instance->start();
}

void GameState::draw_wall_()
{
    auto board_win = static_cast<CEGUI::DefaultWindow*>(win_->getChild("boardWindow"));

    if (added_wall_.orientation() == 0) {
        for (int i = 0; i < added_wall_.cnt(); ++i) {
            float x = 0.1111 * (added_wall_.start_pos() + i);
            float y = 0.1111 * ( 8 - added_wall_.line());
            auto wall_win = CEGUI::WindowManager::getSingleton().loadLayoutFromFile("horizontal_wall.layout");
            wall_win->setPosition(CEGUI::UVector2({x, 0}, {y, -2}));
            wall_win->setName("wallWindow" + std::to_string(wall_idx_));
            ++wall_idx_;
            board_win->addChild(wall_win);
            BOOST_LOG_SEV(lg, boost::log::trivial::info) << "added horizontal wall at "
                << x << ":" << y;
        }
    }
    else {
        for (int i = 0; i < added_wall_.cnt(); ++i) {
            float x = 0.1111 * (added_wall_.line());
            float y = 0.1111 * ( 8 - added_wall_.start_pos() - i);
            auto wall_win = CEGUI::WindowManager::getSingleton().loadLayoutFromFile("vertical_wall.layout");
            wall_win->setPosition(CEGUI::UVector2({x, -2}, {y, 0}));
            wall_win->setName("wallWindow" + std::to_string(wall_idx_));
            ++wall_idx_;
            board_win->addChild(wall_win);
            BOOST_LOG_SEV(lg, boost::log::trivial::info) << "added vertiacl wall at "
                << x << ":" << y;
        }
    }
}

std::shared_ptr<Pawn> GameState::next_pawn() const
{
    auto it = pawn_list_.begin();
    for (;it != pawn_list_.end(); ++it) {
        if (cur_pawn_ && (*it == cur_pawn_)) {
            break;
        }
    }
    if (++it == pawn_list_.end()) {
        return pawn_list_[0];
    }
    else {
        return *it;
    }
}

void GameState::make_move_()
{
    IMove *move = NULL;

    // bot's turn
    if (!players_[cur_pawn_]->is_interactive()) {
        move = players_[cur_pawn_]->get_move();
    }
    // human's turn, handle it in one of event handlers
    else {
        return;
    }

    if (move != NULL) {
        Pos cur_node = board_->pawn_node(cur_pawn_);
        int rc;

        if (WalkMove *walk_move = dynamic_cast<WalkMove*>(move)) {
            BOOST_LOG_SEV(lg, boost::log::trivial::info) << cur_pawn_->color()
                << " move: " << cur_node.row() << ":" << cur_node.col()
                << " -> " << walk_move->node().row() << ":"
                << walk_move->node().col();

            rc = board_->make_walking_move(cur_pawn_, walk_move->node());
            if (rc == 0) {
                pawn_path_.push_back(cur_node);
                pawn_path_.push_back(board_->pawn_node(cur_pawn_));
                status_ = kNeedPawnRedraw;
            }
        }
        else if (WallMove *wall_move = dynamic_cast<WallMove*>(move)) {
            const Wall &wall = wall_move->wall();
            rc = board_->add_wall(wall);
            if (rc == 0) {
                added_wall_ = wall;
                status_ = kNeedDrawWall;
            }
        }
    }
}

bool GameState::is_finished_() const
{
    return board_->is_at_goal_node(cur_pawn_);
}

void GameState::subscribe_for_events_()
{
    win_->getChild("back")->subscribeEvent(
            CEGUI::Window::EventMouseClick,
            CEGUI::Event::Subscriber(
                    &GameState::handle_back_, this
            )
    );
}

bool GameState::handle_back_(const CEGUI::EventArgs &/* e */)
{
    BOOST_LOG_SEV(lg, boost::log::trivial::info) << "returning to start game menu";
    stm_->change_state(std::shared_ptr<IState>(new StartGameState(stm_)));
    return true;
}

bool GameState::handle_end_anim_(const CEGUI::EventArgs &/* e */)
{
    status_ = kPerformedMove;
    return true;
}

bool GameState::handle_pawn_dropped_(const CEGUI::EventArgs &e)
{
    BOOST_LOG_SEV(lg, boost::log::trivial::info) << "pawn was dropped!";

    auto de = static_cast<const CEGUI_Ext::DragEvent &>(e);
    CEGUI::Vector2f rel_pos = CEGUI::CoordConverter::asRelative(
            de.window()->getPosition() + de.pos(),
            {468, 468}  // @fixme get parent size
    );
    Pos node = normalize_pawn_pos_(rel_pos);

    BOOST_LOG_SEV(lg, boost::log::trivial::info) << de.window() << " position "
        << node.row() << ":" << node.col();

    float x_coord;
    float y_coord;

    if (dragging_pawn_node_ != board_->pawn_node(cur_pawn_)) {
        BOOST_LOG_SEV(lg, boost::log::trivial::info) << "pawn is not current";
        x_coord = 0.1111 * dragging_pawn_node_.col();
        y_coord = 0.1111 * (8 - dragging_pawn_node_.row());
    }
    else {
        int rc = board_->make_walking_move(cur_pawn_, node);
        if (rc == 0) {
            x_coord = 0.1111 * node.col();
            y_coord = 0.1111 * (8 - node.row());
            status_ = kPerformedMove;
        }
        else {
            Pos cur_node = board_->pawn_node(cur_pawn_);
            x_coord = 0.1111 * cur_node.col();
            y_coord = 0.1111 * (8 - cur_node.row());
        }
    }

    de.window()->setPosition(CEGUI::UVector2({x_coord, 2}, {y_coord, 2}));

    return true;
}

bool GameState::handle_pawn_start_dragging_(const CEGUI::EventArgs &e)
{
    BOOST_LOG_SEV(lg, boost::log::trivial::info) << "pawn is dragging";

    auto de = static_cast<const CEGUI_Ext::DragEvent &>(e);
    CEGUI::Vector2f rel_pos = CEGUI::CoordConverter::asRelative(
            de.window()->getPosition() + de.pos(),
            {468, 468}
    );
    dragging_pawn_node_ = normalize_pawn_pos_(rel_pos);
    BOOST_LOG_SEV(lg, boost::log::trivial::info) << "position is "
        << dragging_pawn_node_.row() << ":" << dragging_pawn_node_.col();
    return true;
}

Pos GameState::normalize_pawn_pos_(const CEGUI::Vector2f &rel_pos)
{
    return Pos(
            8 - static_cast<int>(rel_pos.d_y / 0.1111),
            static_cast<int>(rel_pos.d_x / 0.1111)
    );
}

}  /* namespace Quoridor */
<|endoftext|>


<commit_before>#include <iostream>
#include "neuralNetwork.h"

int main(int argc, char *argv[]) {
	//Command line arguments are used in order to facilitate
	//the use of the program from the python interface
	if (argc == 1) {
		cout << "Invalid usage.\n" << "Correct usage: \n" << "./network option\n";
		cout << "Valid options: \n" << "A: Train the classifier\n" << "B: Run the classifier over the test file\n" << "C: Predict a crime\n";
		cout << "The first time the program is run, the A parameter must be called first.\n";
		cout << "The program will not run over the test file or predict a crime if it has not been trained first.\n";
		exit(0);
	}
	//The parameter A will train the network
	if (argv[1][0] == 'A') {
		//Dynamic memory is used here to speed up
		//the training process. Since the data set
		//is too big, the program would'nt allow
		//for a normal memory allocation
		double** data = new double*[900000];
		for (int i = 0; i < 900000; i++) {
			data[i] = new double[77];
		}
		double** validationData = new double*[200000];
		for (int i = 0; i < 200000; i++) {
			validationData[i] = new double[77];
		}

		//Constructor parameters: lambda, eta, momentum, input neurons,
		//hidden layers, hidden neurons per layer, output neurons
		NeuralNetwork network(0.6, 0.8, 0.0, 38, 1, 25, 39);
		//The data and validation dynamic arrays
		//are passed to the network. The network
		//uses them by reference
		network.run(30, data, validationData);
		network.saveToFile("saved.txt");

		//Free memory
		for (int i = 0; i < 900000; i++) {
			delete[] data[i];
		}
		delete[] data;
		for (int i = 0; i < 200000; i++) {
			delete[] validationData[i];
		}
		delete[] validationData;
	}
	else if (argv[1][0] == 'B') {
		double** data = new double*[900000];
		for (int i = 0; i < 900000; i++) {
			data[i] = new double[77];
		}
		NeuralNetwork network("saved.txt");
		network.runTest(data);
		for (int i = 0; i < 900000; i++) {
			delete[] data[i];
		}
		delete[] data;
	}
	else if (argv[1][0] == 'C') {
		NeuralNetwork network("saved.txt");
		network.predict();
	}
	else {
		cout << "Invalid usage.\n" << "Correct usage: \n" << "./network option\n";
		cout << "Valid options: \n" << "A: Train the classifier\n" << "B: Run the classifier over the test file\n" << "C: Predict a crime\n";
		cout << "The first time the program is run, the A parameter must be called first.\n";
		cout << "The program will not run over the test file or predict a crime if it has not been trained first.\n";
		exit(0);
	}
	cout << "Finished\n";
	return 0;
}<commit_msg>Final changes<commit_after>#include <iostream>
#include "neuralNetwork.h"

int main(int argc, char *argv[]) {
	//Command line arguments are used in order to facilitate
	//the use of the program from the python interface
	if (argc != 2 || (argv[1][0]!='A' && argv[1][0]!='B' && argv[1][0]!='C')) {
		cout << "Invalid usage.\n" << "Correct usage: \n" << "./network option\n";
		cout << "Valid options: \n" << "A: Train the classifier\n" << "B: Run the classifier over the test file\n" << "C: Predict a crime\n";
		cout << "The first time the program is run, the A parameter must be called first.\n";
		cout << "The program will not run over the test file or predict a crime if it has not been trained first.\n";
		exit(0);
	}
	//The parameter A will train the network
	if (argv[1][0] == 'A') {
		//Dynamic memory is used here to speed up
		//the training process. Since the data set
		//is too big, the program would'nt allow
		//for a normal memory allocation
		double** data = new double*[900000];
		for (int i = 0; i < 900000; i++) {
			data[i] = new double[77];
		}
		double** validationData = new double*[200000];
		for (int i = 0; i < 200000; i++) {
			validationData[i] = new double[77];
		}

		//Constructor parameters: lambda, eta, momentum, input neurons,
		//hidden layers, hidden neurons per layer, output neurons
		NeuralNetwork network(0.6, 0.8, 0.0, 38, 1, 25, 39);
		//The data and validation dynamic arrays
		//are passed to the network. The network
		//uses them by reference
		network.run(2, data, validationData);
		network.saveToFile("saved.txt");

		//Free memory
		for (int i = 0; i < 900000; i++) {
			delete[] data[i];
		}
		delete[] data;
		for (int i = 0; i < 200000; i++) {
			delete[] validationData[i];
		}
		delete[] validationData;
	}
	else if (argv[1][0] == 'B') {
		double** data = new double*[900000];
		for (int i = 0; i < 900000; i++) {
			data[i] = new double[77];
		}
		NeuralNetwork network("saved.txt");
		network.runTest(data);
		for (int i = 0; i < 900000; i++) {
			delete[] data[i];
		}
		delete[] data;
	}
	else if (argv[1][0] == 'C') {
		NeuralNetwork network("saved.txt");
		network.predict();
	}
	cout << "Finished\n";
	return 0;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: sfxmodelfactory.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: kz $ $Date: 2008-03-06 19:56:18 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sfx2.hxx"

#ifndef SFX2_SFXMODELFACTORY_HXX
#include "sfx2/sfxmodelfactory.hxx"
#endif

/** === begin UNO includes === **/
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/lang/XInitialization.hpp>
/** === end UNO includes === **/

#include <comphelper/namedvaluecollection.hxx>
#include <cppuhelper/implbase2.hxx>

#include <algorithm>
#include <functional>

//........................................................................
namespace sfx2
{
//........................................................................

    /** === begin UNO using === **/
    using ::com::sun::star::uno::Reference;
    using ::com::sun::star::uno::XInterface;
    using ::com::sun::star::uno::UNO_QUERY;
    using ::com::sun::star::uno::UNO_QUERY_THROW;
    using ::com::sun::star::uno::UNO_SET_THROW;
    using ::com::sun::star::uno::Exception;
    using ::com::sun::star::uno::RuntimeException;
    using ::com::sun::star::uno::Any;
    using ::com::sun::star::uno::makeAny;
    using ::com::sun::star::lang::XMultiServiceFactory;
    using ::com::sun::star::uno::Sequence;
    using ::com::sun::star::lang::XSingleServiceFactory;
    using ::com::sun::star::lang::XServiceInfo;
    using ::com::sun::star::beans::NamedValue;
    using ::com::sun::star::beans::PropertyValue;
    using ::com::sun::star::lang::XInitialization;
    /** === end UNO using === **/

    //====================================================================
    //= SfxModelFactory - declaration
    //====================================================================
    typedef ::cppu::WeakImplHelper2 <   XSingleServiceFactory
                                    ,   XServiceInfo
                                    >   SfxModelFactory_Base;
    /** implements a XSingleServiceFactory which can be used to created instances
        of classes derived from SfxBaseModel

        In opposite to the default implementations from module cppuhelper, this
        factory evaluates certain creation arguments (passed to createInstanceWithArguments)
        and passes them to the factory function of the derived class.
    */
    class SfxModelFactory : public SfxModelFactory_Base
    {
    public:
        SfxModelFactory(
            const Reference< XMultiServiceFactory >& _rxServiceFactory,
            const ::rtl::OUString& _rImplementationName,
            const SfxModelFactoryFunc _pComponentFactoryFunc,
            const Sequence< ::rtl::OUString >& _rServiceNames
        );

        // XSingleServiceFactory
        virtual Reference< XInterface > SAL_CALL createInstance(  ) throw (Exception, RuntimeException);
        virtual Reference< XInterface > SAL_CALL createInstanceWithArguments( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException);

        // XServiceInfo
        virtual ::rtl::OUString SAL_CALL getImplementationName(  ) throw (RuntimeException);
        virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (RuntimeException);
        virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames(  ) throw (RuntimeException);

    protected:
        virtual ~SfxModelFactory();

    private:
        Reference< XInterface > impl_createInstance( const sal_uInt64 _nCreationFlags ) const;

    private:
        const Reference< XMultiServiceFactory >     m_xServiceFactory;
        const ::rtl::OUString                       m_sImplementationName;
        const Sequence< ::rtl::OUString >           m_aServiceNames;
        const SfxModelFactoryFunc                   m_pComponentFactoryFunc;
    };

    //====================================================================
    //= SfxModelFactory - implementation
    //====================================================================
    //--------------------------------------------------------------------
    SfxModelFactory::SfxModelFactory( const Reference< XMultiServiceFactory >& _rxServiceFactory,
            const ::rtl::OUString& _rImplementationName, const SfxModelFactoryFunc _pComponentFactoryFunc,
            const Sequence< ::rtl::OUString >& _rServiceNames )
        :m_xServiceFactory( _rxServiceFactory )
        ,m_sImplementationName( _rImplementationName )
        ,m_aServiceNames( _rServiceNames )
        ,m_pComponentFactoryFunc( _pComponentFactoryFunc )
    {
    }

    //--------------------------------------------------------------------
    SfxModelFactory::~SfxModelFactory()
    {
    }

    //--------------------------------------------------------------------
    Reference< XInterface > SfxModelFactory::impl_createInstance( const sal_uInt64 _nCreationFlags ) const
    {
        return (*m_pComponentFactoryFunc)( m_xServiceFactory, _nCreationFlags );
    }

    //--------------------------------------------------------------------
    Reference< XInterface > SAL_CALL SfxModelFactory::createInstance(  ) throw (Exception, RuntimeException)
    {
        return impl_createInstance( 0 );
        return createInstanceWithArguments( Sequence< Any >() );
    }

    //--------------------------------------------------------------------
    namespace
    {
        struct IsSpecialArgument : public ::std::unary_function< Any, bool >
        {
            static bool isSpecialArgumentName( const ::rtl::OUString& _rValueName )
            {
                return  _rValueName.equalsAscii( "EmbeddedObject" )
                    ||  _rValueName.equalsAscii( "EmbeddedScriptSupport" );
            }

            bool operator()( const Any& _rArgument ) const
            {
                NamedValue aNamedValue;
                if ( ( _rArgument >>= aNamedValue ) && isSpecialArgumentName( aNamedValue.Name ) )
                    return true;
                PropertyValue aPropertyValue;
                if ( ( _rArgument >>= aPropertyValue ) && isSpecialArgumentName( aPropertyValue.Name ) )
                    return true;
                return false;
            }
        };
    }

    //--------------------------------------------------------------------
    Reference< XInterface > SAL_CALL SfxModelFactory::createInstanceWithArguments( const Sequence< Any >& _rArguments ) throw (Exception, RuntimeException)
    {
        ::comphelper::NamedValueCollection aArgs( _rArguments );
        const sal_Bool bEmbeddedObject = aArgs.getOrDefault( "EmbeddedObject", sal_False );
        const sal_Bool bScriptSupport = aArgs.getOrDefault( "EmbeddedScriptSupport", sal_True );

        sal_uInt64 nCreationFlags =
                ( bEmbeddedObject ? SFXMODEL_EMBEDDED_OBJECT : 0 )
            |   ( bScriptSupport ? 0 : SFXMODEL_DISABLE_EMBEDDED_SCRIPTS );

        Reference< XInterface > xInstance( impl_createInstance( nCreationFlags ) );

        // to mimic the bahaviour of the default factory's createInstanceWithArguments, we initialize
        // the object with the given arguments, stripped by the two special ones
        Sequence< Any > aStrippedArguments( _rArguments.getLength() );
        Any* pStrippedArgs = aStrippedArguments.getArray();
        Any* pStrippedArgsEnd = ::std::remove_copy_if(
            _rArguments.getConstArray(),
            _rArguments.getConstArray() + _rArguments.getLength(),
            pStrippedArgs,
            IsSpecialArgument()
        );
        aStrippedArguments.realloc( pStrippedArgsEnd - pStrippedArgs );

        if ( aStrippedArguments.getLength() )
        {
            Reference< XInitialization > xModelInit( xInstance, UNO_QUERY );
            OSL_ENSURE( xModelInit.is(), "SfxModelFactory::createInstanceWithArguments: no XInitialization!" );
            if ( xModelInit.is() )
                xModelInit->initialize( aStrippedArguments );
        }

        return xInstance;
    }

    //--------------------------------------------------------------------
    ::rtl::OUString SAL_CALL SfxModelFactory::getImplementationName(  ) throw (RuntimeException)
    {
        return m_sImplementationName;
    }

    //--------------------------------------------------------------------
    ::sal_Bool SAL_CALL SfxModelFactory::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException)
    {
        return ::std::find(
            m_aServiceNames.getConstArray(),
            m_aServiceNames.getConstArray() + m_aServiceNames.getLength(),
            _rServiceName
        )  != m_aServiceNames.getConstArray() + m_aServiceNames.getLength();
    }

    //--------------------------------------------------------------------
    Sequence< ::rtl::OUString > SAL_CALL SfxModelFactory::getSupportedServiceNames(  ) throw (RuntimeException)
    {
        return m_aServiceNames;
    }

    //--------------------------------------------------------------------
    Reference< XSingleServiceFactory > createSfxModelFactory( const Reference< XMultiServiceFactory >& _rxServiceFactory,
            const ::rtl::OUString& _rImplementationName, const SfxModelFactoryFunc _pComponentFactoryFunc,
            const Sequence< ::rtl::OUString >& _rServiceNames )
    {
        return new SfxModelFactory( _rxServiceFactory, _rImplementationName, _pComponentFactoryFunc, _rServiceNames );
    }

//........................................................................
} // namespace sfx2
//........................................................................
<commit_msg>#i10000# return impl_createInstance( 0 ) removed<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: sfxmodelfactory.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: obo $ $Date: 2008-03-10 08:32:14 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sfx2.hxx"

#ifndef SFX2_SFXMODELFACTORY_HXX
#include "sfx2/sfxmodelfactory.hxx"
#endif

/** === begin UNO includes === **/
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/lang/XInitialization.hpp>
/** === end UNO includes === **/

#include <comphelper/namedvaluecollection.hxx>
#include <cppuhelper/implbase2.hxx>

#include <algorithm>
#include <functional>

//........................................................................
namespace sfx2
{
//........................................................................

    /** === begin UNO using === **/
    using ::com::sun::star::uno::Reference;
    using ::com::sun::star::uno::XInterface;
    using ::com::sun::star::uno::UNO_QUERY;
    using ::com::sun::star::uno::UNO_QUERY_THROW;
    using ::com::sun::star::uno::UNO_SET_THROW;
    using ::com::sun::star::uno::Exception;
    using ::com::sun::star::uno::RuntimeException;
    using ::com::sun::star::uno::Any;
    using ::com::sun::star::uno::makeAny;
    using ::com::sun::star::lang::XMultiServiceFactory;
    using ::com::sun::star::uno::Sequence;
    using ::com::sun::star::lang::XSingleServiceFactory;
    using ::com::sun::star::lang::XServiceInfo;
    using ::com::sun::star::beans::NamedValue;
    using ::com::sun::star::beans::PropertyValue;
    using ::com::sun::star::lang::XInitialization;
    /** === end UNO using === **/

    //====================================================================
    //= SfxModelFactory - declaration
    //====================================================================
    typedef ::cppu::WeakImplHelper2 <   XSingleServiceFactory
                                    ,   XServiceInfo
                                    >   SfxModelFactory_Base;
    /** implements a XSingleServiceFactory which can be used to created instances
        of classes derived from SfxBaseModel

        In opposite to the default implementations from module cppuhelper, this
        factory evaluates certain creation arguments (passed to createInstanceWithArguments)
        and passes them to the factory function of the derived class.
    */
    class SfxModelFactory : public SfxModelFactory_Base
    {
    public:
        SfxModelFactory(
            const Reference< XMultiServiceFactory >& _rxServiceFactory,
            const ::rtl::OUString& _rImplementationName,
            const SfxModelFactoryFunc _pComponentFactoryFunc,
            const Sequence< ::rtl::OUString >& _rServiceNames
        );

        // XSingleServiceFactory
        virtual Reference< XInterface > SAL_CALL createInstance(  ) throw (Exception, RuntimeException);
        virtual Reference< XInterface > SAL_CALL createInstanceWithArguments( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException);

        // XServiceInfo
        virtual ::rtl::OUString SAL_CALL getImplementationName(  ) throw (RuntimeException);
        virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (RuntimeException);
        virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames(  ) throw (RuntimeException);

    protected:
        virtual ~SfxModelFactory();

    private:
        Reference< XInterface > impl_createInstance( const sal_uInt64 _nCreationFlags ) const;

    private:
        const Reference< XMultiServiceFactory >     m_xServiceFactory;
        const ::rtl::OUString                       m_sImplementationName;
        const Sequence< ::rtl::OUString >           m_aServiceNames;
        const SfxModelFactoryFunc                   m_pComponentFactoryFunc;
    };

    //====================================================================
    //= SfxModelFactory - implementation
    //====================================================================
    //--------------------------------------------------------------------
    SfxModelFactory::SfxModelFactory( const Reference< XMultiServiceFactory >& _rxServiceFactory,
            const ::rtl::OUString& _rImplementationName, const SfxModelFactoryFunc _pComponentFactoryFunc,
            const Sequence< ::rtl::OUString >& _rServiceNames )
        :m_xServiceFactory( _rxServiceFactory )
        ,m_sImplementationName( _rImplementationName )
        ,m_aServiceNames( _rServiceNames )
        ,m_pComponentFactoryFunc( _pComponentFactoryFunc )
    {
    }

    //--------------------------------------------------------------------
    SfxModelFactory::~SfxModelFactory()
    {
    }

    //--------------------------------------------------------------------
    Reference< XInterface > SfxModelFactory::impl_createInstance( const sal_uInt64 _nCreationFlags ) const
    {
        return (*m_pComponentFactoryFunc)( m_xServiceFactory, _nCreationFlags );
    }

    //--------------------------------------------------------------------
    Reference< XInterface > SAL_CALL SfxModelFactory::createInstance(  ) throw (Exception, RuntimeException)
    {
        return createInstanceWithArguments( Sequence< Any >() );
    }

    //--------------------------------------------------------------------
    namespace
    {
        struct IsSpecialArgument : public ::std::unary_function< Any, bool >
        {
            static bool isSpecialArgumentName( const ::rtl::OUString& _rValueName )
            {
                return  _rValueName.equalsAscii( "EmbeddedObject" )
                    ||  _rValueName.equalsAscii( "EmbeddedScriptSupport" );
            }

            bool operator()( const Any& _rArgument ) const
            {
                NamedValue aNamedValue;
                if ( ( _rArgument >>= aNamedValue ) && isSpecialArgumentName( aNamedValue.Name ) )
                    return true;
                PropertyValue aPropertyValue;
                if ( ( _rArgument >>= aPropertyValue ) && isSpecialArgumentName( aPropertyValue.Name ) )
                    return true;
                return false;
            }
        };
    }

    //--------------------------------------------------------------------
    Reference< XInterface > SAL_CALL SfxModelFactory::createInstanceWithArguments( const Sequence< Any >& _rArguments ) throw (Exception, RuntimeException)
    {
        ::comphelper::NamedValueCollection aArgs( _rArguments );
        const sal_Bool bEmbeddedObject = aArgs.getOrDefault( "EmbeddedObject", sal_False );
        const sal_Bool bScriptSupport = aArgs.getOrDefault( "EmbeddedScriptSupport", sal_True );

        sal_uInt64 nCreationFlags =
                ( bEmbeddedObject ? SFXMODEL_EMBEDDED_OBJECT : 0 )
            |   ( bScriptSupport ? 0 : SFXMODEL_DISABLE_EMBEDDED_SCRIPTS );

        Reference< XInterface > xInstance( impl_createInstance( nCreationFlags ) );

        // to mimic the bahaviour of the default factory's createInstanceWithArguments, we initialize
        // the object with the given arguments, stripped by the two special ones
        Sequence< Any > aStrippedArguments( _rArguments.getLength() );
        Any* pStrippedArgs = aStrippedArguments.getArray();
        Any* pStrippedArgsEnd = ::std::remove_copy_if(
            _rArguments.getConstArray(),
            _rArguments.getConstArray() + _rArguments.getLength(),
            pStrippedArgs,
            IsSpecialArgument()
        );
        aStrippedArguments.realloc( pStrippedArgsEnd - pStrippedArgs );

        if ( aStrippedArguments.getLength() )
        {
            Reference< XInitialization > xModelInit( xInstance, UNO_QUERY );
            OSL_ENSURE( xModelInit.is(), "SfxModelFactory::createInstanceWithArguments: no XInitialization!" );
            if ( xModelInit.is() )
                xModelInit->initialize( aStrippedArguments );
        }

        return xInstance;
    }

    //--------------------------------------------------------------------
    ::rtl::OUString SAL_CALL SfxModelFactory::getImplementationName(  ) throw (RuntimeException)
    {
        return m_sImplementationName;
    }

    //--------------------------------------------------------------------
    ::sal_Bool SAL_CALL SfxModelFactory::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException)
    {
        return ::std::find(
            m_aServiceNames.getConstArray(),
            m_aServiceNames.getConstArray() + m_aServiceNames.getLength(),
            _rServiceName
        )  != m_aServiceNames.getConstArray() + m_aServiceNames.getLength();
    }

    //--------------------------------------------------------------------
    Sequence< ::rtl::OUString > SAL_CALL SfxModelFactory::getSupportedServiceNames(  ) throw (RuntimeException)
    {
        return m_aServiceNames;
    }

    //--------------------------------------------------------------------
    Reference< XSingleServiceFactory > createSfxModelFactory( const Reference< XMultiServiceFactory >& _rxServiceFactory,
            const ::rtl::OUString& _rImplementationName, const SfxModelFactoryFunc _pComponentFactoryFunc,
            const Sequence< ::rtl::OUString >& _rServiceNames )
    {
        return new SfxModelFactory( _rxServiceFactory, _rImplementationName, _pComponentFactoryFunc, _rServiceNames );
    }

//........................................................................
} // namespace sfx2
//........................................................................
<|endoftext|>


<commit_before>
#include "string/acdfa.h"

#include <algorithm>

#include <gtest/gtest.h>

namespace {

using T = std::pair<size_t, size_t>;
using VT = std::vector<T>;

const VT Sort(VT src) {
    std::sort(src.begin(), src.end());
    return src;
}

} // namespace

TEST(ACDFATest, test1) {
    ACDFA acdfa;

    EXPECT_ANY_THROW(acdfa.Compile({"", "", ""}));

    acdfa.Compile({"He", "SHe", "Hem", "He"});
    EXPECT_EQ(Sort({{0, 3}, {1, 3}, {1, 3}, {1, 4}}), Sort(acdfa.Run("SHem")));
    EXPECT_EQ(Sort({}), Sort(acdfa.Run("hehe")));
    EXPECT_EQ(Sort({{2, 5}, {3, 5}, {3, 5}, {3, 6}}), Sort(acdfa.Run("heSHemhe")));

    acdfa.Compile({"He", "hE"});
    EXPECT_EQ(Sort({}), Sort(acdfa.Run("he")));
    EXPECT_EQ(Sort({{0, 2}, {4, 6}}), Sort(acdfa.Run("HehehE")));
    EXPECT_EQ(Sort({{2, 4}, {4, 6}}), Sort(acdfa.Run("heHehEhe")));

    acdfa.Compile({"HE", "she", "hEm", "hE"}, true);
    EXPECT_EQ(Sort({{0, 3}, {1, 3}, {1, 3}, {1, 4}}), Sort(acdfa.Run("SHEM")));
    EXPECT_EQ(Sort({{0, 2}, {2, 4}}), Sort(acdfa.Run("hehe")));
    EXPECT_EQ(Sort({}), Sort(acdfa.Run("abcd")));
}
<commit_msg>fix(acdfa): 测试逻辑错误<commit_after>
#include "string/acdfa.h"

#include <algorithm>

#include <gtest/gtest.h>

namespace {

using T = std::pair<size_t, size_t>;
using VT = std::vector<T>;

const VT Sort(VT src) {
    std::sort(src.begin(), src.end());
    return src;
}

} // namespace

TEST(ACDFATest, test1) {
    ACDFA acdfa;

    EXPECT_ANY_THROW(acdfa.Compile({"", "", ""}));

    acdfa.Compile({"He", "SHe", "Hem", "He"});
    EXPECT_EQ(Sort({{0, 3}, {1, 2}, {1, 2}, {1, 3}}), Sort(acdfa.Run("SHem")));
    EXPECT_EQ(Sort({}), Sort(acdfa.Run("hehe")));
    EXPECT_EQ(Sort({{2, 3}, {3, 2}, {3, 2}, {3, 3}}), Sort(acdfa.Run("heSHemhe")));

    acdfa.Compile({"He", "hE"});
    EXPECT_EQ(Sort({}), Sort(acdfa.Run("he")));
    EXPECT_EQ(Sort({{0, 2}, {4, 2}}), Sort(acdfa.Run("HehehE")));
    EXPECT_EQ(Sort({{2, 2}, {4, 2}}), Sort(acdfa.Run("heHehEhe")));

    acdfa.Compile({"HE", "she", "hEm", "hE"}, true);
    EXPECT_EQ(Sort({{0, 3}, {1, 2}, {1, 2}, {1, 3}}), Sort(acdfa.Run("SHEM")));
    EXPECT_EQ(Sort({{0, 2}, {2, 2}}), Sort(acdfa.Run("hehe")));
    EXPECT_EQ(Sort({}), Sort(acdfa.Run("abcd")));
}
<|endoftext|>


<commit_before>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#include "posix.hh"
#include "align.hh"
#include <sys/mman.h>

file_desc
file_desc::temporary(sstring directory) {
    // FIXME: add O_TMPFILE support one day
    directory += "/XXXXXX";
    std::vector<char> templat(directory.c_str(), directory.c_str() + directory.size() + 1);
    int fd = ::mkstemp(templat.data());
    throw_system_error_on(fd == -1);
    int r = ::unlink(templat.data());
    throw_system_error_on(r == -1); // leaks created file, but what can we do?
    return file_desc(fd);
}

void mmap_deleter::operator()(void* ptr) const {
    ::munmap(ptr, _size);
}

mmap_area mmap_anonymous(void* addr, size_t length, int prot, int flags) {
    auto ret = ::mmap(addr, length, prot, flags | MAP_ANONYMOUS, -1, 0);
    throw_system_error_on(ret == MAP_FAILED);
    return mmap_area(reinterpret_cast<char*>(ret), mmap_deleter{length});
}

void* posix_thread::start_routine(void* arg) {
    auto pfunc = reinterpret_cast<std::function<void ()>*>(arg);
    (*pfunc)();
    return nullptr;
}

posix_thread::posix_thread(std::function<void ()> func)
    : posix_thread(attr{}, std::move(func)) {
}

posix_thread::posix_thread(attr a, std::function<void ()> func)
    : _func(std::make_unique<std::function<void ()>>(std::move(func))) {
    pthread_attr_t pa;
    auto r = pthread_attr_init(&pa);
    if (r) {
        throw std::system_error(r, std::system_category());
    }
    auto stack_size = a._stack_size.size;
    if (!stack_size) {
        stack_size = 2 << 20;
    }
    // allocate guard area as well
    _stack = mmap_anonymous(nullptr, stack_size + (4 << 20),
            PROT_NONE, MAP_PRIVATE | MAP_NORESERVE);
    auto stack_start = align_up(_stack.get() + 1, 2 << 20);
    mmap_area real_stack = mmap_anonymous(stack_start, stack_size,
            PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED | MAP_STACK);
    real_stack.release(); // protected by @_stack
    ::madvise(stack_start, stack_size, MADV_HUGEPAGE);
    r = pthread_attr_setstack(&pa, stack_start, stack_size);
    if (r) {
        throw std::system_error(r, std::system_category());
    }
    r = pthread_create(&_pthread, &pa,
                &posix_thread::start_routine, _func.get());
    if (r) {
        throw std::system_error(r, std::system_category());
    }
}

posix_thread::posix_thread(posix_thread&& x)
    : _func(std::move(x._func)), _pthread(x._pthread), _valid(x._valid)
    , _stack(std::move(x._stack)) {
    x._valid = false;
}

posix_thread::~posix_thread() {
    assert(!_valid);
}

void posix_thread::join() {
    assert(_valid);
    pthread_join(_pthread, NULL);
    _valid = false;
}

void pin_this_thread(unsigned cpu_id) {
    cpu_set_t cs;
    CPU_ZERO(&cs);
    CPU_SET(cpu_id, &cs);
    auto r = pthread_setaffinity_np(pthread_self(), sizeof(cs), &cs);
    assert(r == 0);
}

<commit_msg>core: Do not let exceptions out of posix thread callback<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#include "posix.hh"
#include "align.hh"
#include <sys/mman.h>

file_desc
file_desc::temporary(sstring directory) {
    // FIXME: add O_TMPFILE support one day
    directory += "/XXXXXX";
    std::vector<char> templat(directory.c_str(), directory.c_str() + directory.size() + 1);
    int fd = ::mkstemp(templat.data());
    throw_system_error_on(fd == -1);
    int r = ::unlink(templat.data());
    throw_system_error_on(r == -1); // leaks created file, but what can we do?
    return file_desc(fd);
}

void mmap_deleter::operator()(void* ptr) const {
    ::munmap(ptr, _size);
}

mmap_area mmap_anonymous(void* addr, size_t length, int prot, int flags) {
    auto ret = ::mmap(addr, length, prot, flags | MAP_ANONYMOUS, -1, 0);
    throw_system_error_on(ret == MAP_FAILED);
    return mmap_area(reinterpret_cast<char*>(ret), mmap_deleter{length});
}

void* posix_thread::start_routine(void* arg) {
    auto pfunc = reinterpret_cast<std::function<void ()>*>(arg);
    try {
        (*pfunc)();
    } catch (...) {
        // We're in POSIX thread callback, so all exceptions need to be handled.
        std::terminate();
    }
    return nullptr;
}

posix_thread::posix_thread(std::function<void ()> func)
    : posix_thread(attr{}, std::move(func)) {
}

posix_thread::posix_thread(attr a, std::function<void ()> func)
    : _func(std::make_unique<std::function<void ()>>(std::move(func))) {
    pthread_attr_t pa;
    auto r = pthread_attr_init(&pa);
    if (r) {
        throw std::system_error(r, std::system_category());
    }
    auto stack_size = a._stack_size.size;
    if (!stack_size) {
        stack_size = 2 << 20;
    }
    // allocate guard area as well
    _stack = mmap_anonymous(nullptr, stack_size + (4 << 20),
            PROT_NONE, MAP_PRIVATE | MAP_NORESERVE);
    auto stack_start = align_up(_stack.get() + 1, 2 << 20);
    mmap_area real_stack = mmap_anonymous(stack_start, stack_size,
            PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED | MAP_STACK);
    real_stack.release(); // protected by @_stack
    ::madvise(stack_start, stack_size, MADV_HUGEPAGE);
    r = pthread_attr_setstack(&pa, stack_start, stack_size);
    if (r) {
        throw std::system_error(r, std::system_category());
    }
    r = pthread_create(&_pthread, &pa,
                &posix_thread::start_routine, _func.get());
    if (r) {
        throw std::system_error(r, std::system_category());
    }
}

posix_thread::posix_thread(posix_thread&& x)
    : _func(std::move(x._func)), _pthread(x._pthread), _valid(x._valid)
    , _stack(std::move(x._stack)) {
    x._valid = false;
}

posix_thread::~posix_thread() {
    assert(!_valid);
}

void posix_thread::join() {
    assert(_valid);
    pthread_join(_pthread, NULL);
    _valid = false;
}

void pin_this_thread(unsigned cpu_id) {
    cpu_set_t cs;
    CPU_ZERO(&cs);
    CPU_SET(cpu_id, &cs);
    auto r = pthread_setaffinity_np(pthread_self(), sizeof(cs), &cs);
    assert(r == 0);
}

<|endoftext|>


<commit_before>#pragma ident "$Id$"

/// @file IndexedColorMap.cpp Defines an indexed color map. Class defintions.

//============================================================================
//
//  This file is part of GPSTk, the GPS Toolkit.
//
//  The GPSTk 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
//  any later version.
//
//  The GPSTk 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 GPSTk; if not, write to the Free Software Foundation,
//  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Copyright 2004, The University of Texas at Austin
//
//============================================================================

#include "IndexedColorMap.hpp"

namespace vdraw
{
  IndexedColorMap::IndexedColorMap(int icols, int irows, const Palette &pp, int base)
  {
    cols = icols;
    rows = irows;
    p = pp;

    // Initialize the color array
    c = new int*[rows];

    for(int row=0;row<rows;row++)
      c[row] = new int[cols];

    for(int row=0;row<rows;row++)
      for(int col=0;col<cols;col++)
        c[row][col] = base;
  }

  IndexedColorMap::reset()
  {
    if(c)
    {
      for(int row=0;row<rows;row++)
        delete[] c[row];
      delete[] c;
    }

    cols=rows=0;
    c=0;
  }
}
<commit_msg>Added return type for 'reset' function<commit_after>#pragma ident "$Id$"

/// @file IndexedColorMap.cpp Defines an indexed color map. Class defintions.

//============================================================================
//
//  This file is part of GPSTk, the GPS Toolkit.
//
//  The GPSTk 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
//  any later version.
//
//  The GPSTk 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 GPSTk; if not, write to the Free Software Foundation,
//  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Copyright 2004, The University of Texas at Austin
//
//============================================================================

#include "IndexedColorMap.hpp"

namespace vdraw
{
  IndexedColorMap::IndexedColorMap(int icols, int irows, const Palette &pp, int base)
  {
    cols = icols;
    rows = irows;
    p = pp;

    // Initialize the color array
    c = new int*[rows];

    for(int row=0;row<rows;row++)
      c[row] = new int[cols];

    for(int row=0;row<rows;row++)
      for(int col=0;col<cols;col++)
        c[row][col] = base;
  }

  void IndexedColorMap::reset()
  {
    if(c)
    {
      for(int row=0;row<rows;row++)
        delete[] c[row];
      delete[] c;
    }

    cols=rows=0;
    c=0;
  }
}
<|endoftext|>