<commit_before>#include "EffectPlatformLLGI.h"
#include "../3rdParty/LLGI/src/LLGI.Buffer.h"
#include "../3rdParty/LLGI/src/LLGI.CommandList.h"
#include "../3rdParty/LLGI/src/LLGI.Graphics.h"
#include "../3rdParty/LLGI/src/LLGI.PipelineState.h"
#include "../3rdParty/LLGI/src/LLGI.Platform.h"
#include "../3rdParty/LLGI/src/LLGI.Shader.h"
#include "../3rdParty/LLGI/src/LLGI.Texture.h"

#include "../../3rdParty/stb/stb_image_write.h"

void EffectPlatformLLGI::CreateCheckedTexture()
{
	LLGI::TextureInitializationParameter param;
	param.Size.X = initParam_.WindowSize[0];
	param.Size.Y = initParam_.WindowSize[1];
	checkTexture_ = graphics_->CreateTexture(param);

	auto b = (uint8_t*)checkTexture_->Lock();

	memcpy(b, checkeredPattern_.data(), param.Size.X * param.Size.Y * 4);

	checkTexture_->Unlock();
}

void EffectPlatformLLGI::CreateResources()
{
	CreateShaders();

	LLGI::RenderTextureInitializationParameter renderParam;
	renderParam.Size = LLGI::Vec2I(initParam_.WindowSize[0], initParam_.WindowSize[1]);
	LLGI::DepthTextureInitializationParameter depthParam;
	depthParam.Size = LLGI::Vec2I(initParam_.WindowSize[0], initParam_.WindowSize[1]);
	colorBuffer_ = graphics_->CreateRenderTexture(renderParam);
	depthBuffer_ = graphics_->CreateDepthTexture(depthParam);
	renderPass_ = graphics_->CreateRenderPass((LLGI::Texture**)&colorBuffer_, 1, depthBuffer_);

	vb_ = graphics_->CreateBuffer(LLGI::BufferUsageType::Vertex, sizeof(SimpleVertex) * 4);
	ib_ = graphics_->CreateBuffer(LLGI::BufferUsageType::Index, 2 * 6);
	auto vb_buf = (SimpleVertex*)vb_->Lock();
	vb_buf[0].Pos = LLGI::Vec3F(-1.0f, 1.0f, 0.5f);
	vb_buf[1].Pos = LLGI::Vec3F(1.0f, 1.0f, 0.5f);
	vb_buf[2].Pos = LLGI::Vec3F(1.0f, -1.0f, 0.5f);
	vb_buf[3].Pos = LLGI::Vec3F(-1.0f, -1.0f, 0.5f);

	vb_buf[0].UV = LLGI::Vec2F(0.0f, 0.0f);
	vb_buf[1].UV = LLGI::Vec2F(1.0f, 0.0f);
	vb_buf[2].UV = LLGI::Vec2F(1.0f, 1.0f);
	vb_buf[3].UV = LLGI::Vec2F(0.0f, 1.0f);

	vb_buf[0].Color = LLGI::Color8();
	vb_buf[1].Color = LLGI::Color8();
	vb_buf[2].Color = LLGI::Color8();
	vb_buf[3].Color = LLGI::Color8();

	vb_->Unlock();

	auto ib_buf = (uint16_t*)ib_->Lock();
	ib_buf[0] = 0;
	ib_buf[1] = 1;
	ib_buf[2] = 2;
	ib_buf[3] = 0;
	ib_buf[4] = 2;
	ib_buf[5] = 3;
	ib_->Unlock();

	rppip_ = graphics_->CreateRenderPassPipelineState(renderPass_);

	{
		pip_ = graphics_->CreatePiplineState();
		pip_->VertexLayouts[0] = LLGI::VertexLayoutFormat::R32G32B32_FLOAT;
		pip_->VertexLayouts[1] = LLGI::VertexLayoutFormat::R32G32_FLOAT;
		pip_->VertexLayouts[2] = LLGI::VertexLayoutFormat::R8G8B8A8_UNORM;
		pip_->VertexLayoutNames[0] = "POSITION";
		pip_->VertexLayoutNames[1] = "UV";
		pip_->VertexLayoutNames[2] = "COLOR";
		pip_->VertexLayoutCount = 3;
		pip_->IsDepthTestEnabled = false;
		pip_->IsDepthWriteEnabled = false;
		pip_->Culling = LLGI::CullingMode::DoubleSide;
		pip_->SetShader(LLGI::ShaderStageType::Vertex, shader_vs_);
		pip_->SetShader(LLGI::ShaderStageType::Pixel, shader_ps_);
		pip_->SetRenderPassPipelineState(rppip_);
		pip_->Compile();
	}
}

EffectPlatformLLGI::EffectPlatformLLGI(LLGI::DeviceType deviceType)
	: deviceType_(deviceType)
{
}

EffectPlatformLLGI ::~EffectPlatformLLGI()
{
}

void EffectPlatformLLGI::InitializeWindow()
{
	if (!glfwInit())
	{
		throw "Failed to initialize glfw";
	}

	glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);

	glfwWindow_ = glfwCreateWindow(initParam_.WindowSize[0], initParam_.WindowSize[1], "Example glfw", nullptr, nullptr);

	if (glfwWindow_ == nullptr)
	{
		glfwTerminate();
		throw "Failed to create an window.";
	}

	llgiWindow_ = new LLGIWindow(glfwWindow_);

	LLGI::PlatformParameter platformParam;
	platformParam.Device = deviceType_;
	platform_ = LLGI::CreatePlatform(platformParam, llgiWindow_);
	graphics_ = platform_->CreateGraphics();
	sfMemoryPool_ = graphics_->CreateSingleFrameMemoryPool(1024 * 1024, 128);
	commandListPool_ = std::make_shared<LLGI::CommandListPool>(graphics_, sfMemoryPool_, 3);
}

void EffectPlatformLLGI::Present()
{
	graphics_->Execute(commandList_.get());
	platform_->Present();
}

bool EffectPlatformLLGI::DoEvent()
{
	if (!platform_->NewFrame())
		return false;

	glfwPollEvents();

	sfMemoryPool_->NewFrame();
	commandList_ = LLGI::CreateSharedPtr(commandListPool_->Get(true));

	return true;
}

void EffectPlatformLLGI::PreDestroyDevice()
{
	graphics_->WaitFinish();

	// Vulkan requires to release before destroy devices
	commandListEfk_.Reset();
	sfMemoryPoolEfk_.Reset();
}

void EffectPlatformLLGI::DestroyDevice()
{
	LLGI::SafeRelease(sfMemoryPool_);
	commandListPool_.reset();
	LLGI::SafeRelease(graphics_);
	LLGI::SafeRelease(platform_);

	ES_SAFE_DELETE(llgiWindow_);

	if (glfwWindow_ != nullptr)
	{
		glfwDestroyWindow(glfwWindow_);
		glfwTerminate();
		glfwWindow_ = nullptr;
	}

	ES_SAFE_RELEASE(renderPass_);
	ES_SAFE_RELEASE(colorBuffer_);
	ES_SAFE_RELEASE(depthBuffer_);
	ES_SAFE_RELEASE(shader_vs_);
	ES_SAFE_RELEASE(shader_ps_);
	ES_SAFE_RELEASE(vb_);
	ES_SAFE_RELEASE(ib_);
	ES_SAFE_RELEASE(rppip_);
	ES_SAFE_RELEASE(pip_);
	ES_SAFE_RELEASE(screenPip_);
	ES_SAFE_RELEASE(checkTexture_);

	commandList_.reset();
}

void EffectPlatformLLGI::BeginRendering()
{
	LLGI::Color8 color;
	color.R = 64;
	color.G = 64;
	color.B = 64;
	color.A = 255;
	renderPass_->SetClearColor(color);
	renderPass_->SetIsColorCleared(true);
	renderPass_->SetIsDepthCleared(true);

	commandList_->Begin();
	commandList_->BeginRenderPass(renderPass_);

	// check
	commandList_->SetVertexBuffer(vb_, sizeof(SimpleVertex), 0);
	commandList_->SetIndexBuffer(ib_, 2);
	commandList_->SetPipelineState(pip_);
	commandList_->SetTexture(
		checkTexture_, LLGI::TextureWrapMode::Repeat, LLGI::TextureMinMagFilter::Nearest, 0, LLGI::ShaderStageType::Pixel);
	commandList_->Draw(2);

	sfMemoryPoolEfk_->NewFrame();
}

void EffectPlatformLLGI::EndRendering()
{
	commandList_->EndRenderPass();

	auto currentScreen = platform_->GetCurrentScreen(LLGI::Color8(), true);

	if (screenPip_ == nullptr)
	{
		auto rpip = graphics_->CreateRenderPassPipelineState(currentScreen);
		screenFormat_ = rpip->Key.RenderTargetFormats.at(0);

		{
			screenPip_ = graphics_->CreatePiplineState();
			screenPip_->VertexLayouts[0] = LLGI::VertexLayoutFormat::R32G32B32_FLOAT;
			screenPip_->VertexLayouts[1] = LLGI::VertexLayoutFormat::R32G32_FLOAT;
			screenPip_->VertexLayouts[2] = LLGI::VertexLayoutFormat::R8G8B8A8_UNORM;
			screenPip_->VertexLayoutNames[0] = "POSITION";
			screenPip_->VertexLayoutNames[1] = "UV";
			screenPip_->VertexLayoutNames[2] = "COLOR";
			screenPip_->VertexLayoutCount = 3;
			screenPip_->IsDepthTestEnabled = false;
			screenPip_->IsDepthWriteEnabled = false;
			screenPip_->Culling = LLGI::CullingMode::DoubleSide;
			screenPip_->SetShader(LLGI::ShaderStageType::Vertex, shader_vs_);
			screenPip_->SetShader(LLGI::ShaderStageType::Pixel, shader_ps_);
			screenPip_->SetRenderPassPipelineState(rpip);
			screenPip_->Compile();
		}

		ES_SAFE_RELEASE(rpip);
	}

	commandList_->BeginRenderPass(currentScreen);
	commandList_->SetVertexBuffer(vb_, sizeof(SimpleVertex), 0);
	commandList_->SetIndexBuffer(ib_, 2);
	commandList_->SetPipelineState(screenPip_);
	commandList_->SetTexture(
		colorBuffer_, LLGI::TextureWrapMode::Repeat, LLGI::TextureMinMagFilter::Nearest, 0, LLGI::ShaderStageType::Pixel);
	commandList_->Draw(2);
	commandList_->EndRenderPass();

	commandList_->End();
}

bool EffectPlatformLLGI::TakeScreenshot(const char* path)
{
	commandList_->WaitUntilCompleted();

	LLGI::Color8 color;
	color.R = 255;
	color.G = 255;
	color.B = 255;
	color.A = 255;

	auto texture = platform_->GetCurrentScreen(color, true)->GetRenderTexture(0);
	auto data = graphics_->CaptureRenderTarget(texture);

	if (screenFormat_ == LLGI::TextureFormatType::B8G8R8A8_UNORM)
	{
		for (size_t i = 0; i < data.size(); i += 4)
		{
			std::swap(data[i + 0], data[i + 2]);
		}
	}

	stbi_write_png(path, initParam_.WindowSize[0], initParam_.WindowSize[1], 4, data.data(), initParam_.WindowSize[0] * 4);

	return true;
}
<commit_msg>Fix a bug where test on DX12 fails<commit_after>#include "EffectPlatformLLGI.h"
#include "../3rdParty/LLGI/src/LLGI.Buffer.h"
#include "../3rdParty/LLGI/src/LLGI.CommandList.h"
#include "../3rdParty/LLGI/src/LLGI.Graphics.h"
#include "../3rdParty/LLGI/src/LLGI.PipelineState.h"
#include "../3rdParty/LLGI/src/LLGI.Platform.h"
#include "../3rdParty/LLGI/src/LLGI.Shader.h"
#include "../3rdParty/LLGI/src/LLGI.Texture.h"

#include "../../3rdParty/stb/stb_image_write.h"

void EffectPlatformLLGI::CreateCheckedTexture()
{
	LLGI::TextureInitializationParameter param;
	param.Size.X = initParam_.WindowSize[0];
	param.Size.Y = initParam_.WindowSize[1];
	checkTexture_ = graphics_->CreateTexture(param);

	auto b = (uint8_t*)checkTexture_->Lock();

	memcpy(b, checkeredPattern_.data(), param.Size.X * param.Size.Y * 4);

	checkTexture_->Unlock();
}

void EffectPlatformLLGI::CreateResources()
{
	CreateShaders();

	LLGI::RenderTextureInitializationParameter renderParam;
	renderParam.Size = LLGI::Vec2I(initParam_.WindowSize[0], initParam_.WindowSize[1]);
	LLGI::DepthTextureInitializationParameter depthParam;
	depthParam.Size = LLGI::Vec2I(initParam_.WindowSize[0], initParam_.WindowSize[1]);
	colorBuffer_ = graphics_->CreateRenderTexture(renderParam);
	depthBuffer_ = graphics_->CreateDepthTexture(depthParam);
	renderPass_ = graphics_->CreateRenderPass((LLGI::Texture**)&colorBuffer_, 1, depthBuffer_);

	vb_ = graphics_->CreateBuffer(LLGI::BufferUsageType::Vertex | LLGI::BufferUsageType::MapWrite, sizeof(SimpleVertex) * 4);
	ib_ = graphics_->CreateBuffer(LLGI::BufferUsageType::Index | LLGI::BufferUsageType::MapWrite, 2 * 6);
	auto vb_buf = (SimpleVertex*)vb_->Lock();
	vb_buf[0].Pos = LLGI::Vec3F(-1.0f, 1.0f, 0.5f);
	vb_buf[1].Pos = LLGI::Vec3F(1.0f, 1.0f, 0.5f);
	vb_buf[2].Pos = LLGI::Vec3F(1.0f, -1.0f, 0.5f);
	vb_buf[3].Pos = LLGI::Vec3F(-1.0f, -1.0f, 0.5f);

	vb_buf[0].UV = LLGI::Vec2F(0.0f, 0.0f);
	vb_buf[1].UV = LLGI::Vec2F(1.0f, 0.0f);
	vb_buf[2].UV = LLGI::Vec2F(1.0f, 1.0f);
	vb_buf[3].UV = LLGI::Vec2F(0.0f, 1.0f);

	vb_buf[0].Color = LLGI::Color8();
	vb_buf[1].Color = LLGI::Color8();
	vb_buf[2].Color = LLGI::Color8();
	vb_buf[3].Color = LLGI::Color8();

	vb_->Unlock();

	auto ib_buf = (uint16_t*)ib_->Lock();
	ib_buf[0] = 0;
	ib_buf[1] = 1;
	ib_buf[2] = 2;
	ib_buf[3] = 0;
	ib_buf[4] = 2;
	ib_buf[5] = 3;
	ib_->Unlock();

	rppip_ = graphics_->CreateRenderPassPipelineState(renderPass_);

	{
		pip_ = graphics_->CreatePiplineState();
		pip_->VertexLayouts[0] = LLGI::VertexLayoutFormat::R32G32B32_FLOAT;
		pip_->VertexLayouts[1] = LLGI::VertexLayoutFormat::R32G32_FLOAT;
		pip_->VertexLayouts[2] = LLGI::VertexLayoutFormat::R8G8B8A8_UNORM;
		pip_->VertexLayoutNames[0] = "POSITION";
		pip_->VertexLayoutNames[1] = "UV";
		pip_->VertexLayoutNames[2] = "COLOR";
		pip_->VertexLayoutCount = 3;
		pip_->IsDepthTestEnabled = false;
		pip_->IsDepthWriteEnabled = false;
		pip_->Culling = LLGI::CullingMode::DoubleSide;
		pip_->SetShader(LLGI::ShaderStageType::Vertex, shader_vs_);
		pip_->SetShader(LLGI::ShaderStageType::Pixel, shader_ps_);
		pip_->SetRenderPassPipelineState(rppip_);
		pip_->Compile();
	}
}

EffectPlatformLLGI::EffectPlatformLLGI(LLGI::DeviceType deviceType)
	: deviceType_(deviceType)
{
}

EffectPlatformLLGI ::~EffectPlatformLLGI()
{
}

void EffectPlatformLLGI::InitializeWindow()
{
	if (!glfwInit())
	{
		throw "Failed to initialize glfw";
	}

	glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);

	glfwWindow_ = glfwCreateWindow(initParam_.WindowSize[0], initParam_.WindowSize[1], "Example glfw", nullptr, nullptr);

	if (glfwWindow_ == nullptr)
	{
		glfwTerminate();
		throw "Failed to create an window.";
	}

	llgiWindow_ = new LLGIWindow(glfwWindow_);

	LLGI::PlatformParameter platformParam;
	platformParam.Device = deviceType_;
	platform_ = LLGI::CreatePlatform(platformParam, llgiWindow_);
	graphics_ = platform_->CreateGraphics();
	sfMemoryPool_ = graphics_->CreateSingleFrameMemoryPool(1024 * 1024, 128);
	commandListPool_ = std::make_shared<LLGI::CommandListPool>(graphics_, sfMemoryPool_, 3);
}

void EffectPlatformLLGI::Present()
{
	graphics_->Execute(commandList_.get());
	platform_->Present();
}

bool EffectPlatformLLGI::DoEvent()
{
	if (!platform_->NewFrame())
		return false;

	glfwPollEvents();

	sfMemoryPool_->NewFrame();
	commandList_ = LLGI::CreateSharedPtr(commandListPool_->Get(true));

	return true;
}

void EffectPlatformLLGI::PreDestroyDevice()
{
	graphics_->WaitFinish();

	// Vulkan requires to release before destroy devices
	commandListEfk_.Reset();
	sfMemoryPoolEfk_.Reset();
}

void EffectPlatformLLGI::DestroyDevice()
{
	LLGI::SafeRelease(sfMemoryPool_);
	commandListPool_.reset();
	LLGI::SafeRelease(graphics_);
	LLGI::SafeRelease(platform_);

	ES_SAFE_DELETE(llgiWindow_);

	if (glfwWindow_ != nullptr)
	{
		glfwDestroyWindow(glfwWindow_);
		glfwTerminate();
		glfwWindow_ = nullptr;
	}

	ES_SAFE_RELEASE(renderPass_);
	ES_SAFE_RELEASE(colorBuffer_);
	ES_SAFE_RELEASE(depthBuffer_);
	ES_SAFE_RELEASE(shader_vs_);
	ES_SAFE_RELEASE(shader_ps_);
	ES_SAFE_RELEASE(vb_);
	ES_SAFE_RELEASE(ib_);
	ES_SAFE_RELEASE(rppip_);
	ES_SAFE_RELEASE(pip_);
	ES_SAFE_RELEASE(screenPip_);
	ES_SAFE_RELEASE(checkTexture_);

	commandList_.reset();
}

void EffectPlatformLLGI::BeginRendering()
{
	LLGI::Color8 color;
	color.R = 64;
	color.G = 64;
	color.B = 64;
	color.A = 255;
	renderPass_->SetClearColor(color);
	renderPass_->SetIsColorCleared(true);
	renderPass_->SetIsDepthCleared(true);

	commandList_->Begin();
	commandList_->BeginRenderPass(renderPass_);

	// check
	commandList_->SetVertexBuffer(vb_, sizeof(SimpleVertex), 0);
	commandList_->SetIndexBuffer(ib_, 2);
	commandList_->SetPipelineState(pip_);
	commandList_->SetTexture(
		checkTexture_, LLGI::TextureWrapMode::Repeat, LLGI::TextureMinMagFilter::Nearest, 0, LLGI::ShaderStageType::Pixel);
	commandList_->Draw(2);

	sfMemoryPoolEfk_->NewFrame();
}

void EffectPlatformLLGI::EndRendering()
{
	commandList_->EndRenderPass();

	auto currentScreen = platform_->GetCurrentScreen(LLGI::Color8(), true);

	if (screenPip_ == nullptr)
	{
		auto rpip = graphics_->CreateRenderPassPipelineState(currentScreen);
		screenFormat_ = rpip->Key.RenderTargetFormats.at(0);

		{
			screenPip_ = graphics_->CreatePiplineState();
			screenPip_->VertexLayouts[0] = LLGI::VertexLayoutFormat::R32G32B32_FLOAT;
			screenPip_->VertexLayouts[1] = LLGI::VertexLayoutFormat::R32G32_FLOAT;
			screenPip_->VertexLayouts[2] = LLGI::VertexLayoutFormat::R8G8B8A8_UNORM;
			screenPip_->VertexLayoutNames[0] = "POSITION";
			screenPip_->VertexLayoutNames[1] = "UV";
			screenPip_->VertexLayoutNames[2] = "COLOR";
			screenPip_->VertexLayoutCount = 3;
			screenPip_->IsDepthTestEnabled = false;
			screenPip_->IsDepthWriteEnabled = false;
			screenPip_->Culling = LLGI::CullingMode::DoubleSide;
			screenPip_->SetShader(LLGI::ShaderStageType::Vertex, shader_vs_);
			screenPip_->SetShader(LLGI::ShaderStageType::Pixel, shader_ps_);
			screenPip_->SetRenderPassPipelineState(rpip);
			screenPip_->Compile();
		}

		ES_SAFE_RELEASE(rpip);
	}

	commandList_->BeginRenderPass(currentScreen);
	commandList_->SetVertexBuffer(vb_, sizeof(SimpleVertex), 0);
	commandList_->SetIndexBuffer(ib_, 2);
	commandList_->SetPipelineState(screenPip_);
	commandList_->SetTexture(
		colorBuffer_, LLGI::TextureWrapMode::Repeat, LLGI::TextureMinMagFilter::Nearest, 0, LLGI::ShaderStageType::Pixel);
	commandList_->Draw(2);
	commandList_->EndRenderPass();

	commandList_->End();
}

bool EffectPlatformLLGI::TakeScreenshot(const char* path)
{
	commandList_->WaitUntilCompleted();

	LLGI::Color8 color;
	color.R = 255;
	color.G = 255;
	color.B = 255;
	color.A = 255;

	auto texture = platform_->GetCurrentScreen(color, true)->GetRenderTexture(0);
	auto data = graphics_->CaptureRenderTarget(texture);

	if (screenFormat_ == LLGI::TextureFormatType::B8G8R8A8_UNORM)
	{
		for (size_t i = 0; i < data.size(); i += 4)
		{
			std::swap(data[i + 0], data[i + 2]);
		}
	}

	stbi_write_png(path, initParam_.WindowSize[0], initParam_.WindowSize[1], 4, data.data(), initParam_.WindowSize[0] * 4);

	return true;
}
<|endoftext|>


<commit_before><commit_msg>add missing initializer<commit_after><|endoftext|>


<commit_before>/*
 * Process.cpp
 *
 * Copyright (C) 2006 by Universitaet Stuttgart (VIS). Alle Rechte vorbehalten.
 */

#include "vislib/Process.h"

#include <cstdarg>

#include "vislib/assert.h"
#include "vislib/Console.h"
#include "vislib/error.h"
#include "vislib/IllegalParamException.h"
#include "vislib/IllegalStateException.h"
#ifdef _WIN32 // TODO: PAM disabled
#include "vislib/ImpersonationContext.h"
#endif // TODO
#include "vislib/Path.h"
#include "vislib/RawStorage.h"
#include "vislib/SystemException.h"
#include "vislib/UnsupportedOperationException.h"

/*
 * vislib::sys::Process::EMPTY_ENVIRONMENT
 */
const vislib::sys::Environment::Snapshot
vislib::sys::Process::EMPTY_ENVIRONMENT;

/*
 * vislib::sys::Process::Process
 */
vislib::sys::Process::Process(void) {
#ifdef _WIN32
    this->hProcess = NULL;
#else /* _WIN32 */
    this->pid = -1;
#endif /* _WIN32 */
}

/*
 * vislib::sys::Process::~Process
 */
vislib::sys::Process::~Process(void) {
    // TODO: Implement
}

/*
 * vislib::sys::Process::Process
 */
vislib::sys::Process::Process(const Process& rhs) {
    throw UnsupportedOperationException("Process", __FILE__, __LINE__);
}

/*
 * vislib::sys::Process::create
 */
void vislib::sys::Process::create(const char *command, const char *arguments[],
        const char *user, const char *domain, const char *password,
        const Environment::Snapshot& environment,
        const char *currentDirectory) {
    ASSERT(command != NULL);

#ifdef _WIN32
    const char **arg = arguments;
    HANDLE hToken = NULL;
    StringA cmdLine("\"");
    cmdLine += command;
    cmdLine += "\"";
    if (arg != NULL) {
        cmdLine += " ";

        while (*arg != NULL) {
            cmdLine += *arg;
            arg++;
        }
    }

    /* A process must not be started twice. */
    if (this->hProcess != NULL) {
        throw IllegalStateException("This process was already created.",
            __FILE__, __LINE__);
    }

    STARTUPINFOA si;
    ::ZeroMemory(&si, sizeof(STARTUPINFOA));
    si.cb = sizeof(STARTUPINFOA);

    PROCESS_INFORMATION pi;
    ::ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));

    if ((user != NULL) && (password != NULL)) {
        if (::LogonUserA(user, domain, password, LOGON32_LOGON_INTERACTIVE,
                LOGON32_PROVIDER_DEFAULT, &hToken) == FALSE) {
            throw SystemException(__FILE__, __LINE__);
        }

        // TODO: hToken has insufficient permissions to spawn process.
        if (::CreateProcessAsUserA(hToken, NULL,
                const_cast<char *>(cmdLine.PeekBuffer()), NULL, NULL, FALSE, 0,
                const_cast<void *>(static_cast<const void *>(environment)),
                currentDirectory, &si, &pi)
                == FALSE) {
            throw SystemException(__FILE__, __LINE__);
        }
    } else {
        if (::CreateProcessA(NULL, const_cast<char *>(cmdLine.PeekBuffer()),
                NULL, NULL, FALSE, 0,
                const_cast<void *>(static_cast<const void *>(environment)),
                currentDirectory, &si, &pi) == FALSE) {
            throw SystemException(__FILE__, __LINE__);
        }
    }

    ::CloseHandle(pi.hThread);
    this->hProcess = pi.hProcess;

#else /* _WIN32 */
   // TODO: PAM disabled
    StringA query;  // Query to which to expand shell commands.
    StringA cmd;    // The command actually run.
    int pipe[2];    // A pipe to get the error code of exec.

    /* A process must not be started twice. */
    if (this->pid >= 0) {
        throw IllegalStateException("This process was already created.",
            __FILE__, __LINE__);
    }

    /* Detect and expand shell commands first first. */
    query.Format("which %s", command);
    if (Console::Run(query.PeekBuffer(), &cmd) == 0) {
        cmd.TrimEnd("\r\n");
    } else {
        cmd = Path::Resolve(command);
    }
    ASSERT(Path::IsAbsolute(cmd));

    /* Open a pipe to get the exec error codes. */
    if (::pipe(pipe) == -1) {
        throw SystemException(__FILE__, __LINE__);
    }

    /* Make the system close the pipe if exec is called successfully. */
    if (::fcntl(pipe[1], F_SETFD, FD_CLOEXEC)) {
        ::close(pipe[0]);
        ::close(pipe[1]);
        throw SystemException(__FILE__, __LINE__);
    }

    /* Create new process. */
    this->pid = ::fork();
    if (this->pid == 0) {
        /* We are in the child process now. */
        ::close(pipe[0]);       // We do not need the read end any more.

        /** Impersonate as new user. */
        if ((user != NULL) && (password != NULL)) {
            //ic.Impersonate(user, NULL, password);
            ASSERT(false);
        }

        /* Change to working directory, if specified. */
        if (currentDirectory != NULL) {
            if (::chdir(currentDirectory) != 0) {
                ::write(pipe[1], &errno, sizeof(errno));
            }
        }

        if (environment.IsEmpty() && (arguments == NULL)) {
            char *tmp[] = { const_cast<char *>(cmd.PeekBuffer()), NULL };
            ::execv(cmd.PeekBuffer(), tmp);
        } else {
            int cntArgs = 1;
            if (arguments != NULL) {
                while (arguments[i] != NULL) {
                    cntArgs++;
                }
            }
            vislib::RawStorage args((cntArgs + 1) * sizeof(char *));
            args.As<char *>()[0] = const_cast<char *>(cmd.PeekBuffer());
            args.As<char *>()[cntArgs] = NULL;
            for (int i = 1; i < cntArgs; i++) {
                args.As<char *>()[i] = arguments[i - 1];
            }

            ::execve(cmd.PeekBuffer(), args, reinterpret_cast<char * const*>(
                static_cast<const void *>((environment)));
        }

        /* exec failed at this point, so report error to parent. */
        ::write(pipe[1], &errno, sizeof(errno));
        ::close(pipe[1]);
        ::_exit(errno);

    } else if (this->pid < 0) {
        /* Process creating failed. */
        ::close(pipe[0]);       // There is no child which could write.
        ::close(pipe[1]);       // We do not need the write end any more.
        throw SystemException(__FILE__, __LINE__);

    } else {
        /* Process was spawned, we are in parent. */
        ASSERT(this->pid > 0);
        ::close(pipe[1]);       // We do not need the write end any more.

        /* Try to read error from child process if e. g. exec failed. */
        if (read(pipe[0], &errno, sizeof(errno)) != -1) {
            /* Child process wrote an error code, so report it. */
            ASSERT(::GetLastError() == errno);  // Exception will use GLE.
            this->pid = -1;
            ::close(pipe[0]);
            throw SystemException(__FILE__, __LINE__);
        } else {
            /* Reading error failed, so the child already closed the pipe. */
            ::close(pipe[0]);
        }
    }
#endif /* _WIN32 */
}

/*
 * vislib::sys::Process::operator =
 */
vislib::sys::Process& vislib::sys::Process::operator =(const Process& rhs) {
    if (this != &rhs) {
        throw IllegalParamException("rhs", __FILE__, __LINE__);
    }

    return *this;
}
<commit_msg>Process gcc issues<commit_after>/*
 * Process.cpp
 *
 * Copyright (C) 2006 by Universitaet Stuttgart (VIS). Alle Rechte vorbehalten.
 */

#include "vislib/Process.h"

#include <cstdarg>

#ifndef _WIN32
#include <fcntl.h>
#endif /* !_WIN32 */

#include "vislib/assert.h"
#include "vislib/Console.h"
#include "vislib/error.h"
#include "vislib/IllegalParamException.h"
#include "vislib/IllegalStateException.h"
#ifdef _WIN32 // TODO: PAM disabled
#include "vislib/ImpersonationContext.h"
#endif // TODO
#include "vislib/Path.h"
#include "vislib/RawStorage.h"
#include "vislib/SystemException.h"
#include "vislib/UnsupportedOperationException.h"

/*
 * vislib::sys::Process::EMPTY_ENVIRONMENT
 */
const vislib::sys::Environment::Snapshot
vislib::sys::Process::EMPTY_ENVIRONMENT;

/*
 * vislib::sys::Process::Process
 */
vislib::sys::Process::Process(void) {
#ifdef _WIN32
    this->hProcess = NULL;
#else /* _WIN32 */
    this->pid = -1;
#endif /* _WIN32 */
}

/*
 * vislib::sys::Process::~Process
 */
vislib::sys::Process::~Process(void) {
    // TODO: Implement
}

/*
 * vislib::sys::Process::Process
 */
vislib::sys::Process::Process(const Process& rhs) {
    throw UnsupportedOperationException("Process", __FILE__, __LINE__);
}

/*
 * vislib::sys::Process::create
 */
void vislib::sys::Process::create(const char *command, const char *arguments[],
        const char *user, const char *domain, const char *password,
        const Environment::Snapshot& environment,
        const char *currentDirectory) {
    ASSERT(command != NULL);

#ifdef _WIN32
    const char **arg = arguments;
    HANDLE hToken = NULL;
    StringA cmdLine("\"");
    cmdLine += command;
    cmdLine += "\"";
    if (arg != NULL) {
        cmdLine += " ";

        while (*arg != NULL) {
            cmdLine += *arg;
            arg++;
        }
    }

    /* A process must not be started twice. */
    if (this->hProcess != NULL) {
        throw IllegalStateException("This process was already created.",
            __FILE__, __LINE__);
    }

    STARTUPINFOA si;
    ::ZeroMemory(&si, sizeof(STARTUPINFOA));
    si.cb = sizeof(STARTUPINFOA);

    PROCESS_INFORMATION pi;
    ::ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));

    if ((user != NULL) && (password != NULL)) {
        if (::LogonUserA(user, domain, password, LOGON32_LOGON_INTERACTIVE,
                LOGON32_PROVIDER_DEFAULT, &hToken) == FALSE) {
            throw SystemException(__FILE__, __LINE__);
        }

        // TODO: hToken has insufficient permissions to spawn process.
        if (::CreateProcessAsUserA(hToken, NULL,
                const_cast<char *>(cmdLine.PeekBuffer()), NULL, NULL, FALSE, 0,
                const_cast<void *>(static_cast<const void *>(environment)),
                currentDirectory, &si, &pi)
                == FALSE) {
            throw SystemException(__FILE__, __LINE__);
        }
    } else {
        if (::CreateProcessA(NULL, const_cast<char *>(cmdLine.PeekBuffer()),
                NULL, NULL, FALSE, 0,
                const_cast<void *>(static_cast<const void *>(environment)),
                currentDirectory, &si, &pi) == FALSE) {
            throw SystemException(__FILE__, __LINE__);
        }
    }

    ::CloseHandle(pi.hThread);
    this->hProcess = pi.hProcess;

#else /* _WIN32 */
   // TODO: PAM disabled
    StringA query;  // Query to which to expand shell commands.
    StringA cmd;    // The command actually run.
    int pipe[2];    // A pipe to get the error code of exec.

    /* A process must not be started twice. */
    if (this->pid >= 0) {
        throw IllegalStateException("This process was already created.",
            __FILE__, __LINE__);
    }

    /* Detect and expand shell commands first first. */
    query.Format("which %s", command);
    if (Console::Run(query.PeekBuffer(), &cmd) == 0) {
        cmd.TrimEnd("\r\n");
    } else {
        cmd = Path::Resolve(command);
    }
    ASSERT(Path::IsAbsolute(cmd));

    /* Open a pipe to get the exec error codes. */
    if (::pipe(pipe) == -1) {
        throw SystemException(__FILE__, __LINE__);
    }

    /* Make the system close the pipe if exec is called successfully. */
    if (::fcntl(pipe[1], F_SETFD, FD_CLOEXEC)) {
        ::close(pipe[0]);
        ::close(pipe[1]);
        throw SystemException(__FILE__, __LINE__);
    }

    /* Create new process. */
    this->pid = ::fork();
    if (this->pid == 0) {
        /* We are in the child process now. */
        ::close(pipe[0]);       // We do not need the read end any more.

        /** Impersonate as new user. */
        if ((user != NULL) && (password != NULL)) {
            //ic.Impersonate(user, NULL, password);
            ASSERT(false);
        }

        /* Change to working directory, if specified. */
        if (currentDirectory != NULL) {
            if (::chdir(currentDirectory) != 0) {
                ::write(pipe[1], &errno, sizeof(errno));
            }
        }

        if (environment.IsEmpty() && (arguments == NULL)) {
            char *tmp[] = { const_cast<char *>(cmd.PeekBuffer()), NULL };
            ::execv(cmd.PeekBuffer(), tmp);
        } else {
            int cntArgs = 1;
            if (arguments != NULL) {
                for (int i = 0; (arguments[i] != NULL); i++) {
                    cntArgs++;
                }
            }
            vislib::RawStorage args((cntArgs + 1) * sizeof(char *));
            args.As<char *>()[0] = const_cast<char *>(cmd.PeekBuffer());
            args.As<char *>()[cntArgs] = NULL;
            for (int i = 1; i < cntArgs; i++) {
                args.As<char *>()[i] = const_cast<char *>(arguments[i - 1]);
            }

            ::execve(cmd.PeekBuffer(), args.As<char *>(),
		reinterpret_cast<char **>(
		const_cast<void *>(static_cast<const void *>(environment))));
        }

        /* exec failed at this point, so report error to parent. */
        ::write(pipe[1], &errno, sizeof(errno));
        ::close(pipe[1]);
        ::_exit(errno);

    } else if (this->pid < 0) {
        /* Process creating failed. */
        ::close(pipe[0]);       // There is no child which could write.
        ::close(pipe[1]);       // We do not need the write end any more.
        throw SystemException(__FILE__, __LINE__);

    } else {
        /* Process was spawned, we are in parent. */
        ASSERT(this->pid > 0);
        ::close(pipe[1]);       // We do not need the write end any more.

        /* Try to read error from child process if e. g. exec failed. */
        if (read(pipe[0], &errno, sizeof(errno)) != -1) {
            /* Child process wrote an error code, so report it. */
            // SystemException will use GetLastError, ensure correct code.
            ASSERT(static_cast<int>(::GetLastError()) == errno);
            this->pid = -1;
            ::close(pipe[0]);
            throw SystemException(__FILE__, __LINE__);
        } else {
            /* Reading error failed, so the child already closed the pipe. */
            ::close(pipe[0]);
        }
    }
#endif /* _WIN32 */
}

/*
 * vislib::sys::Process::operator =
 */
vislib::sys::Process& vislib::sys::Process::operator =(const Process& rhs) {
    if (this != &rhs) {
        throw IllegalParamException("rhs", __FILE__, __LINE__);
    }

    return *this;
}
<|endoftext|>


<commit_before>
// Copyright 2010-2012 University of Washington. All Rights Reserved.
// LICENSE_PLACEHOLDER
// This software was created with Government support under DE
// AC05-76RL01830 awarded by the United States Department of
// Energy. The Government has certain rights in the software.

#ifndef __DELEGATE_HPP__
#define __DELEGATE_HPP__

#include "Grappa.hpp"
#include "Message.hpp"
#include "FullEmpty.hpp"
#include "Message.hpp"
#include "ConditionVariable.hpp"
#include "LegacyDelegate.hpp"
#include "MessagePool.hpp"
#include <type_traits>

GRAPPA_DECLARE_STAT(SummarizingStatistic<uint64_t>, flat_combiner_fetch_and_add_amount);
GRAPPA_DECLARE_STAT(SimpleStatistic<uint64_t>, delegate_ops_short_circuited);

GRAPPA_DECLARE_STAT(SummarizingStatistic<double>, delegate_op_roundtrip_latency);

namespace Grappa {
  namespace delegate {
    /// @addtogroup Delegates
    /// @{

    /// Overloaded version for func with void return type.
    template <typename F>
    inline auto call(Core dest, F func)
        -> typename std::enable_if<std::is_void<decltype(func())>::value, void>::type {
      delegate_stats.count_op();
      Core origin = Grappa::mycore();

      if (dest == origin) {
        // short-circuit if local
        delegate_ops_short_circuited++;
        return func();
      } else {
        int64_t network_time = 0;
        int64_t start_time = Grappa_get_timestamp();
        FullEmpty<bool> result;
        send_message(dest, [&result, origin, func, &network_time, start_time] {
          delegate_stats.count_op_am();

          func();

          // TODO: replace with handler-safe send_message
          send_heap_message(origin, [&result, &network_time, start_time] {
            network_time = Grappa_get_timestamp();
            delegate_stats.record_network_latency(start_time);
            result.writeXF(true);
          });
        }); // send message

        // ... and wait for the call to complete
        result.readFF();
        delegate_stats.record_wakeup_latency(start_time, network_time);
        return;
      }
    }

    /// Implements essentially a blocking remote procedure call. Callable object (lambda,
    /// function pointer, or functor object) is called from the `dest` core and the return
    /// value is sent back to the calling task.
    template <typename F>
    inline auto call(Core dest, F func)
      -> typename std::enable_if<!std::is_void<decltype(func())>::value, decltype(func())>::type {
      // Note: code below (calling call_async) could be used to avoid duplication of code,
      // but call_async adds some overhead (object creation overhead, especially for short
      // -circuit case and extra work in MessagePool)
      //   AsyncHandle<decltype(func())> a;
      //   MessagePool<sizeof(Message<F>)> pool;
      //   a.call_async(pool, dest, func);
      //   return a.get_result();
      // TODO: find a way to implement using async version that doesn't introduce overhead

      delegate_stats.count_op();
      using R = decltype(func());
      Core origin = Grappa::mycore();

      if (dest == origin) {
        // short-circuit if local
        delegate_ops_short_circuited++;
        return func();
      } else {
        FullEmpty<R> result;
        int64_t network_time = 0;
        int64_t start_time = Grappa_get_timestamp();

        send_message(dest, [&result, origin, func, &network_time, start_time] {
          delegate_stats.count_op_am();
          R val = func();

          // TODO: replace with handler-safe send_message
          send_heap_message(origin, [&result, val, &network_time, start_time] {
            network_time = Grappa_get_timestamp();
            delegate_stats.record_network_latency(start_time);
            result.writeXF(val); // can't block in message, assumption is that result is already empty
          });
        }); // send message
        // ... and wait for the result
        R r = result.readFE();
        delegate_stats.record_wakeup_latency(start_time, network_time);
        return r;
      }
    }

    template< typename T, typename F >
    inline auto call(GlobalAddress<T> target, F func) -> decltype(func()) {
      return call(target.core(), [target,func]{ return func(target.pointer()); });
    }

    /// Read the value (potentially remote) at the given GlobalAddress, blocks the calling task until
    /// round-trip communication is complete.
    /// @warning Target object must lie on a single node (not span blocks in global address space).
    template< typename T >
    T read(GlobalAddress<T> target) {
      delegate_stats.count_word_read();
      return call(target.node(), [target]() -> T {
        delegate_stats.count_word_read_am();
        return *target.pointer();
      });
    }

    /// Blocking remote write.
    /// @warning Target object must lie on a single node (not span blocks in global address space).
    template< typename T, typename U >
    void write(GlobalAddress<T> target, U value) {
      delegate_stats.count_word_write();
      // TODO: don't return any val, requires changes to `delegate::call()`.
      return call(target.node(), [target, value] {
        delegate_stats.count_word_write_am();
        *target.pointer() = value;
      });
    }

    /// Fetch the value at `target`, increment the value stored there with `inc` and return the
    /// original value to blocking thread.
    /// @warning Target object must lie on a single node (not span blocks in global address space).
    template< typename T, typename U >
    T fetch_and_add(GlobalAddress<T> target, U inc) {
      delegate_stats.count_word_fetch_add();
      return call(target.node(), [target, inc]() -> T {
        delegate_stats.count_word_fetch_add_am();
        T* p = target.pointer();
        T r = *p;
        *p += inc;
        return r;
      });
    }

    /// Flat combines fetch_and_add to a single global address
    /// @warning Target object must lie on a single node (not span blocks in global address space).
    template < typename T, typename U >
    class FlatCombiner {
      // TODO: generalize to define other types of combiners
      private:
        // configuration
        const GlobalAddress<T> target;
        const U initVal;
        const uint64_t flush_threshold;

        // state
        T result;
        U increment;
        uint64_t committed;
        uint64_t participant_count;
        uint64_t ready_waiters;
        bool outstanding;
        ConditionVariable untilNotOutstanding;
        ConditionVariable untilReceived;

        // wait until fetch add unit is in aggregate mode
        // TODO: add concurrency (multiple fetch add units)
        void block_until_ready() {
          while ( outstanding ) {
            ready_waiters++;
            Grappa::wait(&untilNotOutstanding);
            ready_waiters--;
          }
        }

        void set_ready() {
          outstanding = false;
          Grappa::broadcast(&untilNotOutstanding);
        }

        void set_not_ready() {
          outstanding = true;
        }

      public:
        FlatCombiner( GlobalAddress<T> target, uint64_t flush_threshold, U initVal )
         : target( target )
         , initVal( initVal )
         , flush_threshold( flush_threshold )
         , result()
         , increment( initVal )
         , committed( 0 )
         , participant_count( 0 )
         , ready_waiters( 0 )
         , outstanding( false )
         , untilNotOutstanding()
         , untilReceived()
         {}

        /// Promise that in the future
        /// you will call `fetch_and_add`.
        ///
        /// Must be called before a call to `fetch_and_add`
        ///
        /// After calling promise, this task must NOT have a dependence on any
        /// `fetch_and_add` occurring before it calls `fetch_and_add` itself
        /// or deadlock may occur.
        ///
        /// For good performance, should allow other
        /// tasks to run before calling `fetch_and_add`
        void promise() {
          committed += 1;
        }
        // because tasks run serially, promise() replaces the flat combining tree

        T fetch_and_add( U inc ) {

          block_until_ready();

          // fetch add unit is now aggregating so add my inc

          participant_count++;
          committed--;
          increment += inc;

          // if I'm the last entered client and either the flush threshold
          // is reached or there are no more committed participants then start the flush
          if ( ready_waiters == 0 && (participant_count >= flush_threshold || committed == 0 )) {
            set_not_ready();
            uint64_t increment_total = increment;
            flat_combiner_fetch_and_add_amount += increment_total;
            auto t = target;
            result = call(target.node(), [t, increment_total]() -> U {
              T * p = t.pointer();
              uint64_t r = *p;
              *p += increment_total;
              return r;
            });
            // tell the others that the result has arrived
            Grappa::broadcast(&untilReceived);
          } else {
            // someone else will start the flush
            Grappa::wait(&untilReceived);
          }

          uint64_t my_start = result;
          result += inc;
          participant_count--;
          increment -= inc;   // for validation purposes (could just set to 0)
          CHECK( increment >= 0 );
          if ( participant_count == 0 ) {
            CHECK( increment == 0 ) << "increment = " << increment << " even though all participants are done";
            set_ready();
          }

          return my_start;
        }
    };

    /// If value at `target` equals `cmp_val`, set the value to `new_val` and return `true`,
    /// otherwise do nothing and return `false`.
    /// @warning Target object must lie on a single node (not span blocks in global address space).
    template< typename T, typename U, typename V >
    bool compare_and_swap(GlobalAddress<T> target, U cmp_val, V new_val) {
      delegate_stats.count_word_compare_swap();
      return call(target.node(), [target, cmp_val, new_val]() -> bool {
        T * p = target.pointer();
        delegate_stats.count_word_compare_swap_am();
        if (cmp_val == *p) {
          *p = new_val;
          return true;
        } else {
          return false;
        }
      });
    }

    /// @}
  } // namespace delegate
} // namespace Grappa

#endif
<commit_msg>Refactor delegate::call to use new lambda-specialization technique<commit_after>
// Copyright 2010-2012 University of Washington. All Rights Reserved.
// LICENSE_PLACEHOLDER
// This software was created with Government support under DE
// AC05-76RL01830 awarded by the United States Department of
// Energy. The Government has certain rights in the software.

#ifndef __DELEGATE_HPP__
#define __DELEGATE_HPP__

#include "Grappa.hpp"
#include "Message.hpp"
#include "FullEmpty.hpp"
#include "Message.hpp"
#include "ConditionVariable.hpp"
#include "LegacyDelegate.hpp"
#include "MessagePool.hpp"
#include <type_traits>

GRAPPA_DECLARE_STAT(SummarizingStatistic<uint64_t>, flat_combiner_fetch_and_add_amount);
GRAPPA_DECLARE_STAT(SimpleStatistic<uint64_t>, delegate_ops_short_circuited);

GRAPPA_DECLARE_STAT(SummarizingStatistic<double>, delegate_op_roundtrip_latency);

namespace Grappa {
    /// @addtogroup Delegates
    /// @{

  namespace impl {

    /// Overloaded version for func with void return type.
    template <typename F>
    inline void call(Core dest, F func, void (F::*mf)() const) {
      delegate_stats.count_op();
      Core origin = Grappa::mycore();

      if (dest == origin) {
        // short-circuit if local
        delegate_ops_short_circuited++;
        return func();
      } else {
        int64_t network_time = 0;
        int64_t start_time = Grappa_get_timestamp();
        FullEmpty<bool> result;
        send_message(dest, [&result, origin, func, &network_time, start_time] {
          delegate_stats.count_op_am();

          func();

          // TODO: replace with handler-safe send_message
          send_heap_message(origin, [&result, &network_time, start_time] {
            network_time = Grappa_get_timestamp();
            delegate_stats.record_network_latency(start_time);
            result.writeXF(true);
          });
        }); // send message

        // ... and wait for the call to complete
        result.readFF();
        delegate_stats.record_wakeup_latency(start_time, network_time);
        return;
      }
    }

    /// Implements essentially a blocking remote procedure call. Callable object (lambda,
    /// function pointer, or functor object) is called from the `dest` core and the return
    /// value is sent back to the calling task.
    template <typename F>
    inline auto call(Core dest, F func, decltype(func()) (F::*mf)() const) -> decltype(func()) {
      // -> typename std::enable_if<!std::is_void<decltype(func())>::value, decltype(func())>::type {
      // Note: code below (calling call_async) could be used to avoid duplication of code,
      // but call_async adds some overhead (object creation overhead, especially for short
      // -circuit case and extra work in MessagePool)
      //   AsyncHandle<decltype(func())> a;
      //   MessagePool<sizeof(Message<F>)> pool;
      //   a.call_async(pool, dest, func);
      //   return a.get_result();
      // TODO: find a way to implement using async version that doesn't introduce overhead

      delegate_stats.count_op();
      using R = decltype(func());
      Core origin = Grappa::mycore();

      if (dest == origin) {
        // short-circuit if local
        delegate_ops_short_circuited++;
        return func();
      } else {
        FullEmpty<R> result;
        int64_t network_time = 0;
        int64_t start_time = Grappa_get_timestamp();

        send_message(dest, [&result, origin, func, &network_time, start_time] {
          delegate_stats.count_op_am();
          R val = func();

          // TODO: replace with handler-safe send_message
          send_heap_message(origin, [&result, val, &network_time, start_time] {
            network_time = Grappa_get_timestamp();
            delegate_stats.record_network_latency(start_time);
            result.writeXF(val); // can't block in message, assumption is that result is already empty
          });
        }); // send message
        // ... and wait for the result
        R r = result.readFE();
        delegate_stats.record_wakeup_latency(start_time, network_time);
        return r;
      }
    }

  } // namespace impl

  namespace delegate {

    template <typename F>
    inline auto call(Core dest, F func) -> decltype(func()) {
      return impl::call(dest, func, &F::operator());
    }

    template< typename T, typename F >
    inline auto call(GlobalAddress<T> target, F func) -> decltype(func()) {
      return call(target.core(), [target,func]{ return func(target.pointer()); });
    }

    /// Read the value (potentially remote) at the given GlobalAddress, blocks the calling task until
    /// round-trip communication is complete.
    /// @warning Target object must lie on a single node (not span blocks in global address space).
    template< typename T >
    T read(GlobalAddress<T> target) {
      delegate_stats.count_word_read();
      return call(target.node(), [target]() -> T {
        delegate_stats.count_word_read_am();
        return *target.pointer();
      });
    }

    /// Blocking remote write.
    /// @warning Target object must lie on a single node (not span blocks in global address space).
    template< typename T, typename U >
    void write(GlobalAddress<T> target, U value) {
      delegate_stats.count_word_write();
      // TODO: don't return any val, requires changes to `delegate::call()`.
      return call(target.node(), [target, value] {
        delegate_stats.count_word_write_am();
        *target.pointer() = value;
      });
    }

    /// Fetch the value at `target`, increment the value stored there with `inc` and return the
    /// original value to blocking thread.
    /// @warning Target object must lie on a single node (not span blocks in global address space).
    template< typename T, typename U >
    T fetch_and_add(GlobalAddress<T> target, U inc) {
      delegate_stats.count_word_fetch_add();
      return call(target.node(), [target, inc]() -> T {
        delegate_stats.count_word_fetch_add_am();
        T* p = target.pointer();
        T r = *p;
        *p += inc;
        return r;
      });
    }

    /// Flat combines fetch_and_add to a single global address
    /// @warning Target object must lie on a single node (not span blocks in global address space).
    template < typename T, typename U >
    class FlatCombiner {
      // TODO: generalize to define other types of combiners
      private:
        // configuration
        const GlobalAddress<T> target;
        const U initVal;
        const uint64_t flush_threshold;

        // state
        T result;
        U increment;
        uint64_t committed;
        uint64_t participant_count;
        uint64_t ready_waiters;
        bool outstanding;
        ConditionVariable untilNotOutstanding;
        ConditionVariable untilReceived;

        // wait until fetch add unit is in aggregate mode
        // TODO: add concurrency (multiple fetch add units)
        void block_until_ready() {
          while ( outstanding ) {
            ready_waiters++;
            Grappa::wait(&untilNotOutstanding);
            ready_waiters--;
          }
        }

        void set_ready() {
          outstanding = false;
          Grappa::broadcast(&untilNotOutstanding);
        }

        void set_not_ready() {
          outstanding = true;
        }

      public:
        FlatCombiner( GlobalAddress<T> target, uint64_t flush_threshold, U initVal )
         : target( target )
         , initVal( initVal )
         , flush_threshold( flush_threshold )
         , result()
         , increment( initVal )
         , committed( 0 )
         , participant_count( 0 )
         , ready_waiters( 0 )
         , outstanding( false )
         , untilNotOutstanding()
         , untilReceived()
         {}

        /// Promise that in the future
        /// you will call `fetch_and_add`.
        ///
        /// Must be called before a call to `fetch_and_add`
        ///
        /// After calling promise, this task must NOT have a dependence on any
        /// `fetch_and_add` occurring before it calls `fetch_and_add` itself
        /// or deadlock may occur.
        ///
        /// For good performance, should allow other
        /// tasks to run before calling `fetch_and_add`
        void promise() {
          committed += 1;
        }
        // because tasks run serially, promise() replaces the flat combining tree

        T fetch_and_add( U inc ) {

          block_until_ready();

          // fetch add unit is now aggregating so add my inc

          participant_count++;
          committed--;
          increment += inc;

          // if I'm the last entered client and either the flush threshold
          // is reached or there are no more committed participants then start the flush
          if ( ready_waiters == 0 && (participant_count >= flush_threshold || committed == 0 )) {
            set_not_ready();
            uint64_t increment_total = increment;
            flat_combiner_fetch_and_add_amount += increment_total;
            auto t = target;
            result = call(target.node(), [t, increment_total]() -> U {
              T * p = t.pointer();
              uint64_t r = *p;
              *p += increment_total;
              return r;
            });
            // tell the others that the result has arrived
            Grappa::broadcast(&untilReceived);
          } else {
            // someone else will start the flush
            Grappa::wait(&untilReceived);
          }

          uint64_t my_start = result;
          result += inc;
          participant_count--;
          increment -= inc;   // for validation purposes (could just set to 0)
          CHECK( increment >= 0 );
          if ( participant_count == 0 ) {
            CHECK( increment == 0 ) << "increment = " << increment << " even though all participants are done";
            set_ready();
          }

          return my_start;
        }
    };

    /// If value at `target` equals `cmp_val`, set the value to `new_val` and return `true`,
    /// otherwise do nothing and return `false`.
    /// @warning Target object must lie on a single node (not span blocks in global address space).
    template< typename T, typename U, typename V >
    bool compare_and_swap(GlobalAddress<T> target, U cmp_val, V new_val) {
      delegate_stats.count_word_compare_swap();
      return call(target.node(), [target, cmp_val, new_val]() -> bool {
        T * p = target.pointer();
        delegate_stats.count_word_compare_swap_am();
        if (cmp_val == *p) {
          *p = new_val;
          return true;
        } else {
          return false;
        }
      });
    }

    /// @}
  } // namespace delegate
} // namespace Grappa

#endif
<|endoftext|>


<commit_before>#include "device.h"

device::device( QWidget *parent)//shared_ptr<ofApp> _ofAppPtr,
	: QWidget(parent)
{
	ui.setupUi(this);

	// here we create a ofapp with an ofQtWindow
	// then we extract a pointer to QOpenGLWidget
	// and we insert it in the layout.
	ofSetLogLevel(OF_LOG_VERBOSE);
	ofLogToConsole();

	// create an app and a window and initialize
	// ofLoop is not used, Qt will call events
	ofAppPtr = make_shared<ofApp>();
	windowPtr = make_shared<ofAppQtWindow>(this->parentWidget());
	ofAppPtr->window = windowPtr;
	ofSetupOpenGL(windowPtr, 400, 400, OF_WINDOW);
	ofRunApp(windowPtr, ofAppPtr);

	// add widget to layout
	layout = ui.horizontalLayout;
	layout->addWidget(windowPtr->getQOpenGLWidget());
	ui.widget_2->setLayout(layout);
}

device::~device()
{
	// tell the ofMainLoop that this window has to close.
	ofGetMainLoop()->removeWindow(windowPtr);
}

void device::on_Size_slider_sliderMoved(int value) {
	ofAppPtr->radius.set(value);
}<commit_msg>ofRunApp must be after creating setLayout<commit_after>#include "device.h"

device::device( QWidget *parent)//shared_ptr<ofApp> _ofAppPtr,
	: QWidget(parent)
{
	ui.setupUi(this);

	// here we create a ofapp with an ofQtWindow
	// then we extract a pointer to QOpenGLWidget
	// and we insert it in the layout.
//	ofSetLogLevel(OF_LOG_VERBOSE);
//	ofLogToConsole();

	// create an app and a window and initialize
	// ofLoop is not used, Qt will call events
	ofAppPtr = make_shared<ofApp>();
	windowPtr = make_shared<ofAppQtWindow>(this->parentWidget());
	windowPtr->setAppPtr(ofAppPtr);
	ofAppPtr->window = windowPtr;
	ofSetupOpenGL(windowPtr, 400, 400, OF_WINDOW);

	// add widget to layout
	layout = ui.horizontalLayout;
	layout->addWidget(windowPtr->getQOpenGLWidget());
	ui.widget_2->setLayout(layout);

	// initialize OF must be here!
	ofRunApp(windowPtr, ofAppPtr);
}

device::~device()
{
	// tell the ofMainLoop that this window has to close.
	ofAppPtr = nullptr; // this removes warnings on console
	ofGetMainLoop()->removeWindow(windowPtr);
}

void device::on_Size_slider_sliderMoved(int value) {
	ofAppPtr->radius.set(value);
}<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_LOCALFUNCTIONAL_CODIM0_HH
#define DUNE_GDT_LOCALFUNCTIONAL_CODIM0_HH

#include <vector>
#include <utility>
#include <type_traits>
#include <limits>

#include <dune/stuff/common/disable_warnings.hh>
#include <dune/common/dynmatrix.hh>

#include <dune/geometry/quadraturerules.hh>
#include <dune/stuff/common/reenable_warnings.hh>

#include <dune/stuff/functions/interfaces.hh>

#include "../localevaluation/interface.hh"
#include "interface.hh"

namespace Dune {
namespace GDT {
namespace LocalFunctional {

// forward, to be used in the traits
template <class UnaryEvaluationImp>
class Codim0Integral;

template <class UnaryEvaluationImp>
class Codim0IntegralTraits
{
  static_assert(std::is_base_of<LocalEvaluation::Codim0Interface<typename UnaryEvaluationImp::Traits, 1>,
                                UnaryEvaluationImp>::value,
                "UnaryEvaluationImp has to be derived from LocalEvaluation::Codim0Interface< ..., 1 >!");

public:
  typedef Codim0Integral<UnaryEvaluationImp> derived_type;
  typedef LocalEvaluation::Codim0Interface<typename UnaryEvaluationImp::Traits, 1> UnaryEvaluationType;
};

template <class UnaryEvaluationImp>
class Codim0Integral : public LocalFunctional::Codim0Interface<Codim0IntegralTraits<UnaryEvaluationImp>>
{
public:
  typedef Codim0IntegralTraits<UnaryEvaluationImp> Traits;
  typedef typename Traits::UnaryEvaluationType UnaryEvaluationType;

private:
  static const size_t numTmpObjectsRequired_ = 1;

public:
  template <class... Args>
  explicit Codim0Integral(Args&&... args)
    : evaluation_(std::forward<Args>(args)...)
  {
  }

  Codim0Integral(const UnaryEvaluationImp eval)
    : evaluation_(eval)
  {
  }

  size_t numTmpObjectsRequired() const
  {
    return numTmpObjectsRequired_;
  }

  /**
   *  \brief      Applies the local functional.
   *  \tparam T   Traits of the BaseFunctionSetInterface implementation, representing the type of the testBase
   *  \attention  ret is assumed to be zero!
   */
  template <class E, class D, int d, class R, int r, int rC>
  void apply(const Stuff::LocalfunctionSetInterface<E, D, d, R, r, rC>& testBase, Dune::DynamicVector<R>& ret,
             std::vector<Dune::DynamicVector<R>>& tmpLocalVectors) const
  {
    // local inducing function
    const auto& entity        = testBase.entity();
    const auto localFunctions = evaluation_.localFunctions(entity);
    // quadrature
    typedef Dune::QuadratureRules<D, d> VolumeQuadratureRules;
    typedef Dune::QuadratureRule<D, d> VolumeQuadratureType;
    const size_t integrand_order = evaluation().order(localFunctions, testBase);
    assert(integrand_order < std::numeric_limits<int>::max());
    const VolumeQuadratureType& volumeQuadrature = VolumeQuadratureRules::rule(entity.type(), int(integrand_order));
    // check vector and tmp storage
    ret *= 0.0;
    const size_t size = testBase.size();
    assert(ret.size() >= size);
    assert(tmpLocalVectors.size() >= numTmpObjectsRequired_);
    Dune::DynamicVector<R>& localVector = tmpLocalVectors[0];
    // loop over all quadrature points
    const auto quadPointEndIt = volumeQuadrature.end();
    for (auto quadPointIt = volumeQuadrature.begin(); quadPointIt != quadPointEndIt; ++quadPointIt) {
      const Dune::FieldVector<D, d> x = quadPointIt->position();
      // integration factors
      const double integrationFactor = entity.geometry().integrationElement(x);
      const double quadratureWeight  = quadPointIt->weight();
      // evaluate the local operation
      evaluation().evaluate(localFunctions, testBase, x, localVector);
      // compute integral
      for (size_t ii = 0; ii < size; ++ii) {
        ret[ii] += localVector[ii] * integrationFactor * quadratureWeight;
      } // compute integral
    } // loop over all quadrature points
  } // ... apply(...)

private:
  const UnaryEvaluationType& evaluation() const
  {
    return evaluation_;
  }

  const UnaryEvaluationImp evaluation_;
}; // class Codim0Integral

} // namespace LocalFunctional
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_LOCALFUNCTIONAL_CODIM0_HH
<commit_msg>[localfunctional.codim0] do not guard dune includes<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_LOCALFUNCTIONAL_CODIM0_HH
#define DUNE_GDT_LOCALFUNCTIONAL_CODIM0_HH

#include <vector>
#include <utility>
#include <type_traits>
#include <limits>

#include <dune/common/dynmatrix.hh>

#include <dune/geometry/quadraturerules.hh>

#include <dune/stuff/functions/interfaces.hh>

#include "../localevaluation/interface.hh"
#include "interface.hh"

namespace Dune {
namespace GDT {
namespace LocalFunctional {

// forward, to be used in the traits
template <class UnaryEvaluationImp>
class Codim0Integral;

template <class UnaryEvaluationImp>
class Codim0IntegralTraits
{
  static_assert(std::is_base_of<LocalEvaluation::Codim0Interface<typename UnaryEvaluationImp::Traits, 1>,
                                UnaryEvaluationImp>::value,
                "UnaryEvaluationImp has to be derived from LocalEvaluation::Codim0Interface< ..., 1 >!");

public:
  typedef Codim0Integral<UnaryEvaluationImp> derived_type;
  typedef LocalEvaluation::Codim0Interface<typename UnaryEvaluationImp::Traits, 1> UnaryEvaluationType;
};

template <class UnaryEvaluationImp>
class Codim0Integral : public LocalFunctional::Codim0Interface<Codim0IntegralTraits<UnaryEvaluationImp>>
{
public:
  typedef Codim0IntegralTraits<UnaryEvaluationImp> Traits;
  typedef typename Traits::UnaryEvaluationType UnaryEvaluationType;

private:
  static const size_t numTmpObjectsRequired_ = 1;

public:
  template <class... Args>
  explicit Codim0Integral(Args&&... args)
    : evaluation_(std::forward<Args>(args)...)
  {
  }

  Codim0Integral(const UnaryEvaluationImp eval)
    : evaluation_(eval)
  {
  }

  size_t numTmpObjectsRequired() const
  {
    return numTmpObjectsRequired_;
  }

  /**
   *  \brief      Applies the local functional.
   *  \tparam T   Traits of the BaseFunctionSetInterface implementation, representing the type of the testBase
   *  \attention  ret is assumed to be zero!
   */
  template <class E, class D, int d, class R, int r, int rC>
  void apply(const Stuff::LocalfunctionSetInterface<E, D, d, R, r, rC>& testBase, Dune::DynamicVector<R>& ret,
             std::vector<Dune::DynamicVector<R>>& tmpLocalVectors) const
  {
    // local inducing function
    const auto& entity        = testBase.entity();
    const auto localFunctions = evaluation_.localFunctions(entity);
    // quadrature
    typedef Dune::QuadratureRules<D, d> VolumeQuadratureRules;
    typedef Dune::QuadratureRule<D, d> VolumeQuadratureType;
    const size_t integrand_order = evaluation().order(localFunctions, testBase);
    assert(integrand_order < std::numeric_limits<int>::max());
    const VolumeQuadratureType& volumeQuadrature = VolumeQuadratureRules::rule(entity.type(), int(integrand_order));
    // check vector and tmp storage
    ret *= 0.0;
    const size_t size = testBase.size();
    assert(ret.size() >= size);
    assert(tmpLocalVectors.size() >= numTmpObjectsRequired_);
    Dune::DynamicVector<R>& localVector = tmpLocalVectors[0];
    // loop over all quadrature points
    const auto quadPointEndIt = volumeQuadrature.end();
    for (auto quadPointIt = volumeQuadrature.begin(); quadPointIt != quadPointEndIt; ++quadPointIt) {
      const Dune::FieldVector<D, d> x = quadPointIt->position();
      // integration factors
      const double integrationFactor = entity.geometry().integrationElement(x);
      const double quadratureWeight  = quadPointIt->weight();
      // evaluate the local operation
      evaluation().evaluate(localFunctions, testBase, x, localVector);
      // compute integral
      for (size_t ii = 0; ii < size; ++ii) {
        ret[ii] += localVector[ii] * integrationFactor * quadratureWeight;
      } // compute integral
    } // loop over all quadrature points
  } // ... apply(...)

private:
  const UnaryEvaluationType& evaluation() const
  {
    return evaluation_;
  }

  const UnaryEvaluationImp evaluation_;
}; // class Codim0Integral

} // namespace LocalFunctional
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_LOCALFUNCTIONAL_CODIM0_HH
<|endoftext|>


<commit_before>// This file is part of the dune-stuff project:
//   https://users.dune-project.org/projects/dune-stuff
// Copyright holders: Rene Milk, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
//
// Contributors: Kirsten Weber

#ifndef DUNE_STUFF_FUNCTIONS_EXPRESSION_HH
#define DUNE_STUFF_FUNCTIONS_EXPRESSION_HH

#include "config.h"

#include <vector>
#include <limits>

#include <dune/common/fvector.hh>

#include <dune/stuff/common/configtree.hh>
#include <dune/stuff/common/exceptions.hh>

#include "expression/base.hh"
#include "interfaces.hh"
#include "default.hh"
#include "constant.hh"

namespace Dune {
namespace Stuff {
namespace Functions {

/**
 *  \attention  If you add the create() and default_config() method, do not forget to enable the matrix valued
 *              versions in test/function_expression.cc
 */
template< class EntityImp, class DomainFieldImp, int domainDim, class RangeFieldImp, int rangeDim, int rangeDimCols = 1 >
class Expression
  : public LocalizableFunctionInterface< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, rangeDimCols >
{
  typedef LocalizableFunctionInterface
      < EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, rangeDimCols >               BaseType;
  typedef Expression< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, rangeDimCols > ThisType;
  typedef MathExpressionBase
      < DomainFieldImp, domainDim, RangeFieldImp, rangeDim*rangeDimCols > MathExpressionFunctionType;

  class Localfunction
    : public LocalfunctionInterface< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, rangeDimCols >
  {
    typedef LocalfunctionInterface< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, rangeDimCols > BaseType;
  public:
    typedef typename BaseType::EntityType EntityType;

    typedef typename BaseType::DomainFieldType  DomainFieldType;
    static const unsigned int                   dimDomain = BaseType::dimDomain;
    typedef typename BaseType::DomainType       DomainType;

    typedef typename BaseType::RangeFieldType RangeFieldType;
    static const unsigned int                 dimRange = BaseType::dimRange;
    static const unsigned int                 dimRangeCols = BaseType::dimRangeCols;
    typedef typename BaseType::RangeType      RangeType;

    typedef typename BaseType::JacobianRangeType JacobianRangeType;

    Localfunction(const EntityType& ent,
                  const std::shared_ptr< const MathExpressionFunctionType >& function,
                  const size_t ord)
      : BaseType(ent)
      , function_(function)
      , order_(ord)
      , tmp_vector_(0)
    {}

    Localfunction(const Localfunction& /*other*/) = delete;

    Localfunction& operator=(const Localfunction& /*other*/) = delete;

    virtual size_t order() const DS_OVERRIDE
    {
      return order_;
    }

    virtual void evaluate(const DomainType& xx, RangeType& ret) const DS_OVERRIDE
    {
      function_->evaluate(this->entity().geometry().global(xx), tmp_vector_);
      for (size_t ii = 0; ii < dimRange; ++ii) {
        auto& retRow = ret[ii];
        for (size_t jj = 0; jj < dimRangeCols; ++jj) {
          retRow[jj] = tmp_vector_[ii*dimRange + jj];
        }
      }
    } // ... evaluate(...)

    virtual void jacobian(const DomainType& /*xx*/, JacobianRangeType& DUNE_UNUSED(ret)) const DS_OVERRIDE
    {
      DUNE_THROW_COLORFULLY(NotImplemented,
                            "If we decided on the JacobianRangeType of matrix valued functions we have to implement "
                            << "gradients for this function!");
    }

  private:
    const std::shared_ptr< const MathExpressionFunctionType > function_;
    const size_t order_;
    mutable FieldVector< RangeFieldType, dimRange*dimRangeCols > tmp_vector_;
  }; // class Localfunction

public:
  typedef typename BaseType::EntityType         EntityType;
  typedef typename BaseType::LocalfunctionType  LocalfunctionType;

  typedef typename BaseType::DomainFieldType  DomainFieldType;
  static const unsigned int                   dimDomain = BaseType::dimDomain;
  typedef typename BaseType::DomainType       DomainType;

  typedef typename BaseType::RangeFieldType     RangeFieldType;
  static const unsigned int                     dimRange = BaseType::dimRange;
  static const unsigned int                     dimRangeCols = BaseType::dimRangeCols;
  typedef typename LocalfunctionType::RangeType RangeType;

  static std::string static_id()
  {
    return BaseType::static_id() + ".expression";
  }

  Expression(const std::string variable,
             const std::string expression,
             const size_t ord = 0,
             const std::string nm = static_id())
    : function_(new MathExpressionFunctionType(variable, expression))
    , order_(ord)
    , name_(nm)
  {}

  Expression(const std::string variable,
             const std::vector< std::string > expressions,
             const size_t ord = 0,
             const std::string nm = static_id())
    : function_(new MathExpressionFunctionType(variable, expressions))
    , order_(ord)
    , name_(nm)
  {}

  Expression(const ThisType& other)
    : function_(other.function_)
    , order_(other.order_)
    , name_(other.name_)
  {}

  ThisType& operator=(const ThisType& other)
  {
    if (this != &other) {
      function_ = other.function_;
      order_ = other.order_;
      name_ = other.name_;
    }
    return *this;
  }

  virtual std::string name() const DS_OVERRIDE
  {
    return name_;
  }

  virtual std::unique_ptr< LocalfunctionType > local_function(const EntityType& entity) const DS_OVERRIDE
  {
    return std::unique_ptr< Localfunction >(new Localfunction(entity, function_, order_));
  }

private:
  std::shared_ptr< const MathExpressionFunctionType > function_;
  size_t order_;
  std::string name_;
}; // class FunctionExpression

template< class EntityImp, class DomainFieldImp, int domainDim, class RangeFieldImp, int rangeDim >
class Expression< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, 1 >
  : public GlobalFunctionInterface< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim >
{
  typedef GlobalFunctionInterface< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim > BaseType;
  typedef Expression< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, 1 > ThisType;
  typedef MathExpressionBase < DomainFieldImp, domainDim, RangeFieldImp, rangeDim > MathExpressionFunctionType;
  typedef MathExpressionBase < DomainFieldImp, domainDim, RangeFieldImp, domainDim > MathExpressionGradientType;

public:
  typedef typename BaseType::EntityType         EntityType;
  typedef typename BaseType::LocalfunctionType  LocalfunctionType;

  typedef typename BaseType::DomainFieldType      DomainFieldType;
  static const unsigned int                       dimDomain = BaseType::dimDomain;
  typedef typename LocalfunctionType::DomainType  DomainType;

  typedef typename BaseType::RangeFieldType     RangeFieldType;
  static const unsigned int                     dimRange = BaseType::dimRange;
  static const unsigned int                     dimRangeCols = BaseType::dimRangeCols;
  typedef typename LocalfunctionType::RangeType RangeType;

  typedef typename LocalfunctionType::JacobianRangeType JacobianRangeType;

  static std::string static_id()
  {
    return BaseType::static_id() + ".expression";
  }

  static Common::ConfigTree default_config(const std::string sub_name = "")
  {
    Common::ConfigTree config;
    config["variable"] = "x";
    config["expression"] = "[x[0] sin(x[0]) exp(x[0])]";
    config["order"] = "1";
    config["name"] = static_id();
    if (sub_name.empty())
      return config;
    else {
      Common::ConfigTree tmp;
      tmp.add(config, sub_name);
      return tmp;
    }
  } // ... default_config(...)

  static std::unique_ptr< ThisType > create(const Common::ConfigTree config = default_config(), const std::string sub_name = static_id())
  {
    // get correct config
    const Common::ConfigTree cfg = config.has_sub(sub_name) ? config.sub(sub_name) : config;
    const Common::ConfigTree default_cfg = default_config();
    // create
    return Common::make_unique< ThisType >(
          cfg.get("variable",   default_cfg.get< std::string >("variable")),
          cfg.get("expression", default_cfg.get< std::vector< std::string > >("expression")),
          cfg.get("order",      default_cfg.get< size_t >("order")),
          cfg.get("name",       default_cfg.get< std::string >("name"))
    );
  } // ... create(...)

  Expression(const std::string variable,
             const std::string expression,
             const size_t ord = 0,
             const std::string nm = static_id(),
             const std::vector< std::vector< std::string > > gradient_expressions
                = std::vector< std::vector< std::string > >())
    : function_(new MathExpressionFunctionType(variable, expression))
    , order_(ord)
    , name_(nm)
  {
    build_gradients(variable, gradient_expressions);
  }

  Expression(const std::string variable,
             const std::vector< std::string > expressions,
             const size_t ord = 0,
             const std::string nm = static_id(),
             const std::vector< std::vector< std::string > > gradient_expressions
                = std::vector< std::vector< std::string > >())
    : function_(new MathExpressionFunctionType(variable, expressions))
    , order_(ord)
    , name_(nm)
  {
    build_gradients(variable, gradient_expressions);
  }

  virtual ThisType* copy() const DS_OVERRIDE
  {
    return new ThisType(*this);
  }

  virtual std::string name() const DS_OVERRIDE
  {
    return name_;
  }

  virtual size_t order() const DS_OVERRIDE
  {
    return order_;
  }

  virtual void evaluate(const DomainType& xx, RangeType& ret) const DS_OVERRIDE
  {
    function_->evaluate(xx, ret);
  }

  virtual void jacobian(const DomainType& xx, JacobianRangeType& ret) const DS_OVERRIDE
  {
    if (gradients_.size() == 0)
      DUNE_THROW_COLORFULLY(NotImplemented, "This function does not provide any gradients!");
    assert(gradients_.size() == dimRange);
    for (size_t ii = 0; ii < dimRange; ++ii) {
      gradients_[ii]->evaluate(xx, ret[ii]);
    }
  } // ... jacobian(...)
private:
  void build_gradients(const std::string variable,
                       const std::vector< std::vector< std::string > >& gradient_expressions)
  {
    assert(gradient_expressions.size() == 0 || gradient_expressions.size() >= dimRange);
    if (gradient_expressions.size() > 0)
      for (size_t rr = 0; rr < dimRange; ++rr) {
        const auto& gradient_expression = gradient_expressions[rr];
        assert(gradient_expression.size() >= dimDomain);
        gradients_.emplace_back(new MathExpressionGradientType(variable, gradient_expression));
      }
  } // ... build_gradients(...)

  std::shared_ptr< const MathExpressionFunctionType > function_;
  size_t order_;
  std::string name_;
  std::vector< std::shared_ptr< const MathExpressionGradientType > > gradients_;
}; // class Expression< ..., 1 >

} // namespace Functions
} // namespace Stuff
} // namespace Dune

#ifdef DUNE_STUFF_FUNCTIONS_TO_LIB
# define DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGE(etype, ddim) \
  DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGECOLS(etype, ddim, 1) \
  DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGECOLS(etype, ddim, 2) \
  DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGECOLS(etype, ddim, 3)

# define DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGECOLS(etype, ddim, rdim) \
  DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DOMAINFIELDTYPES(etype, ddim, rdim, 2) \
  DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DOMAINFIELDTYPES(etype, ddim, rdim, 3)

# define DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DOMAINFIELDTYPES(etype, ddim, rdim, rcdim) \
  DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_RANGEFIELDTYPES(etype, double, ddim, rdim, rcdim)

# define DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_RANGEFIELDTYPES(etype, dftype, ddim, rdim, rcdim) \
  DUNE_STUFF_FUNCTIONS_EXPRESSION_LAST_EXPANSION(etype, dftype, ddim, double, rdim, rcdim) \
  DUNE_STUFF_FUNCTIONS_EXPRESSION_LAST_EXPANSION(etype, dftype, ddim, long double, rdim, rcdim)

# define DUNE_STUFF_FUNCTIONS_EXPRESSION_LAST_EXPANSION(etype, dftype, ddim, rftype, rdim, rcdim) \
  extern template class Dune::Stuff::Functions::Expression< etype, dftype, ddim, rftype, rdim, rcdim >;

# if HAVE_DUNE_GRID

DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGE(DuneStuffFunctionsInterfacesSGrid1dEntityType, 1)
DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGE(DuneStuffFunctionsInterfacesSGrid2dEntityType, 2)
DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGE(DuneStuffFunctionsInterfacesSGrid3dEntityType, 3)

DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGE(DuneStuffFunctionsInterfacesYaspGrid1dEntityType, 1)
DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGE(DuneStuffFunctionsInterfacesYaspGrid2dEntityType, 2)
DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGE(DuneStuffFunctionsInterfacesYaspGrid3dEntityType, 3)

#   if HAVE_ALUGRID_SERIAL_H || HAVE_ALUGRID_PARALLEL_H

DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGE(DuneStuffFunctionsInterfacesAluSimplexGrid2dEntityType, 2)
DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGE(DuneStuffFunctionsInterfacesAluSimplexGrid3dEntityType, 3)
DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGE(DuneStuffFunctionsInterfacesAluCubeGrid3dEntityType, 3)

#   endif // HAVE_ALUGRID_SERIAL_H || HAVE_ALUGRID_PARALLEL_H
# endif // HAVE_DUNE_GRID

# undef DUNE_STUFF_FUNCTIONS_EXPRESSION_LAST_EXPANSION
# undef DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_RANGEFIELDTYPES
# undef DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DOMAINFIELDTYPES
# undef DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGECOLS
# undef DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGE
#endif // DUNE_STUFF_FUNCTIONS_TO_LIB

#endif // DUNE_STUFF_FUNCTIONS_EXPRESSION_HH
<commit_msg>[functions.expression] style fix<commit_after>// This file is part of the dune-stuff project:
//   https://users.dune-project.org/projects/dune-stuff
// Copyright holders: Rene Milk, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
//
// Contributors: Kirsten Weber

#ifndef DUNE_STUFF_FUNCTIONS_EXPRESSION_HH
#define DUNE_STUFF_FUNCTIONS_EXPRESSION_HH

#include "config.h"

#include <vector>
#include <limits>

#include <dune/common/fvector.hh>

#include <dune/stuff/common/configtree.hh>
#include <dune/stuff/common/exceptions.hh>

#include "expression/base.hh"
#include "interfaces.hh"
#include "default.hh"
#include "constant.hh"

namespace Dune {
namespace Stuff {
namespace Functions {

/**
 *  \attention  If you add the create() and default_config() method, do not forget to enable the matrix valued
 *              versions in test/function_expression.cc
 */
template< class EntityImp, class DomainFieldImp, int domainDim, class RangeFieldImp, int rangeDim, int rangeDimCols = 1 >
class Expression
  : public LocalizableFunctionInterface< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, rangeDimCols >
{
  typedef LocalizableFunctionInterface
      < EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, rangeDimCols >               BaseType;
  typedef Expression< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, rangeDimCols > ThisType;
  typedef MathExpressionBase
      < DomainFieldImp, domainDim, RangeFieldImp, rangeDim*rangeDimCols > MathExpressionFunctionType;

  class Localfunction
    : public LocalfunctionInterface< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, rangeDimCols >
  {
    typedef LocalfunctionInterface< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, rangeDimCols > BaseType;
  public:
    typedef typename BaseType::EntityType EntityType;

    typedef typename BaseType::DomainFieldType  DomainFieldType;
    static const unsigned int                   dimDomain = BaseType::dimDomain;
    typedef typename BaseType::DomainType       DomainType;

    typedef typename BaseType::RangeFieldType RangeFieldType;
    static const unsigned int                 dimRange = BaseType::dimRange;
    static const unsigned int                 dimRangeCols = BaseType::dimRangeCols;
    typedef typename BaseType::RangeType      RangeType;

    typedef typename BaseType::JacobianRangeType JacobianRangeType;

    Localfunction(const EntityType& ent,
                  const std::shared_ptr< const MathExpressionFunctionType >& function,
                  const size_t ord)
      : BaseType(ent)
      , function_(function)
      , order_(ord)
      , tmp_vector_(0)
    {}

    Localfunction(const Localfunction& /*other*/) = delete;

    Localfunction& operator=(const Localfunction& /*other*/) = delete;

    virtual size_t order() const DS_OVERRIDE
    {
      return order_;
    }

    virtual void evaluate(const DomainType& xx, RangeType& ret) const DS_OVERRIDE
    {
      function_->evaluate(this->entity().geometry().global(xx), tmp_vector_);
      for (size_t ii = 0; ii < dimRange; ++ii) {
        auto& retRow = ret[ii];
        for (size_t jj = 0; jj < dimRangeCols; ++jj) {
          retRow[jj] = tmp_vector_[ii*dimRange + jj];
        }
      }
    } // ... evaluate(...)

    virtual void jacobian(const DomainType& /*xx*/, JacobianRangeType& /*ret*/) const DS_OVERRIDE
    {
      DUNE_THROW_COLORFULLY(NotImplemented,
                            "If we decided on the JacobianRangeType of matrix valued functions we have to implement "
                            << "gradients for this function!");
    }

  private:
    const std::shared_ptr< const MathExpressionFunctionType > function_;
    const size_t order_;
    mutable FieldVector< RangeFieldType, dimRange*dimRangeCols > tmp_vector_;
  }; // class Localfunction

public:
  typedef typename BaseType::EntityType         EntityType;
  typedef typename BaseType::LocalfunctionType  LocalfunctionType;

  typedef typename BaseType::DomainFieldType  DomainFieldType;
  static const unsigned int                   dimDomain = BaseType::dimDomain;
  typedef typename BaseType::DomainType       DomainType;

  typedef typename BaseType::RangeFieldType     RangeFieldType;
  static const unsigned int                     dimRange = BaseType::dimRange;
  static const unsigned int                     dimRangeCols = BaseType::dimRangeCols;
  typedef typename LocalfunctionType::RangeType RangeType;

  static std::string static_id()
  {
    return BaseType::static_id() + ".expression";
  }

  Expression(const std::string variable,
             const std::string expression,
             const size_t ord = 0,
             const std::string nm = static_id())
    : function_(new MathExpressionFunctionType(variable, expression))
    , order_(ord)
    , name_(nm)
  {}

  Expression(const std::string variable,
             const std::vector< std::string > expressions,
             const size_t ord = 0,
             const std::string nm = static_id())
    : function_(new MathExpressionFunctionType(variable, expressions))
    , order_(ord)
    , name_(nm)
  {}

  Expression(const ThisType& other)
    : function_(other.function_)
    , order_(other.order_)
    , name_(other.name_)
  {}

  ThisType& operator=(const ThisType& other)
  {
    if (this != &other) {
      function_ = other.function_;
      order_ = other.order_;
      name_ = other.name_;
    }
    return *this;
  }

  virtual std::string name() const DS_OVERRIDE
  {
    return name_;
  }

  virtual std::unique_ptr< LocalfunctionType > local_function(const EntityType& entity) const DS_OVERRIDE
  {
    return std::unique_ptr< Localfunction >(new Localfunction(entity, function_, order_));
  }

private:
  std::shared_ptr< const MathExpressionFunctionType > function_;
  size_t order_;
  std::string name_;
}; // class FunctionExpression

template< class EntityImp, class DomainFieldImp, int domainDim, class RangeFieldImp, int rangeDim >
class Expression< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, 1 >
  : public GlobalFunctionInterface< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim >
{
  typedef GlobalFunctionInterface< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim > BaseType;
  typedef Expression< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, 1 > ThisType;
  typedef MathExpressionBase < DomainFieldImp, domainDim, RangeFieldImp, rangeDim > MathExpressionFunctionType;
  typedef MathExpressionBase < DomainFieldImp, domainDim, RangeFieldImp, domainDim > MathExpressionGradientType;

public:
  typedef typename BaseType::EntityType         EntityType;
  typedef typename BaseType::LocalfunctionType  LocalfunctionType;

  typedef typename BaseType::DomainFieldType      DomainFieldType;
  static const unsigned int                       dimDomain = BaseType::dimDomain;
  typedef typename LocalfunctionType::DomainType  DomainType;

  typedef typename BaseType::RangeFieldType     RangeFieldType;
  static const unsigned int                     dimRange = BaseType::dimRange;
  static const unsigned int                     dimRangeCols = BaseType::dimRangeCols;
  typedef typename LocalfunctionType::RangeType RangeType;

  typedef typename LocalfunctionType::JacobianRangeType JacobianRangeType;

  static std::string static_id()
  {
    return BaseType::static_id() + ".expression";
  }

  static Common::ConfigTree default_config(const std::string sub_name = "")
  {
    Common::ConfigTree config;
    config["variable"] = "x";
    config["expression"] = "[x[0] sin(x[0]) exp(x[0])]";
    config["order"] = "1";
    config["name"] = static_id();
    if (sub_name.empty())
      return config;
    else {
      Common::ConfigTree tmp;
      tmp.add(config, sub_name);
      return tmp;
    }
  } // ... default_config(...)

  static std::unique_ptr< ThisType > create(const Common::ConfigTree config = default_config(), const std::string sub_name = static_id())
  {
    // get correct config
    const Common::ConfigTree cfg = config.has_sub(sub_name) ? config.sub(sub_name) : config;
    const Common::ConfigTree default_cfg = default_config();
    // create
    return Common::make_unique< ThisType >(
          cfg.get("variable",   default_cfg.get< std::string >("variable")),
          cfg.get("expression", default_cfg.get< std::vector< std::string > >("expression")),
          cfg.get("order",      default_cfg.get< size_t >("order")),
          cfg.get("name",       default_cfg.get< std::string >("name"))
    );
  } // ... create(...)

  Expression(const std::string variable,
             const std::string expression,
             const size_t ord = 0,
             const std::string nm = static_id(),
             const std::vector< std::vector< std::string > > gradient_expressions
                = std::vector< std::vector< std::string > >())
    : function_(new MathExpressionFunctionType(variable, expression))
    , order_(ord)
    , name_(nm)
  {
    build_gradients(variable, gradient_expressions);
  }

  Expression(const std::string variable,
             const std::vector< std::string > expressions,
             const size_t ord = 0,
             const std::string nm = static_id(),
             const std::vector< std::vector< std::string > > gradient_expressions
                = std::vector< std::vector< std::string > >())
    : function_(new MathExpressionFunctionType(variable, expressions))
    , order_(ord)
    , name_(nm)
  {
    build_gradients(variable, gradient_expressions);
  }

  virtual ThisType* copy() const DS_OVERRIDE
  {
    return new ThisType(*this);
  }

  virtual std::string name() const DS_OVERRIDE
  {
    return name_;
  }

  virtual size_t order() const DS_OVERRIDE
  {
    return order_;
  }

  virtual void evaluate(const DomainType& xx, RangeType& ret) const DS_OVERRIDE
  {
    function_->evaluate(xx, ret);
  }

  virtual void jacobian(const DomainType& xx, JacobianRangeType& ret) const DS_OVERRIDE
  {
    if (gradients_.size() == 0)
      DUNE_THROW_COLORFULLY(NotImplemented, "This function does not provide any gradients!");
    assert(gradients_.size() == dimRange);
    for (size_t ii = 0; ii < dimRange; ++ii) {
      gradients_[ii]->evaluate(xx, ret[ii]);
    }
  } // ... jacobian(...)
private:
  void build_gradients(const std::string variable,
                       const std::vector< std::vector< std::string > >& gradient_expressions)
  {
    assert(gradient_expressions.size() == 0 || gradient_expressions.size() >= dimRange);
    if (gradient_expressions.size() > 0)
      for (size_t rr = 0; rr < dimRange; ++rr) {
        const auto& gradient_expression = gradient_expressions[rr];
        assert(gradient_expression.size() >= dimDomain);
        gradients_.emplace_back(new MathExpressionGradientType(variable, gradient_expression));
      }
  } // ... build_gradients(...)

  std::shared_ptr< const MathExpressionFunctionType > function_;
  size_t order_;
  std::string name_;
  std::vector< std::shared_ptr< const MathExpressionGradientType > > gradients_;
}; // class Expression< ..., 1 >

} // namespace Functions
} // namespace Stuff
} // namespace Dune

#ifdef DUNE_STUFF_FUNCTIONS_TO_LIB
# define DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGE(etype, ddim) \
  DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGECOLS(etype, ddim, 1) \
  DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGECOLS(etype, ddim, 2) \
  DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGECOLS(etype, ddim, 3)

# define DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGECOLS(etype, ddim, rdim) \
  DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DOMAINFIELDTYPES(etype, ddim, rdim, 2) \
  DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DOMAINFIELDTYPES(etype, ddim, rdim, 3)

# define DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DOMAINFIELDTYPES(etype, ddim, rdim, rcdim) \
  DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_RANGEFIELDTYPES(etype, double, ddim, rdim, rcdim)

# define DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_RANGEFIELDTYPES(etype, dftype, ddim, rdim, rcdim) \
  DUNE_STUFF_FUNCTIONS_EXPRESSION_LAST_EXPANSION(etype, dftype, ddim, double, rdim, rcdim) \
  DUNE_STUFF_FUNCTIONS_EXPRESSION_LAST_EXPANSION(etype, dftype, ddim, long double, rdim, rcdim)

# define DUNE_STUFF_FUNCTIONS_EXPRESSION_LAST_EXPANSION(etype, dftype, ddim, rftype, rdim, rcdim) \
  extern template class Dune::Stuff::Functions::Expression< etype, dftype, ddim, rftype, rdim, rcdim >;

# if HAVE_DUNE_GRID

DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGE(DuneStuffFunctionsInterfacesSGrid1dEntityType, 1)
DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGE(DuneStuffFunctionsInterfacesSGrid2dEntityType, 2)
DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGE(DuneStuffFunctionsInterfacesSGrid3dEntityType, 3)

DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGE(DuneStuffFunctionsInterfacesYaspGrid1dEntityType, 1)
DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGE(DuneStuffFunctionsInterfacesYaspGrid2dEntityType, 2)
DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGE(DuneStuffFunctionsInterfacesYaspGrid3dEntityType, 3)

#   if HAVE_ALUGRID_SERIAL_H || HAVE_ALUGRID_PARALLEL_H

DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGE(DuneStuffFunctionsInterfacesAluSimplexGrid2dEntityType, 2)
DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGE(DuneStuffFunctionsInterfacesAluSimplexGrid3dEntityType, 3)
DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGE(DuneStuffFunctionsInterfacesAluCubeGrid3dEntityType, 3)

#   endif // HAVE_ALUGRID_SERIAL_H || HAVE_ALUGRID_PARALLEL_H
# endif // HAVE_DUNE_GRID

# undef DUNE_STUFF_FUNCTIONS_EXPRESSION_LAST_EXPANSION
# undef DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_RANGEFIELDTYPES
# undef DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DOMAINFIELDTYPES
# undef DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGECOLS
# undef DUNE_STUFF_FUNCTIONS_EXPRESSION_LIST_DIMRANGE
#endif // DUNE_STUFF_FUNCTIONS_TO_LIB

#endif // DUNE_STUFF_FUNCTIONS_EXPRESSION_HH
<|endoftext|>


<commit_before><commit_msg>ImpEditView::ShowCursor: don't assume map mode is twips<commit_after><|endoftext|>


<commit_before><commit_msg>mesa: Minor clean ups in _mesa_uniform<commit_after><|endoftext|>


<commit_before>/**
 * @file jsoncpp-qt.cpp
 * @date Created on: May 5, 2011
 * @author: samh
 */

#include "json/jsoncpp-qt.h"

#include <QtCore/QVariant>

#include "json/json.h"

namespace Json {

void JsonValue_to_QVariant(const Json::Value& jv, QVariant& qv) {
    switch(jv.type()) {
    case nullValue:
        qv = QVariant();
        break;
    case intValue:
    case uintValue:
        qv = QVariant(jv.asLargestInt());
        break;
    case realValue:
        qv = QVariant(jv.asDouble());
        break;
    case stringValue:
        qv = QVariant(jv.asCString());
        break;
    case booleanValue:
        qv = QVariant(jv.asBool());
        break;
    case arrayValue:
    {
        QVariantList l;
        foreach(Value jvitem, jv) {
            QVariant qvitem;
            JsonValue_to_QVariant(jvitem, qvitem);
            l << qvitem;
        }
        qv = l;
        break;
    }
    case objectValue:
    {
        QVariantMap m;
        foreach(std::string key, jv.getMemberNames()) {
            QVariant qvitem;
            JsonValue_to_QVariant(jv[key], qvitem);
            m.insert(QString::fromStdString(key), qvitem);
        }
        qv = m;
        break;
    }
    }
}

void QVariant_to_JsonValue(const QVariant& qv, Json::Value& jv) {
    switch(qv.type()) {
    case QVariant::Invalid:
        jv = Value::null;
        break;
    case QVariant::Int:
    case QVariant::LongLong:
    case QVariant::UInt:
    case QVariant::ULongLong:
        jv = qv.toLongLong();
        break;
    case QVariant::Double:
        jv = qv.toDouble();
        break;
    case QVariant::Bool:
        jv = qv.toBool();
        break;
    case QVariant::List:
    case QVariant::StringList:
    {
        QVariantList qvlist = qv.toList();
        foreach(QVariant qvitem, qvlist) {
            Value jvitem;
            QVariant_to_JsonValue(qvitem, jvitem);
            jv.append(jvitem);
        }
        break;
    }
    case QVariant::Map:
    {
        QVariantMap qvmap = qv.toMap();
        QMapIterator<QString, QVariant> it(qvmap);
        while (it.hasNext()) {
            it.next();
            Value jvitem;
            QVariant_to_JsonValue(it.value(), jvitem);
            jv[it.key().toStdString()] = jvitem;
        }
        break;
    }
    default:
        jv = qv.toString().toStdString();
    }
}

QtReader::QtReader() {
    m_reader.reset(new Json::Reader());
}

QtReader::~QtReader() {
}

// How should this return errors?
//bool QtReader::parse(QIODevice& iodevice, QVariant& root) {
//
//}

bool QtReader::parse(const QString& document, QVariant& root) {
    Json::Value jsonRoot;
    bool parsingSuccessful = m_reader->parse(document.toStdString(), jsonRoot);
    if (parsingSuccessful) {
        JsonValue_to_QVariant(jsonRoot, root);
    }
    return parsingSuccessful;
}

QString QtReader::getFormattedErrorMessages() {
    return QString::fromStdString(m_reader->getFormattedErrorMessages());
}

QString QtWriter::write(const QVariant& root) {
    Json::Value value;
    QVariant_to_JsonValue(root, value);
    return QString::fromStdString(value.toStyledString());
}
}
<commit_msg>Differentiate unsigned integer; fix ambiguous conversions (it's not entirely clear when this is an error)<commit_after>/**
 * @file jsoncpp-qt.cpp
 * @date Created on: May 5, 2011
 * @author: samh
 */

#include "json/jsoncpp-qt.h"

#include <QtCore/QVariant>

#include "json/json.h"

namespace Json {

void JsonValue_to_QVariant(const Json::Value& jv, QVariant& qv) {
    switch(jv.type()) {
    case nullValue:
        qv = QVariant();
        break;
    case intValue:
        qv = QVariant(static_cast<qlonglong>(jv.asLargestInt()));
        break;
    case uintValue:
        qv = QVariant(static_cast<qulonglong>(jv.asLargestUInt()));
        break;
    case realValue:
        qv = QVariant(jv.asDouble());
        break;
    case stringValue:
        qv = QVariant(jv.asCString());
        break;
    case booleanValue:
        qv = QVariant(jv.asBool());
        break;
    case arrayValue:
    {
        QVariantList l;
        foreach(Value jvitem, jv) {
            QVariant qvitem;
            JsonValue_to_QVariant(jvitem, qvitem);
            l << qvitem;
        }
        qv = l;
        break;
    }
    case objectValue:
    {
        QVariantMap m;
        foreach(std::string key, jv.getMemberNames()) {
            QVariant qvitem;
            JsonValue_to_QVariant(jv[key], qvitem);
            m.insert(QString::fromStdString(key), qvitem);
        }
        qv = m;
        break;
    }
    }
}

void QVariant_to_JsonValue(const QVariant& qv, Json::Value& jv) {
    switch(qv.type()) {
    case QVariant::Invalid:
        jv = Value::null;
        break;
    case QVariant::Int:
    case QVariant::LongLong:
        jv = static_cast<Json::Value::Int64>(qv.toLongLong());
        break;
    case QVariant::UInt:
    case QVariant::ULongLong:
        jv = static_cast<Json::Value::UInt64>(qv.toULongLong());
        break;
    case QVariant::Double:
        jv = qv.toDouble();
        break;
    case QVariant::Bool:
        jv = qv.toBool();
        break;
    case QVariant::List:
    case QVariant::StringList:
    {
        QVariantList qvlist = qv.toList();
        foreach(QVariant qvitem, qvlist) {
            Value jvitem;
            QVariant_to_JsonValue(qvitem, jvitem);
            jv.append(jvitem);
        }
        break;
    }
    case QVariant::Map:
    {
        QVariantMap qvmap = qv.toMap();
        QMapIterator<QString, QVariant> it(qvmap);
        while (it.hasNext()) {
            it.next();
            Value jvitem;
            QVariant_to_JsonValue(it.value(), jvitem);
            jv[it.key().toStdString()] = jvitem;
        }
        break;
    }
    default:
        jv = qv.toString().toStdString();
    }
}

QtReader::QtReader() {
    m_reader.reset(new Json::Reader());
}

QtReader::~QtReader() {
}

// How should this return errors?
//bool QtReader::parse(QIODevice& iodevice, QVariant& root) {
//
//}

bool QtReader::parse(const QString& document, QVariant& root) {
    Json::Value jsonRoot;
    bool parsingSuccessful = m_reader->parse(document.toStdString(), jsonRoot);
    if (parsingSuccessful) {
        JsonValue_to_QVariant(jsonRoot, root);
    }
    return parsingSuccessful;
}

QString QtReader::getFormattedErrorMessages() {
    return QString::fromStdString(m_reader->getFormattedErrorMessages());
}

QString QtWriter::write(const QVariant& root) {
    Json::Value value;
    QVariant_to_JsonValue(root, value);
    return QString::fromStdString(value.toStyledString());
}
}
<|endoftext|>