<commit_before>#include <stdlib.h>

#include "base/logging.h"
#include "base/NativeApp.h"
#include "gl_state.h"

#ifdef _WIN32
#include "GL/wglew.h"
#endif

#if defined(USING_GLES2)
#if defined(ANDROID) || defined(BLACKBERRY)
PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC eglGetSystemTimeFrequencyNV;
PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV;
PFNGLDRAWTEXTURENVPROC glDrawTextureNV;
PFNGLCOPYIMAGESUBDATANVPROC glCopyImageSubDataNV ;
PFNGLMAPBUFFERPROC glMapBuffer;

PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT;
PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOES;
PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOES;
PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArraysOES;
PFNGLISVERTEXARRAYOESPROC glIsVertexArrayOES;
#endif
#endif

OpenGLState glstate;
GLExtensions gl_extensions;
std::string g_all_gl_extensions;
std::string g_all_egl_extensions;

int OpenGLState::state_count = 0;

void OpenGLState::Initialize() {
	if (initialized)
		return;
	initialized = true;

	Restore();
}

void OpenGLState::Restore() {
	int count = 0;

	blend.restore(); count++;
	blendEquation.restore(); count++;
	blendFuncSeparate.restore(); count++;
	blendColor.restore(); count++;

	scissorTest.restore(); count++;
	scissorRect.restore(); count++;

	cullFace.restore(); count++;
	cullFaceMode.restore(); count++;
	frontFace.restore(); count++;

	depthTest.restore(); count++;
	depthRange.restore(); count++;
	depthFunc.restore(); count++;
	depthWrite.restore(); count++;

	colorMask.restore(); count++;
	viewport.restore(); count++;

	stencilTest.restore(); count++;
	stencilOp.restore(); count++;
	stencilFunc.restore(); count++;

	dither.restore(); count++;

#if !defined(USING_GLES2)
	colorLogicOp.restore(); count++;
	logicOp.restore(); count++;
#endif

	if (count != state_count) {
		FLOG("OpenGLState::Restore is missing some states");
	}
}

// http://stackoverflow.com/questions/16147700/opengl-es-using-tegra-specific-extensions-gl-ext-texture-array

void CheckGLExtensions() {
	// Make sure to only do this once. It's okay to call CheckGLExtensions from wherever.
	static bool done = false;
	if (done)
		return;
	done = true;
	memset(&gl_extensions, 0, sizeof(gl_extensions));

	const char *renderer = (const char *)glGetString(GL_RENDERER);
	const char *versionStr = (const char *)glGetString(GL_VERSION);

	// Check vendor string to try and guess GPU
	const char *cvendor = (char *)glGetString(GL_VENDOR);
	// TODO: move this stuff to gpu_features.cpp
	if (cvendor) {
		const std::string vendor(cvendor);
		if (vendor == "NVIDIA Corporation"
			|| vendor == "Nouveau"
			|| vendor == "nouveau") {
				gl_extensions.gpuVendor = GPU_VENDOR_NVIDIA;
		} else if (vendor == "Advanced Micro Devices, Inc."
			|| vendor == "ATI Technologies Inc.") {
				gl_extensions.gpuVendor = GPU_VENDOR_AMD;
		} else if (vendor == "Intel"
			|| vendor == "Intel Inc."
			|| vendor == "Intel Corporation"
			|| vendor == "Tungsten Graphics, Inc") { // We'll assume this last one means Intel
				gl_extensions.gpuVendor = GPU_VENDOR_INTEL;
		} else if (vendor == "ARM") {
			gl_extensions.gpuVendor = GPU_VENDOR_ARM;
		} else if (vendor == "Imagination Technologies") {
			gl_extensions.gpuVendor = GPU_VENDOR_POWERVR;
		} else if (vendor == "Qualcomm") {
			gl_extensions.gpuVendor = GPU_VENDOR_ADRENO;
		} else if (vendor == "Broadcom") {
			gl_extensions.gpuVendor = GPU_VENDOR_BROADCOM;
			// Just for reference: Galaxy Y has renderer == "VideoCore IV HW"
		} else {
			gl_extensions.gpuVendor = GPU_VENDOR_UNKNOWN;
		}
	} else {
		gl_extensions.gpuVendor = GPU_VENDOR_UNKNOWN;
	}

	ILOG("GPU Vendor : %s ; GL version str: %s", cvendor, versionStr ? versionStr : "N/A");

#ifndef USING_GLES2
	char buffer[64] = {0};
	if (versionStr) {
		strncpy(buffer, versionStr, 63);
	}
	const char *lastNumStart = buffer;
	int numVer = 0;
	int len = (int)strlen(buffer);
	for (int i = 0; i < len && numVer < 3; i++) {
		if (buffer[i] == '.') {
			buffer[i] = 0;
			gl_extensions.ver[numVer++] = strtol(lastNumStart, NULL, 10);
			i++;
			lastNumStart = buffer + i;
		}
	}
	if (numVer < 3)
		gl_extensions.ver[numVer++] = strtol(lastNumStart, NULL, 10);
#else
	gl_extensions.ver[0] = 2;
#endif

#if defined(USING_GLES2)
	// MAY_HAVE_GLES3 defined on all platforms that support it
#if defined(MAY_HAVE_GLES3)
	// Try to load GLES 3.0 only if "3.0" found in version
	// This simple heuristic avoids issues on older devices where you can only call eglGetProcAddress a limited
	// number of times.
	if (strstr(versionStr, "3.0") && GL_TRUE == gl3stubInit()) {
		gl_extensions.ver[0] = 3;
		gl_extensions.GLES3 = true;
		ILOG("Full OpenGL ES 3.0 support detected!\n");
		// Though, let's ban Mali from the GLES 3 path for now, see #4078
		if (strstr(renderer, "Mali") != 0) {
			gl_extensions.GLES3 = false;
		}
	}
#endif
#else
	// If the GL version >= 4.3, we know it's a true superset of OpenGL ES 3.0 and can thus enable
	// all the same modern paths.
	// Most of it could be enabled on lower GPUs as well, but let's start this way.
	if (gl_extensions.VersionGEThan(4, 3, 0)) {
		gl_extensions.GLES3 = true;
	}
#endif

	const char *extString = (const char *)glGetString(GL_EXTENSIONS);
	if (extString) {
		g_all_gl_extensions = extString;
	} else {
		g_all_gl_extensions = "";
	}

#ifdef WIN32
	const char *wglString = 0;
	if (wglGetExtensionsStringEXT)
		wglString = wglGetExtensionsStringEXT();
	if (wglString) {
		gl_extensions.EXT_swap_control_tear = strstr(wglString, "WGL_EXT_swap_control_tear") != 0;
		g_all_egl_extensions = wglString;
	} else {
		g_all_egl_extensions = "";
	}
#elif !defined(USING_GLES2)
	// const char *glXString = glXQueryExtensionString();
	// gl_extensions.EXT_swap_control_tear = strstr(glXString, "GLX_EXT_swap_control_tear") != 0;
#endif

	gl_extensions.NV_draw_texture = strstr(extString, "GL_NV_draw_texture") != 0;
	gl_extensions.ARB_blend_func_extended = strstr(extString, "GL_ARB_blend_func_extended") != 0;
	if (gl_extensions.gpuVendor == GPU_VENDOR_INTEL || !gl_extensions.VersionGEThan(3, 0, 0)) {
		// Force this extension to off on sub 3.0 OpenGL versions as it does not seem reliable
		// Also on Intel, see https://github.com/hrydgard/ppsspp/issues/4867
		gl_extensions.ARB_blend_func_extended = false;
	}

#ifdef USING_GLES2
	gl_extensions.OES_packed_depth_stencil = strstr(extString, "GL_OES_packed_depth_stencil") != 0;
	gl_extensions.OES_depth24 = strstr(extString, "GL_OES_depth24") != 0;
	gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0;
	gl_extensions.OES_mapbuffer = strstr(extString, "GL_OES_mapbuffer") != 0;
	gl_extensions.EXT_blend_minmax = strstr(extString, "GL_EXT_blend_minmax") != 0;
	gl_extensions.EXT_shader_framebuffer_fetch = (strstr(extString, "GL_EXT_shader_framebuffer_fetch") != 0) || (strstr(extString, "GL_NV_shader_framebuffer_fetch") != 0);
	gl_extensions.NV_copy_image = strstr(extString, "GL_NV_copy_image") != 0;
	gl_extensions.EXT_unpack_subimage = strstr(extString, "GL_EXT_unpack_subimage") != 0;
#if defined(ANDROID) || defined(BLACKBERRY)
	// On Android, incredibly, this is not consistently non-zero! It does seem to have the same value though.
	// https://twitter.com/ID_AA_Carmack/status/387383037794603008
#ifdef _DEBUG
	void *invalidAddress = (void *)eglGetProcAddress("InvalidGlCall1");
	void *invalidAddress2 = (void *)eglGetProcAddress("AnotherInvalidGlCall2");
	DLOG("Addresses returned for invalid extensions: %p %p", invalidAddress, invalidAddress2);
#endif

	if (gl_extensions.NV_draw_texture) {
		glDrawTextureNV = (PFNGLDRAWTEXTURENVPROC)eglGetProcAddress("glDrawTextureNV");
	}

	if (gl_extensions.NV_copy_image) {
		glCopyImageSubDataNV = (PFNGLCOPYIMAGESUBDATANVPROC)eglGetProcAddress("glCopyImageSubDataNV");
	}

	gl_extensions.OES_vertex_array_object = strstr(extString, "GL_OES_vertex_array_object") != 0;
	if (gl_extensions.OES_vertex_array_object) {
		glGenVertexArraysOES = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress ( "glGenVertexArraysOES" );
		glBindVertexArrayOES = (PFNGLBINDVERTEXARRAYOESPROC)eglGetProcAddress ( "glBindVertexArrayOES" );
		glDeleteVertexArraysOES = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress ( "glDeleteVertexArraysOES" );
		glIsVertexArrayOES = (PFNGLISVERTEXARRAYOESPROC)eglGetProcAddress ( "glIsVertexArrayOES" );
	}

	gl_extensions.EXT_discard_framebuffer = strstr(extString, "GL_EXT_discard_framebuffer") != 0;
	if (gl_extensions.EXT_discard_framebuffer) {
		glDiscardFramebufferEXT = (PFNGLDISCARDFRAMEBUFFEREXTPROC)eglGetProcAddress("glDiscardFramebufferEXT");
	}
#else
	gl_extensions.OES_vertex_array_object = false;
	gl_extensions.EXT_discard_framebuffer = false;
#endif
#else
	// Desktops support minmax and subimage unpack (GL_UNPACK_ROW_LENGTH etc)
	gl_extensions.EXT_blend_minmax = true;
	gl_extensions.EXT_unpack_subimage = true;
#endif
	// GLES 3 subsumes many ES2 extensions.
	if (gl_extensions.GLES3) {
		gl_extensions.EXT_unpack_subimage = true;
	}

#if defined(ANDROID) || defined(BLACKBERRY)
	if (gl_extensions.OES_mapbuffer) {
		glMapBuffer = (PFNGLMAPBUFFERPROC)eglGetProcAddress( "glMapBufferOES" );
	}

	// Look for EGL extensions
	EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);

	const char *eglString = eglQueryString(display, EGL_EXTENSIONS);
	if (eglString) {
		g_all_egl_extensions = eglString;

		gl_extensions.EGL_NV_system_time = strstr(eglString, "EGL_NV_system_time") != 0;
		gl_extensions.EGL_NV_coverage_sample = strstr(eglString, "EGL_NV_coverage_sample") != 0;

		if (gl_extensions.EGL_NV_system_time) {
			eglGetSystemTimeNV = (PFNEGLGETSYSTEMTIMENVPROC) eglGetProcAddress("eglGetSystemTimeNV");
			eglGetSystemTimeFrequencyNV = (PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) eglGetProcAddress("eglGetSystemTimeFrequencyNV");
		}
	} else {
		g_all_egl_extensions = "";
	}
#endif

#ifdef USING_GLES2
	gl_extensions.FBO_ARB = true;
	gl_extensions.FBO_EXT = false;
	gl_extensions.ATIClampBug = gl_extensions.gpuVendor == GPU_VENDOR_NVIDIA;   // Tegras - TODO: more specific check
#else
	gl_extensions.FBO_ARB = false;
	gl_extensions.FBO_EXT = false;
	gl_extensions.PBO_ARB = true;
	if (extString) {
		gl_extensions.FBO_ARB = strstr(extString, "GL_ARB_framebuffer_object") != 0;
		gl_extensions.FBO_EXT = strstr(extString, "GL_EXT_framebuffer_object") != 0;
		gl_extensions.PBO_ARB = strstr(extString, "GL_ARB_pixel_buffer_object") != 0;
		gl_extensions.ATIClampBug = ((strncmp(renderer, "ATI RADEON X", 12) == 0) || (strncmp(renderer, "ATI MOBILITY RADEON X", 21) == 0));
	}
#endif

	ProcessGPUFeatures();
}

void OpenGLState::SetVSyncInterval(int interval) {
#ifdef _WIN32
	if (wglSwapIntervalEXT)
		wglSwapIntervalEXT(interval);
#endif
}
<commit_msg>Add gl_extensions.ARB_shader_image_load_store<commit_after>#include <stdlib.h>

#include "base/logging.h"
#include "base/NativeApp.h"
#include "gl_state.h"

#ifdef _WIN32
#include "GL/wglew.h"
#endif

#if defined(USING_GLES2)
#if defined(ANDROID) || defined(BLACKBERRY)
PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC eglGetSystemTimeFrequencyNV;
PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV;
PFNGLDRAWTEXTURENVPROC glDrawTextureNV;
PFNGLCOPYIMAGESUBDATANVPROC glCopyImageSubDataNV ;
PFNGLMAPBUFFERPROC glMapBuffer;

PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT;
PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOES;
PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOES;
PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArraysOES;
PFNGLISVERTEXARRAYOESPROC glIsVertexArrayOES;
#endif
#endif

OpenGLState glstate;
GLExtensions gl_extensions;
std::string g_all_gl_extensions;
std::string g_all_egl_extensions;

int OpenGLState::state_count = 0;

void OpenGLState::Initialize() {
	if (initialized)
		return;
	initialized = true;

	Restore();
}

void OpenGLState::Restore() {
	int count = 0;

	blend.restore(); count++;
	blendEquation.restore(); count++;
	blendFuncSeparate.restore(); count++;
	blendColor.restore(); count++;

	scissorTest.restore(); count++;
	scissorRect.restore(); count++;

	cullFace.restore(); count++;
	cullFaceMode.restore(); count++;
	frontFace.restore(); count++;

	depthTest.restore(); count++;
	depthRange.restore(); count++;
	depthFunc.restore(); count++;
	depthWrite.restore(); count++;

	colorMask.restore(); count++;
	viewport.restore(); count++;

	stencilTest.restore(); count++;
	stencilOp.restore(); count++;
	stencilFunc.restore(); count++;

	dither.restore(); count++;

#if !defined(USING_GLES2)
	colorLogicOp.restore(); count++;
	logicOp.restore(); count++;
#endif

	if (count != state_count) {
		FLOG("OpenGLState::Restore is missing some states");
	}
}

// http://stackoverflow.com/questions/16147700/opengl-es-using-tegra-specific-extensions-gl-ext-texture-array

void CheckGLExtensions() {
	// Make sure to only do this once. It's okay to call CheckGLExtensions from wherever.
	static bool done = false;
	if (done)
		return;
	done = true;
	memset(&gl_extensions, 0, sizeof(gl_extensions));

	const char *renderer = (const char *)glGetString(GL_RENDERER);
	const char *versionStr = (const char *)glGetString(GL_VERSION);

	// Check vendor string to try and guess GPU
	const char *cvendor = (char *)glGetString(GL_VENDOR);
	// TODO: move this stuff to gpu_features.cpp
	if (cvendor) {
		const std::string vendor(cvendor);
		if (vendor == "NVIDIA Corporation"
			|| vendor == "Nouveau"
			|| vendor == "nouveau") {
				gl_extensions.gpuVendor = GPU_VENDOR_NVIDIA;
		} else if (vendor == "Advanced Micro Devices, Inc."
			|| vendor == "ATI Technologies Inc.") {
				gl_extensions.gpuVendor = GPU_VENDOR_AMD;
		} else if (vendor == "Intel"
			|| vendor == "Intel Inc."
			|| vendor == "Intel Corporation"
			|| vendor == "Tungsten Graphics, Inc") { // We'll assume this last one means Intel
				gl_extensions.gpuVendor = GPU_VENDOR_INTEL;
		} else if (vendor == "ARM") {
			gl_extensions.gpuVendor = GPU_VENDOR_ARM;
		} else if (vendor == "Imagination Technologies") {
			gl_extensions.gpuVendor = GPU_VENDOR_POWERVR;
		} else if (vendor == "Qualcomm") {
			gl_extensions.gpuVendor = GPU_VENDOR_ADRENO;
		} else if (vendor == "Broadcom") {
			gl_extensions.gpuVendor = GPU_VENDOR_BROADCOM;
			// Just for reference: Galaxy Y has renderer == "VideoCore IV HW"
		} else {
			gl_extensions.gpuVendor = GPU_VENDOR_UNKNOWN;
		}
	} else {
		gl_extensions.gpuVendor = GPU_VENDOR_UNKNOWN;
	}

	ILOG("GPU Vendor : %s ; GL version str: %s", cvendor, versionStr ? versionStr : "N/A");

#ifndef USING_GLES2
	char buffer[64] = {0};
	if (versionStr) {
		strncpy(buffer, versionStr, 63);
	}
	const char *lastNumStart = buffer;
	int numVer = 0;
	int len = (int)strlen(buffer);
	for (int i = 0; i < len && numVer < 3; i++) {
		if (buffer[i] == '.') {
			buffer[i] = 0;
			gl_extensions.ver[numVer++] = strtol(lastNumStart, NULL, 10);
			i++;
			lastNumStart = buffer + i;
		}
	}
	if (numVer < 3)
		gl_extensions.ver[numVer++] = strtol(lastNumStart, NULL, 10);
#else
	gl_extensions.ver[0] = 2;
#endif

#if defined(USING_GLES2)
	// MAY_HAVE_GLES3 defined on all platforms that support it
#if defined(MAY_HAVE_GLES3)
	// Try to load GLES 3.0 only if "3.0" found in version
	// This simple heuristic avoids issues on older devices where you can only call eglGetProcAddress a limited
	// number of times.
	if (strstr(versionStr, "3.0") && GL_TRUE == gl3stubInit()) {
		gl_extensions.ver[0] = 3;
		gl_extensions.GLES3 = true;
		ILOG("Full OpenGL ES 3.0 support detected!\n");
		// Though, let's ban Mali from the GLES 3 path for now, see #4078
		if (strstr(renderer, "Mali") != 0) {
			gl_extensions.GLES3 = false;
		}
	}
#endif
#else
	// If the GL version >= 4.3, we know it's a true superset of OpenGL ES 3.0 and can thus enable
	// all the same modern paths.
	// Most of it could be enabled on lower GPUs as well, but let's start this way.
	if (gl_extensions.VersionGEThan(4, 3, 0)) {
		gl_extensions.GLES3 = true;
	}
#endif

	const char *extString = (const char *)glGetString(GL_EXTENSIONS);
	if (extString) {
		g_all_gl_extensions = extString;
	} else {
		g_all_gl_extensions = "";
	}

#ifdef WIN32
	const char *wglString = 0;
	if (wglGetExtensionsStringEXT)
		wglString = wglGetExtensionsStringEXT();
	if (wglString) {
		gl_extensions.EXT_swap_control_tear = strstr(wglString, "WGL_EXT_swap_control_tear") != 0;
		g_all_egl_extensions = wglString;
	} else {
		g_all_egl_extensions = "";
	}
#elif !defined(USING_GLES2)
	// const char *glXString = glXQueryExtensionString();
	// gl_extensions.EXT_swap_control_tear = strstr(glXString, "GLX_EXT_swap_control_tear") != 0;
#endif

	gl_extensions.NV_draw_texture = strstr(extString, "GL_NV_draw_texture") != 0;
	gl_extensions.ARB_blend_func_extended = strstr(extString, "GL_ARB_blend_func_extended") != 0;
	gl_extensions.ARB_shader_image_load_store = strstr(extString, "GL_ARB_shader_image_load_store") != 0;
	if (gl_extensions.gpuVendor == GPU_VENDOR_INTEL || !gl_extensions.VersionGEThan(3, 0, 0)) {
		// Force this extension to off on sub 3.0 OpenGL versions as it does not seem reliable
		// Also on Intel, see https://github.com/hrydgard/ppsspp/issues/4867
		gl_extensions.ARB_blend_func_extended = false;
	}

#ifdef USING_GLES2
	gl_extensions.OES_packed_depth_stencil = strstr(extString, "GL_OES_packed_depth_stencil") != 0;
	gl_extensions.OES_depth24 = strstr(extString, "GL_OES_depth24") != 0;
	gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0;
	gl_extensions.OES_mapbuffer = strstr(extString, "GL_OES_mapbuffer") != 0;
	gl_extensions.EXT_blend_minmax = strstr(extString, "GL_EXT_blend_minmax") != 0;
	gl_extensions.EXT_shader_framebuffer_fetch = (strstr(extString, "GL_EXT_shader_framebuffer_fetch") != 0) || (strstr(extString, "GL_NV_shader_framebuffer_fetch") != 0);
	gl_extensions.NV_copy_image = strstr(extString, "GL_NV_copy_image") != 0;
	gl_extensions.EXT_unpack_subimage = strstr(extString, "GL_EXT_unpack_subimage") != 0;
#if defined(ANDROID) || defined(BLACKBERRY)
	// On Android, incredibly, this is not consistently non-zero! It does seem to have the same value though.
	// https://twitter.com/ID_AA_Carmack/status/387383037794603008
#ifdef _DEBUG
	void *invalidAddress = (void *)eglGetProcAddress("InvalidGlCall1");
	void *invalidAddress2 = (void *)eglGetProcAddress("AnotherInvalidGlCall2");
	DLOG("Addresses returned for invalid extensions: %p %p", invalidAddress, invalidAddress2);
#endif

	if (gl_extensions.NV_draw_texture) {
		glDrawTextureNV = (PFNGLDRAWTEXTURENVPROC)eglGetProcAddress("glDrawTextureNV");
	}

	if (gl_extensions.NV_copy_image) {
		glCopyImageSubDataNV = (PFNGLCOPYIMAGESUBDATANVPROC)eglGetProcAddress("glCopyImageSubDataNV");
	}

	gl_extensions.OES_vertex_array_object = strstr(extString, "GL_OES_vertex_array_object") != 0;
	if (gl_extensions.OES_vertex_array_object) {
		glGenVertexArraysOES = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress ( "glGenVertexArraysOES" );
		glBindVertexArrayOES = (PFNGLBINDVERTEXARRAYOESPROC)eglGetProcAddress ( "glBindVertexArrayOES" );
		glDeleteVertexArraysOES = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress ( "glDeleteVertexArraysOES" );
		glIsVertexArrayOES = (PFNGLISVERTEXARRAYOESPROC)eglGetProcAddress ( "glIsVertexArrayOES" );
	}

	gl_extensions.EXT_discard_framebuffer = strstr(extString, "GL_EXT_discard_framebuffer") != 0;
	if (gl_extensions.EXT_discard_framebuffer) {
		glDiscardFramebufferEXT = (PFNGLDISCARDFRAMEBUFFEREXTPROC)eglGetProcAddress("glDiscardFramebufferEXT");
	}
#else
	gl_extensions.OES_vertex_array_object = false;
	gl_extensions.EXT_discard_framebuffer = false;
#endif
#else
	// Desktops support minmax and subimage unpack (GL_UNPACK_ROW_LENGTH etc)
	gl_extensions.EXT_blend_minmax = true;
	gl_extensions.EXT_unpack_subimage = true;
#endif
	// GLES 3 subsumes many ES2 extensions.
	if (gl_extensions.GLES3) {
		gl_extensions.EXT_unpack_subimage = true;
	}

#if defined(ANDROID) || defined(BLACKBERRY)
	if (gl_extensions.OES_mapbuffer) {
		glMapBuffer = (PFNGLMAPBUFFERPROC)eglGetProcAddress( "glMapBufferOES" );
	}

	// Look for EGL extensions
	EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);

	const char *eglString = eglQueryString(display, EGL_EXTENSIONS);
	if (eglString) {
		g_all_egl_extensions = eglString;

		gl_extensions.EGL_NV_system_time = strstr(eglString, "EGL_NV_system_time") != 0;
		gl_extensions.EGL_NV_coverage_sample = strstr(eglString, "EGL_NV_coverage_sample") != 0;

		if (gl_extensions.EGL_NV_system_time) {
			eglGetSystemTimeNV = (PFNEGLGETSYSTEMTIMENVPROC) eglGetProcAddress("eglGetSystemTimeNV");
			eglGetSystemTimeFrequencyNV = (PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) eglGetProcAddress("eglGetSystemTimeFrequencyNV");
		}
	} else {
		g_all_egl_extensions = "";
	}
#endif

#ifdef USING_GLES2
	gl_extensions.FBO_ARB = true;
	gl_extensions.FBO_EXT = false;
	gl_extensions.ATIClampBug = gl_extensions.gpuVendor == GPU_VENDOR_NVIDIA;   // Tegras - TODO: more specific check
#else
	gl_extensions.FBO_ARB = false;
	gl_extensions.FBO_EXT = false;
	gl_extensions.PBO_ARB = true;
	if (extString) {
		gl_extensions.FBO_ARB = strstr(extString, "GL_ARB_framebuffer_object") != 0;
		gl_extensions.FBO_EXT = strstr(extString, "GL_EXT_framebuffer_object") != 0;
		gl_extensions.PBO_ARB = strstr(extString, "GL_ARB_pixel_buffer_object") != 0;
		gl_extensions.ATIClampBug = ((strncmp(renderer, "ATI RADEON X", 12) == 0) || (strncmp(renderer, "ATI MOBILITY RADEON X", 21) == 0));
	}
#endif

	ProcessGPUFeatures();
}

void OpenGLState::SetVSyncInterval(int interval) {
#ifdef _WIN32
	if (wglSwapIntervalEXT)
		wglSwapIntervalEXT(interval);
#endif
}
<|endoftext|>


<commit_before>#include "symtab.h"
#include "util.h"
#include <map>

using namespace std;

map<string,string> symtab;
map<string,string> revsymtab;
int label_count = 0;

bool add_to_symtab(std::string symbol, std::string value) {
	if ( symtab.count(symbol) )
		return false;
	symtab[symbol] = value;
	revsymtab[value] = symbol;
	return true;
}

bool read_from_symtab(std::string symbol, std::string &value) {
	if ( !symtab.count(symbol) )
		return false;
	value = symtab[symbol];
	return true;
}

bool find_from_symtab(std::string &symbol, std::string value) {
	if ( !revsymtab.count(value) )
		return false;
	symbol = revsymtab[value];
	return true;
}

bool give_label(std::string &label, std::string location) {
	if ( find_from_symtab(label,location) )
		return true;
	label = "label" + int2str(label_count++);
	add_to_symtab(label,location);
	return false;
}

bool give_label(std::string location) {
	string temp;
	return give_label(temp,location);
}

void initialize_symtab() {
	symtab.clear();
	revsymtab.clear();
	label_count = 0;
}

bool are_same_in_symtab(std::string symbol, std::string value) {
	string temp;
	if ( !read_from_symtab(symbol,temp) ) {
		return false;
	}
	return (value==temp);
}<commit_msg>Clean up symtab.cpp<commit_after>#include "symtab.h"
#include "util.h"
#include <map>

using namespace std;

map<string,string> symtab;
map<string,string> revsymtab;
int label_count = 0;

bool add_to_symtab(std::string symbol, std::string value) {
	if ( symtab.count(symbol) )
		return false;
	symtab[symbol] = value;
	revsymtab[value] = symbol;
	return true;
}

bool find_from_symtab(std::string &symbol, std::string value) {
	if ( !revsymtab.count(value) )
		return false;
	symbol = revsymtab[value];
	return true;
}

bool give_label(std::string location) {
	string label;
	if ( find_from_symtab(label,location) )
		return true;
	label = "label" + int2str(label_count++);
	add_to_symtab(label,location);
	return false;
}

void initialize_symtab() {
	symtab.clear();
	revsymtab.clear();
	label_count = 0;
}
<|endoftext|>


<commit_before>/***********************************************************************
    filename:   ShaderParameterBindings.cpp
    created:    18th July 2013
    author:     Lukas Meindl
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2013 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/

#include "CEGUI/ShaderParameterBindings.h"
#include "CEGUI/System.h"

#include "Glm/glm.hpp"

namespace CEGUI
{
//----------------------------------------------------------------------------//
ShaderParameterBindings::ShaderParameterBindings()
{
}

//----------------------------------------------------------------------------//
ShaderParameterBindings::~ShaderParameterBindings()
{
    ShaderParameterBindingsMap::iterator current = d_shaderParameterBindings.begin();
    ShaderParameterBindingsMap::iterator end = d_shaderParameterBindings.end();

    while (current != end)
    {
        delete current->second;

        current = d_shaderParameterBindings.erase(current);
    }
}

//----------------------------------------------------------------------------//
void ShaderParameterBindings::removeParameter(const std::string& parameterName)
{
    ShaderParameterBindingsMap::iterator found_iterator = d_shaderParameterBindings.find(parameterName);
    if (found_iterator != d_shaderParameterBindings.end())
    {
        delete found_iterator->second;
        d_shaderParameterBindings.erase(found_iterator);
    }
}

//----------------------------------------------------------------------------//
void ShaderParameterBindings::setParameter(const std::string& parameterName, ShaderParameter* shaderParameter)
{
    std::map<std::string, ShaderParameter*>::iterator iter = d_shaderParameterBindings.find(parameterName);
    if(iter != d_shaderParameterBindings.end())
    {
        delete iter->second;
        iter->second = shaderParameter;
    }
    else
    {
        std::pair<std::string, ShaderParameter*> shader_params_pair(parameterName, shaderParameter);
        d_shaderParameterBindings.insert(shader_params_pair);
    }
}

//----------------------------------------------------------------------------//
void ShaderParameterBindings::setParameter(const std::string& parameterName, const glm::mat4& matrix)
{
    ShaderParameterMatrix* shaderParameterMatrix = new ShaderParameterMatrix(matrix);

    setParameter(parameterName, shaderParameterMatrix);
}

//----------------------------------------------------------------------------//
void ShaderParameterBindings::setParameter(const std::string& parameterName, const CEGUI::Texture* texture)
{
    ShaderParameterTexture* shaderParameterTexture = new ShaderParameterTexture(texture);

    setParameter(parameterName, shaderParameterTexture);
}

//----------------------------------------------------------------------------//
const ShaderParameterBindings::ShaderParameterBindingsMap& ShaderParameterBindings::getShaderParameterBindings()
{
    return d_shaderParameterBindings;
}

//----------------------------------------------------------------------------//
}
<commit_msg>FIX: wrong case<commit_after>/***********************************************************************
    filename:   ShaderParameterBindings.cpp
    created:    18th July 2013
    author:     Lukas Meindl
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2013 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/

#include "CEGUI/ShaderParameterBindings.h"
#include "CEGUI/System.h"

#include "glm/glm.hpp"

namespace CEGUI
{
//----------------------------------------------------------------------------//
ShaderParameterBindings::ShaderParameterBindings()
{
}

//----------------------------------------------------------------------------//
ShaderParameterBindings::~ShaderParameterBindings()
{
    ShaderParameterBindingsMap::iterator current = d_shaderParameterBindings.begin();
    ShaderParameterBindingsMap::iterator end = d_shaderParameterBindings.end();

    while (current != end)
    {
        delete current->second;

        current = d_shaderParameterBindings.erase(current);
    }
}

//----------------------------------------------------------------------------//
void ShaderParameterBindings::removeParameter(const std::string& parameterName)
{
    ShaderParameterBindingsMap::iterator found_iterator = d_shaderParameterBindings.find(parameterName);
    if (found_iterator != d_shaderParameterBindings.end())
    {
        delete found_iterator->second;
        d_shaderParameterBindings.erase(found_iterator);
    }
}

//----------------------------------------------------------------------------//
void ShaderParameterBindings::setParameter(const std::string& parameterName, ShaderParameter* shaderParameter)
{
    std::map<std::string, ShaderParameter*>::iterator iter = d_shaderParameterBindings.find(parameterName);
    if(iter != d_shaderParameterBindings.end())
    {
        delete iter->second;
        iter->second = shaderParameter;
    }
    else
    {
        std::pair<std::string, ShaderParameter*> shader_params_pair(parameterName, shaderParameter);
        d_shaderParameterBindings.insert(shader_params_pair);
    }
}

//----------------------------------------------------------------------------//
void ShaderParameterBindings::setParameter(const std::string& parameterName, const glm::mat4& matrix)
{
    ShaderParameterMatrix* shaderParameterMatrix = new ShaderParameterMatrix(matrix);

    setParameter(parameterName, shaderParameterMatrix);
}

//----------------------------------------------------------------------------//
void ShaderParameterBindings::setParameter(const std::string& parameterName, const CEGUI::Texture* texture)
{
    ShaderParameterTexture* shaderParameterTexture = new ShaderParameterTexture(texture);

    setParameter(parameterName, shaderParameterTexture);
}

//----------------------------------------------------------------------------//
const ShaderParameterBindings::ShaderParameterBindingsMap& ShaderParameterBindings::getShaderParameterBindings()
{
    return d_shaderParameterBindings;
}

//----------------------------------------------------------------------------//
}
<|endoftext|>


<commit_before>#ifndef INCLUDE_AL_PARAMETERGUI_HPP
#define INCLUDE_AL_PARAMETERGUI_HPP

/*	AlloSystem --
	Multimedia / virtual environment application class library

	Copyright (C) 2009. AlloSphere Research Group, Media Arts & Technology, UCSB.
	Copyright (C) 2012. The Regents of the University of California.
	All rights reserved.

	Redistribution and use in source and binary forms, with or without
	modification, are permitted provided that the following conditions are met:

		Redistributions of source code must retain the above copyright notice,
		this list of conditions and the following disclaimer.

		Redistributions in binary form must reproduce the above copyright
		notice, this list of conditions and the following disclaimer in the
		documentation and/or other materials provided with the distribution.

		Neither the name of the University of California nor the names of its
		contributors may be used to endorse or promote products derived from
		this software without specific prior written permission.

	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
	AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
	IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
	ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
	LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
	CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
	POSSIBILITY OF SUCH DAMAGE.

	File description:
	GUI generation from group of al::Parameter

	File author(s):
	Andres Cabrera 2016, andres@mat.ucsb.edu
*/

#include <vector>
#include <mutex>
#include <iostream>
#include <algorithm>
#include <memory>
#include <map>

#include "alloGLV/al_ControlGLV.hpp"
#include "allocore/system/al_Parameter.hpp"
#include "allocore/system/al_Preset.hpp"
#include "allocore/io/al_App.hpp"

#include <GLV/glv.h>

namespace al {

class PresetButtons : public glv::Buttons {
public:
	PresetButtons(const glv::Rect& r=glv::Rect(), int nx=1, int ny=1,
	              bool momentary=false, bool mutExc=false,
	              glv::SymbolFunc on=glv::draw::rectangle, glv::SymbolFunc off=0) :
	    glv::Buttons(r, nx, ny, momentary, mutExc, on, off),
	    mStore(false)
	{
	}

	~PresetButtons () {
	}

	void setPresetHandler(PresetHandler &presetHandler) {
		mPresetHandler = &presetHandler;
	}

	virtual bool onAssignData(glv::Data& d, int ind1, int ind2)
	{
		d.set(true); // Always keep one button on
		int index = ind1 + (ind2 *this->sizeX());
		//		std::cout << index << std::endl;
		if (mStore){
			if (presetName == "") {
				presetName = std::to_string(index);
			}
			mPresetHandler->storePreset(index, presetName);
		} else {
			presetName = mPresetHandler->recallPreset(index);
		}
		glv::Buttons::onAssignData(d, ind1, ind2);
		return true;
	}

	bool mStore;
	std::string presetName;

private:
	PresetHandler *mPresetHandler;
	glv::Button *mStoreButton;
};

class ParameterGUI {
public:
	ParameterGUI() :
	    mBox(glv::Direction::S),
	    mPresetHandler(nullptr),
	    mPresetButtons(glv::Rect(), 10, 4, false, true),
	    mButtonScale(1.0f)
	{
		mPresetButtons.enable(glv::Property::SelectOnDrag);
		mPresetButtons.width(200);
		mBox.colors().set(glv::StyleColor::SmokyGray);
		mBox.colors().back.set(0.05, 0.95);
		mBox.colors().selection.set(glv::HSV(0.67,0.5,0.5));
		mBox.enable(glv::Controllable);
		mDetachableGUI << mBox;
	}

	~ParameterGUI() {
		for(WidgetWrapper *w: mWrappers) {
			delete w;
		}
	}

	void setParentWindow(Window& win) {
		mDetachableGUI.parentWindow(win);
	}

	void setParentApp(App *app) {
		App::Windows ws = app->windows();
		if (ws.size() > 0) {
			setParentWindow(*(ws[0]));
		} else {
			std::cout << "ERROR: Can't attach to app. No windows available." << std::endl;
		}
	}

	ParameterGUI &addParameter(Parameter &parameter);

	ParameterGUI &registerPresetHandler(PresetHandler &handler);

	static void presetSavedInButton(const glv::Notification &n) {
		glv::Button *button = static_cast<glv::Button *>(n.receiver());
		button->setValue(false);
	}

	static void presetChangeCallback(int index, void *sender,void *userData)
	{
		ParameterGUI *gui = static_cast<ParameterGUI *>(userData);
		glv::Data &d = gui->mPresetButtons.data();
		const int *shape = d.shape();
		for (int x = 0; x < shape[0]; ++x) {
			for (int y = 0; y < shape[1]; ++y) {
				d.assign<int>(false, x, y); // Must manually set them all off...
			}
		}
		gui->mPresetButtons.presetName = gui->mPresetHandler->availablePresets()[index];
		d.assign<int>(true, index); // Do it this way to avoid the GUi triggering callbacks.

//		gui->mPresetButtons.setValue(index);
		std::cout << "preset Change callback" << std::endl;
	}

	static void widgetChangeCallback(const glv::Notification& n) {
		glv::Widget &sender = *n.sender<glv::Widget>();
		WidgetWrapper &receiver = *n.receiver<WidgetWrapper>();
		receiver.lock->lock();
		double value = sender.getValue<double>();
		receiver.lock->unlock();
		receiver.parameter->setNoCalls(value);
	}

	static void valueChangedCallback(float value, void *sender, void *wrapper) {
		WidgetWrapper *w = static_cast<WidgetWrapper *>(wrapper);
		w->lock->lock(); // Is the setting of the value from the mouse also protected? Do we need to protect that?
		glv::Data &d = w->widget->data();
		d.assign<double>(value); // We need to assign this way to avoid triggering callbacks.
		w->lock->unlock();
	}

	void SetButtonBoxScale(float scale) {mButtonScale = scale;}

	/// Add new parameter to GUI
	ParameterGUI &operator << (Parameter& newParam){ return addParameter(newParam); }

	/// Add new parameter to GUI
	ParameterGUI &operator << (Parameter* newParam){ return addParameter(*newParam); }

	/// Add new View to GUI
	ParameterGUI &operator << (glv::View* newView){
		mBox << newView;
		mBox.fit();
		return *this;}
	/// Add new parameter to GUI
	ParameterGUI &operator << (PresetHandler &presetHandler){ return registerPresetHandler(presetHandler); }

	struct WidgetWrapper {
		Parameter *parameter;
		glv::Widget *widget;
		std::mutex *lock;
	};

private:
	glv::Box mBox;
	PresetButtons mPresetButtons;
	GLVDetachable mDetachableGUI;
	std::mutex mParameterGUILock;
	std::vector<WidgetWrapper *> mWrappers;
	PresetHandler *mPresetHandler;
	float mButtonScale;
};

}

#endif
<commit_msg>Added getDetachableView() to ParameterGUI class<commit_after>#ifndef INCLUDE_AL_PARAMETERGUI_HPP
#define INCLUDE_AL_PARAMETERGUI_HPP

/*	AlloSystem --
	Multimedia / virtual environment application class library

	Copyright (C) 2009. AlloSphere Research Group, Media Arts & Technology, UCSB.
	Copyright (C) 2012. The Regents of the University of California.
	All rights reserved.

	Redistribution and use in source and binary forms, with or without
	modification, are permitted provided that the following conditions are met:

		Redistributions of source code must retain the above copyright notice,
		this list of conditions and the following disclaimer.

		Redistributions in binary form must reproduce the above copyright
		notice, this list of conditions and the following disclaimer in the
		documentation and/or other materials provided with the distribution.

		Neither the name of the University of California nor the names of its
		contributors may be used to endorse or promote products derived from
		this software without specific prior written permission.

	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
	AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
	IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
	ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
	LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
	CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
	POSSIBILITY OF SUCH DAMAGE.

	File description:
	GUI generation from group of al::Parameter

	File author(s):
	Andres Cabrera 2016, andres@mat.ucsb.edu
*/

#include <vector>
#include <mutex>
#include <iostream>
#include <algorithm>
#include <memory>
#include <map>

#include "alloGLV/al_ControlGLV.hpp"
#include "allocore/system/al_Parameter.hpp"
#include "allocore/system/al_Preset.hpp"
#include "allocore/io/al_App.hpp"

#include <GLV/glv.h>

namespace al {

class PresetButtons : public glv::Buttons {
public:
	PresetButtons(const glv::Rect& r=glv::Rect(), int nx=1, int ny=1,
	              bool momentary=false, bool mutExc=false,
	              glv::SymbolFunc on=glv::draw::rectangle, glv::SymbolFunc off=0) :
	    glv::Buttons(r, nx, ny, momentary, mutExc, on, off),
	    mStore(false)
	{
	}

	~PresetButtons () {
	}

	void setPresetHandler(PresetHandler &presetHandler) {
		mPresetHandler = &presetHandler;
	}

	virtual bool onAssignData(glv::Data& d, int ind1, int ind2)
	{
		d.set(true); // Always keep one button on
		int index = ind1 + (ind2 *this->sizeX());
		//		std::cout << index << std::endl;
		if (mStore){
			if (presetName == "") {
				presetName = std::to_string(index);
			}
			mPresetHandler->storePreset(index, presetName);
		} else {
			presetName = mPresetHandler->recallPreset(index);
		}
		glv::Buttons::onAssignData(d, ind1, ind2);
		return true;
	}

	bool mStore;
	std::string presetName;

private:
	PresetHandler *mPresetHandler;
	glv::Button *mStoreButton;
};

class ParameterGUI {
public:
	ParameterGUI() :
	    mBox(glv::Direction::S),
	    mPresetButtons(glv::Rect(), 10, 4, false, true),
	    mPresetHandler(nullptr),
	    mButtonScale(1.0f)
	{
		mPresetButtons.enable(glv::Property::SelectOnDrag);
		mPresetButtons.width(200);
		mBox.colors().set(glv::StyleColor::SmokyGray);
		mBox.colors().back.set(0.05, 0.95);
		mBox.colors().selection.set(glv::HSV(0.67,0.5,0.5));
		mBox.enable(glv::Controllable);
		mDetachableGUI << mBox;
	}

	~ParameterGUI() {
		for(WidgetWrapper *w: mWrappers) {
			delete w;
		}
	}

	void setParentWindow(Window& win) {
		mDetachableGUI.parentWindow(win);
	}

	void setParentApp(App *app) {
		App::Windows ws = app->windows();
		if (ws.size() > 0) {
			setParentWindow(*(ws[0]));
		} else {
			std::cout << "ERROR: Can't attach to app. No windows available." << std::endl;
		}
	}

	GLVDetachable &getDetachableView() {return mDetachableGUI;}

	ParameterGUI &addParameter(Parameter &parameter);

	ParameterGUI &registerPresetHandler(PresetHandler &handler);

	static void presetSavedInButton(const glv::Notification &n) {
		glv::Button *button = static_cast<glv::Button *>(n.receiver());
		button->setValue(false);
	}

	static void presetChangeCallback(int index, void *sender,void *userData)
	{
		ParameterGUI *gui = static_cast<ParameterGUI *>(userData);
		glv::Data &d = gui->mPresetButtons.data();
		const int *shape = d.shape();
		for (int x = 0; x < shape[0]; ++x) {
			for (int y = 0; y < shape[1]; ++y) {
				d.assign<int>(false, x, y); // Must manually set them all off...
			}
		}
		gui->mPresetButtons.presetName = gui->mPresetHandler->availablePresets()[index];
		d.assign<int>(true, index); // Do it this way to avoid the GUi triggering callbacks.

//		gui->mPresetButtons.setValue(index);
		std::cout << "preset Change callback" << std::endl;
	}

	static void widgetChangeCallback(const glv::Notification& n) {
		glv::Widget &sender = *n.sender<glv::Widget>();
		WidgetWrapper &receiver = *n.receiver<WidgetWrapper>();
		receiver.lock->lock();
		double value = sender.getValue<double>();
		receiver.lock->unlock();
		receiver.parameter->setNoCalls(value);
	}

	static void valueChangedCallback(float value, void *sender, void *wrapper) {
		WidgetWrapper *w = static_cast<WidgetWrapper *>(wrapper);
		w->lock->lock(); // Is the setting of the value from the mouse also protected? Do we need to protect that?
		glv::Data &d = w->widget->data();
		d.assign<double>(value); // We need to assign this way to avoid triggering callbacks.
		w->lock->unlock();
	}

	void SetButtonBoxScale(float scale) {mButtonScale = scale;}

	/// Add new parameter to GUI
	ParameterGUI &operator << (Parameter& newParam){ return addParameter(newParam); }

	/// Add new parameter to GUI
	ParameterGUI &operator << (Parameter* newParam){ return addParameter(*newParam); }

	/// Add new View to GUI
	ParameterGUI &operator << (glv::View* newView){
		mBox << newView;
		mBox.fit();
		return *this;}
	/// Add new parameter to GUI
	ParameterGUI &operator << (PresetHandler &presetHandler){ return registerPresetHandler(presetHandler); }

	struct WidgetWrapper {
		Parameter *parameter;
		glv::Widget *widget;
		std::mutex *lock;
	};

private:
	glv::Box mBox;
	PresetButtons mPresetButtons;
	GLVDetachable mDetachableGUI;
	std::mutex mParameterGUILock;
	std::vector<WidgetWrapper *> mWrappers;
	PresetHandler *mPresetHandler;
	float mButtonScale;
};

}

#endif
<|endoftext|>


<commit_before>#ifndef BOX_HPP
#define BOX_HPP

#include <glm/vec3.hpp>
#include <glm/glm.hpp>
#include "shape.hpp"
#include "hit.hpp"

class Box: public Shape{
    glm::vec3 min_;
    glm::vec3 max_;

  public:
    Box();
    Box(glm::vec3 const& min, glm::vec3 const& max);
    Box(glm::vec3 const& min, glm::vec3 const& max, std::shared_ptr<Material> const& mat, std::string const& name);

    glm::vec3 const& get_min() const;
    glm::vec3 const& get_max() const;

    void sortMinMax();

    Hit intersect(Ray const& inray) override;
};

#endif<commit_msg>Final Commit<commit_after>#ifndef BOX_HPP
#define BOX_HPP

#include <glm/vec3.hpp>
#include <glm/glm.hpp>
#include "shape.hpp"
#include "hit.hpp"

class Box: public Shape
{
public:

  Box();

  Box(glm::vec3 const& min, glm::vec3 const& max);

  Box(glm::vec3 const& min, glm::vec3 const& max, std::shared_ptr<Material> const& mat, std::string const& name);

  glm::vec3 const& get_min() const;

  glm::vec3 const& get_max() const;

  void sortMinMax();

  Hit intersect(Ray const& inray) override;

private:

	glm::vec3 min_;

  glm::vec3 max_;
};

#endif<|endoftext|>


<commit_before>/*
 *    Copyright (c) <2002-2009> <Jean-Philippe Barrette-LaPierre>
 *
 *    Permission is hereby granted, free of charge, to any person obtaining
 *    a copy of this software and associated documentation files
 *    (curlpp), to deal in the Software without restriction,
 *    including without limitation the rights to use, copy, modify, merge,
 *    publish, distribute, sublicense, and/or sell copies of the Software,
 *    and to permit persons to whom the Software is furnished to do so,
 *    subject to the following conditions:
 *
 *    The above copyright notice and this permission notice shall be included
 *    in all copies or substantial portions of the Software.
 *
 *    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 *    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 *    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 *    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 *    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#ifndef CURLPP_FORM_HPP
#define CURLPP_FORM_HPP

#include "internal/buildconfig.h"
#include <utilspp/clone_ptr.hpp>

#include <curl/curl.h>

#include <list>
#include <string>

#pragma warning(push)
#pragma warning(disable: 4512) // assignment operator could not be generated

namespace curlpp
{

	class FormPart;

	typedef std::list<utilspp::clone_ptr<curlpp::FormPart> > Forms;

	/**
	* This class is used internally to wrap over curl_httppost
	* class.
	*/

	class CURLPPAPI HttpPost
	{

	public:

		HttpPost(const Forms & posts);
		HttpPost();
		~HttpPost();

		/**
		* initialize the HTTP post with the list of forms. The Forms
		* will be cloned.
		*/
		HttpPost & operator=(const Forms & posts);

		operator Forms() { return getList(); }

		/**
		* return the curl_httppost representation of this HTTP Post.
		* Be aware that the memory return is owned by the current
		* instance, so don't try to delete it.
		*/
		::curl_httppost * cHttpPost() const;

		/**
		* Free all HTTP posts.
		*/
		void clear();

		/**
		* Get the list.
		*/
		Forms getList();

	private:

		::curl_httppost * mFirst;
		::curl_httppost * mLast;
		Forms mForms;

	};

	/**
	* This class is the base representation of a post. You need
	* to inherit from it to define a type of post.
	*/

	class CURLPPAPI FormPart
	{
		friend class HttpPost;

	public:

		/**
		* initialize the FormPart. "name" is the name of the field.
		*/
		FormPart(const char * name);

		/**
		* initialize the FormPart. "name" is the name of the field.
		*/
		FormPart(const std::string & name);

		virtual ~FormPart();

		virtual FormPart * clone() const = 0;

	protected:

		/**
		* it will add himself to the curl_httppost * first.
		*/
		virtual void add(::curl_httppost ** first,
			::curl_httppost ** last) = 0;

		/**
		* Contain the name of the field.
		*/
		const std::string mName;

	};

namespace FormParts
{

	/**
	* This class is a file post. It will send a file in the
	* HTTP post.
	*/

	class CURLPPAPI File : public FormPart
	{

	public:

		/**
		* initialize a File part. "name" is the name of the field.
		* "filename" is the string that holds the filename.
		*/
		File(const char * name,
			const char * filename);

		/**
		* initialize a File part. "name" is the name of the field.
		* "filename" is the string that holds the filename.
		* "contentType" is the MIME type of the file.
		*/
		File(const char * name,
			const char * filename,
			const char * contentType);

		/**
		* initialize a File part. "name" is the name of the field.
		* "filename" is the string that holds the filename.
		*/
		File(const std::string & name,
			const std::string & filename);

		/**
		* initialize a File part. "name" is the name of the field.
		* "filename" is the string that holds the filename.
		* "contentType" is the MIME type of the file.
		*/
		File(const std::string & name,
			const std::string & filename,
			const std::string & contentType);

		virtual ~File();

		/**
		* This function will return a copy of the instance.
		*/
		virtual File * clone() const;

	private:

		void add(::curl_httppost ** first,
			::curl_httppost ** last);

	private:

		const std::string mFilename;
		const std::string mContentType;

	};

	/**
	* This class is a file post. It will send a file in the
	* HTTP post.
	*/

	class CURLPPAPI Content : public FormPart
	{

	public:

		/**
		* initialize a Content part. "name" is the name of the field.
		* "content" is the string that holds the filename.
		*/
		Content(const char * name,
			const char * content);

		/**
		* initialize a Content part. "name" is the name of the field.
		* "content" is the string that holds the filename.
		* "contentType" is the MIME type of the file.
		*/
		Content(const char * name,
			const char * content,
			const char * contentType);

		/**
		* initialize a Content part. "name" is the name of the field.
		* "content" is the string that holds the content.
		*/
		Content(const std::string & name,
			const std::string & content);

		/**
		* initialize a Content part. "name" is the name of the field.
		* "content" is the string that holds the content.
		* "content_type" is the MIME type of the file.
		*/
		Content(const std::string & name,
			const std::string & content,
			const std::string & content_type);

		virtual ~Content();

		/**
		* This function will return a copy of the instance.
		*/
		virtual Content * clone() const;

	private:

		void add(::curl_httppost ** first,
			::curl_httppost ** last);

	private:

		const std::string mContent;
		const std::string mContentType;

	};

} // namespace FormParts

} // namespace curlpp

#pragma warning(pop)

namespace cURLpp = curlpp;

#endif //CURLPP_FORM_HPP
<commit_msg>curlpp DLL: Reverting a home-brewed warning fix<commit_after>/*
 *    Copyright (c) <2002-2009> <Jean-Philippe Barrette-LaPierre>
 *
 *    Permission is hereby granted, free of charge, to any person obtaining
 *    a copy of this software and associated documentation files
 *    (curlpp), to deal in the Software without restriction,
 *    including without limitation the rights to use, copy, modify, merge,
 *    publish, distribute, sublicense, and/or sell copies of the Software,
 *    and to permit persons to whom the Software is furnished to do so,
 *    subject to the following conditions:
 *
 *    The above copyright notice and this permission notice shall be included
 *    in all copies or substantial portions of the Software.
 *
 *    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 *    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 *    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 *    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 *    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#ifndef CURLPP_FORM_HPP
#define CURLPP_FORM_HPP

#include "internal/buildconfig.h"
#include <utilspp/clone_ptr.hpp>

#include <curl/curl.h>

#include <list>
#include <string>

namespace curlpp
{

	class FormPart;

	typedef std::list<utilspp::clone_ptr<curlpp::FormPart> > Forms;

	/**
	* This class is used internally to wrap over curl_httppost
	* class.
	*/

	class CURLPPAPI HttpPost
	{

	public:

		HttpPost(const Forms & posts);
		HttpPost();
		~HttpPost();

		/**
		* initialize the HTTP post with the list of forms. The Forms
		* will be cloned.
		*/
		HttpPost & operator=(const Forms & posts);

		operator Forms() { return getList(); }

		/**
		* return the curl_httppost representation of this HTTP Post.
		* Be aware that the memory return is owned by the current
		* instance, so don't try to delete it.
		*/
		::curl_httppost * cHttpPost() const;

		/**
		* Free all HTTP posts.
		*/
		void clear();

		/**
		* Get the list.
		*/
		Forms getList();

	private:

		::curl_httppost * mFirst;
		::curl_httppost * mLast;
		Forms mForms;

	};

	/**
	* This class is the base representation of a post. You need
	* to inherit from it to define a type of post.
	*/

	class CURLPPAPI FormPart
	{
		friend class HttpPost;

	public:

		/**
		* initialize the FormPart. "name" is the name of the field.
		*/
		FormPart(const char * name);

		/**
		* initialize the FormPart. "name" is the name of the field.
		*/
		FormPart(const std::string & name);

		virtual ~FormPart();

		virtual FormPart * clone() const = 0;

	protected:

		/**
		* it will add himself to the curl_httppost * first.
		*/
		virtual void add(::curl_httppost ** first,
			::curl_httppost ** last) = 0;

		/**
		* Contain the name of the field.
		*/
		const std::string mName;

	};

namespace FormParts
{

	/**
	* This class is a file post. It will send a file in the
	* HTTP post.
	*/

	class CURLPPAPI File : public FormPart
	{

	public:

		/**
		* initialize a File part. "name" is the name of the field.
		* "filename" is the string that holds the filename.
		*/
		File(const char * name,
			const char * filename);

		/**
		* initialize a File part. "name" is the name of the field.
		* "filename" is the string that holds the filename.
		* "contentType" is the MIME type of the file.
		*/
		File(const char * name,
			const char * filename,
			const char * contentType);

		/**
		* initialize a File part. "name" is the name of the field.
		* "filename" is the string that holds the filename.
		*/
		File(const std::string & name,
			const std::string & filename);

		/**
		* initialize a File part. "name" is the name of the field.
		* "filename" is the string that holds the filename.
		* "contentType" is the MIME type of the file.
		*/
		File(const std::string & name,
			const std::string & filename,
			const std::string & contentType);

		virtual ~File();

		/**
		* This function will return a copy of the instance.
		*/
		virtual File * clone() const;

	private:

		void add(::curl_httppost ** first,
			::curl_httppost ** last);

	private:

		const std::string mFilename;
		const std::string mContentType;

	};

	/**
	* This class is a file post. It will send a file in the
	* HTTP post.
	*/

	class CURLPPAPI Content : public FormPart
	{

	public:

		/**
		* initialize a Content part. "name" is the name of the field.
		* "content" is the string that holds the filename.
		*/
		Content(const char * name,
			const char * content);

		/**
		* initialize a Content part. "name" is the name of the field.
		* "content" is the string that holds the filename.
		* "contentType" is the MIME type of the file.
		*/
		Content(const char * name,
			const char * content,
			const char * contentType);

		/**
		* initialize a Content part. "name" is the name of the field.
		* "content" is the string that holds the content.
		*/
		Content(const std::string & name,
			const std::string & content);

		/**
		* initialize a Content part. "name" is the name of the field.
		* "content" is the string that holds the content.
		* "content_type" is the MIME type of the file.
		*/
		Content(const std::string & name,
			const std::string & content,
			const std::string & content_type);

		virtual ~Content();

		/**
		* This function will return a copy of the instance.
		*/
		virtual Content * clone() const;

	private:

		void add(::curl_httppost ** first,
			::curl_httppost ** last);

	private:

		const std::string mContent;
		const std::string mContentType;

	};

} // namespace FormParts

} // namespace curlpp

namespace cURLpp = curlpp;

#endif //CURLPP_FORM_HPP
<|endoftext|>


<commit_before>/**
 * Appcelerator Titanium - licensed under the Apache Public License 2
 * see LICENSE in the root folder for details on the license.
 * Copyright (c) 2009 Appcelerator, Inc. All Rights Reserved.
 */

#include "win32_pipe.h"

namespace ti
{
	Win32Pipe::Win32Pipe(bool isReader) :
		NativePipe(isReader),
		logger(Logger::Get("Process.Win32Pipe"))
	{
		SECURITY_ATTRIBUTES attr;
		attr.nLength              = sizeof(attr);
		attr.lpSecurityDescriptor = NULL;
		attr.bInheritHandle       = TRUE;

		::CreatePipe(&readHandle, &writeHandle, &attr, 0);
	}

	void Win32Pipe::Close()
	{
		NativePipe::Close();
	}

	int Win32Pipe::RawRead(char *buffer, int size)
	{
		if (readHandle != INVALID_HANDLE_VALUE) {
			DWORD bytesRead;
			BOOL ok = ReadFile(readHandle, buffer, size, &bytesRead, NULL);
			int error = GetLastError();
			if (ok)
			{
				return bytesRead;
			}
			else if (error == ERROR_BROKEN_PIPE)
			{
				return -1;
			}
			else
			{
				throw ValueException::FromString("Error writing anonymous pipe");
			}
		}
		return -1;
	}

	int Win32Pipe::RawWrite(const char *data, int size)
	{
		if (writeHandle != INVALID_HANDLE_VALUE) {
			DWORD bytesWritten;
			BOOL ok = WriteFile(writeHandle, (LPCVOID)data, size, &bytesWritten, NULL);
			if (ok || GetLastError() == ERROR_BROKEN_PIPE) {
				return bytesWritten;
			}
			else {
				throw ValueException::FromString("Error writing anonymous pipe");
			}
		}
		return 0;
	}

	void Win32Pipe::DuplicateRead(HANDLE process, LPHANDLE handle)
	{
		DuplicateHandle(process, readHandle, process, handle, 0, TRUE, DUPLICATE_SAME_ACCESS);
      	CloseHandle(readHandle);
	}

	void Win32Pipe::DuplicateWrite(HANDLE process, LPHANDLE handle)
	{
		DuplicateHandle(process, writeHandle, process, handle, 0, TRUE, DUPLICATE_SAME_ACCESS);
		CloseHandle(writeHandle);
	}

	void Win32Pipe::CloseNativeRead()
	{
		if (readHandle != INVALID_HANDLE_VALUE)
		{
			CloseHandle(readHandle);
			readHandle = INVALID_HANDLE_VALUE;
		}
	}

	void Win32Pipe::CloseNativeWrite()
	{
		if (writeHandle != INVALID_HANDLE_VALUE)
		{
			CloseHandle(writeHandle);
			writeHandle = INVALID_HANDLE_VALUE;
		}
	}

	void Win32Pipe::CloseNative()
	{
		this->CloseNativeRead();
		this->CloseNativeWrite();
	}
}
<commit_msg>use inherited handles in pipe constructor<commit_after>/**
 * Appcelerator Titanium - licensed under the Apache Public License 2
 * see LICENSE in the root folder for details on the license.
 * Copyright (c) 2009 Appcelerator, Inc. All Rights Reserved.
 */

#include "win32_pipe.h"

namespace ti
{
	Win32Pipe::Win32Pipe(bool isReader) :
		NativePipe(isReader),
		logger(Logger::Get("Process.Win32Pipe"))
	{
		SECURITY_ATTRIBUTES attr;
		attr.nLength              = sizeof(attr);
		attr.lpSecurityDescriptor = NULL;
		attr.bInheritHandle       = FALSE;

		::CreatePipe(&readHandle, &writeHandle, &attr, 0);
	}

	void Win32Pipe::Close()
	{
		NativePipe::Close();
	}

	int Win32Pipe::RawRead(char *buffer, int size)
	{
		if (readHandle != INVALID_HANDLE_VALUE) {
			DWORD bytesRead;
			BOOL ok = ReadFile(readHandle, buffer, size, &bytesRead, NULL);
			int error = GetLastError();
			if (ok)
			{
				return bytesRead;
			}
			else if (error == ERROR_BROKEN_PIPE)
			{
				return -1;
			}
			else
			{
				throw ValueException::FromString("Error writing anonymous pipe");
			}
		}
		return -1;
	}

	int Win32Pipe::RawWrite(const char *data, int size)
	{
		if (writeHandle != INVALID_HANDLE_VALUE) {
			DWORD bytesWritten;
			BOOL ok = WriteFile(writeHandle, (LPCVOID)data, size, &bytesWritten, NULL);
			if (ok || GetLastError() == ERROR_BROKEN_PIPE) {
				return bytesWritten;
			}
			else {
				throw ValueException::FromString("Error writing anonymous pipe");
			}
		}
		return 0;
	}

	void Win32Pipe::DuplicateRead(HANDLE process, LPHANDLE handle)
	{
		DuplicateHandle(process, readHandle, process, handle, 0, TRUE, DUPLICATE_SAME_ACCESS);
      	CloseHandle(readHandle);
	}

	void Win32Pipe::DuplicateWrite(HANDLE process, LPHANDLE handle)
	{
		DuplicateHandle(process, writeHandle, process, handle, 0, TRUE, DUPLICATE_SAME_ACCESS);
		CloseHandle(writeHandle);
	}

	void Win32Pipe::CloseNativeRead()
	{
		if (readHandle != INVALID_HANDLE_VALUE)
		{
			CloseHandle(readHandle);
			readHandle = INVALID_HANDLE_VALUE;
		}
	}

	void Win32Pipe::CloseNativeWrite()
	{
		if (writeHandle != INVALID_HANDLE_VALUE)
		{
			CloseHandle(writeHandle);
			writeHandle = INVALID_HANDLE_VALUE;
		}
	}

	void Win32Pipe::CloseNative()
	{
		this->CloseNativeRead();
		this->CloseNativeWrite();
	}
}
<|endoftext|>


<commit_before>#include <include/amici_serialization.h>
#include "testfunctions.h"
#include <include/amici_model.h>
#include <include/amici_solver_cvodes.h>

#include "CppUTest/TestHarness.h"
#include "CppUTestExt/MockSupport.h"

void checkReturnDataEqual(amici::ReturnData const& r, amici::ReturnData const& s) {
    CHECK_EQUAL(r.np, s.np);
    CHECK_EQUAL(r.nk, s.nk);
    CHECK_EQUAL(r.nx, s.nx);
    CHECK_EQUAL(r.nxtrue, s.nxtrue);
    CHECK_EQUAL(r.ny, s.ny);
    CHECK_EQUAL(r.nytrue, s.nytrue);
    CHECK_EQUAL(r.nz, s.nz);
    CHECK_EQUAL(r.nztrue, s.nztrue);
    CHECK_EQUAL(r.ne, s.ne);
    CHECK_EQUAL(r.nJ, s.nJ);
    CHECK_EQUAL(r.nplist, s.nplist);
    CHECK_EQUAL(r.nmaxevent, s.nmaxevent);
    CHECK_EQUAL(r.nt, s.nt);
    CHECK_EQUAL(r.newton_maxsteps, s.newton_maxsteps);
    CHECK_TRUE(r.pscale == s.pscale);
    CHECK_EQUAL(r.o2mode, s.o2mode);
    CHECK_EQUAL(r.sensi, s.sensi);
    CHECK_EQUAL(r.sensi_meth, s.sensi_meth);

    using amici::checkEqualArray;
    checkEqualArray(r.ts, s.ts, 1e-16, 1e-16, "ts");
    checkEqualArray(r.xdot, s.xdot, 1e-16, 1e-16, "xdot");
    checkEqualArray(r.J, s.J, 1e-16, 1e-16, "J");
    checkEqualArray(r.z, s.z, 1e-16, 1e-16, "z");
    checkEqualArray(r.sigmaz, s.sigmaz,1e-16, 1e-16, "sigmaz");
    checkEqualArray(r.sz, s.sz, 1e-16, 1e-16, "sz");
    checkEqualArray(r.ssigmaz, s.ssigmaz, 1e-16, 1e-16, "ssigmaz");
    checkEqualArray(r.rz, s.rz, 1e-16, 1e-16, "rz");
    checkEqualArray(r.srz, s.srz, 1e-16, 1e-16, "srz");
    checkEqualArray(r.s2rz, s.s2rz, 1e-16, 1e-16, "s2rz");
    checkEqualArray(r.x, s.x, 1e-16, 1e-16, "x");
    checkEqualArray(r.sx, s.sx, 1e-16, 1e-16, "sx");

    checkEqualArray(r.y, s.y, 1e-16, 1e-16, "y");
    checkEqualArray(r.sigmay, s.sigmay, 1e-16, 1e-16, "sigmay");
    checkEqualArray(r.sy, s.sy, 1e-16, 1e-16, "sy");
    checkEqualArray(r.ssigmay, s.ssigmay, 1e-16, 1e-16, "ssigmay");

    CHECK_TRUE(r.numsteps == s.numsteps);
    CHECK_TRUE(r.numstepsB == s.numstepsB);
    CHECK_TRUE(r.numrhsevals == s.numrhsevals);
    CHECK_TRUE(r.numrhsevalsB == s.numrhsevalsB);
    CHECK_TRUE(r.numerrtestfails == s.numerrtestfails);
    CHECK_TRUE(r.numerrtestfailsB == s.numerrtestfailsB);
    CHECK_TRUE(r.numnonlinsolvconvfails == s.numnonlinsolvconvfails);
    CHECK_TRUE(r.numnonlinsolvconvfailsB == s.numnonlinsolvconvfailsB);
    CHECK_TRUE(r.order == s.order);

    CHECK_TRUE(r.newton_status == s.newton_status);
    CHECK_TRUE(r.newton_numsteps == s.newton_numsteps);
    CHECK_TRUE(r.newton_numlinsteps == s.newton_numlinsteps);

    DOUBLES_EQUAL(r.newton_time, s.newton_time, 1e-16);
    checkEqualArray(r.x0, s.x0, 1e-16, 1e-16, "x0");
    checkEqualArray(r.sx0, s.sx0, 1e-16, 1e-16, "sx0");

    CHECK_TRUE(r.llh == s.llh || (std::isnan(r.llh) && std::isnan(s.llh)));
    CHECK_TRUE(r.chi2 == s.chi2 || (std::isnan(r.llh) && std::isnan(s.llh)));
    CHECK_EQUAL(r.status, s.status);

    checkEqualArray(r.sllh, s.sllh, 1e-5, 1e-5, "sllh");
    checkEqualArray(r.s2llh, s.s2llh, 1e-5, 1e-5, "s2llh");
}

// clang-format off
TEST_GROUP(dataSerialization){

    void setup() {

    }

    void teardown() {
    }
};
// clang-format on

TEST(dataSerialization, testFile) {
    int np = 1;
    int nk = 2;
    int nx = 3;
    int nz = 4;
    amici::CVodeSolver solver;
    amici::Model_Test m = amici::Model_Test(nx, nx, 4, 4, nz, nz, 8, 9, 10, 11, 12, 13, 14, 15, amici::AMICI_O2MODE_NONE,
                                             std::vector<realtype>(np,0.0),std::vector<realtype>(nk,0.0),std::vector<int>(np,0),
                                             std::vector<realtype>(nx,0.0),std::vector<int>(nz,0));

    {
        std::ofstream ofs("sstore.dat");
        boost::archive::text_oarchive oar(ofs);
        oar & static_cast<amici::Solver&>(solver);
        oar & static_cast<amici::Model&>(m);
    }
    {
        std::ifstream ifs("sstore.dat");
        boost::archive::text_iarchive iar(ifs);
        amici::CVodeSolver v;
        amici::Model_Test n;
        iar &static_cast<amici::Solver&>(v);
        iar &static_cast<amici::Model&>(n);
        CHECK_TRUE(solver == v);
        CHECK_TRUE(m == n);

    }
}

TEST(dataSerialization, testChar) {
    amici::CVodeSolver solver;
    solver.setAbsoluteTolerance(4);

    int length;
    char *buf = amici::serializeToChar(solver, &length);

    amici::CVodeSolver v = amici::deserializeFromChar<amici::CVodeSolver>(buf, length);

    delete[] buf;
    CHECK_TRUE(solver == v);
}

TEST(dataSerialization, testStdVec) {
    amici::CVodeSolver solver;
    solver.setAbsoluteTolerance(4);

    auto buf = amici::serializeToStdVec(solver);
    amici::CVodeSolver v = amici::deserializeFromChar<amici::CVodeSolver>(buf.data(), buf.size());

    CHECK_TRUE(solver == v);
}

TEST(dataSerialization, testString) {
    int np = 1;
    int nk = 2;
    int nx = 3;
    int nz = 4;
    amici::CVodeSolver solver;
    amici::Model_Test m = amici::Model_Test(nx, nx, 4, 4, nz, nz, 8, 9, 10, 11, 12, 13, 14, 15, amici::AMICI_O2MODE_NONE,
                                             std::vector<realtype>(np,0.0),std::vector<realtype>(nk,0.0),std::vector<int>(np,0),
                                             std::vector<realtype>(nx,0.0),std::vector<int>(nz,0));

    amici::ReturnData r(solver, &m);

    std::string serialized = amici::serializeToString(r);

    checkReturnDataEqual(r, amici::deserializeFromString<amici::ReturnData>(serialized));
}

<commit_msg>fix missing std::nan in testsSerialization.cpp<commit_after>#include <include/amici_serialization.h>
#include "testfunctions.h"
#include <include/amici_model.h>
#include <include/amici_solver_cvodes.h>

#include <cmath>

#include "CppUTest/TestHarness.h"
#include "CppUTestExt/MockSupport.h"

void checkReturnDataEqual(amici::ReturnData const& r, amici::ReturnData const& s) {
    CHECK_EQUAL(r.np, s.np);
    CHECK_EQUAL(r.nk, s.nk);
    CHECK_EQUAL(r.nx, s.nx);
    CHECK_EQUAL(r.nxtrue, s.nxtrue);
    CHECK_EQUAL(r.ny, s.ny);
    CHECK_EQUAL(r.nytrue, s.nytrue);
    CHECK_EQUAL(r.nz, s.nz);
    CHECK_EQUAL(r.nztrue, s.nztrue);
    CHECK_EQUAL(r.ne, s.ne);
    CHECK_EQUAL(r.nJ, s.nJ);
    CHECK_EQUAL(r.nplist, s.nplist);
    CHECK_EQUAL(r.nmaxevent, s.nmaxevent);
    CHECK_EQUAL(r.nt, s.nt);
    CHECK_EQUAL(r.newton_maxsteps, s.newton_maxsteps);
    CHECK_TRUE(r.pscale == s.pscale);
    CHECK_EQUAL(r.o2mode, s.o2mode);
    CHECK_EQUAL(r.sensi, s.sensi);
    CHECK_EQUAL(r.sensi_meth, s.sensi_meth);

    using amici::checkEqualArray;
    checkEqualArray(r.ts, s.ts, 1e-16, 1e-16, "ts");
    checkEqualArray(r.xdot, s.xdot, 1e-16, 1e-16, "xdot");
    checkEqualArray(r.J, s.J, 1e-16, 1e-16, "J");
    checkEqualArray(r.z, s.z, 1e-16, 1e-16, "z");
    checkEqualArray(r.sigmaz, s.sigmaz,1e-16, 1e-16, "sigmaz");
    checkEqualArray(r.sz, s.sz, 1e-16, 1e-16, "sz");
    checkEqualArray(r.ssigmaz, s.ssigmaz, 1e-16, 1e-16, "ssigmaz");
    checkEqualArray(r.rz, s.rz, 1e-16, 1e-16, "rz");
    checkEqualArray(r.srz, s.srz, 1e-16, 1e-16, "srz");
    checkEqualArray(r.s2rz, s.s2rz, 1e-16, 1e-16, "s2rz");
    checkEqualArray(r.x, s.x, 1e-16, 1e-16, "x");
    checkEqualArray(r.sx, s.sx, 1e-16, 1e-16, "sx");

    checkEqualArray(r.y, s.y, 1e-16, 1e-16, "y");
    checkEqualArray(r.sigmay, s.sigmay, 1e-16, 1e-16, "sigmay");
    checkEqualArray(r.sy, s.sy, 1e-16, 1e-16, "sy");
    checkEqualArray(r.ssigmay, s.ssigmay, 1e-16, 1e-16, "ssigmay");

    CHECK_TRUE(r.numsteps == s.numsteps);
    CHECK_TRUE(r.numstepsB == s.numstepsB);
    CHECK_TRUE(r.numrhsevals == s.numrhsevals);
    CHECK_TRUE(r.numrhsevalsB == s.numrhsevalsB);
    CHECK_TRUE(r.numerrtestfails == s.numerrtestfails);
    CHECK_TRUE(r.numerrtestfailsB == s.numerrtestfailsB);
    CHECK_TRUE(r.numnonlinsolvconvfails == s.numnonlinsolvconvfails);
    CHECK_TRUE(r.numnonlinsolvconvfailsB == s.numnonlinsolvconvfailsB);
    CHECK_TRUE(r.order == s.order);

    CHECK_TRUE(r.newton_status == s.newton_status);
    CHECK_TRUE(r.newton_numsteps == s.newton_numsteps);
    CHECK_TRUE(r.newton_numlinsteps == s.newton_numlinsteps);

    DOUBLES_EQUAL(r.newton_time, s.newton_time, 1e-16);
    checkEqualArray(r.x0, s.x0, 1e-16, 1e-16, "x0");
    checkEqualArray(r.sx0, s.sx0, 1e-16, 1e-16, "sx0");

    CHECK_TRUE(r.llh == s.llh || (std::isnan(r.llh) && std::isnan(s.llh)));
    CHECK_TRUE(r.chi2 == s.chi2 || (std::isnan(r.llh) && std::isnan(s.llh)));
    CHECK_EQUAL(r.status, s.status);

    checkEqualArray(r.sllh, s.sllh, 1e-5, 1e-5, "sllh");
    checkEqualArray(r.s2llh, s.s2llh, 1e-5, 1e-5, "s2llh");
}

// clang-format off
TEST_GROUP(dataSerialization){

    void setup() {

    }

    void teardown() {
    }
};
// clang-format on

TEST(dataSerialization, testFile) {
    int np = 1;
    int nk = 2;
    int nx = 3;
    int nz = 4;
    amici::CVodeSolver solver;
    amici::Model_Test m = amici::Model_Test(nx, nx, 4, 4, nz, nz, 8, 9, 10, 11, 12, 13, 14, 15, amici::AMICI_O2MODE_NONE,
                                             std::vector<realtype>(np,0.0),std::vector<realtype>(nk,0.0),std::vector<int>(np,0),
                                             std::vector<realtype>(nx,0.0),std::vector<int>(nz,0));

    {
        std::ofstream ofs("sstore.dat");
        boost::archive::text_oarchive oar(ofs);
        oar & static_cast<amici::Solver&>(solver);
        oar & static_cast<amici::Model&>(m);
    }
    {
        std::ifstream ifs("sstore.dat");
        boost::archive::text_iarchive iar(ifs);
        amici::CVodeSolver v;
        amici::Model_Test n;
        iar &static_cast<amici::Solver&>(v);
        iar &static_cast<amici::Model&>(n);
        CHECK_TRUE(solver == v);
        CHECK_TRUE(m == n);

    }
}

TEST(dataSerialization, testChar) {
    amici::CVodeSolver solver;
    solver.setAbsoluteTolerance(4);

    int length;
    char *buf = amici::serializeToChar(solver, &length);

    amici::CVodeSolver v = amici::deserializeFromChar<amici::CVodeSolver>(buf, length);

    delete[] buf;
    CHECK_TRUE(solver == v);
}

TEST(dataSerialization, testStdVec) {
    amici::CVodeSolver solver;
    solver.setAbsoluteTolerance(4);

    auto buf = amici::serializeToStdVec(solver);
    amici::CVodeSolver v = amici::deserializeFromChar<amici::CVodeSolver>(buf.data(), buf.size());

    CHECK_TRUE(solver == v);
}

TEST(dataSerialization, testString) {
    int np = 1;
    int nk = 2;
    int nx = 3;
    int nz = 4;
    amici::CVodeSolver solver;
    amici::Model_Test m = amici::Model_Test(nx, nx, 4, 4, nz, nz, 8, 9, 10, 11, 12, 13, 14, 15, amici::AMICI_O2MODE_NONE,
                                             std::vector<realtype>(np,0.0),std::vector<realtype>(nk,0.0),std::vector<int>(np,0),
                                             std::vector<realtype>(nx,0.0),std::vector<int>(nz,0));

    amici::ReturnData r(solver, &m);

    std::string serialized = amici::serializeToString(r);

    checkReturnDataEqual(r, amici::deserializeFromString<amici::ReturnData>(serialized));
}

<|endoftext|>


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

#ifndef __BASE_BITFIELD_HH__
#define __BASE_BITFIELD_HH__

#include <inttypes.h>

/**
 * Generate a 64-bit mask of 'nbits' 1s, right justified.
 */
inline uint64_t
mask(int nbits)
{
    return (nbits == 64) ? (uint64_t)-1LL : (1ULL << nbits) - 1;
}

/**
 * Extract the bitfield from position 'first' to 'last' (inclusive)
 * from 'val' and right justify it.  MSB is numbered 63, LSB is 0.
 */
template <class T>
inline
T
bits(T val, int first, int last)
{
    int nbits = first - last + 1;
    return (val >> last) & mask(nbits);
}

/**
 * Mask off the given bits in place like bits() but without shifting.
 * msb = 63, lsb = 0
 */
template <class T>
inline
T
mbits(T val, int first, int last)
{
    return val & (mask(first+1) & ~mask(last));
}

inline uint64_t
mask(int first, int last)
{
    return mbits((uint64_t)-1LL, first, last);
}

/**
 * Sign-extend an N-bit value to 64 bits.
 */
template <int N>
inline
int64_t
sext(uint64_t val)
{
    int sign_bit = bits(val, N-1, N-1);
    return sign_bit ? (val | ~mask(N)) : val;
}

/**
 * Return val with bits first to last set to bit_val
 */
template <class T, class B>
inline
T
insertBits(T val, int first, int last, B bit_val)
{
    T bmask = mask(first - last + 1) << last;
    return ((bit_val << last) & bmask) | (val & ~bmask);
}

/**
 * A convenience function to replace bits first to last of val with bit_val
 * in place.
 */
template <class T, class B>
inline
void
replaceBits(T& val, int first, int last, B bit_val)
{
    val = insertBits(val, first, last, bit_val);
}

/**
 * Returns the bit position of the MSB that is set in the input
 */
inline
int
findMsbSet(uint64_t val) {
    int msb = 0;
    if (!val)
        return 0;
    if (bits(val, 63,32)) { msb += 32; val >>= 32; }
    if (bits(val, 31,16)) { msb += 16; val >>= 16; }
    if (bits(val, 15,8))  { msb += 8;  val >>= 8;  }
    if (bits(val, 7,4))   { msb += 4;  val >>= 4;  }
    if (bits(val, 3,2))   { msb += 2;  val >>= 2;  }
    if (bits(val, 1,1))   { msb += 1; }
    return msb;
}

//	The following implements the BitUnion system of defining bitfields
//on top of an underlying class. This is done through the extensive use of
//both named and unnamed unions which all contain the same actual storage.
//Since they're unioned with each other, all of these storage locations
//overlap. This allows all of the bitfields to manipulate the same data
//without having to know about each other. More details are provided with the
//individual components.

//This namespace is for classes which implement the backend of the BitUnion
//stuff. Don't use any of this directly! Use the macros at the end instead.
namespace BitfieldBackend
{
    //A base class for all bitfields. It instantiates the actual storage,
    //and provides getBits and setBits functions for manipulating it. The
    //Data template parameter is type of the underlying storage.
    template<class Data>
    class BitfieldBase
    {
      protected:
        Data __data;

        //This function returns a range of bits from the underlying storage.
        //It relies on the "bits" function above. It's the user's
        //responsibility to make sure that there is a properly overloaded
        //version of this function for whatever type they want to overlay.
        inline uint64_t
        getBits(int first, int last)
        {
            return bits(__data, first, last);
        }

        //Similar to the above, but for settings bits with replaceBits.
        inline void
        setBits(int first, int last, uint64_t val)
        {
            replaceBits(__data, first, last, val);
        }
    };

    //A class which specializes a given base so that it can only be read
    //from. This is accomplished by only passing through the conversion
    //operator.
    template<class Type, class Base>
    class _BitfieldRO : public Base
    {
      public:
        operator const Type ()
        {
            return *((Base *)this);
        }
    };

    //Similar to the above, but only allows writing.
    template<class Type, class Base>
    class _BitfieldWO : public Base
    {
      public:
        const Type operator = (const Type & _data)
        {
            *((Base *)this) = _data;
            return _data;
        }
    };

    //This class implements ordinary bitfields, that is a span of bits
    //who's msb is "first", and who's lsb is "last".
    template<class Data, int first, int last=first>
    class _Bitfield : public BitfieldBase<Data>
    {
      public:
        operator const Data ()
        {
            return this->getBits(first, last);
        }

        const Data
        operator = (const Data & _data)
        {
            this->setBits(first, last, _data);
            return _data;
        }
    };

    //When a BitUnion is set up, an underlying class is created which holds
    //the actual union. This class then inherits from it, and provids the
    //implementations for various operators. Setting things up this way
    //prevents having to redefine these functions in every different BitUnion
    //type. More operators could be implemented in the future, as the need
    //arises.
    template <class Type, class Base>
    class BitUnionOperators : public Base
    {
      public:
        operator const Type ()
        {
            return Base::__data;
        }

        const Type
        operator = (const Type & _data)
        {
            Base::__data = _data;
        }

        bool
        operator < (const Base & base)
        {
            return Base::__data < base.__data;
        }

        bool
        operator == (const Base & base)
        {
            return Base::__data == base.__data;
        }
    };
}

//This macro is a backend for other macros that specialize it slightly.
//First, it creates/extends a namespace "BitfieldUnderlyingClasses" and
//sticks the class which has the actual union in it, which
//BitfieldOperators above inherits from. Putting these classes in a special
//namespace ensures that there will be no collisions with other names as long
//as the BitUnion names themselves are all distinct and nothing else uses
//the BitfieldUnderlyingClasses namespace, which is unlikely. The class itself
//creates a typedef of the "type" parameter called __DataType. This allows
//the type to propagate outside of the macro itself in a controlled way.
//Finally, the base storage is defined which BitfieldOperators will refer to
//in the operators it defines. This macro is intended to be followed by
//bitfield definitions which will end up inside it's union. As explained
//above, these is overlayed the __data member in its entirety by each of the
//bitfields which are defined in the union, creating shared storage with no
//overhead.
#define __BitUnion(type, name) \
    namespace BitfieldUnderlyingClasses \
    { \
        class name; \
    } \
    class BitfieldUnderlyingClasses::name { \
      public: \
        typedef type __DataType; \
        union { \
            type __data;\

//This closes off the class and union started by the above macro. It is
//followed by a typedef which makes "name" refer to a BitfieldOperator
//class inheriting from the class and union just defined, which completes
//building up the type for the user.
#define EndBitUnion(name) \
        }; \
    }; \
    typedef BitfieldBackend::BitUnionOperators< \
        BitfieldUnderlyingClasses::name::__DataType, \
        BitfieldUnderlyingClasses::name> name;

//This sets up a bitfield which has other bitfields nested inside of it. The
//__data member functions like the "underlying storage" of the top level
//BitUnion. Like everything else, it overlays with the top level storage, so
//making it a regular bitfield type makes the entire thing function as a
//regular bitfield when referred to by itself. The operators are defined in
//the macro itself instead of a class for technical reasons. If someone
//determines a way to move them to one, please do so.
#define __SubBitUnion(type, name) \
        union { \
            type __data; \
            inline operator const __DataType () \
            { return __data; } \
            \
            inline const __DataType operator = (const __DataType & _data) \
            { __data = _data; }

//This closes off the union created above and gives it a name. Unlike the top
//level BitUnion, we're interested in creating an object instead of a type.
#define EndSubBitUnion(name) } name;

//The preprocessor will treat everything inside of parenthesis as a single
//argument even if it has commas in it. This is used to pass in templated
//classes which typically have commas to seperate their parameters.
#define wrap(guts) guts

//Read only bitfields
//This wraps another bitfield class inside a _BitfieldRO class using
//inheritance. As explained above, the _BitfieldRO class only passes through
//the conversion operator, so the underlying bitfield can then only be read
//from.
#define __BitfieldRO(base) \
    BitfieldBackend::_BitfieldRO<__DataType, base>
#define __SubBitUnionRO(name, base) \
    __SubBitUnion(wrap(_BitfieldRO<__DataType, base>), name)

//Write only bitfields
//Similar to above, but for making write only versions of bitfields with
//_BitfieldWO.
#define __BitfieldWO(base) \
    BitfieldBackend::_BitfieldWO<__DataType, base>
#define __SubBitUnionWO(name, base) \
    __SubBitUnion(wrap(_BitfieldWO<__DataType, base>), name)

//Regular bitfields
//This uses all of the above to define macros for read/write, read only, and
//write only versions of regular bitfields.
#define Bitfield(first, last) \
    BitfieldBackend::_Bitfield<__DataType, first, last>
#define SubBitUnion(name, first, last) \
    __SubBitUnion(Bitfield(first, last), name)
#define BitfieldRO(first, last) __BitfieldRO(Bitfield(first, last))
#define SubBitUnionRO(name, first, last) \
    __SubBitUnionRO(Bitfield(first, last), name)
#define BitfieldWO(first, last) __BitfieldWO(Bitfield(first, last))
#define SubBitUnionWO(name, first, last) \
    __SubBitUnionWO(Bitfield(first, last), name)

//Use this to define an arbitrary type overlayed with bitfields.
#define BitUnion(type, name) __BitUnion(type, name)

//Use this to define conveniently sized values overlayed with bitfields.
#define BitUnion64(name) __BitUnion(uint64_t, name)
#define BitUnion32(name) __BitUnion(uint32_t, name)
#define BitUnion16(name) __BitUnion(uint16_t, name)
#define BitUnion8(name) __BitUnion(uint8_t, name)

#endif // __BASE_BITFIELD_HH__
<commit_msg>Formatting fixes.<commit_after>/*
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Steve Reinhardt
 *          Nathan Binkert
 */

#ifndef __BASE_BITFIELD_HH__
#define __BASE_BITFIELD_HH__

#include <inttypes.h>

/**
 * Generate a 64-bit mask of 'nbits' 1s, right justified.
 */
inline uint64_t
mask(int nbits)
{
    return (nbits == 64) ? (uint64_t)-1LL : (1ULL << nbits) - 1;
}

/**
 * Extract the bitfield from position 'first' to 'last' (inclusive)
 * from 'val' and right justify it.  MSB is numbered 63, LSB is 0.
 */
template <class T>
inline
T
bits(T val, int first, int last)
{
    int nbits = first - last + 1;
    return (val >> last) & mask(nbits);
}

/**
 * Mask off the given bits in place like bits() but without shifting.
 * msb = 63, lsb = 0
 */
template <class T>
inline
T
mbits(T val, int first, int last)
{
    return val & (mask(first+1) & ~mask(last));
}

inline uint64_t
mask(int first, int last)
{
    return mbits((uint64_t)-1LL, first, last);
}

/**
 * Sign-extend an N-bit value to 64 bits.
 */
template <int N>
inline
int64_t
sext(uint64_t val)
{
    int sign_bit = bits(val, N-1, N-1);
    return sign_bit ? (val | ~mask(N)) : val;
}

/**
 * Return val with bits first to last set to bit_val
 */
template <class T, class B>
inline
T
insertBits(T val, int first, int last, B bit_val)
{
    T bmask = mask(first - last + 1) << last;
    return ((bit_val << last) & bmask) | (val & ~bmask);
}

/**
 * A convenience function to replace bits first to last of val with bit_val
 * in place.
 */
template <class T, class B>
inline
void
replaceBits(T& val, int first, int last, B bit_val)
{
    val = insertBits(val, first, last, bit_val);
}

/**
 * Returns the bit position of the MSB that is set in the input
 */
inline
int
findMsbSet(uint64_t val) {
    int msb = 0;
    if (!val)
        return 0;
    if (bits(val, 63,32)) { msb += 32; val >>= 32; }
    if (bits(val, 31,16)) { msb += 16; val >>= 16; }
    if (bits(val, 15,8))  { msb += 8;  val >>= 8;  }
    if (bits(val, 7,4))   { msb += 4;  val >>= 4;  }
    if (bits(val, 3,2))   { msb += 2;  val >>= 2;  }
    if (bits(val, 1,1))   { msb += 1; }
    return msb;
}

//	The following implements the BitUnion system of defining bitfields
//on top of an underlying class. This is done through the extensive use of
//both named and unnamed unions which all contain the same actual storage.
//Since they're unioned with each other, all of these storage locations
//overlap. This allows all of the bitfields to manipulate the same data
//without having to know about each other. More details are provided with the
//individual components.

//This namespace is for classes which implement the backend of the BitUnion
//stuff. Don't use any of this directly! Use the macros at the end instead.
namespace BitfieldBackend
{
    //A base class for all bitfields. It instantiates the actual storage,
    //and provides getBits and setBits functions for manipulating it. The
    //Data template parameter is type of the underlying storage.
    template<class Data>
    class BitfieldBase
    {
      protected:
        Data __data;

        //This function returns a range of bits from the underlying storage.
        //It relies on the "bits" function above. It's the user's
        //responsibility to make sure that there is a properly overloaded
        //version of this function for whatever type they want to overlay.
        inline uint64_t
        getBits(int first, int last)
        {
            return bits(__data, first, last);
        }

        //Similar to the above, but for settings bits with replaceBits.
        inline void
        setBits(int first, int last, uint64_t val)
        {
            replaceBits(__data, first, last, val);
        }
    };

    //A class which specializes a given base so that it can only be read
    //from. This is accomplished by only passing through the conversion
    //operator.
    template<class Type, class Base>
    class _BitfieldRO : public Base
    {
      public:
        operator const Type ()
        {
            return *((Base *)this);
        }
    };

    //Similar to the above, but only allows writing.
    template<class Type, class Base>
    class _BitfieldWO : public Base
    {
      public:
        const Type operator=(const Type & _data)
        {
            *((Base *)this) = _data;
            return _data;
        }
    };

    //This class implements ordinary bitfields, that is a span of bits
    //who's msb is "first", and who's lsb is "last".
    template<class Data, int first, int last=first>
    class _Bitfield : public BitfieldBase<Data>
    {
      public:
        operator const Data ()
        {
            return this->getBits(first, last);
        }

        const Data
        operator=(const Data & _data)
        {
            this->setBits(first, last, _data);
            return _data;
        }
    };

    //When a BitUnion is set up, an underlying class is created which holds
    //the actual union. This class then inherits from it, and provids the
    //implementations for various operators. Setting things up this way
    //prevents having to redefine these functions in every different BitUnion
    //type. More operators could be implemented in the future, as the need
    //arises.
    template <class Type, class Base>
    class BitUnionOperators : public Base
    {
      public:
        operator const Type ()
        {
            return Base::__data;
        }

        const Type
        operator=(const Type & _data)
        {
            Base::__data = _data;
        }

        bool
        operator<(const Base & base)
        {
            return Base::__data < base.__data;
        }

        bool
        operator==(const Base & base)
        {
            return Base::__data == base.__data;
        }
    };
}

//This macro is a backend for other macros that specialize it slightly.
//First, it creates/extends a namespace "BitfieldUnderlyingClasses" and
//sticks the class which has the actual union in it, which
//BitfieldOperators above inherits from. Putting these classes in a special
//namespace ensures that there will be no collisions with other names as long
//as the BitUnion names themselves are all distinct and nothing else uses
//the BitfieldUnderlyingClasses namespace, which is unlikely. The class itself
//creates a typedef of the "type" parameter called __DataType. This allows
//the type to propagate outside of the macro itself in a controlled way.
//Finally, the base storage is defined which BitfieldOperators will refer to
//in the operators it defines. This macro is intended to be followed by
//bitfield definitions which will end up inside it's union. As explained
//above, these is overlayed the __data member in its entirety by each of the
//bitfields which are defined in the union, creating shared storage with no
//overhead.
#define __BitUnion(type, name) \
    namespace BitfieldUnderlyingClasses \
    { \
        class name; \
    } \
    class BitfieldUnderlyingClasses::name { \
      public: \
        typedef type __DataType; \
        union { \
            type __data;\

//This closes off the class and union started by the above macro. It is
//followed by a typedef which makes "name" refer to a BitfieldOperator
//class inheriting from the class and union just defined, which completes
//building up the type for the user.
#define EndBitUnion(name) \
        }; \
    }; \
    typedef BitfieldBackend::BitUnionOperators< \
        BitfieldUnderlyingClasses::name::__DataType, \
        BitfieldUnderlyingClasses::name> name;

//This sets up a bitfield which has other bitfields nested inside of it. The
//__data member functions like the "underlying storage" of the top level
//BitUnion. Like everything else, it overlays with the top level storage, so
//making it a regular bitfield type makes the entire thing function as a
//regular bitfield when referred to by itself. The operators are defined in
//the macro itself instead of a class for technical reasons. If someone
//determines a way to move them to one, please do so.
#define __SubBitUnion(type, name) \
        union { \
            type __data; \
            inline operator const __DataType () \
            { return __data; } \
            \
            inline const __DataType operator = (const __DataType & _data) \
            { __data = _data; }

//This closes off the union created above and gives it a name. Unlike the top
//level BitUnion, we're interested in creating an object instead of a type.
#define EndSubBitUnion(name) } name;

//The preprocessor will treat everything inside of parenthesis as a single
//argument even if it has commas in it. This is used to pass in templated
//classes which typically have commas to seperate their parameters.
#define wrap(guts) guts

//Read only bitfields
//This wraps another bitfield class inside a _BitfieldRO class using
//inheritance. As explained above, the _BitfieldRO class only passes through
//the conversion operator, so the underlying bitfield can then only be read
//from.
#define __BitfieldRO(base) \
    BitfieldBackend::_BitfieldRO<__DataType, base>
#define __SubBitUnionRO(name, base) \
    __SubBitUnion(wrap(_BitfieldRO<__DataType, base>), name)

//Write only bitfields
//Similar to above, but for making write only versions of bitfields with
//_BitfieldWO.
#define __BitfieldWO(base) \
    BitfieldBackend::_BitfieldWO<__DataType, base>
#define __SubBitUnionWO(name, base) \
    __SubBitUnion(wrap(_BitfieldWO<__DataType, base>), name)

//Regular bitfields
//This uses all of the above to define macros for read/write, read only, and
//write only versions of regular bitfields.
#define Bitfield(first, last) \
    BitfieldBackend::_Bitfield<__DataType, first, last>
#define SubBitUnion(name, first, last) \
    __SubBitUnion(Bitfield(first, last), name)
#define BitfieldRO(first, last) __BitfieldRO(Bitfield(first, last))
#define SubBitUnionRO(name, first, last) \
    __SubBitUnionRO(Bitfield(first, last), name)
#define BitfieldWO(first, last) __BitfieldWO(Bitfield(first, last))
#define SubBitUnionWO(name, first, last) \
    __SubBitUnionWO(Bitfield(first, last), name)

//Use this to define an arbitrary type overlayed with bitfields.
#define BitUnion(type, name) __BitUnion(type, name)

//Use this to define conveniently sized values overlayed with bitfields.
#define BitUnion64(name) __BitUnion(uint64_t, name)
#define BitUnion32(name) __BitUnion(uint32_t, name)
#define BitUnion16(name) __BitUnion(uint16_t, name)
#define BitUnion8(name) __BitUnion(uint8_t, name)

#endif // __BASE_BITFIELD_HH__
<|endoftext|>