<commit_before>/*

Copyright (c) 2003, Arvid Norberg
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 its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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 "libtorrent/pch.hpp"
#include "libtorrent/config.hpp"

#include <boost/scoped_ptr.hpp>
#ifdef TORRENT_WINDOWS
// windows part
#include "libtorrent/utf8.hpp"

#include <windows.h>
#include <winioctl.h>

#ifdef UNICODE
#include "libtorrent/storage.hpp"
#endif

#else
// posix part
#define _FILE_OFFSET_BITS 64
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>

#include <boost/static_assert.hpp>
// make sure the _FILE_OFFSET_BITS define worked
// on this platform
BOOST_STATIC_ASSERT(sizeof(lseek(0, 0, 0)) >= 8);

#endif

#include <boost/filesystem/operations.hpp>
#include "libtorrent/file.hpp"
#include <sstream>
#include <cstring>
#include <vector>

#ifndef O_BINARY
#define O_BINARY 0
#endif

#ifndef O_RANDOM
#define O_RANDOM 0
#endif

#ifdef UNICODE
#include "libtorrent/storage.hpp"
#endif

#include "libtorrent/assert.hpp"

namespace
{
#ifdef TORRENT_WINDOWS
	std::string utf8_native(std::string const& s)
	{
		try
		{
			std::wstring ws;
			libtorrent::utf8_wchar(s, ws);
			std::size_t size = wcstombs(0, ws.c_str(), 0);
			if (size == std::size_t(-1)) return s;
			std::string ret;
			ret.resize(size);
			size = wcstombs(&ret[0], ws.c_str(), size + 1);
			if (size == wchar_t(-1)) return s;
			ret.resize(size);
			return ret;
		}
		catch(std::exception)
		{
			return s;
		}
	}
#else

	enum { mode_in = 1, mode_out = 2 };

	mode_t map_open_mode(int m)
	{
		if (m == (mode_in | mode_out)) return O_RDWR | O_CREAT | O_BINARY | O_RANDOM;
		if (m == mode_out) return O_WRONLY | O_CREAT | O_BINARY | O_RANDOM;
		if (m == mode_in) return O_RDONLY | O_BINARY | O_RANDOM;
		TORRENT_ASSERT(false);
		return 0;
	}
#endif

}

namespace libtorrent
{
	namespace fs = boost::filesystem;

#ifdef TORRENT_WINDOWS
	const file::open_mode file::in(GENERIC_READ);
	const file::open_mode file::out(GENERIC_WRITE);
	const file::seek_mode file::begin(FILE_BEGIN);
	const file::seek_mode file::end(FILE_END);
#else
	const file::open_mode file::in(mode_in);
	const file::open_mode file::out(mode_out);
	const file::seek_mode file::begin(SEEK_SET);
	const file::seek_mode file::end(SEEK_END);
#endif

	file::file()
#ifdef TORRENT_WINDOWS
		: m_file_handle(INVALID_HANDLE_VALUE)
#else
		: m_fd(-1)
#endif
#ifndef NDEBUG
		, m_open_mode(0)
#endif
	{}

	file::file(fs::path const& path, open_mode mode, error_code& ec)
#ifdef TORRENT_WINDOWS
		: m_file_handle(INVALID_HANDLE_VALUE)
#else
		: m_fd(-1)
#endif
#ifndef NDEBUG
		, m_open_mode(0)
#endif
	{
		open(path, mode, ec);
	}

	file::~file()
	{
		close();
	}

	bool file::open(fs::path const& path, open_mode mode, error_code& ec)
	{
		close();
#ifdef TORRENT_WINDOWS

#ifdef UNICODE
		std::wstring file_path(safe_convert(path.native_file_string()));
#else
		std::string file_path = utf8_native(path.native_file_string());
#endif

		m_file_handle = CreateFile(
			file_path.c_str()
			, mode.m_mask
			, FILE_SHARE_READ
			, 0
			, (mode & out)?OPEN_ALWAYS:OPEN_EXISTING
			, FILE_ATTRIBUTE_NORMAL
			, 0);

		if (m_file_handle == INVALID_HANDLE_VALUE)
		{
			ec = error_code(GetLastError(), get_system_category());
			return false;
		}

		// try to make the file sparse if supported
		if (mode & out)
		{
			DWORD temp;
			::DeviceIoControl(m_file_handle, FSCTL_SET_SPARSE, 0, 0
				, 0, 0, &temp, 0);
		}
#else
		// rely on default umask to filter x and w permissions
		// for group and others
		m_fd = ::open(path.native_file_string().c_str()
			, map_open_mode(mode.m_mask), S_IRWXU | S_IRWXG | S_IRWXO);

		if (m_fd == -1)
		{
			ec = error_code(errno, get_posix_category());
			return false;
		}
#endif
#ifndef NDEBUG
		m_open_mode = mode;
#endif
		TORRENT_ASSERT(is_open());
		return true;
	}

	bool file::is_open() const
	{
#ifdef TORRENT_WINDOWS
		return m_file_handle != INVALID_HANDLE_VALUE;
#else
		return m_fd != -1;
#endif
	}

	void file::close()
	{
#ifdef TORRENT_WINDOWS
		if (m_file_handle == INVALID_HANDLE_VALUE) return;
		CloseHandle(m_file_handle);
		m_file_handle = INVALID_HANDLE_VALUE;
#else
		if (m_fd == -1) return;
		::close(m_fd);
		m_fd = -1;
#endif
#ifndef NDEBUG
		m_open_mode = 0;
#endif
	}

	size_type file::read(char* buf, size_type num_bytes, error_code& ec)
	{
		TORRENT_ASSERT((m_open_mode & in) == in);
		TORRENT_ASSERT(buf);
		TORRENT_ASSERT(num_bytes >= 0);
		TORRENT_ASSERT(is_open());

#ifdef TORRENT_WINDOWS

		TORRENT_ASSERT(DWORD(num_bytes) == num_bytes);
		DWORD ret = 0;
		if (num_bytes != 0)
		{
			if (ReadFile(m_file_handle, buf, (DWORD)num_bytes, &ret, 0) == FALSE)
			{
				ec = error_code(GetLastError(), get_system_category());
				return -1;
			}
		}
#else
		size_type ret = ::read(m_fd, buf, num_bytes);
		if (ret == -1) ec = error_code(errno, get_posix_category());
#endif
		return ret;
	}

	size_type file::write(const char* buf, size_type num_bytes, error_code& ec)
	{
		TORRENT_ASSERT((m_open_mode & out) == out);
		TORRENT_ASSERT(buf);
		TORRENT_ASSERT(num_bytes >= 0);
		TORRENT_ASSERT(is_open());

#ifdef TORRENT_WINDOWS

		DWORD ret = 0;
		if (num_bytes != 0)
		{
			if (WriteFile(m_file_handle, buf, (DWORD)num_bytes, &ret, 0) == FALSE)
			{
				ec = error_code(GetLastError(), get_system_category());
				return -1;
			}
		}
#else
		size_type ret = ::write(m_fd, buf, num_bytes);
		if (ret == -1) ec = error_code(errno, get_posix_category());
#endif
		return ret;
	}

  	bool file::set_size(size_type s, error_code& ec)
  	{
  		TORRENT_ASSERT(is_open());
  		TORRENT_ASSERT(s >= 0);

#ifdef TORRENT_WINDOWS
		size_type pos = tell(ec);
		if (ec) return false;
		seek(s, begin, ec);
		if (ec) return false;
		if (::SetEndOfFile(m_file_handle) == FALSE)
		{
			ec = error_code(GetLastError(), get_system_category());
			return false;
		}
#else
		if (ftruncate(m_fd, s) < 0)
		{
			ec = error_code(errno, get_posix_category());
			return false;
		}
#endif
		return true;
	}

	size_type file::seek(size_type offset, seek_mode m, error_code& ec)
	{
		TORRENT_ASSERT(is_open());

#ifdef TORRENT_WINDOWS
		LARGE_INTEGER offs;
		offs.QuadPart = offset;
		if (SetFilePointerEx(m_file_handle, offs, &offs, m.m_val) == FALSE)
		{
			ec = error_code(GetLastError(), get_system_category());
			return -1;
		}
		return offs.QuadPart;
#else
		size_type ret = lseek(m_fd, offset, m.m_val);
		if (ret < 0) ec = error_code(errno, get_posix_category());
		return ret;
#endif
	}

	size_type file::tell(error_code& ec)
	{
		TORRENT_ASSERT(is_open());

#ifdef TORRENT_WINDOWS
		LARGE_INTEGER offs;
		offs.QuadPart = 0;

		// is there any other way to get offset?
		if (SetFilePointerEx(m_file_handle, offs, &offs
			, FILE_CURRENT) == FALSE)
		{
			ec = error_code(GetLastError(), get_system_category());
			return -1;
		}

		return offs.QuadPart;
#else
		size_type ret;
		ret = lseek(m_fd, 0, SEEK_CUR);
		if (ret < 0) ec = error_code(errno, get_posix_category());
		return ret;
#endif
	}
}

<commit_msg>don't set executable permission of files<commit_after>/*

Copyright (c) 2003, Arvid Norberg
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 its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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 "libtorrent/pch.hpp"
#include "libtorrent/config.hpp"

#include <boost/scoped_ptr.hpp>
#ifdef TORRENT_WINDOWS
// windows part
#include "libtorrent/utf8.hpp"

#include <windows.h>
#include <winioctl.h>

#ifdef UNICODE
#include "libtorrent/storage.hpp"
#endif

#else
// posix part
#define _FILE_OFFSET_BITS 64
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>

#include <boost/static_assert.hpp>
// make sure the _FILE_OFFSET_BITS define worked
// on this platform
BOOST_STATIC_ASSERT(sizeof(lseek(0, 0, 0)) >= 8);

#endif

#include <boost/filesystem/operations.hpp>
#include "libtorrent/file.hpp"
#include <sstream>
#include <cstring>
#include <vector>

#ifndef O_BINARY
#define O_BINARY 0
#endif

#ifndef O_RANDOM
#define O_RANDOM 0
#endif

#ifdef UNICODE
#include "libtorrent/storage.hpp"
#endif

#include "libtorrent/assert.hpp"

namespace
{
#ifdef TORRENT_WINDOWS
	std::string utf8_native(std::string const& s)
	{
		try
		{
			std::wstring ws;
			libtorrent::utf8_wchar(s, ws);
			std::size_t size = wcstombs(0, ws.c_str(), 0);
			if (size == std::size_t(-1)) return s;
			std::string ret;
			ret.resize(size);
			size = wcstombs(&ret[0], ws.c_str(), size + 1);
			if (size == wchar_t(-1)) return s;
			ret.resize(size);
			return ret;
		}
		catch(std::exception)
		{
			return s;
		}
	}
#else

	enum { mode_in = 1, mode_out = 2 };

	mode_t map_open_mode(int m)
	{
		if (m == (mode_in | mode_out)) return O_RDWR | O_CREAT | O_BINARY | O_RANDOM;
		if (m == mode_out) return O_WRONLY | O_CREAT | O_BINARY | O_RANDOM;
		if (m == mode_in) return O_RDONLY | O_BINARY | O_RANDOM;
		TORRENT_ASSERT(false);
		return 0;
	}
#endif

}

namespace libtorrent
{
	namespace fs = boost::filesystem;

#ifdef TORRENT_WINDOWS
	const file::open_mode file::in(GENERIC_READ);
	const file::open_mode file::out(GENERIC_WRITE);
	const file::seek_mode file::begin(FILE_BEGIN);
	const file::seek_mode file::end(FILE_END);
#else
	const file::open_mode file::in(mode_in);
	const file::open_mode file::out(mode_out);
	const file::seek_mode file::begin(SEEK_SET);
	const file::seek_mode file::end(SEEK_END);
#endif

	file::file()
#ifdef TORRENT_WINDOWS
		: m_file_handle(INVALID_HANDLE_VALUE)
#else
		: m_fd(-1)
#endif
#ifndef NDEBUG
		, m_open_mode(0)
#endif
	{}

	file::file(fs::path const& path, open_mode mode, error_code& ec)
#ifdef TORRENT_WINDOWS
		: m_file_handle(INVALID_HANDLE_VALUE)
#else
		: m_fd(-1)
#endif
#ifndef NDEBUG
		, m_open_mode(0)
#endif
	{
		open(path, mode, ec);
	}

	file::~file()
	{
		close();
	}

	bool file::open(fs::path const& path, open_mode mode, error_code& ec)
	{
		close();
#ifdef TORRENT_WINDOWS

#ifdef UNICODE
		std::wstring file_path(safe_convert(path.native_file_string()));
#else
		std::string file_path = utf8_native(path.native_file_string());
#endif

		m_file_handle = CreateFile(
			file_path.c_str()
			, mode.m_mask
			, FILE_SHARE_READ
			, 0
			, (mode & out)?OPEN_ALWAYS:OPEN_EXISTING
			, FILE_ATTRIBUTE_NORMAL
			, 0);

		if (m_file_handle == INVALID_HANDLE_VALUE)
		{
			ec = error_code(GetLastError(), get_system_category());
			return false;
		}

		// try to make the file sparse if supported
		if (mode & out)
		{
			DWORD temp;
			::DeviceIoControl(m_file_handle, FSCTL_SET_SPARSE, 0, 0
				, 0, 0, &temp, 0);
		}
#else
		// rely on default umask to filter x and w permissions
		// for group and others
		int permissions = S_IRUSR | S_IWUSR
			| S_IRGRP | S_IWGRP
			| S_IROTH | S_IWOTH;

		m_fd = ::open(path.native_file_string().c_str()
			, map_open_mode(mode.m_mask), permissions);

		if (m_fd == -1)
		{
			ec = error_code(errno, get_posix_category());
			return false;
		}
#endif
#ifndef NDEBUG
		m_open_mode = mode;
#endif
		TORRENT_ASSERT(is_open());
		return true;
	}

	bool file::is_open() const
	{
#ifdef TORRENT_WINDOWS
		return m_file_handle != INVALID_HANDLE_VALUE;
#else
		return m_fd != -1;
#endif
	}

	void file::close()
	{
#ifdef TORRENT_WINDOWS
		if (m_file_handle == INVALID_HANDLE_VALUE) return;
		CloseHandle(m_file_handle);
		m_file_handle = INVALID_HANDLE_VALUE;
#else
		if (m_fd == -1) return;
		::close(m_fd);
		m_fd = -1;
#endif
#ifndef NDEBUG
		m_open_mode = 0;
#endif
	}

	size_type file::read(char* buf, size_type num_bytes, error_code& ec)
	{
		TORRENT_ASSERT((m_open_mode & in) == in);
		TORRENT_ASSERT(buf);
		TORRENT_ASSERT(num_bytes >= 0);
		TORRENT_ASSERT(is_open());

#ifdef TORRENT_WINDOWS

		TORRENT_ASSERT(DWORD(num_bytes) == num_bytes);
		DWORD ret = 0;
		if (num_bytes != 0)
		{
			if (ReadFile(m_file_handle, buf, (DWORD)num_bytes, &ret, 0) == FALSE)
			{
				ec = error_code(GetLastError(), get_system_category());
				return -1;
			}
		}
#else
		size_type ret = ::read(m_fd, buf, num_bytes);
		if (ret == -1) ec = error_code(errno, get_posix_category());
#endif
		return ret;
	}

	size_type file::write(const char* buf, size_type num_bytes, error_code& ec)
	{
		TORRENT_ASSERT((m_open_mode & out) == out);
		TORRENT_ASSERT(buf);
		TORRENT_ASSERT(num_bytes >= 0);
		TORRENT_ASSERT(is_open());

#ifdef TORRENT_WINDOWS

		DWORD ret = 0;
		if (num_bytes != 0)
		{
			if (WriteFile(m_file_handle, buf, (DWORD)num_bytes, &ret, 0) == FALSE)
			{
				ec = error_code(GetLastError(), get_system_category());
				return -1;
			}
		}
#else
		size_type ret = ::write(m_fd, buf, num_bytes);
		if (ret == -1) ec = error_code(errno, get_posix_category());
#endif
		return ret;
	}

  	bool file::set_size(size_type s, error_code& ec)
  	{
  		TORRENT_ASSERT(is_open());
  		TORRENT_ASSERT(s >= 0);

#ifdef TORRENT_WINDOWS
		size_type pos = tell(ec);
		if (ec) return false;
		seek(s, begin, ec);
		if (ec) return false;
		if (::SetEndOfFile(m_file_handle) == FALSE)
		{
			ec = error_code(GetLastError(), get_system_category());
			return false;
		}
#else
		if (ftruncate(m_fd, s) < 0)
		{
			ec = error_code(errno, get_posix_category());
			return false;
		}
#endif
		return true;
	}

	size_type file::seek(size_type offset, seek_mode m, error_code& ec)
	{
		TORRENT_ASSERT(is_open());

#ifdef TORRENT_WINDOWS
		LARGE_INTEGER offs;
		offs.QuadPart = offset;
		if (SetFilePointerEx(m_file_handle, offs, &offs, m.m_val) == FALSE)
		{
			ec = error_code(GetLastError(), get_system_category());
			return -1;
		}
		return offs.QuadPart;
#else
		size_type ret = lseek(m_fd, offset, m.m_val);
		if (ret < 0) ec = error_code(errno, get_posix_category());
		return ret;
#endif
	}

	size_type file::tell(error_code& ec)
	{
		TORRENT_ASSERT(is_open());

#ifdef TORRENT_WINDOWS
		LARGE_INTEGER offs;
		offs.QuadPart = 0;

		// is there any other way to get offset?
		if (SetFilePointerEx(m_file_handle, offs, &offs
			, FILE_CURRENT) == FALSE)
		{
			ec = error_code(GetLastError(), get_system_category());
			return -1;
		}

		return offs.QuadPart;
#else
		size_type ret;
		ret = lseek(m_fd, 0, SEEK_CUR);
		if (ret < 0) ec = error_code(errno, get_posix_category());
		return ret;
#endif
	}
}

<|endoftext|>


<commit_before>#include "game.hpp"

#include "main_state.hpp"

#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
#include <iostream>

Game::~Game() {
    m_res_manager.shutdown();
    TTF_Quit();
    SDL_CloseAudio();
    SDL_DestroyRenderer(m_render);
    SDL_DestroyWindow(m_window);
    Mix_Quit();
    IMG_Quit();
    SDL_Quit();
}

int Game::init() {
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) != 0) {
        std::cerr << "SDL_Init Error: " << SDL_GetError() << std::endl;
        return 1;
    }

    int width = 800;
    int height = 600;

    m_window = SDL_CreateWindow("Hello World!", 100, 100, width, height, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
    if (m_window == nullptr) {
        std::cerr << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
        SDL_Quit();
        return 1;
    }

    m_render =
        SDL_CreateRenderer(m_window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);

    if (m_render == nullptr) {
        SDL_DestroyWindow(m_window);
        std::cerr << "SDL_CreateRenderer Error: " << SDL_GetError() << std::endl;
        SDL_Quit();
        return 1;
    }

    if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) != 0) {
        std::cerr << "SDL_mixer could not initialize! SDL_mixer Error: " << Mix_GetError()
                  << std::endl;
        return 1;
    }

    if (TTF_Init() != 0) {
        std::cerr << "SDL_ttf could not initialize! SDL_ttf Error: " << TTF_GetError() << std::endl;
        return 1;
    }

    m_res_manager.load_texture("gradient", "res/gradient.png", m_render);
    m_res_manager.load_texture("player", "res/player.png", m_render);
    m_res_manager.load_texture("fire", "res/fire.png", m_render);
    m_res_manager.load_texture("orb", "res/orb.png", m_render);
    m_res_manager.load_texture("dirt", "res/dirt.png", m_render);
    m_res_manager.load_texture("inner_bound", "res/inner_bound.png", m_render);
    m_res_manager.load_texture("outer_bound", "res/outer_bound.png", m_render);
    m_res_manager.load_font("font20", "res/DejaVuSans.ttf", 20);

    SDL_RenderSetLogicalSize(m_render, width, height);

    entityx::Entity entity = m_ex.entities.create();
    entity.assign<Position>();

    m_states.push({"main", std::make_unique<MainState>(this)});
    m_states.top().second->init();

    return 0;
}

void Game::mainloop() {
    int current_time = SDL_GetTicks();
    double dt = (current_time - m_last_frame_time) / 1000.0;
    m_last_frame_time = current_time;

    m_states.top().second->update(dt);
}

SDL_Renderer *Game::renderer() {
    return m_render;
}

SDL_Window *Game::window() {
    return m_window;
}

ResourceManager &Game::res_manager() {
    return m_res_manager;
}

std::stack<std::pair<std::string, std::unique_ptr<State>>> &Game::states() {
    return m_states;
}

bool Game::is_running() {
    return m_running;
}

void Game::shutdown() {
    m_running = false;
#ifdef __EMSCRIPTEN__
    emscripten_cancel_main_loop();
#endif
}

void Game::popstate() {
    m_states.pop();
}

const std::string &Game::statename() const {
    return m_states.top().first;
}

const SDL_Rect &Game::world_size() const {
    return m_world_size;
}
<commit_msg>Enable vsync<commit_after>#include "game.hpp"

#include "main_state.hpp"

#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
#include <iostream>

Game::~Game() {
    m_res_manager.shutdown();
    TTF_Quit();
    SDL_CloseAudio();
    SDL_DestroyRenderer(m_render);
    SDL_DestroyWindow(m_window);
    Mix_Quit();
    IMG_Quit();
    SDL_Quit();
}

int Game::init() {
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) != 0) {
        std::cerr << "SDL_Init Error: " << SDL_GetError() << std::endl;
        return 1;
    }

    int width = 800;
    int height = 600;

    m_window = SDL_CreateWindow("Hello World!", 100, 100, width, height, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
    if (m_window == nullptr) {
        std::cerr << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
        SDL_Quit();
        return 1;
    }

    m_render =
        SDL_CreateRenderer(m_window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);

    if (m_render == nullptr) {
        SDL_DestroyWindow(m_window);
        std::cerr << "SDL_CreateRenderer Error: " << SDL_GetError() << std::endl;
        SDL_Quit();
        return 1;
    }

    auto swap_interval = SDL_GL_SetSwapInterval(-1);
    if (swap_interval != 0) {
        SDL_GL_SetSwapInterval(1);
    }

    if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) != 0) {
        std::cerr << "SDL_mixer could not initialize! SDL_mixer Error: " << Mix_GetError()
                  << std::endl;
        return 1;
    }

    if (TTF_Init() != 0) {
        std::cerr << "SDL_ttf could not initialize! SDL_ttf Error: " << TTF_GetError() << std::endl;
        return 1;
    }

    m_res_manager.load_texture("gradient", "res/gradient.png", m_render);
    m_res_manager.load_texture("player", "res/player.png", m_render);
    m_res_manager.load_texture("fire", "res/fire.png", m_render);
    m_res_manager.load_texture("orb", "res/orb.png", m_render);
    m_res_manager.load_texture("dirt", "res/dirt.png", m_render);
    m_res_manager.load_texture("inner_bound", "res/inner_bound.png", m_render);
    m_res_manager.load_texture("outer_bound", "res/outer_bound.png", m_render);
    m_res_manager.load_font("font20", "res/DejaVuSans.ttf", 20);

    SDL_RenderSetLogicalSize(m_render, width, height);

    entityx::Entity entity = m_ex.entities.create();
    entity.assign<Position>();

    m_states.push({"main", std::make_unique<MainState>(this)});
    m_states.top().second->init();

    return 0;
}

void Game::mainloop() {
    int current_time = SDL_GetTicks();
    double dt = (current_time - m_last_frame_time) / 1000.0;
    m_last_frame_time = current_time;

    m_states.top().second->update(dt);
}

SDL_Renderer *Game::renderer() {
    return m_render;
}

SDL_Window *Game::window() {
    return m_window;
}

ResourceManager &Game::res_manager() {
    return m_res_manager;
}

std::stack<std::pair<std::string, std::unique_ptr<State>>> &Game::states() {
    return m_states;
}

bool Game::is_running() {
    return m_running;
}

void Game::shutdown() {
    m_running = false;
#ifdef __EMSCRIPTEN__
    emscripten_cancel_main_loop();
#endif
}

void Game::popstate() {
    m_states.pop();
}

const std::string &Game::statename() const {
    return m_states.top().first;
}

const SDL_Rect &Game::world_size() const {
    return m_world_size;
}
<|endoftext|>


<commit_before>#include <QApplication>
#include <QFontDatabase>
#include "neovimconnector.h"
#include "mainwindow.h"

/**
 * Neovim Qt GUI
 *
 * Usage:
 *   nvim-qt --server <SOCKET>
 *   nvim-qt [...]
 *
 * When --server is not provided, a Neovim instance will be spawned. All arguments
 * are passed to the Neovim process.
 */
int main(int argc, char **argv)
{
	QApplication app(argc, argv);
	app.setApplicationDisplayName("Neovim");
	app.setWindowIcon(QIcon(":/neovim.png"));

	// Load bundled fonts
	if (QFontDatabase::addApplicationFont(":/DejaVuSansMono.ttf") == -1) {
		qWarning("Unable to load bundled font");
	}
	if (QFontDatabase::addApplicationFont(":/DejaVuSansMono-Bold.ttf") == -1) {
		qWarning("Unable to load bundled bold font");
	}
	if (QFontDatabase::addApplicationFont(":/DejaVuSansMono-Oblique.ttf") == -1) {
		qWarning("Unable to load bundled italic font");
	}
	if (QFontDatabase::addApplicationFont(":/DejaVuSansMono-BoldOblique.ttf") == -1) {
		qWarning("Unable to load bundled bold/italic font");
	}

	QString server;
	QStringList args = app.arguments().mid(1);
	int serverIdx = args.indexOf("--server");
	if (serverIdx != -1 && args.size() > serverIdx+1) {
		server = args.at(serverIdx+1);
		args.removeAt(serverIdx);
		args.removeAt(serverIdx);
	}

	NeovimQt::NeovimConnector *c;
	if (!server.isEmpty()) {
		c = NeovimQt::NeovimConnector::connectToNeovim(server);
	} else {
		c = NeovimQt::NeovimConnector::spawn(args);
	}

#ifdef NEOVIMQT_GUI_WIDGET
	NeovimQt::Shell *win = new NeovimQt::Shell(c);
#else
	NeovimQt::MainWindow *win = new NeovimQt::MainWindow(c);
#endif
	win->show();
	return app.exec();
}

<commit_msg>GUI: Redirect Qt messages to $NEOVIM_QT_LOG<commit_after>#include <QApplication>
#include <QFontDatabase>
#include <QtGlobal>
#include <QFile>
#include "neovimconnector.h"
#include "mainwindow.h"

/**
 * A log handler for Qt messages, all messages are dumped into the file
 * passed via the NEOVIM_QT_LOG variable. Some information is only available
 * in debug builds (e.g. qDebug is only called in debug builds).
 *
 * In UNIX Qt prints messages to the console output, but in Windows this is
 * the only way to get Qt's debug/warning messages.
 */
void logger(QtMsgType type, const QMessageLogContext& ctx, const QString& msg)
{
	QFile logFile(qgetenv("NEOVIM_QT_LOG"));
	if (logFile.open(QIODevice::Append | QIODevice::Text)) {
		QTextStream stream(&logFile);
		stream << msg << "\n";
	}
}

/**
 * Neovim Qt GUI
 *
 * Usage:
 *   nvim-qt --server <SOCKET>
 *   nvim-qt [...]
 *
 * When --server is not provided, a Neovim instance will be spawned. All arguments
 * are passed to the Neovim process.
 */
int main(int argc, char **argv)
{
	QApplication app(argc, argv);
	app.setApplicationDisplayName("Neovim");
	app.setWindowIcon(QIcon(":/neovim.png"));

	if (!qgetenv("NEOVIM_QT_LOG").isEmpty()) {
		qInstallMessageHandler(logger);
	}

	// Load bundled fonts
	if (QFontDatabase::addApplicationFont(":/DejaVuSansMono.ttf") == -1) {
		qWarning("Unable to load bundled font");
	}
	if (QFontDatabase::addApplicationFont(":/DejaVuSansMono-Bold.ttf") == -1) {
		qWarning("Unable to load bundled bold font");
	}
	if (QFontDatabase::addApplicationFont(":/DejaVuSansMono-Oblique.ttf") == -1) {
		qWarning("Unable to load bundled italic font");
	}
	if (QFontDatabase::addApplicationFont(":/DejaVuSansMono-BoldOblique.ttf") == -1) {
		qWarning("Unable to load bundled bold/italic font");
	}

	QString server;
	QStringList args = app.arguments().mid(1);
	int serverIdx = args.indexOf("--server");
	if (serverIdx != -1 && args.size() > serverIdx+1) {
		server = args.at(serverIdx+1);
		args.removeAt(serverIdx);
		args.removeAt(serverIdx);
	}

	NeovimQt::NeovimConnector *c;
	if (!server.isEmpty()) {
		c = NeovimQt::NeovimConnector::connectToNeovim(server);
	} else {
		c = NeovimQt::NeovimConnector::spawn(args);
	}

#ifdef NEOVIMQT_GUI_WIDGET
	NeovimQt::Shell *win = new NeovimQt::Shell(c);
#else
	NeovimQt::MainWindow *win = new NeovimQt::MainWindow(c);
#endif
	win->show();
	return app.exec();
}

<|endoftext|>


<commit_before>#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "serialconfig.h"
#include "qlineeditlabel.h"

#include <QtDebug>
#include <QMessageBox>
#include <QPushButton>
#include <QLayout>
#include <QStandardPaths>

#define SETTING_BTNLBL "buttonLabel/"
#define SETTING_WINDOW "window/"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    mSd(parent),
    mSettings("iconux.org","qShowDesigner")
{
    ui->setupUi(this);

    //QString configpath = QStandardPaths::standardLocations(QStandardPaths::ConfigLocation).first();
    //mSettings = new QSettings(configpath + "/qShowDesigner.ini", QSettings::IniFormat);
    //qDebug() << "Loaded config file " <<  configpath + "/qShowDesigner.ini";

    mStatusLabel = new QLabel(this);
    ui->statusBar->addWidget(mStatusLabel, 1);
    ui->statusBar->setSizeGripEnabled(false);
    mStatusLabel->setText("Not Connected");

    ui->gridLayout->setColumnStretch(1,1);

    // set each button text to numbers 1 through 12
    // load each button label text from settings or initialize to Scene #
    for(int row = 0; row < 12; row++)
    {
        QString btnStr = QString::number(row+1);
        QString lblText = "Scene " + btnStr;

        QPushButton *sceneBtn = new QPushButton(btnStr, this);
        sceneBtn->setMaximumWidth(50);
        ui->gridLayout->addWidget(sceneBtn, row, 0);
        // connect each button to the same slot which selects the scene
        connect( sceneBtn, SIGNAL(released()), this, SLOT(on_btn_num_released()));

        QLineEditLabel *lel = new QLineEditLabel(this);
        lel->showAsLabel();
        lel->setText( mSettings.value(SETTING_BTNLBL + btnStr, lblText).toString());
        ui->gridLayout->addWidget(lel, row, 1);
        connect( lel, SIGNAL(editingFinished()), this, SLOT(on_editing_finished()));
    }

    // load always on top setting
    ui->actionAlways_on_top->setChecked(mSettings.value(SETTING_WINDOW "alwaysontop", false).toBool());

    /*for(int row = 0; row < ui->gridLayout->rowCount(); row++)
    {
        QLayoutItem *item = ui->gridLayout->itemAtPosition(row, 1);

        QLineEditLabel *label = qobject_cast<QLineEditLabel*> (item->widget());
        if ( !label )
        {
            continue;
        }
        QString lblText = "Scene " + QString::number(row+1);
        label->setText( lblText );
    }*/

    connect( &mSd, SIGNAL(pageChanged(quint16)), this, SLOT(on_page_changed(quint16)));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::contextMenuEvent(QContextMenuEvent *event)
{

}

void MainWindow::on_action_Connect_triggered()
{
    SerialConfig sc(this);
    sc.exec();
    if (sc.result() == QDialog::Accepted)
    {
        mStatusLabel->setText("Connecting...");
        if (!mSd.ConnectToShowDesigner(sc.GetPort()))
        {
            mStatusLabel->setText("Not Connected");
            ui->statusBar->showMessage("Connection Failed");
            ShowErrorMessage("Failed to Connect to Show Designer", mSd.GetErrorString());
        }
        else
        {
            mStatusLabel->setText("Connected");
        }
    }
}

void MainWindow::on_actionExit_triggered()
{
    close();
}

void MainWindow::on_btn_num_released()
{
    QPushButton *clickedButton = qobject_cast<QPushButton*>(sender());
    QString buttonNumber = clickedButton->text();
    int btnNum = buttonNumber.toInt();

    qDebug() << "Button " << btnNum << " was released";

    if (!mSd.PushButton(btnNum))
    {
        ui->statusBar->showMessage("Failed to set scene");
    }

    for (int row = 0; row < ui->gridLayout->rowCount(); row++)
    {
        QLayoutItem *item = ui->gridLayout->itemAtPosition(row, 0);
        QPushButton *btn = qobject_cast<QPushButton*> (item->widget());
        btn->setStyleSheet("");
    }
    clickedButton->setStyleSheet("background-color:red");
}

void MainWindow::on_actionAlways_on_top_triggered()
{
    Qt::WindowFlags flags = windowFlags();
    if (ui->actionAlways_on_top->isChecked())
    {
       flags |= Qt::WindowStaysOnTopHint;
       // for Linux/X11, need to also set flag to bypass window manager
       //flags |= Qt::X11BypassWindowManagerHint;
    }
    else
    {
        flags &= ~Qt::WindowStaysOnTopHint;
        //flags &= ~Qt::X11BypassWindowManagerHint;
    }
    mSettings.setValue(SETTING_WINDOW "alwaysontop", ui->actionAlways_on_top->isChecked());
    show();
}

void MainWindow::on_editing_finished()
{
    Save();
}

void MainWindow::on_page_changed(quint16 pageNo)
{
    ui->lePage->setText(QString::number((uint)pageNo));
}

void MainWindow::ShowErrorMessage(const QString &text, const QString &informativeText)
{
    QMessageBox msgBox;
    msgBox.setText(text);
    msgBox.setInformativeText(informativeText);
    msgBox.setStandardButtons(QMessageBox::Ok);
    msgBox.setDefaultButton(QMessageBox::Ok);
    int ret = msgBox.exec();
}

void MainWindow::Save()
{
    qDebug() << "Saving settings";
    for (int row; row < ui->gridLayout->rowCount(); row++)
    {
        QString rowStr = QString::number(row+1);
        QLayoutItem *item = ui->gridLayout->itemAtPosition(row, 1);
        QLineEditLabel *label = qobject_cast<QLineEditLabel*> (item->widget());
        mSettings.setValue(SETTING_BTNLBL + rowStr, label->text());
    }
    mSettings.sync();
    qDebug() << mSettings.status();
}

void MainWindow::on_btnDown_clicked()
{
    mSd.RequestPageDown();
}

void MainWindow::on_btnUp_clicked()
{
    mSd.RequestPageUp();
}
<commit_msg>Fixed unitialized variable when saving button labels<commit_after>#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "serialconfig.h"
#include "qlineeditlabel.h"

#include <QtDebug>
#include <QMessageBox>
#include <QPushButton>
#include <QLayout>
#include <QStandardPaths>

#define SETTING_BTNLBL "buttonLabel/"
#define SETTING_WINDOW "window/"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    mSd(parent),
    mSettings("iconux.org","qShowDesigner")
{
    ui->setupUi(this);

    //QString configpath = QStandardPaths::standardLocations(QStandardPaths::ConfigLocation).first();
    //mSettings = new QSettings(configpath + "/qShowDesigner.ini", QSettings::IniFormat);
    //qDebug() << "Loaded config file " <<  configpath + "/qShowDesigner.ini";

    mStatusLabel = new QLabel(this);
    ui->statusBar->addWidget(mStatusLabel, 1);
    ui->statusBar->setSizeGripEnabled(false);
    mStatusLabel->setText("Not Connected");

    ui->gridLayout->setColumnStretch(1,1);

    // set each button text to numbers 1 through 12
    // load each button label text from settings or initialize to Scene #
    for(int row = 0; row < 12; row++)
    {
        QString btnStr = QString::number(row+1);
        QString lblText = "Scene " + btnStr;

        QPushButton *sceneBtn = new QPushButton(btnStr, this);
        sceneBtn->setMaximumWidth(50);
        ui->gridLayout->addWidget(sceneBtn, row, 0);
        // connect each button to the same slot which selects the scene
        connect( sceneBtn, SIGNAL(released()), this, SLOT(on_btn_num_released()));

        QLineEditLabel *lel = new QLineEditLabel(this);
        lel->showAsLabel();
        lel->setText( mSettings.value(SETTING_BTNLBL + btnStr, lblText).toString());
        ui->gridLayout->addWidget(lel, row, 1);
        connect( lel, SIGNAL(editingFinished()), this, SLOT(on_editing_finished()));
    }

    // load always on top setting
    ui->actionAlways_on_top->setChecked(mSettings.value(SETTING_WINDOW "alwaysontop", false).toBool());

    /*for(int row = 0; row < ui->gridLayout->rowCount(); row++)
    {
        QLayoutItem *item = ui->gridLayout->itemAtPosition(row, 1);

        QLineEditLabel *label = qobject_cast<QLineEditLabel*> (item->widget());
        if ( !label )
        {
            continue;
        }
        QString lblText = "Scene " + QString::number(row+1);
        label->setText( lblText );
    }*/

    connect( &mSd, SIGNAL(pageChanged(quint16)), this, SLOT(on_page_changed(quint16)));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::contextMenuEvent(QContextMenuEvent *event)
{

}

void MainWindow::on_action_Connect_triggered()
{
    SerialConfig sc(this);
    sc.exec();
    if (sc.result() == QDialog::Accepted)
    {
        mStatusLabel->setText("Connecting...");
        if (!mSd.ConnectToShowDesigner(sc.GetPort()))
        {
            mStatusLabel->setText("Not Connected");
            ui->statusBar->showMessage("Connection Failed");
            ShowErrorMessage("Failed to Connect to Show Designer", mSd.GetErrorString());
        }
        else
        {
            mStatusLabel->setText("Connected");
        }
    }
}

void MainWindow::on_actionExit_triggered()
{
    close();
}

void MainWindow::on_btn_num_released()
{
    QPushButton *clickedButton = qobject_cast<QPushButton*>(sender());
    QString buttonNumber = clickedButton->text();
    int btnNum = buttonNumber.toInt();

    qDebug() << "Button " << btnNum << " was released";

    if (!mSd.PushButton(btnNum))
    {
        ui->statusBar->showMessage("Failed to set scene");
    }

    for (int row = 0; row < ui->gridLayout->rowCount(); row++)
    {
        QLayoutItem *item = ui->gridLayout->itemAtPosition(row, 0);
        QPushButton *btn = qobject_cast<QPushButton*> (item->widget());
        btn->setStyleSheet("");
    }
    clickedButton->setStyleSheet("background-color:red");
}

void MainWindow::on_actionAlways_on_top_triggered()
{
    Qt::WindowFlags flags = windowFlags();
    if (ui->actionAlways_on_top->isChecked())
    {
       flags |= Qt::WindowStaysOnTopHint;
       // for Linux/X11, need to also set flag to bypass window manager
       //flags |= Qt::X11BypassWindowManagerHint;
    }
    else
    {
        flags &= ~Qt::WindowStaysOnTopHint;
        //flags &= ~Qt::X11BypassWindowManagerHint;
    }
    mSettings.setValue(SETTING_WINDOW "alwaysontop", ui->actionAlways_on_top->isChecked());
    show();
}

void MainWindow::on_editing_finished()
{
    Save();
}

void MainWindow::on_page_changed(quint16 pageNo)
{
    ui->lePage->setText(QString::number((uint)pageNo));
}

void MainWindow::ShowErrorMessage(const QString &text, const QString &informativeText)
{
    QMessageBox msgBox;
    msgBox.setText(text);
    msgBox.setInformativeText(informativeText);
    msgBox.setStandardButtons(QMessageBox::Ok);
    msgBox.setDefaultButton(QMessageBox::Ok);
    int ret = msgBox.exec();
}

void MainWindow::Save()
{
    qDebug() << "Saving settings";
    for (int row = 0; row < ui->gridLayout->rowCount(); row++)
    {
        QString rowStr = QString::number(row+1);
        QLayoutItem *item = ui->gridLayout->itemAtPosition(row, 1);
        QLineEditLabel *label = qobject_cast<QLineEditLabel*> (item->widget());
        mSettings.setValue(SETTING_BTNLBL + rowStr, label->text());
    }
    mSettings.sync();
    qDebug() << mSettings.status();
}

void MainWindow::on_btnDown_clicked()
{
    mSd.RequestPageDown();
}

void MainWindow::on_btnUp_clicked()
{
    mSd.RequestPageUp();
}
<|endoftext|>


<commit_before>#include <array>
#include "h5writer.h"

H5Writer::H5Writer()
{
	m_enabled = false;
	m_h5file = 0;
	m_fn.assign("");
	m_w = NULL;
}

H5Writer::~H5Writer()
{
	close();
}

bool H5Writer::open(const char *fn)
{
	if (isEnabled()) {
		return false;
	}
	// Create a new file using default properties.
	m_h5file = H5Fcreate(fn, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);

	if (m_h5file < 0) {
		return false;
	}

	m_fn.assign(fn);

	fprintf(stdout,"%s: started logging to %s.\n", name(), fn);

	// we intentionally don't enable here: rather, enable in the subclasses

	return true;
}

bool H5Writer::close()
{

	if (isEnabled()) {	// subclass should have disabled already honestly.
		disable();
		fprintf(stdout,"%s: stopped logging to file\n", name());
		m_fn.clear();
	}

	if (m_h5file) {
		H5Fclose(m_h5file);
		m_h5file = 0;
	}

	return true;
}

bool H5Writer::isEnabled()
{
	return m_enabled;
}

void H5Writer::enable()
{
	m_enabled = true;
}

void H5Writer::disable()
{
	m_enabled = false;
}

size_t H5Writer::bytes()
{
	return 0;
}

string H5Writer::filename()
{
	return m_fn;
}

void H5Writer::registerWidget(GtkWidget *w)
{
	m_w = w;
}

void H5Writer::draw()
{
	if (isEnabled()) {

		size_t n = filename().find_last_of("/");
		char str[256];

		double b = bytes() / 1e6;

		if (b >= 1e3) {
			b /= 1e3;
			snprintf(str, 256, "%s: %.2f GB",
				filename().substr(n+1).c_str(), b);
		} else {
			snprintf(str, 256, "%s: %.2f MB",
				filename().substr(n+1).c_str(), b);
		}
		gtk_label_set_text(GTK_LABEL(m_w), str);
	}
}
<commit_msg>make pretty<commit_after>#include <array>
#include "h5writer.h"

H5Writer::H5Writer()
{
	m_enabled = false;
	m_h5file = 0;
	m_fn.assign("");
	m_w = NULL;
}

H5Writer::~H5Writer()
{
	close();
}

bool H5Writer::open(const char *fn)
{
	if (isEnabled()) {
		return false;
	}
	// Create a new file using default properties.
	m_h5file = H5Fcreate(fn, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);

	if (m_h5file < 0) {
		return false;
	}

	m_fn.assign(fn);

	fprintf(stdout,"%s: started logging to %s.\n", name(), fn);

	// we intentionally don't enable here: rather, enable in the subclasses

	return true;
}

bool H5Writer::close()
{

	if (isEnabled()) {	// subclass should have disabled already honestly.
		disable();
		fprintf(stdout,"%s: stopped logging to file\n", name());
		m_fn.clear();
	}

	if (m_h5file) {
		H5Fclose(m_h5file);
		m_h5file = 0;
	}

	return true;
}

bool H5Writer::isEnabled()
{
	return m_enabled;
}

void H5Writer::enable()
{
	m_enabled = true;
}

void H5Writer::disable()
{
	m_enabled = false;
}

size_t H5Writer::bytes()
{
	return 0;
}

string H5Writer::filename()
{
	return m_fn;
}

void H5Writer::registerWidget(GtkWidget *w)
{
	m_w = w;
}

void H5Writer::draw()
{
	if (isEnabled()) {

		size_t n = filename().find_last_of("/");
		char str[256];

		double b = bytes() / 1e6;

		if (b >= 1e3) {
			b /= 1e3;
			snprintf(str, 256, "%s: %.2f GB",
			         filename().substr(n+1).c_str(), b);
		} else {
			snprintf(str, 256, "%s: %.2f MB",
			         filename().substr(n+1).c_str(), b);
		}
		gtk_label_set_text(GTK_LABEL(m_w), str);
	}
}
<|endoftext|>


<commit_before>#include "settingsManager.h"
#include <QHash>
#include <QStringList>

#include <QFile>
#include <QTextStream>

SettingsManager* SettingsManager::mInstance = NULL;

SettingsManager::SettingsManager() : mSettings("SPbSU", "QReal")
{
	initDefaultValues();
	load();
}

void SettingsManager:: setValue(QString const &name, QVariant const &value)
{
	instance()->set(name, value);
}

QVariant SettingsManager::value(QString const &key, QVariant const &defaultValue)
{
	return instance()->get(key, defaultValue);
}

QVariant SettingsManager::value(QString const &key)
{
	return instance()->get(key);
}

SettingsManager* SettingsManager::instance()
{
	if (mInstance == NULL) {
		mInstance = new SettingsManager();
	}
	return mInstance;
}

void SettingsManager::set(QString const &name, QVariant const &value)
{
	mData[name] = value;
}

QVariant SettingsManager::get(QString const &name, QVariant const &defaultValue) const
{
	if (mData.contains(name)) {
		return mData[name];
	}
	if (mDefaultValues.contains(name) && defaultValue == QVariant()) {
		return mDefaultValues[name];
	}
	return defaultValue;
}

void SettingsManager::saveData()
{
	foreach (QString name, mData.keys()) {
		mSettings.setValue(name, mData[name]);
	}
	mSettings.sync();
}

void SettingsManager::load()
{
	foreach (QString name, mSettings.allKeys()) {
		mData[name] = mSettings.value(name);
	}
}

void SettingsManager::initDefaultValues()
{
	QSettings values("../qrkernel/settingsDefaultValues", QSettings::NativeFormat);

	foreach (QString key, values.allKeys()) {
		mDefaultValues.insert(key, values.value(key));
	}
}
<commit_msg>Path to file with default settings fixed<commit_after>#include "settingsManager.h"
#include <QHash>
#include <QStringList>

#include <QFile>
#include <QTextStream>

SettingsManager* SettingsManager::mInstance = NULL;

SettingsManager::SettingsManager() : mSettings("SPbSU", "QReal")
{
	initDefaultValues();
	load();
}

void SettingsManager:: setValue(QString const &name, QVariant const &value)
{
	instance()->set(name, value);
}

QVariant SettingsManager::value(QString const &key, QVariant const &defaultValue)
{
	return instance()->get(key, defaultValue);
}

QVariant SettingsManager::value(QString const &key)
{
	return instance()->get(key);
}

SettingsManager* SettingsManager::instance()
{
	if (mInstance == NULL) {
		mInstance = new SettingsManager();
	}
	return mInstance;
}

void SettingsManager::set(QString const &name, QVariant const &value)
{
	mData[name] = value;
}

QVariant SettingsManager::get(QString const &name, QVariant const &defaultValue) const
{
	if (mData.contains(name)) {
		return mData[name];
	}
	if (mDefaultValues.contains(name) && defaultValue == QVariant()) {
		return mDefaultValues[name];
	}
	return defaultValue;
}

void SettingsManager::saveData()
{
	foreach (QString name, mData.keys()) {
		mSettings.setValue(name, mData[name]);
	}
	mSettings.sync();
}

void SettingsManager::load()
{
	foreach (QString name, mSettings.allKeys()) {
		mData[name] = mSettings.value(name);
	}
}

void SettingsManager::initDefaultValues()
{
	QSettings values(":/settingsDefaultValues", QSettings::NativeFormat);

	foreach (QString key, values.allKeys()) {
		mDefaultValues.insert(key, values.value(key));
	}
}
<|endoftext|>


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

#include <limits.h>
#include <string.h>

#include <iostream>
#include <sstream>

#include "Host.h"
#include "NebulaLog.h"

/* ************************************************************************ */
/* Host :: Constructor/Destructor                                           */
/* ************************************************************************ */

Host::Host(
    int     id,
    string _hostname,
    string _im_mad_name,
    string _vmm_mad_name,
    string _tm_mad_name):
        PoolObjectSQL(id),
        hostname(_hostname),
        state(INIT),
        im_mad_name(_im_mad_name),
        vmm_mad_name(_vmm_mad_name),
        tm_mad_name(_tm_mad_name),
        last_monitored(0),
        cluster(ClusterPool::DEFAULT_CLUSTER_NAME),
        host_template()
        {};

Host::~Host(){};

/* ************************************************************************ */
/* Host :: Database Access Functions                                        */
/* ************************************************************************ */

const char * Host::table = "host_pool";

const char * Host::db_names = "(oid,host_name,state,im_mad,vm_mad,"
                              "tm_mad,last_mon_time, cluster, template)";

const char * Host::db_bootstrap = "CREATE TABLE IF NOT EXISTS host_pool ("
    "oid INTEGER PRIMARY KEY,host_name VARCHAR(512), state INTEGER,"
    "im_mad VARCHAR(128),vm_mad VARCHAR(128),tm_mad VARCHAR(128),"
    "last_mon_time INTEGER, cluster VARCHAR(128), template TEXT, "
    "UNIQUE(host_name, im_mad, vm_mad, tm_mad) )";

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::select_cb(void * nil, int num, char **values, char ** names)
{
    if ((!values[OID]) ||
        (!values[HOST_NAME]) ||
        (!values[STATE]) ||
        (!values[IM_MAD]) ||
        (!values[VM_MAD]) ||
        (!values[TM_MAD]) ||
        (!values[LAST_MON_TIME]) ||
        (!values[CLUSTER]) ||
        (!values[TEMPLATE]) ||
        (num != LIMIT ))
    {
        return -1;
    }

    oid      = atoi(values[OID]);
    hostname = values[HOST_NAME];
    state    = static_cast<HostState>(atoi(values[STATE]));

    im_mad_name  = values[IM_MAD];
    vmm_mad_name = values[VM_MAD];
    tm_mad_name  = values[TM_MAD];

    last_monitored = static_cast<time_t>(atoi(values[LAST_MON_TIME]));

    cluster = values[CLUSTER];

    host_template.from_xml(values[TEMPLATE]);

    host_share.hsid  = oid;

    return 0;
}

/* ------------------------------------------------------------------------ */

int Host::select(SqlDB *db)
{
    ostringstream   oss;
    int             rc;
    int             boid;

    set_callback(static_cast<Callbackable::Callback>(&Host::select_cb));

    oss << "SELECT * FROM " << table << " WHERE oid = " << oid;

    boid = oid;
    oid  = -1;

    rc = db->exec(oss, this);

    unset_callback();

    if ((rc != 0) || (oid != boid ))
    {
        return -1;
    }

    if ( rc != 0 )
    {
        return -1;
    }

    // Select the host shares from the DB
    rc = host_share.select(db);

    if ( rc != 0 )
    {
        return rc;
    }

    return 0;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::insert(SqlDB *db, string& error_str)
{
    int rc;
    map<int,HostShare *>::iterator iter;

    // Set up the share ID, to insert it
    if ( host_share.hsid == -1 )
    {
        host_share.hsid = oid;
    }

    // Update the HostShare
    rc = host_share.insert(db, error_str);

    if ( rc != 0 )
    {
        return rc;
    }

    //Insert the Host
    rc = insert_replace(db, false);

    if ( rc != 0 )
    {
        error_str = "Error inserting Host in DB.";
        host_share.drop(db);

        return rc;
    }

    return 0;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::update(SqlDB *db)
{
    int    rc;

    // Update the HostShare
    rc = host_share.update(db);

    if ( rc != 0 )
    {
        return rc;
    }

    rc = insert_replace(db, true);

    if ( rc != 0 )
    {
        return rc;
    }

    return 0;

}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::insert_replace(SqlDB *db, bool replace)
{
    ostringstream   oss;

    int    rc;
    string xml_template;

    char * sql_hostname;
    char * sql_im_mad_name;
    char * sql_tm_mad_name;
    char * sql_vmm_mad_name;
    char * sql_cluster;
    char * sql_template;

   // Update the Host

    sql_hostname = db->escape_str(hostname.c_str());

    if ( sql_hostname == 0 )
    {
        goto error_hostname;
    }

    sql_im_mad_name = db->escape_str(im_mad_name.c_str());

    if ( sql_im_mad_name == 0 )
    {
        goto error_im;
    }

    sql_tm_mad_name = db->escape_str(tm_mad_name.c_str());

    if ( sql_tm_mad_name == 0 )
    {
        goto error_tm;
    }

    sql_vmm_mad_name = db->escape_str(vmm_mad_name.c_str());

    if ( sql_vmm_mad_name == 0 )
    {
        goto error_vmm;
    }

    sql_cluster = db->escape_str(cluster.c_str());

    if ( sql_cluster == 0 )
    {
        goto error_cluster;
    }

    host_template.to_xml(xml_template);
    sql_template = db->escape_str(xml_template.c_str());

    if ( sql_template == 0 )
    {
        goto error_template;
    }

    if(replace)
    {
        oss << "REPLACE";
    }
    else
    {
        oss << "INSERT";
    }

    // Construct the SQL statement to Insert or Replace

    oss <<" INTO "<< table <<" "<< db_names <<" VALUES ("
        <<          oid                 << ","
        << "'" <<   sql_hostname        << "',"
        <<          state               << ","
        << "'" <<   sql_im_mad_name     << "',"
        << "'" <<   sql_vmm_mad_name    << "',"
        << "'" <<   sql_tm_mad_name     << "',"
        <<          last_monitored      << ","
        << "'" <<   sql_cluster         << "',"
        << "'" <<   sql_template        << "')";

    rc = db->exec(oss);

    db->free_str(sql_hostname);
    db->free_str(sql_im_mad_name);
    db->free_str(sql_tm_mad_name);
    db->free_str(sql_vmm_mad_name);
    db->free_str(sql_cluster);
    db->free_str(sql_template);

    return rc;

error_template:
    db->free_str(sql_cluster);
error_cluster:
    db->free_str(sql_vmm_mad_name);
error_vmm:
    db->free_str(sql_tm_mad_name);
error_tm:
    db->free_str(sql_im_mad_name);
error_im:
    db->free_str(sql_hostname);
error_hostname:
    return -1;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::dump(ostringstream& oss, int num, char **values, char **names)
{
    if ((!values[OID]) ||
        (!values[HOST_NAME]) ||
        (!values[STATE]) ||
        (!values[IM_MAD]) ||
        (!values[VM_MAD]) ||
        (!values[TM_MAD]) ||
        (!values[LAST_MON_TIME]) ||
        (!values[CLUSTER]) ||
        (!values[TEMPLATE]) ||
        (num != LIMIT + HostShare::LIMIT ))
    {
        return -1;
    }

    oss <<
        "<HOST>" <<
            "<ID>"           << values[OID]          <<"</ID>"           <<
            "<NAME>"         << values[HOST_NAME]    <<"</NAME>"         <<
            "<STATE>"        << values[STATE]        <<"</STATE>"        <<
            "<IM_MAD>"       << values[IM_MAD]       <<"</IM_MAD>"       <<
            "<VM_MAD>"       << values[VM_MAD]       <<"</VM_MAD>"       <<
            "<TM_MAD>"       << values[TM_MAD]       <<"</TM_MAD>"       <<
            "<LAST_MON_TIME>"<< values[LAST_MON_TIME]<<"</LAST_MON_TIME>"<<
            "<CLUSTER>"      << values[CLUSTER]      <<"</CLUSTER>"      <<
            values[TEMPLATE];

    HostShare::dump(oss,num - LIMIT, values + LIMIT, names + LIMIT);

    oss << "</HOST>";

    return 0;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::drop(SqlDB * db)
{
    ostringstream oss;
    int rc;

    host_share.drop(db);

    oss << "DELETE FROM " << table << " WHERE oid=" << oid;

    rc = db->exec(oss);

    if ( rc == 0 )
    {
        set_valid(false);
    }

    return rc;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::update_info(string &parse_str)
{
    char *  error_msg;
    int     rc;

    rc = host_template.parse(parse_str, &error_msg);

    if ( rc != 0 )
    {
        NebulaLog::log("ONE", Log::ERROR, error_msg);

        free(error_msg);
        return -1;
    }

    get_template_attribute("TOTALCPU",host_share.max_cpu);
    get_template_attribute("TOTALMEMORY",host_share.max_mem);

    get_template_attribute("FREECPU",host_share.free_cpu);
    get_template_attribute("FREEMEMORY",host_share.free_mem);

    get_template_attribute("USEDCPU",host_share.used_cpu);
    get_template_attribute("USEDMEMORY",host_share.used_mem);

    return 0;
}

/* ************************************************************************ */
/* Host :: Misc                                                             */
/* ************************************************************************ */

ostream& operator<<(ostream& os, Host& host)
{
    string host_str;

    os << host.to_xml(host_str);

    return os;
};

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

string& Host::to_xml(string& xml) const
{
    string template_xml;
    string share_xml;
    ostringstream   oss;

    oss <<
    "<HOST>"
       "<ID>"            << oid       	   << "</ID>"            <<
       "<NAME>"          << hostname 	   << "</NAME>"          <<
       "<STATE>"         << state          << "</STATE>"         <<
       "<IM_MAD>"        << im_mad_name    << "</IM_MAD>"        <<
       "<VM_MAD>"        << vmm_mad_name   << "</VM_MAD>"        <<
       "<TM_MAD>"        << tm_mad_name    << "</TM_MAD>"        <<
       "<LAST_MON_TIME>" << last_monitored << "</LAST_MON_TIME>" <<
       "<CLUSTER>"       << cluster        << "</CLUSTER>"       <<
       host_share.to_xml(share_xml)  <<
       host_template.to_xml(template_xml) <<
    "</HOST>";

    xml = oss.str();

    return xml;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

string& Host::to_str(string& str) const
{
    string template_str;
    string share_str;

    ostringstream   os;

    os <<
        "ID      =  "  << oid            << endl <<
        "NAME = "      << hostname       << endl <<
        "STATE    = "  << state          << endl <<
        "IM MAD   = "  << im_mad_name    << endl <<
        "VMM MAD  = "  << vmm_mad_name   << endl <<
        "TM MAD   = "  << tm_mad_name    << endl <<
        "LAST_MON = "  << last_monitored << endl <<
        "CLUSTER  = "  << cluster        << endl <<
        "ATTRIBUTES"   << endl << host_template.to_str(template_str) << endl <<
        "HOST SHARES"  << endl << host_share.to_str(share_str) <<endl;

    str = os.str();

    return str;
}
<commit_msg>bug #308: Only hostnames are now unique. Adjusted column sizes.<commit_after>/* ------------------------------------------------------------------------ */
/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org)           */
/*                                                                          */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may  */
/* not use this file except in compliance with the License. You may obtain  */
/* a copy of the License at                                                 */
/*                                                                          */
/* http://www.apache.org/licenses/LICENSE-2.0                               */
/*                                                                          */
/* Unless required by applicable law or agreed to in writing, software      */
/* distributed under the License is distributed on an "AS IS" BASIS,        */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and      */
/* limitations under the License.                                           */
/* ------------------------------------------------------------------------ */

#include <limits.h>
#include <string.h>

#include <iostream>
#include <sstream>

#include "Host.h"
#include "NebulaLog.h"

/* ************************************************************************ */
/* Host :: Constructor/Destructor                                           */
/* ************************************************************************ */

Host::Host(
    int     id,
    string _hostname,
    string _im_mad_name,
    string _vmm_mad_name,
    string _tm_mad_name):
        PoolObjectSQL(id),
        hostname(_hostname),
        state(INIT),
        im_mad_name(_im_mad_name),
        vmm_mad_name(_vmm_mad_name),
        tm_mad_name(_tm_mad_name),
        last_monitored(0),
        cluster(ClusterPool::DEFAULT_CLUSTER_NAME),
        host_template()
        {};

Host::~Host(){};

/* ************************************************************************ */
/* Host :: Database Access Functions                                        */
/* ************************************************************************ */

const char * Host::table = "host_pool";

const char * Host::db_names = "(oid,host_name,state,im_mad,vm_mad,"
                              "tm_mad,last_mon_time, cluster, template)";

const char * Host::db_bootstrap = "CREATE TABLE IF NOT EXISTS host_pool ("
    "oid INTEGER PRIMARY KEY,host_name VARCHAR(256), state INTEGER,"
    "im_mad VARCHAR(128),vm_mad VARCHAR(128),tm_mad VARCHAR(128),"
    "last_mon_time INTEGER, cluster VARCHAR(128), template TEXT, "
    "UNIQUE(host_name))";

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::select_cb(void * nil, int num, char **values, char ** names)
{
    if ((!values[OID]) ||
        (!values[HOST_NAME]) ||
        (!values[STATE]) ||
        (!values[IM_MAD]) ||
        (!values[VM_MAD]) ||
        (!values[TM_MAD]) ||
        (!values[LAST_MON_TIME]) ||
        (!values[CLUSTER]) ||
        (!values[TEMPLATE]) ||
        (num != LIMIT ))
    {
        return -1;
    }

    oid      = atoi(values[OID]);
    hostname = values[HOST_NAME];
    state    = static_cast<HostState>(atoi(values[STATE]));

    im_mad_name  = values[IM_MAD];
    vmm_mad_name = values[VM_MAD];
    tm_mad_name  = values[TM_MAD];

    last_monitored = static_cast<time_t>(atoi(values[LAST_MON_TIME]));

    cluster = values[CLUSTER];

    host_template.from_xml(values[TEMPLATE]);

    host_share.hsid  = oid;

    return 0;
}

/* ------------------------------------------------------------------------ */

int Host::select(SqlDB *db)
{
    ostringstream   oss;
    int             rc;
    int             boid;

    set_callback(static_cast<Callbackable::Callback>(&Host::select_cb));

    oss << "SELECT * FROM " << table << " WHERE oid = " << oid;

    boid = oid;
    oid  = -1;

    rc = db->exec(oss, this);

    unset_callback();

    if ((rc != 0) || (oid != boid ))
    {
        return -1;
    }

    if ( rc != 0 )
    {
        return -1;
    }

    // Select the host shares from the DB
    rc = host_share.select(db);

    if ( rc != 0 )
    {
        return rc;
    }

    return 0;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::insert(SqlDB *db, string& error_str)
{
    int rc;
    map<int,HostShare *>::iterator iter;

    // Set up the share ID, to insert it
    if ( host_share.hsid == -1 )
    {
        host_share.hsid = oid;
    }

    // Update the HostShare
    rc = host_share.insert(db, error_str);

    if ( rc != 0 )
    {
        return rc;
    }

    //Insert the Host
    rc = insert_replace(db, false);

    if ( rc != 0 )
    {
        error_str = "Error inserting Host in DB.";
        host_share.drop(db);

        return rc;
    }

    return 0;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::update(SqlDB *db)
{
    int    rc;

    // Update the HostShare
    rc = host_share.update(db);

    if ( rc != 0 )
    {
        return rc;
    }

    rc = insert_replace(db, true);

    if ( rc != 0 )
    {
        return rc;
    }

    return 0;

}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::insert_replace(SqlDB *db, bool replace)
{
    ostringstream   oss;

    int    rc;
    string xml_template;

    char * sql_hostname;
    char * sql_im_mad_name;
    char * sql_tm_mad_name;
    char * sql_vmm_mad_name;
    char * sql_cluster;
    char * sql_template;

   // Update the Host

    sql_hostname = db->escape_str(hostname.c_str());

    if ( sql_hostname == 0 )
    {
        goto error_hostname;
    }

    sql_im_mad_name = db->escape_str(im_mad_name.c_str());

    if ( sql_im_mad_name == 0 )
    {
        goto error_im;
    }

    sql_tm_mad_name = db->escape_str(tm_mad_name.c_str());

    if ( sql_tm_mad_name == 0 )
    {
        goto error_tm;
    }

    sql_vmm_mad_name = db->escape_str(vmm_mad_name.c_str());

    if ( sql_vmm_mad_name == 0 )
    {
        goto error_vmm;
    }

    sql_cluster = db->escape_str(cluster.c_str());

    if ( sql_cluster == 0 )
    {
        goto error_cluster;
    }

    host_template.to_xml(xml_template);
    sql_template = db->escape_str(xml_template.c_str());

    if ( sql_template == 0 )
    {
        goto error_template;
    }

    if(replace)
    {
        oss << "REPLACE";
    }
    else
    {
        oss << "INSERT";
    }

    // Construct the SQL statement to Insert or Replace

    oss <<" INTO "<< table <<" "<< db_names <<" VALUES ("
        <<          oid                 << ","
        << "'" <<   sql_hostname        << "',"
        <<          state               << ","
        << "'" <<   sql_im_mad_name     << "',"
        << "'" <<   sql_vmm_mad_name    << "',"
        << "'" <<   sql_tm_mad_name     << "',"
        <<          last_monitored      << ","
        << "'" <<   sql_cluster         << "',"
        << "'" <<   sql_template        << "')";

    rc = db->exec(oss);

    db->free_str(sql_hostname);
    db->free_str(sql_im_mad_name);
    db->free_str(sql_tm_mad_name);
    db->free_str(sql_vmm_mad_name);
    db->free_str(sql_cluster);
    db->free_str(sql_template);

    return rc;

error_template:
    db->free_str(sql_cluster);
error_cluster:
    db->free_str(sql_vmm_mad_name);
error_vmm:
    db->free_str(sql_tm_mad_name);
error_tm:
    db->free_str(sql_im_mad_name);
error_im:
    db->free_str(sql_hostname);
error_hostname:
    return -1;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::dump(ostringstream& oss, int num, char **values, char **names)
{
    if ((!values[OID]) ||
        (!values[HOST_NAME]) ||
        (!values[STATE]) ||
        (!values[IM_MAD]) ||
        (!values[VM_MAD]) ||
        (!values[TM_MAD]) ||
        (!values[LAST_MON_TIME]) ||
        (!values[CLUSTER]) ||
        (!values[TEMPLATE]) ||
        (num != LIMIT + HostShare::LIMIT ))
    {
        return -1;
    }

    oss <<
        "<HOST>" <<
            "<ID>"           << values[OID]          <<"</ID>"           <<
            "<NAME>"         << values[HOST_NAME]    <<"</NAME>"         <<
            "<STATE>"        << values[STATE]        <<"</STATE>"        <<
            "<IM_MAD>"       << values[IM_MAD]       <<"</IM_MAD>"       <<
            "<VM_MAD>"       << values[VM_MAD]       <<"</VM_MAD>"       <<
            "<TM_MAD>"       << values[TM_MAD]       <<"</TM_MAD>"       <<
            "<LAST_MON_TIME>"<< values[LAST_MON_TIME]<<"</LAST_MON_TIME>"<<
            "<CLUSTER>"      << values[CLUSTER]      <<"</CLUSTER>"      <<
            values[TEMPLATE];

    HostShare::dump(oss,num - LIMIT, values + LIMIT, names + LIMIT);

    oss << "</HOST>";

    return 0;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::drop(SqlDB * db)
{
    ostringstream oss;
    int rc;

    host_share.drop(db);

    oss << "DELETE FROM " << table << " WHERE oid=" << oid;

    rc = db->exec(oss);

    if ( rc == 0 )
    {
        set_valid(false);
    }

    return rc;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::update_info(string &parse_str)
{
    char *  error_msg;
    int     rc;

    rc = host_template.parse(parse_str, &error_msg);

    if ( rc != 0 )
    {
        NebulaLog::log("ONE", Log::ERROR, error_msg);

        free(error_msg);
        return -1;
    }

    get_template_attribute("TOTALCPU",host_share.max_cpu);
    get_template_attribute("TOTALMEMORY",host_share.max_mem);

    get_template_attribute("FREECPU",host_share.free_cpu);
    get_template_attribute("FREEMEMORY",host_share.free_mem);

    get_template_attribute("USEDCPU",host_share.used_cpu);
    get_template_attribute("USEDMEMORY",host_share.used_mem);

    return 0;
}

/* ************************************************************************ */
/* Host :: Misc                                                             */
/* ************************************************************************ */

ostream& operator<<(ostream& os, Host& host)
{
    string host_str;

    os << host.to_xml(host_str);

    return os;
};

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

string& Host::to_xml(string& xml) const
{
    string template_xml;
    string share_xml;
    ostringstream   oss;

    oss <<
    "<HOST>"
       "<ID>"            << oid       	   << "</ID>"            <<
       "<NAME>"          << hostname 	   << "</NAME>"          <<
       "<STATE>"         << state          << "</STATE>"         <<
       "<IM_MAD>"        << im_mad_name    << "</IM_MAD>"        <<
       "<VM_MAD>"        << vmm_mad_name   << "</VM_MAD>"        <<
       "<TM_MAD>"        << tm_mad_name    << "</TM_MAD>"        <<
       "<LAST_MON_TIME>" << last_monitored << "</LAST_MON_TIME>" <<
       "<CLUSTER>"       << cluster        << "</CLUSTER>"       <<
       host_share.to_xml(share_xml)  <<
       host_template.to_xml(template_xml) <<
    "</HOST>";

    xml = oss.str();

    return xml;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

string& Host::to_str(string& str) const
{
    string template_str;
    string share_str;

    ostringstream   os;

    os <<
        "ID      =  "  << oid            << endl <<
        "NAME = "      << hostname       << endl <<
        "STATE    = "  << state          << endl <<
        "IM MAD   = "  << im_mad_name    << endl <<
        "VMM MAD  = "  << vmm_mad_name   << endl <<
        "TM MAD   = "  << tm_mad_name    << endl <<
        "LAST_MON = "  << last_monitored << endl <<
        "CLUSTER  = "  << cluster        << endl <<
        "ATTRIBUTES"   << endl << host_template.to_str(template_str) << endl <<
        "HOST SHARES"  << endl << host_share.to_str(share_str) <<endl;

    str = os.str();

    return str;
}
<|endoftext|>


<commit_before>/** @file
    @brief Implementation

    @date 2017

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

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

// Internal Includes
#include "Properties.h"
#include "ValveStrCpy.h"

// Library/third-party includes
// - none

// Standard includes
#include <iostream>
#include <string>
#include <type_traits>

using namespace vr;

namespace {
template <typename T>
struct PropertyTypeTagTrait
    : std::integral_constant<PropertyTypeTag_t, k_unInvalidPropertyTag> {};
/// Semicolon intentionally omitted at the end of this macro definition
#define OSVRVIVE_DEFINE_PROPERTY_TYPE_TAG(TYPE, TAG)                           \
    template <>                                                                \
    struct PropertyTypeTagTrait<TYPE>                                          \
        : std::integral_constant<PropertyTypeTag_t, TAG> {}

OSVRVIVE_DEFINE_PROPERTY_TYPE_TAG(float, k_unFloatPropertyTag);
OSVRVIVE_DEFINE_PROPERTY_TYPE_TAG(std::int32_t, k_unInt32PropertyTag);
OSVRVIVE_DEFINE_PROPERTY_TYPE_TAG(std::uint64_t, k_unUint64PropertyTag);
OSVRVIVE_DEFINE_PROPERTY_TYPE_TAG(bool, k_unBoolPropertyTag);
OSVRVIVE_DEFINE_PROPERTY_TYPE_TAG(std::string, k_unStringPropertyTag);
OSVRVIVE_DEFINE_PROPERTY_TYPE_TAG(vr::HmdMatrix34_t,
                                  k_unHmdMatrix34PropertyTag);

/// Note: if you add a type here, you must also make sure it's added to the
/// PropertyStoreVariant, as well as to Properties::WritePropertyBatch

#undef OSVRVIVE_DEFINE_PROPERTY_TYPE_TAG

struct GetContainedTypeTag : boost::static_visitor<PropertyTypeTag_t> {
    template <typename T> PropertyTypeTag_t operator()(T const &val) {
        return PropertyTypeTagTrait<T>::value;
    }
};
struct ValueSizeGetter : boost::static_visitor<std::size_t> {
    template <typename T> std::size_t operator()(T const &) const {
        return sizeof(T);
    }
    std::size_t operator()(std::string const &s) const {
        // add 1 for null terminator
        return s.size() + 1;
    }
};

template <typename T> inline std::size_t getValueSize(T const &val) {
    return ValueSizeGetter()(val);
}

struct ValueGetter : boost::static_visitor<> {
    ValueGetter(PropertyRead_t &batchEntry) : batchEntry_(&batchEntry) {}
    template <typename T> void operator()(T const &val) const {
        *reinterpret_cast<T *>(batchEntry_->pvBuffer) = val;
    }
    void operator()(std::string const &s) const {
        char *strBuf = reinterpret_cast<char *>(batchEntry_->pvBuffer);
        valveStrCpy(s, strBuf, batchEntry_->unBufferSize);
    }

  private:
    PropertyRead_t *batchEntry_;
};
} // namespace

inline void readProperty(PropertiesStore const &store,
                         PropertyRead_t &batchEntry) {
    if (!store.containsAnyType(batchEntry.prop)) {
        batchEntry.eError = TrackedProp_UnknownProperty;
        return;
    }
    auto &val = store.getVariant(batchEntry.prop);
    auto containedTag = val.apply_visitor(GetContainedTypeTag());
    bool actuallyGet = true;
    if (containedTag != batchEntry.unTag) {
        actuallyGet = false;
        batchEntry.unTag = containedTag;
    }
    batchEntry.unRequiredBufferSize =
        static_cast<std::uint32_t>(val.apply_visitor(ValueSizeGetter()));

    if (batchEntry.unRequiredBufferSize > batchEntry.unBufferSize) {
        return;
    }
    if (!actuallyGet) {
        return;
    }
    val.apply_visitor(ValueGetter(batchEntry));
}
Properties::Properties()
    : m_logger(osvr::util::log::make_logger("Properties")) {

    /*addDeviceAt(0);
    vr::PropertyWrite_t writeBatch;
    writeBatch.prop = Prop_UserConfigPath_String;
    writeBatch.writeType = PropertyWrite_Set;
    std::string userConfigPath = "C:/Program Files(x86)/Steam/config";
    writeBatch.unBufferSize = userConfigPath.length();
    writeBatch.pvBuffer = (char *)userConfigPath.c_str();
    writeBatch.unTag = k_unStringPropertyTag;
    WritePropertyBatch(1, &writeBatch, 1);

    writeBatch.prop = Prop_InstallPath_String;
    writeBatch.writeType = PropertyWrite_Set;
    std::string installPath = "C:/Program Files (x86)/Steam/config/lighthouse";
    writeBatch.unBufferSize = installPath.length();
    writeBatch.pvBuffer = (char*)userConfigPath.c_str();
    writeBatch.unTag = k_unStringPropertyTag;
    WritePropertyBatch(1, &writeBatch, 1);*/
}

ETrackedPropertyError
Properties::ReadPropertyBatch(PropertyContainerHandle_t ulContainerHandle,
                              PropertyRead_t *pBatch,
                              uint32_t unBatchEntryCount) {
    uint64_t deviceId = ulContainerHandle - 1;
    if (!hasDeviceAt(deviceId)) {
        m_logger->error("doesn't have the property container with id: ")
            << ulContainerHandle;
        return TrackedProp_InvalidDevice;
    }
    auto &store = m_propertyStores.at(deviceId);
    ETrackedPropertyError ret = TrackedProp_Success;
    for (std::uint32_t i = 0; i < unBatchEntryCount; ++i) {
        auto &entry = pBatch[i];

        m_logger->info() << "ReadPropertyBatch: Entry " << i << ", Property ID "
                         << entry.prop << ", Supplied tag type " << entry.unTag;
        readProperty(store, pBatch[i]);
        if (pBatch[i].eError != TrackedProp_Success) {
            ret = pBatch[i].eError;
            /// @todo OK to early out on first error?
            return ret;
        }
    }

    return ret;
}

ETrackedPropertyError
Properties::WritePropertyBatch(PropertyContainerHandle_t ulContainerHandle,
                               PropertyWrite_t *pBatch,
                               uint32_t unBatchEntryCount) {
    if (pBatch == nullptr) {
        m_logger->error("pBatch is null");
        return TrackedProp_InvalidOperation;
    }
    uint64_t deviceId = ulContainerHandle - 1;
    if (!hasDeviceAt(deviceId)) {
        addDeviceAt(deviceId);
    }
    PropertiesStore &pStore = m_propertyStores[deviceId];
    for (std::uint32_t i = 0; i < unBatchEntryCount; ++i) {
        auto &entry = pBatch[i];
        if (entry.writeType == PropertyWrite_Set) {
            entry.eError = vr::TrackedProp_Success;
            switch (entry.unTag) {
            case k_unFloatPropertyTag: {
                auto val = *(reinterpret_cast<float *>(entry.pvBuffer));
                pStore.set(pBatch->prop, val);
                break;
            }
            case k_unInt32PropertyTag: {
                auto val = *(reinterpret_cast<int32_t *>(entry.pvBuffer));
                pStore.set(entry.prop, val);
                break;
            }
            case k_unUint64PropertyTag: {
                auto val = *(reinterpret_cast<uint64_t *>(entry.pvBuffer));
                pStore.set(entry.prop, val);
                break;
            }
            case k_unBoolPropertyTag: {
                auto val = *(reinterpret_cast<bool *>(entry.pvBuffer));
                pStore.set(entry.prop, val);
                break;
            }
            case k_unStringPropertyTag: {
                pStore.set(entry.prop, std::string(reinterpret_cast<char *>(
                                           entry.pvBuffer)));
                break;
            }
            case k_unHmdMatrix34PropertyTag: {
                auto val =
                    *(reinterpret_cast<vr::HmdMatrix34_t *>(entry.pvBuffer));
                pStore.set(entry.prop, val);
                break;
            }
            default: {
                m_logger->error()
                    << "In property setting: Unhandled property tag type: "
                    << entry.unTag << " for property ID" << entry.prop;
                entry.eError = vr::TrackedProp_InvalidOperation;
                break;
            }
            }
        } else if (entry.writeType == PropertyWrite_Erase) {
            pStore.erase(entry.prop);
        } else if (entry.writeType == PropertyWrite_SetError) {
            m_logger->info("set error");
        } else {
            m_logger->error("unknown writeType: ") << entry.writeType;
            return vr::TrackedProp_InvalidOperation;
        }
    }

    return vr::TrackedProp_Success;
}

const char *Properties::GetPropErrorNameFromEnum(ETrackedPropertyError error) {
    switch (error) {
    case vr::TrackedProp_Success:
        return "Success";
    case vr::TrackedProp_WrongDataType:
        return "Wrong Data Type";
    case vr::TrackedProp_WrongDeviceClass:
        return "Wrong Device Class";
    case vr::TrackedProp_BufferTooSmall:
        return "Buffer too small";
    case vr::TrackedProp_UnknownProperty:
        return "Unknown property";
    case vr::TrackedProp_InvalidDevice:
        return "Invalid device";
    case vr::TrackedProp_CouldNotContactServer:
        return "Could not contact server";
    case vr::TrackedProp_ValueNotProvidedByDevice:
        return "Value not provided by device";
    case vr::TrackedProp_StringExceedsMaximumLength:
        return "String exceeds maximum length";
    case vr::TrackedProp_NotYetAvailable:
        return "Not yet available";
    case vr::TrackedProp_PermissionDenied:
        return "Permission denied";
    case vr::TrackedProp_InvalidOperation:
        return "Invalid operation";
    default:
        return "Other undocumented error";
    }
}

PropertyContainerHandle_t
Properties::TrackedDeviceToPropertyContainer(TrackedDeviceIndex_t nDevice) {
    m_logger->info("TrackedDeviceToPropertyContainer")
        << " at index " << nDevice;
    if (!hasDeviceAt(nDevice)) {
        addDeviceAt(nDevice);
    }
    PropertyContainerHandle_t containerId = nDevice + 1;
    return containerId;
}

bool Properties::hasDeviceAt(const std::uint64_t idx) const {
    return (idx < m_propertyStores.size());
}

void Properties::addDeviceAt(const std::uint64_t idx) {
    /// @todo this is kind of redundant with reserveIds
    m_logger->info("addDeviceAt ") << idx;
    if (!(idx < m_propertyStores.size())) {
        /// OK, we need to reserve more room
        reserveIds(idx + 1);
    }
}

bool Properties::reserveIds(std::uint64_t n) {
    if (m_propertyStores.size() < n) {
        m_propertyStores.resize(n);
        return true;
    }
    return false;
}
<commit_msg>apply driver properties, if they're found<commit_after>/** @file
    @brief Implementation

    @date 2017

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

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

// Internal Includes
#include "Properties.h"
#include "FindDriver.h"
#include "ValveStrCpy.h"

// Library/third-party includes
// - none

// Standard includes
#include <iostream>
#include <string>
#include <type_traits>

using namespace vr;

namespace {
template <typename T>
struct PropertyTypeTagTrait
    : std::integral_constant<PropertyTypeTag_t, k_unInvalidPropertyTag> {};
/// Semicolon intentionally omitted at the end of this macro definition
#define OSVRVIVE_DEFINE_PROPERTY_TYPE_TAG(TYPE, TAG)                           \
    template <>                                                                \
    struct PropertyTypeTagTrait<TYPE>                                          \
        : std::integral_constant<PropertyTypeTag_t, TAG> {}

OSVRVIVE_DEFINE_PROPERTY_TYPE_TAG(float, k_unFloatPropertyTag);
OSVRVIVE_DEFINE_PROPERTY_TYPE_TAG(std::int32_t, k_unInt32PropertyTag);
OSVRVIVE_DEFINE_PROPERTY_TYPE_TAG(std::uint64_t, k_unUint64PropertyTag);
OSVRVIVE_DEFINE_PROPERTY_TYPE_TAG(bool, k_unBoolPropertyTag);
OSVRVIVE_DEFINE_PROPERTY_TYPE_TAG(std::string, k_unStringPropertyTag);
OSVRVIVE_DEFINE_PROPERTY_TYPE_TAG(vr::HmdMatrix34_t,
                                  k_unHmdMatrix34PropertyTag);

/// Note: if you add a type here, you must also make sure it's added to the
/// PropertyStoreVariant, as well as to Properties::WritePropertyBatch

#undef OSVRVIVE_DEFINE_PROPERTY_TYPE_TAG

struct GetContainedTypeTag : boost::static_visitor<PropertyTypeTag_t> {
    template <typename T> PropertyTypeTag_t operator()(T const &val) {
        return PropertyTypeTagTrait<T>::value;
    }
};
struct ValueSizeGetter : boost::static_visitor<std::size_t> {
    template <typename T> std::size_t operator()(T const &) const {
        return sizeof(T);
    }
    std::size_t operator()(std::string const &s) const {
        // add 1 for null terminator
        return s.size() + 1;
    }
};

template <typename T> inline std::size_t getValueSize(T const &val) {
    return ValueSizeGetter()(val);
}

struct ValueGetter : boost::static_visitor<> {
    ValueGetter(PropertyRead_t &batchEntry) : batchEntry_(&batchEntry) {}
    template <typename T> void operator()(T const &val) const {
        *reinterpret_cast<T *>(batchEntry_->pvBuffer) = val;
    }
    void operator()(std::string const &s) const {
        char *strBuf = reinterpret_cast<char *>(batchEntry_->pvBuffer);
        valveStrCpy(s, strBuf, batchEntry_->unBufferSize);
    }

  private:
    PropertyRead_t *batchEntry_;
};
} // namespace

inline void readProperty(PropertiesStore const &store,
                         PropertyRead_t &batchEntry) {
    if (!store.containsAnyType(batchEntry.prop)) {
        batchEntry.eError = TrackedProp_UnknownProperty;
        return;
    }
    auto &val = store.getVariant(batchEntry.prop);
    auto containedTag = val.apply_visitor(GetContainedTypeTag());
    bool actuallyGet = true;
    if (containedTag != batchEntry.unTag) {
        actuallyGet = false;
        batchEntry.unTag = containedTag;
    }
    batchEntry.unRequiredBufferSize =
        static_cast<std::uint32_t>(val.apply_visitor(ValueSizeGetter()));

    if (batchEntry.unRequiredBufferSize > batchEntry.unBufferSize) {
        return;
    }
    if (!actuallyGet) {
        return;
    }
    val.apply_visitor(ValueGetter(batchEntry));
}
Properties::Properties()
    : m_logger(osvr::util::log::make_logger("Properties")) {

    osvr::vive::LocationInfo locations;
    locations = osvr::vive::findLocationInfoForDriver();
    if (locations.driverFound) {
        addDeviceAt(0);
        vr::PropertyWrite_t writeBatch;
        writeBatch.prop = Prop_UserConfigPath_String;
        writeBatch.writeType = PropertyWrite_Set;
        std::string userConfigPath = locations.driverConfigDir;
        writeBatch.unBufferSize = userConfigPath.length();
        writeBatch.pvBuffer = (char *)userConfigPath.c_str();
        writeBatch.unTag = k_unStringPropertyTag;
        WritePropertyBatch(1, &writeBatch, 1);

        writeBatch.prop = Prop_InstallPath_String;
        writeBatch.writeType = PropertyWrite_Set;
        std::string installPath = locations.driverRoot;
        writeBatch.unBufferSize = installPath.length();
        writeBatch.pvBuffer = (char *)userConfigPath.c_str();
        writeBatch.unTag = k_unStringPropertyTag;
        WritePropertyBatch(1, &writeBatch, 1);
    }
}

ETrackedPropertyError
Properties::ReadPropertyBatch(PropertyContainerHandle_t ulContainerHandle,
                              PropertyRead_t *pBatch,
                              uint32_t unBatchEntryCount) {
    uint64_t deviceId = ulContainerHandle - 1;
    if (!hasDeviceAt(deviceId)) {
        m_logger->error("doesn't have the property container with id: ")
            << ulContainerHandle;
        return TrackedProp_InvalidDevice;
    }
    auto &store = m_propertyStores.at(deviceId);
    ETrackedPropertyError ret = TrackedProp_Success;
    for (std::uint32_t i = 0; i < unBatchEntryCount; ++i) {
        auto &entry = pBatch[i];

        m_logger->info() << "ReadPropertyBatch: Entry " << i << ", Property ID "
                         << entry.prop << ", Supplied tag type " << entry.unTag;
        readProperty(store, pBatch[i]);
        if (pBatch[i].eError != TrackedProp_Success) {
            ret = pBatch[i].eError;
            /// @todo OK to early out on first error?
            return ret;
        }
    }

    return ret;
}

ETrackedPropertyError
Properties::WritePropertyBatch(PropertyContainerHandle_t ulContainerHandle,
                               PropertyWrite_t *pBatch,
                               uint32_t unBatchEntryCount) {
    if (pBatch == nullptr) {
        m_logger->error("pBatch is null");
        return TrackedProp_InvalidOperation;
    }
    uint64_t deviceId = ulContainerHandle - 1;
    if (!hasDeviceAt(deviceId)) {
        addDeviceAt(deviceId);
    }
    PropertiesStore &pStore = m_propertyStores[deviceId];
    for (std::uint32_t i = 0; i < unBatchEntryCount; ++i) {
        auto &entry = pBatch[i];
        if (entry.writeType == PropertyWrite_Set) {
            entry.eError = vr::TrackedProp_Success;
            switch (entry.unTag) {
            case k_unFloatPropertyTag: {
                auto val = *(reinterpret_cast<float *>(entry.pvBuffer));
                pStore.set(pBatch->prop, val);
                break;
            }
            case k_unInt32PropertyTag: {
                auto val = *(reinterpret_cast<int32_t *>(entry.pvBuffer));
                pStore.set(entry.prop, val);
                break;
            }
            case k_unUint64PropertyTag: {
                auto val = *(reinterpret_cast<uint64_t *>(entry.pvBuffer));
                pStore.set(entry.prop, val);
                break;
            }
            case k_unBoolPropertyTag: {
                auto val = *(reinterpret_cast<bool *>(entry.pvBuffer));
                pStore.set(entry.prop, val);
                break;
            }
            case k_unStringPropertyTag: {
                pStore.set(entry.prop, std::string(reinterpret_cast<char *>(
                                           entry.pvBuffer)));
                break;
            }
            case k_unHmdMatrix34PropertyTag: {
                auto val =
                    *(reinterpret_cast<vr::HmdMatrix34_t *>(entry.pvBuffer));
                pStore.set(entry.prop, val);
                break;
            }
            default: {
                m_logger->error()
                    << "In property setting: Unhandled property tag type: "
                    << entry.unTag << " for property ID" << entry.prop;
                entry.eError = vr::TrackedProp_InvalidOperation;
                break;
            }
            }
        } else if (entry.writeType == PropertyWrite_Erase) {
            pStore.erase(entry.prop);
        } else if (entry.writeType == PropertyWrite_SetError) {
            m_logger->info("set error");
        } else {
            m_logger->error("unknown writeType: ") << entry.writeType;
            return vr::TrackedProp_InvalidOperation;
        }
    }

    return vr::TrackedProp_Success;
}

const char *Properties::GetPropErrorNameFromEnum(ETrackedPropertyError error) {
    switch (error) {
    case vr::TrackedProp_Success:
        return "Success";
    case vr::TrackedProp_WrongDataType:
        return "Wrong Data Type";
    case vr::TrackedProp_WrongDeviceClass:
        return "Wrong Device Class";
    case vr::TrackedProp_BufferTooSmall:
        return "Buffer too small";
    case vr::TrackedProp_UnknownProperty:
        return "Unknown property";
    case vr::TrackedProp_InvalidDevice:
        return "Invalid device";
    case vr::TrackedProp_CouldNotContactServer:
        return "Could not contact server";
    case vr::TrackedProp_ValueNotProvidedByDevice:
        return "Value not provided by device";
    case vr::TrackedProp_StringExceedsMaximumLength:
        return "String exceeds maximum length";
    case vr::TrackedProp_NotYetAvailable:
        return "Not yet available";
    case vr::TrackedProp_PermissionDenied:
        return "Permission denied";
    case vr::TrackedProp_InvalidOperation:
        return "Invalid operation";
    default:
        return "Other undocumented error";
    }
}

PropertyContainerHandle_t
Properties::TrackedDeviceToPropertyContainer(TrackedDeviceIndex_t nDevice) {
    m_logger->info("TrackedDeviceToPropertyContainer")
        << " at index " << nDevice;
    if (!hasDeviceAt(nDevice)) {
        addDeviceAt(nDevice);
    }
    PropertyContainerHandle_t containerId = nDevice + 1;
    return containerId;
}

bool Properties::hasDeviceAt(const std::uint64_t idx) const {
    return (idx < m_propertyStores.size());
}

void Properties::addDeviceAt(const std::uint64_t idx) {
    /// @todo this is kind of redundant with reserveIds
    m_logger->info("addDeviceAt ") << idx;
    if (!(idx < m_propertyStores.size())) {
        /// OK, we need to reserve more room
        reserveIds(idx + 1);
    }
}

bool Properties::reserveIds(std::uint64_t n) {
    if (m_propertyStores.size() < n) {
        m_propertyStores.resize(n);
        return true;
    }
    return false;
}
<|endoftext|>