<commit_before>/*
 * BatteryTech
 * Copyright (c) 2010 Battery Powered Games LLC.
 *
 * This code is a component of BatteryTech and is subject to the 'BatteryTech
 * End User License Agreement'.  Among other important provisions, this
 * license prohibits the distribution of source code to anyone other than
 * authorized parties.  If you have any questions or would like an additional
 * copy of the license, please contact: support@batterypoweredgames.com
 */

//============================================================================
// Name        : boot.cpp
// Description : Android bootstrap and JNI linkage
//============================================================================

#ifdef ANDROID_NDK
#include "androidtypes.h"
#include "../platformgeneral.h"
#include "../../batterytech.h"
#include "../../render/GraphicsConfiguration.h"
#include "importgl.h"
#include <jni.h>
#include <android/log.h>
#include "../../util/strx.h"
#include "../opengles.h"
#include "../../audio/AudioManager.h"

using namespace BatteryTech;

#ifdef __cplusplus
extern "C" {
#endif

// the current env for the call
JNIEnv *jnienv;
jobject javaBoot;
extern AudioManager *_andSndMgr; // from androidgeneral
GraphicsConfiguration *gConfig;

void determineGPUCapabilities();
BatteryTech::SpecialKey getSpecialKey(int keyCode);

void Java_com_batterypoweredgames_batterytech_Boot_init(JNIEnv* env, jobject thiz, jint width, jint height, jboolean usingGLES2) {
	jnienv = env;
	javaBoot = thiz;
	importGLInit(usingGLES2);
	gConfig = new GraphicsConfiguration;
	determineGPUCapabilities();
	btInit(gConfig, width, height);
	jnienv = 0;
	javaBoot = 0;
}

void Java_com_batterypoweredgames_batterytech_Boot_setScreenSize(JNIEnv* env, jobject thiz, jint width, jint height) {
	jnienv = env;
	javaBoot = thiz;
	btSetScreenSize(width, height);
	jnienv = 0;
	javaBoot = 0;
}

void Java_com_batterypoweredgames_batterytech_Boot_release(JNIEnv* env, jobject thiz) {
	jnienv = env;
	javaBoot = thiz;
	btRelease();
	delete gConfig;
	importGLDeinit();
	jnienv = 0;
	javaBoot = 0;
}

void Java_com_batterypoweredgames_batterytech_Boot_update(JNIEnv* env, jobject thiz, jfloat delta) {
	//__android_log_print(ANDROID_LOG_DEBUG, "BatteryTech Boot", "delta is %f", delta);
	jnienv = env;
	javaBoot = thiz;
	btUpdate((F32)delta);
	jnienv = 0;
	javaBoot = 0;
}

void Java_com_batterypoweredgames_batterytech_Boot_draw(JNIEnv* env, jobject thiz) {
	jnienv = env;
	javaBoot = thiz;
	btDraw();
	jnienv = 0;
	javaBoot = 0;
}

void Java_com_batterypoweredgames_batterytech_Boot_suspend(JNIEnv* env, jobject thiz) {
	jnienv = env;
	javaBoot = thiz;
	btSuspend();
	jnienv = 0;
	javaBoot = 0;
}

void Java_com_batterypoweredgames_batterytech_Boot_resume(JNIEnv* env, jobject thiz) {
	jnienv = env;
	javaBoot = thiz;
	btResume();
	jnienv = 0;
	javaBoot = 0;
}

void Java_com_batterypoweredgames_batterytech_Boot_setPointerState(JNIEnv* env, jobject thiz, jint pointerId, jboolean down, jint x, jint y) {
	jnienv = env;
	javaBoot = thiz;
	btSetPointerState(pointerId, down, x, y);
	jnienv = 0;
	javaBoot = 0;
}

void Java_com_batterypoweredgames_batterytech_Boot_keyUp(JNIEnv* env, jobject thiz, jint keyChar, jint keyCode) {
	jnienv = env;
	javaBoot = thiz;
	btKeyUp(keyChar, getSpecialKey(keyCode));
	jnienv = 0;
	javaBoot = 0;
}

void Java_com_batterypoweredgames_batterytech_Boot_keyDown(JNIEnv* env, jobject thiz, jint keyChar, jint keyCode) {
	jnienv = env;
	javaBoot = thiz;
	btKeyDown(keyChar, getSpecialKey(keyCode));
	jnienv = 0;
	javaBoot = 0;
}

void Java_com_batterypoweredgames_batterytech_Boot_keyPressed(JNIEnv* env, jobject thiz, jint keyChar, jint keyCode) {
	jnienv = env;
	javaBoot = thiz;
	btKeyPressed(keyChar, getSpecialKey(keyCode));
	jnienv = 0;
	javaBoot = 0;
}

void Java_com_batterypoweredgames_batterytech_Boot_accelerometerChanged(JNIEnv* env, jobject thiz, jfloat x, jfloat y, jfloat z) {
	//__android_log_print(ANDROID_LOG_DEBUG, "BatteryTech Boot", "delta is %f", delta);
	jnienv = env;
	javaBoot = thiz;
	btAccelerometerChanged(x,y,z);
	jnienv = 0;
	javaBoot = 0;
}

void Java_com_batterypoweredgames_batterytech_Boot_fillAudioBuffer(JNIEnv* env, jobject thiz, jshortArray jPCMData, jint length) {
	if (_andSndMgr) {
		signed short *buf = new signed short[length / 2];
		_andSndMgr->fillBuffer(buf, length);
		env->SetShortArrayRegion(jPCMData, 0, length / 2, buf);
		delete [] buf;
	}
}

jboolean Java_com_batterypoweredgames_batterytech_Boot_callback(JNIEnv* env, jobject thiz, jstring data) {
	jnienv = env;
	javaBoot = thiz;
	jboolean ret = FALSE;
	if (data) {
		jboolean isCopy;
		const char *jnibuf = jnienv->GetStringUTFChars(data, &isCopy);
		ret = btCallback(jnibuf);
		jnienv->ReleaseStringUTFChars(data, jnibuf);
	}
	jnienv = 0;
	javaBoot = 0;
	return ret;
}

void determineGPUCapabilities() {
	const char *vendor = (const char*)glGetString(GL_VENDOR);
	const char *renderer = (const char*)glGetString(GL_RENDERER);
	const char *version = (const char*)glGetString(GL_VERSION);
	const char *extensions = (const char*)glGetString(GL_EXTENSIONS);
	// 1.0 = 0, 1.1 = 1, 2.0 = 2
	int ver = 0;
	__android_log_print(ANDROID_LOG_DEBUG, "BatteryTech", "OpenGL Vendor %s", vendor);
	__android_log_print(ANDROID_LOG_DEBUG, "BatteryTech", "OpenGL Renderer %s", renderer);
	__android_log_print(ANDROID_LOG_DEBUG, "BatteryTech", "OpenGL Version %s", version);
	if (strstr(version, "2.0")) {
		__android_log_print(ANDROID_LOG_DEBUG, "BatteryTech", "OpenGL ES Version 2.0 found");
		ver = 2;
		gConfig->supportsShaders = TRUE;
		gConfig->supportsFBOs = TRUE;
	} else if (strstr(version, "1.1")) {
		__android_log_print(ANDROID_LOG_DEBUG, "BatteryTech", "OpenGL ES Version 1.1 found");
		ver = 1;
	}
	if (ver == 0) {
		__android_log_print(ANDROID_LOG_DEBUG, "BatteryTech", "OpenGL ES Version 1.0 found");
	}
	if ((ver > 0) || gles_checkExtension(GLES_EXT_GENERATE_MIPMAP)) {
		__android_log_print(ANDROID_LOG_DEBUG, "BatteryTech", "HW MipMap Gen Supported");
		gConfig->supportsHWmipmapgen = TRUE;
	}
	if (gles_checkExtension(GLES_EXT_TEXTURE_FLOAT)) {
		__android_log_print(ANDROID_LOG_DEBUG, "BatteryTech", "Float textures supported");
		gConfig->supportsFloatTextures = TRUE;
	}
	if (gles_checkExtension(GLES_EXT_DEPTH_TEXTURE)) {
		__android_log_print(ANDROID_LOG_DEBUG, "BatteryTech", "Depth textures supported");
		gConfig->supportsDepthTextures = TRUE;
	}
	if ((ver > 0) || gles_checkExtension(GLES_EXT_VERTEX_BUFFER_OBJECT)) {
		__android_log_print(ANDROID_LOG_DEBUG, "BatteryTech", "VBOs Supported");
		gConfig->supportsVBOs = TRUE;
	}
	if (strstr(renderer, "MSM7500")) {
		__android_log_print(ANDROID_LOG_DEBUG, "BatteryTech", "HW UV Transform not supported");
		gConfig->supportsUVTransform = FALSE;
	} else {
		__android_log_print(ANDROID_LOG_DEBUG, "BatteryTech", "HW UV Transform supported");
		gConfig->supportsUVTransform = TRUE;
	}
	if (strstr(renderer, ANDROID_RENDERER_PIXELFLINGER)) {
		gConfig->softGPU = TRUE;
	}
}

BatteryTech::SpecialKey getSpecialKey(int keyCode) {
	if (keyCode == 82) {
		return BatteryTech::SKEY_MENU;
	} else if (keyCode == 4) {
		return BatteryTech::SKEY_BACK;
	} else if (keyCode == 27) {
		return BatteryTech::SKEY_CAMERA;
	} else {
		return BatteryTech::SKEY_NULL;
	}
}

void Java_com_batterypoweredgames_batterytech_Boot_setGraphicsContextLost(JNIEnv* env, jobject thiz, jboolean wasLost) {
	jnienv = env;
	javaBoot = thiz;
	btSetGraphicsContextLost(wasLost);
	jnienv = 0;
	javaBoot = 0;
}
#ifdef __cplusplus
}
#endif

#endif /* _ANDROID */
<commit_msg>BatteryTech - Fixed Android OpenGL ES 3.0+<commit_after>/*
 * BatteryTech
 * Copyright (c) 2010 Battery Powered Games LLC.
 *
 * This code is a component of BatteryTech and is subject to the 'BatteryTech
 * End User License Agreement'.  Among other important provisions, this
 * license prohibits the distribution of source code to anyone other than
 * authorized parties.  If you have any questions or would like an additional
 * copy of the license, please contact: support@batterypoweredgames.com
 */

//============================================================================
// Name        : boot.cpp
// Description : Android bootstrap and JNI linkage
//============================================================================

#ifdef ANDROID_NDK
#include "androidtypes.h"
#include "../platformgeneral.h"
#include "../../batterytech.h"
#include "../../render/GraphicsConfiguration.h"
#include "importgl.h"
#include <jni.h>
#include <android/log.h>
#include "../../util/strx.h"
#include "../opengles.h"
#include "../../audio/AudioManager.h"

using namespace BatteryTech;

#ifdef __cplusplus
extern "C" {
#endif

// the current env for the call
JNIEnv *jnienv;
jobject javaBoot;
extern AudioManager *_andSndMgr; // from androidgeneral
GraphicsConfiguration *gConfig;

void determineGPUCapabilities();
BatteryTech::SpecialKey getSpecialKey(int keyCode);

void Java_com_batterypoweredgames_batterytech_Boot_init(JNIEnv* env, jobject thiz, jint width, jint height, jboolean usingGLES2) {
	jnienv = env;
	javaBoot = thiz;
	importGLInit(usingGLES2);
	gConfig = new GraphicsConfiguration;
	determineGPUCapabilities();
	btInit(gConfig, width, height);
	jnienv = 0;
	javaBoot = 0;
}

void Java_com_batterypoweredgames_batterytech_Boot_setScreenSize(JNIEnv* env, jobject thiz, jint width, jint height) {
	jnienv = env;
	javaBoot = thiz;
	btSetScreenSize(width, height);
	jnienv = 0;
	javaBoot = 0;
}

void Java_com_batterypoweredgames_batterytech_Boot_release(JNIEnv* env, jobject thiz) {
	jnienv = env;
	javaBoot = thiz;
	btRelease();
	delete gConfig;
	importGLDeinit();
	jnienv = 0;
	javaBoot = 0;
}

void Java_com_batterypoweredgames_batterytech_Boot_update(JNIEnv* env, jobject thiz, jfloat delta) {
	//__android_log_print(ANDROID_LOG_DEBUG, "BatteryTech Boot", "delta is %f", delta);
	jnienv = env;
	javaBoot = thiz;
	btUpdate((F32)delta);
	jnienv = 0;
	javaBoot = 0;
}

void Java_com_batterypoweredgames_batterytech_Boot_draw(JNIEnv* env, jobject thiz) {
	jnienv = env;
	javaBoot = thiz;
	btDraw();
	jnienv = 0;
	javaBoot = 0;
}

void Java_com_batterypoweredgames_batterytech_Boot_suspend(JNIEnv* env, jobject thiz) {
	jnienv = env;
	javaBoot = thiz;
	btSuspend();
	jnienv = 0;
	javaBoot = 0;
}

void Java_com_batterypoweredgames_batterytech_Boot_resume(JNIEnv* env, jobject thiz) {
	jnienv = env;
	javaBoot = thiz;
	btResume();
	jnienv = 0;
	javaBoot = 0;
}

void Java_com_batterypoweredgames_batterytech_Boot_setPointerState(JNIEnv* env, jobject thiz, jint pointerId, jboolean down, jint x, jint y) {
	jnienv = env;
	javaBoot = thiz;
	btSetPointerState(pointerId, down, x, y);
	jnienv = 0;
	javaBoot = 0;
}

void Java_com_batterypoweredgames_batterytech_Boot_keyUp(JNIEnv* env, jobject thiz, jint keyChar, jint keyCode) {
	jnienv = env;
	javaBoot = thiz;
	btKeyUp(keyChar, getSpecialKey(keyCode));
	jnienv = 0;
	javaBoot = 0;
}

void Java_com_batterypoweredgames_batterytech_Boot_keyDown(JNIEnv* env, jobject thiz, jint keyChar, jint keyCode) {
	jnienv = env;
	javaBoot = thiz;
	btKeyDown(keyChar, getSpecialKey(keyCode));
	jnienv = 0;
	javaBoot = 0;
}

void Java_com_batterypoweredgames_batterytech_Boot_keyPressed(JNIEnv* env, jobject thiz, jint keyChar, jint keyCode) {
	jnienv = env;
	javaBoot = thiz;
	btKeyPressed(keyChar, getSpecialKey(keyCode));
	jnienv = 0;
	javaBoot = 0;
}

void Java_com_batterypoweredgames_batterytech_Boot_accelerometerChanged(JNIEnv* env, jobject thiz, jfloat x, jfloat y, jfloat z) {
	//__android_log_print(ANDROID_LOG_DEBUG, "BatteryTech Boot", "delta is %f", delta);
	jnienv = env;
	javaBoot = thiz;
	btAccelerometerChanged(x,y,z);
	jnienv = 0;
	javaBoot = 0;
}

void Java_com_batterypoweredgames_batterytech_Boot_fillAudioBuffer(JNIEnv* env, jobject thiz, jshortArray jPCMData, jint length) {
	if (_andSndMgr) {
		signed short *buf = new signed short[length / 2];
		_andSndMgr->fillBuffer(buf, length);
		env->SetShortArrayRegion(jPCMData, 0, length / 2, buf);
		delete [] buf;
	}
}

jboolean Java_com_batterypoweredgames_batterytech_Boot_callback(JNIEnv* env, jobject thiz, jstring data) {
	jnienv = env;
	javaBoot = thiz;
	jboolean ret = FALSE;
	if (data) {
		jboolean isCopy;
		const char *jnibuf = jnienv->GetStringUTFChars(data, &isCopy);
		ret = btCallback(jnibuf);
		jnienv->ReleaseStringUTFChars(data, jnibuf);
	}
	jnienv = 0;
	javaBoot = 0;
	return ret;
}

void determineGPUCapabilities() {
	const char *vendor = (const char*)glGetString(GL_VENDOR);
	const char *renderer = (const char*)glGetString(GL_RENDERER);
	const char *version = (const char*)glGetString(GL_VERSION);
	const char *extensions = (const char*)glGetString(GL_EXTENSIONS);
	// 1.0 = 0, 1.1 = 1, 2.0/3.0 = 2
	int ver = 0;
	__android_log_print(ANDROID_LOG_DEBUG, "BatteryTech", "OpenGL Vendor %s", vendor);
	__android_log_print(ANDROID_LOG_DEBUG, "BatteryTech", "OpenGL Renderer %s", renderer);
	__android_log_print(ANDROID_LOG_DEBUG, "BatteryTech", "OpenGL Version %s", version);
	if ((strstr(version, "1.0") || strstr(version, "1.1")) && !(strstr(version, "2.0") || strstr(version, "3.0"))) {
		__android_log_print(ANDROID_LOG_DEBUG, "BatteryTech", "OpenGL ES Version 1.0/1.1 found");
		if (!strstr(version, "1.0")) {
			ver = 1;
		}
	} else {
		__android_log_print(ANDROID_LOG_DEBUG, "BatteryTech", "OpenGL ES Version 2.0/3.0 found");
		gConfig->supportsShaders = TRUE;
		gConfig->supportsFBOs = TRUE;
		ver = 2;
	}
	if ((ver > 0) || gles_checkExtension(GLES_EXT_GENERATE_MIPMAP)) {
		__android_log_print(ANDROID_LOG_DEBUG, "BatteryTech", "HW MipMap Gen Supported");
		gConfig->supportsHWmipmapgen = TRUE;
	}
	if (gles_checkExtension(GLES_EXT_TEXTURE_FLOAT)) {
		__android_log_print(ANDROID_LOG_DEBUG, "BatteryTech", "Float textures supported");
		gConfig->supportsFloatTextures = TRUE;
	}
	if (gles_checkExtension(GLES_EXT_DEPTH_TEXTURE)) {
		__android_log_print(ANDROID_LOG_DEBUG, "BatteryTech", "Depth textures supported");
		gConfig->supportsDepthTextures = TRUE;
	}
	if ((ver > 0) || gles_checkExtension(GLES_EXT_VERTEX_BUFFER_OBJECT)) {
		__android_log_print(ANDROID_LOG_DEBUG, "BatteryTech", "VBOs Supported");
		gConfig->supportsVBOs = TRUE;
	}
	if (strstr(renderer, "MSM7500")) {
		__android_log_print(ANDROID_LOG_DEBUG, "BatteryTech", "HW UV Transform not supported");
		gConfig->supportsUVTransform = FALSE;
	} else {
		__android_log_print(ANDROID_LOG_DEBUG, "BatteryTech", "HW UV Transform supported");
		gConfig->supportsUVTransform = TRUE;
	}
	if (strstr(renderer, ANDROID_RENDERER_PIXELFLINGER)) {
		gConfig->softGPU = TRUE;
	}
}

BatteryTech::SpecialKey getSpecialKey(int keyCode) {
	if (keyCode == 82) {
		return BatteryTech::SKEY_MENU;
	} else if (keyCode == 4) {
		return BatteryTech::SKEY_BACK;
	} else if (keyCode == 27) {
		return BatteryTech::SKEY_CAMERA;
	} else {
		return BatteryTech::SKEY_NULL;
	}
}

void Java_com_batterypoweredgames_batterytech_Boot_setGraphicsContextLost(JNIEnv* env, jobject thiz, jboolean wasLost) {
	jnienv = env;
	javaBoot = thiz;
	btSetGraphicsContextLost(wasLost);
	jnienv = 0;
	javaBoot = 0;
}
#ifdef __cplusplus
}
#endif

#endif /* _ANDROID */
<|endoftext|>


<commit_before>/**
 * @file
 *
 * Includes all external headers.
 */
#pragma once

#include <algorithm>
#include <numeric>
#include <limits>
#include <utility>
#include <functional>
#include <vector>
#include <memory>
#include <string>
#include <sstream>
#include <iomanip>
#include <initializer_list>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <cstddef>
#include <cmath>
#include <unistd.h>
#include <getopt.h>
#include <dlfcn.h>

#include <eigen3/Eigen/Dense>
#include <eigen3/Eigen/Sparse>

#ifdef HAVE_OMP_H
#include <omp.h>
#endif
<commit_msg>Removed Eigen header include for sparse matrices.<commit_after>/**
 * @file
 *
 * Includes all external headers.
 */
#pragma once

#include <algorithm>
#include <numeric>
#include <limits>
#include <utility>
#include <functional>
#include <vector>
#include <memory>
#include <string>
#include <sstream>
#include <iomanip>
#include <initializer_list>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <cstddef>
#include <cmath>
#include <unistd.h>
#include <getopt.h>
#include <dlfcn.h>

#include <eigen3/Eigen/Dense>

#ifdef HAVE_OMP_H
#include <omp.h>
#endif
<|endoftext|>


<commit_before>/*  Sirikata Utilities -- Sirikata Utilities
 *  Singleton.hpp
 *
 *  Copyright (c) 2009, Daniel Reiter Horn
 *  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 Sirikata 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.
 */

#ifndef _SIRIKATA_SINGLETON_HPP_
#define _SIRIKATA_SINGLETON_HPP_
namespace Sirikata {

template <class T> class AutoSingleton {
    static std::auto_ptr<T>sInstance;
public:
    static T&getSingleton() {
        if (sInstance.get()==NULL)  {
            std::auto_ptr<T> tmp(new T);
            sInstance = tmp;
        }
        return *static_cast<T*>(sInstance.get());
    }
    AutoSingleton() {
        if (sInstance.get()==NULL) {
            std::auto_ptr<T> tmp(static_cast<T*>(this));
            sInstance=tmp;
        }
    }
    virtual ~AutoSingleton() {
        if (sInstance.get()==this)
            sInstance.release();
    }
    static void destroy() {
        sInstance.reset();
    }
};

}

#define AUTO_SINGLETON_INSTANCE(ClassName) template<>std::auto_ptr<ClassName>Sirikata::AutoSingleton<ClassName>::sInstance= std::auto_ptr<ClassName>()

#endif
<commit_msg>fixed options memory leak due to autoptr being inited twice<commit_after>/*  Sirikata Utilities -- Sirikata Utilities
 *  Singleton.hpp
 *
 *  Copyright (c) 2009, Daniel Reiter Horn
 *  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 Sirikata 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.
 */

#ifndef _SIRIKATA_SINGLETON_HPP_
#define _SIRIKATA_SINGLETON_HPP_
namespace Sirikata {

template <class T> class AutoSingleton {
    static std::auto_ptr<T>sInstance;
public:
    static T&getSingleton() {
        if (sInstance.get()==NULL)  {
            std::auto_ptr<T> tmp(new T);
            sInstance = tmp;
        }
        return *static_cast<T*>(sInstance.get());
    }
    AutoSingleton() {
        if (sInstance.get()==NULL) {
            std::auto_ptr<T> tmp(static_cast<T*>(this));
            sInstance=tmp;
        }
    }
    virtual ~AutoSingleton() {
        if (sInstance.get()==this)
            sInstance.release();
    }
    static void destroy() {
        sInstance.reset();
    }
};

}
#define AUTO_SINGLETON_INSTANCE(ClassName) template std::auto_ptr<ClassName> Sirikata::AutoSingleton<ClassName>::sInstance; template<>std::auto_ptr<ClassName>Sirikata::AutoSingleton<ClassName>::sInstance

#endif
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include "core/posix.hh"
#include "core/vla.hh"
#include "core/reactor.hh"
#include "core/future-util.hh"
#include "core/stream.hh"
#include "core/circular_buffer.hh"
#include "core/align.hh"
#include <atomic>
#include <list>
#include <queue>
#include <fcntl.h>
#include <linux/if_tun.h>
#include "ip.hh"

#include <xen/xen.h>

#include <xen/memory.h>
#include <xen/sys/gntalloc.h>

#include "core/xen/xenstore.hh"
#include "core/xen/evtchn.hh"

#include "xenfront.hh"
#include <unordered_set>

using namespace net;

namespace xen {

using phys = uint64_t;

class xenfront_net_device : public net::device {
private:
    bool _userspace;
    stream<packet> _rx_stream;
    net::hw_features _hw_features;

    std::string _device_str;
    xenstore* _xenstore = xenstore::instance();
    unsigned _otherend;
    std::string _backend;
    gntalloc *_gntalloc;
    evtchn   *_evtchn;
    port _tx_evtchn;
    port _rx_evtchn;

    front_ring<tx> _tx_ring;
    front_ring<rx> _rx_ring;

    grant_head *_tx_refs;
    grant_head *_rx_refs;

    std::list<std::pair<std::string, std::string>> _features;
    static std::unordered_set<std::string> _supported_features;

    ethernet_address _hw_address;

    port bind_tx_evtchn();
    port bind_rx_evtchn();

    future<> alloc_rx_references();
    future<> handle_tx_completions();
    future<> queue_rx_packet();

    void alloc_one_rx_reference(unsigned id);
    std::string path(std::string s) { return _device_str + "/" + s; }

public:
    explicit xenfront_net_device(boost::program_options::variables_map opts, bool userspace);
    ~xenfront_net_device();
    virtual subscription<packet> receive(std::function<future<> (packet)> next) override;
    virtual future<> send(packet p) override;

    ethernet_address hw_address();
    net::hw_features hw_features();
};

std::unordered_set<std::string>
xenfront_net_device::_supported_features = {
    "feature-split-event-channels",
    "feature-rx-copy",
};

subscription<packet>
xenfront_net_device::receive(std::function<future<> (packet)> next) {
    auto sub = _rx_stream.listen(std::move(next));
    keep_doing([this] {
        return _rx_evtchn.pending().then([this] {
            return queue_rx_packet();
        });
    });

    return std::move(sub);
}

future<>
xenfront_net_device::send(packet _p) {

    uint32_t frag = 0;
    // There doesn't seem to be a way to tell xen, when using the userspace
    // drivers, to map a particular page. Therefore, the only alternative
    // here is to copy. All pages shared must come from the gntalloc mmap.
    //
    // A better solution could be to change the packet allocation path to
    // use a pre-determined page for data.
    //
    // In-kernel should be fine

    // FIXME: negotiate and use scatter/gather
    _p.linearize();

    return _tx_ring.entries.get_index().then([this, p = std::move(_p), frag] (unsigned idx) mutable {

        auto req_prod = _tx_ring._sring->req_prod;

        auto f = p.frag(frag);

        auto ref = _tx_refs->new_ref(f.base, f.size);

        assert(!_tx_ring.entries[idx]);

        _tx_ring.entries[idx] = ref;

        auto req = &_tx_ring._sring->_ring[idx].req;
        req->gref = ref.xen_id;
        req->offset = 0;
        req->flags = {};
        if (p.offload_info().protocol != ip_protocol_num::unused) {
            req->flags.csum_blank = true;
            req->flags.data_validated = true;
        } else {
            req->flags.data_validated = true;
        }
        req->id = idx;
        req->size = f.size;

        _tx_ring.req_prod_pvt = idx;
        _tx_ring._sring->req_prod = req_prod + 1;

        _tx_ring._sring->req_event++;
        if ((frag + 1) == p.nr_frags()) {
            _tx_evtchn.notify();
            return make_ready_future<>();
        } else {
            return make_ready_future<>();
        }
    });

    // FIXME: Don't forget to clear all grant refs when frontend closes. Or is it automatic?
}

#define rmb() asm volatile("lfence":::"memory");
#define wmb() asm volatile("":::"memory");

template <typename T>
future<unsigned> front_ring<T>::entries::get_index() {
    return _available.wait().then([this] {
        auto ret = _ids.front();
        _ids.pop();
        return make_ready_future<unsigned>(ret);
    });
}

template <typename T>
void front_ring<T>::entries::free_index(unsigned id) {
    _ids.push(id);
    _available.signal();
}

future<> xenfront_net_device::queue_rx_packet() {

    auto rsp_cons = _rx_ring.rsp_cons;
    rmb();
    auto rsp_prod = _rx_ring._sring->rsp_prod;

    while (rsp_cons < rsp_prod) {
        auto rsp = _rx_ring[rsp_cons].rsp;
        auto& entry = _rx_ring.entries[rsp.id];

        rsp_cons++;
        _rx_ring.rsp_cons = rsp_cons;

        if (rsp.status < 0) {
            printf("Packet error: Handle it\n");
            continue;
        }
        auto rsp_size = rsp.status;

        packet p(static_cast<char *>(entry.page) + rsp.offset, rsp_size);
        _rx_stream.produce(std::move(p));

        _rx_ring._sring->rsp_event = rsp_cons + 1;

        rsp_prod = _rx_ring._sring->rsp_prod;

        _rx_refs->free_ref(entry);
        _rx_ring.entries.free_index(rsp.id);
    }

    // FIXME: Queue_rx maybe should not be a future then
    return make_ready_future<>();
}

void xenfront_net_device::alloc_one_rx_reference(unsigned index) {

    _rx_ring.entries[index] = _rx_refs->new_ref();

    // This is how the backend knows where to put data.
    auto req =  &_rx_ring._sring->_ring[index].req;
    req->id = index;
    req->gref = _rx_ring.entries[index].xen_id;
}

future<> xenfront_net_device::alloc_rx_references() {
    return _rx_ring.entries.get_index().then([this] (unsigned i) {
        auto req_prod = _rx_ring.req_prod_pvt;
        alloc_one_rx_reference(i);
        ++req_prod;
        _rx_ring.req_prod_pvt = req_prod;
        wmb();
        _rx_ring._sring->req_prod = req_prod;
        /* ready */
        _rx_evtchn.notify();
    });
}

future<> xenfront_net_device::handle_tx_completions() {
    auto prod = _tx_ring._sring->rsp_prod;
    rmb();

    for (unsigned i = _tx_ring.rsp_cons; i != prod; i++) {
        auto rsp = _tx_ring[i].rsp;

        if (rsp.status == 1) {
            continue;
        }

        if (rsp.status != 0) {
            printf("Packet error: Handle it\n");
            continue;
        }

        auto& entry = _tx_ring.entries[rsp.id];
        _tx_refs->free_ref(entry);
        _tx_ring.entries.free_index(rsp.id);
    }
    _tx_ring.rsp_cons = prod;
    _tx_ring._sring->rsp_event = prod + 1;
    return make_ready_future<>();
}

ethernet_address xenfront_net_device::hw_address() {
    return _hw_address;
}

net::hw_features xenfront_net_device::hw_features() {
    return _hw_features;
}

port xenfront_net_device::bind_tx_evtchn() {
    return _evtchn->bind();
}

port xenfront_net_device::bind_rx_evtchn() {

    auto split = _xenstore->read_or_default<int>(_backend + "/feature-split-event-channels");
    if (split) {
        return _evtchn->bind();
    }
    return _evtchn->bind(_tx_evtchn.number());
}

xenfront_net_device::xenfront_net_device(boost::program_options::variables_map opts, bool userspace)
    : _userspace(userspace)
    , _rx_stream()
    , _device_str("device/vif/" + std::to_string(opts["vif"].as<unsigned>()))
    , _otherend(_xenstore->read<int>(path("backend-id")))
    , _backend(_xenstore->read(path("backend")))
    , _gntalloc(gntalloc::instance(_userspace, _otherend))
    , _evtchn(evtchn::instance(_userspace, _otherend))
    , _tx_evtchn(bind_tx_evtchn())
    , _rx_evtchn(bind_rx_evtchn())
    , _tx_ring(_gntalloc->alloc_ref())
    , _rx_ring(_gntalloc->alloc_ref())
    , _tx_refs(_gntalloc->alloc_ref(front_ring<tx>::nr_ents))
    , _rx_refs(_gntalloc->alloc_ref(front_ring<rx>::nr_ents))
    , _hw_address(net::parse_ethernet_address(_xenstore->read(path("mac")))) {

    _rx_stream.started();

    auto all_features = _xenstore->ls(_backend);
    std::unordered_map<std::string, int> features_nack;

    for (auto&& feat : all_features) {
        if (feat.compare(0, 8, "feature-") == 0 && !_supported_features.count(feat)) {
            features_nack[feat] = 0;
        }
    }
    if (!opts["split-event-channels"].as<bool>()) {
        features_nack["feature-split-event-channels"] = 0;
    }

    _hw_features.rx_csum_offload = true;
    _hw_features.tx_csum_offload = true;

    for (auto&s : all_features) {
        auto value = _xenstore->read(_backend + "/" + s);
        _features.push_back(std::make_pair(s, value));
    }

    {
        auto t = xenstore::xenstore_transaction();

        for (auto&& f: features_nack) {
            _xenstore->write(path(f.first), f.second, t);
        }

        _xenstore->write<int>(path("event-channel-tx"), _tx_evtchn.number(), t);
        _xenstore->write<int>(path("event-channel-rx"), _rx_evtchn.number(), t);
        _xenstore->write<int>(path("tx-ring-ref"), _tx_ring.ref, t);
        _xenstore->write<int>(path("rx-ring-ref"), _rx_ring.ref, t);
        _xenstore->write<int>(path("state"), 4, t);
    }

    keep_doing([this] {
        return alloc_rx_references();
    });
    keep_doing([this] () {
        return _tx_evtchn.pending().then([this] {
            handle_tx_completions();
        });
    });
}

xenfront_net_device::~xenfront_net_device() {

    {
        auto t = xenstore::xenstore_transaction();

        for (auto& f: _features) {
            _xenstore->remove(path(f.first), t);
        }
        _xenstore->remove(path("event-channel-tx"), t);
        _xenstore->remove(path("event-channel-rx"), t);
        _xenstore->remove(path("tx-ring-ref"), t);
        _xenstore->remove(path("rx-ring-ref"), t);
        _xenstore->write<int>(path("state"), 6, t);
    }

    _xenstore->write<int>(path("state"), 1);
}

boost::program_options::options_description
get_xenfront_net_options_description() {

    boost::program_options::options_description opts(
            "xenfront net options");
    opts.add_options()
        ("vif",
                boost::program_options::value<unsigned>()->default_value(0),
                "vif number to hijack")
        ("split-event-channels",
                boost::program_options::value<bool>()->default_value(true),
                "Split event channel support")
        ;
    return opts;
}

std::unique_ptr<net::device> create_xenfront_net_device(boost::program_options::variables_map opts, bool userspace) {
    auto ptr = std::make_unique<xenfront_net_device>(opts, userspace);
    // This assumes only one device per cpu. Will need to be fixed when
    // this assumption will no longer hold.
    dev = ptr.get();
    return std::move(ptr);
}

}
<commit_msg>xen: positively acknowledge supported features<commit_after>/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include "core/posix.hh"
#include "core/vla.hh"
#include "core/reactor.hh"
#include "core/future-util.hh"
#include "core/stream.hh"
#include "core/circular_buffer.hh"
#include "core/align.hh"
#include <atomic>
#include <list>
#include <queue>
#include <fcntl.h>
#include <linux/if_tun.h>
#include "ip.hh"

#include <xen/xen.h>

#include <xen/memory.h>
#include <xen/sys/gntalloc.h>

#include "core/xen/xenstore.hh"
#include "core/xen/evtchn.hh"

#include "xenfront.hh"
#include <unordered_set>

using namespace net;

namespace xen {

using phys = uint64_t;

class xenfront_net_device : public net::device {
private:
    bool _userspace;
    stream<packet> _rx_stream;
    net::hw_features _hw_features;

    std::string _device_str;
    xenstore* _xenstore = xenstore::instance();
    unsigned _otherend;
    std::string _backend;
    gntalloc *_gntalloc;
    evtchn   *_evtchn;
    port _tx_evtchn;
    port _rx_evtchn;

    front_ring<tx> _tx_ring;
    front_ring<rx> _rx_ring;

    grant_head *_tx_refs;
    grant_head *_rx_refs;

    std::list<std::pair<std::string, std::string>> _features;
    static std::unordered_set<std::string> _supported_features;

    ethernet_address _hw_address;

    port bind_tx_evtchn();
    port bind_rx_evtchn();

    future<> alloc_rx_references();
    future<> handle_tx_completions();
    future<> queue_rx_packet();

    void alloc_one_rx_reference(unsigned id);
    std::string path(std::string s) { return _device_str + "/" + s; }

public:
    explicit xenfront_net_device(boost::program_options::variables_map opts, bool userspace);
    ~xenfront_net_device();
    virtual subscription<packet> receive(std::function<future<> (packet)> next) override;
    virtual future<> send(packet p) override;

    ethernet_address hw_address();
    net::hw_features hw_features();
};

std::unordered_set<std::string>
xenfront_net_device::_supported_features = {
    "feature-split-event-channels",
    "feature-rx-copy",
};

subscription<packet>
xenfront_net_device::receive(std::function<future<> (packet)> next) {
    auto sub = _rx_stream.listen(std::move(next));
    keep_doing([this] {
        return _rx_evtchn.pending().then([this] {
            return queue_rx_packet();
        });
    });

    return std::move(sub);
}

future<>
xenfront_net_device::send(packet _p) {

    uint32_t frag = 0;
    // There doesn't seem to be a way to tell xen, when using the userspace
    // drivers, to map a particular page. Therefore, the only alternative
    // here is to copy. All pages shared must come from the gntalloc mmap.
    //
    // A better solution could be to change the packet allocation path to
    // use a pre-determined page for data.
    //
    // In-kernel should be fine

    // FIXME: negotiate and use scatter/gather
    _p.linearize();

    return _tx_ring.entries.get_index().then([this, p = std::move(_p), frag] (unsigned idx) mutable {

        auto req_prod = _tx_ring._sring->req_prod;

        auto f = p.frag(frag);

        auto ref = _tx_refs->new_ref(f.base, f.size);

        assert(!_tx_ring.entries[idx]);

        _tx_ring.entries[idx] = ref;

        auto req = &_tx_ring._sring->_ring[idx].req;
        req->gref = ref.xen_id;
        req->offset = 0;
        req->flags = {};
        if (p.offload_info().protocol != ip_protocol_num::unused) {
            req->flags.csum_blank = true;
            req->flags.data_validated = true;
        } else {
            req->flags.data_validated = true;
        }
        req->id = idx;
        req->size = f.size;

        _tx_ring.req_prod_pvt = idx;
        _tx_ring._sring->req_prod = req_prod + 1;

        _tx_ring._sring->req_event++;
        if ((frag + 1) == p.nr_frags()) {
            _tx_evtchn.notify();
            return make_ready_future<>();
        } else {
            return make_ready_future<>();
        }
    });

    // FIXME: Don't forget to clear all grant refs when frontend closes. Or is it automatic?
}

#define rmb() asm volatile("lfence":::"memory");
#define wmb() asm volatile("":::"memory");

template <typename T>
future<unsigned> front_ring<T>::entries::get_index() {
    return _available.wait().then([this] {
        auto ret = _ids.front();
        _ids.pop();
        return make_ready_future<unsigned>(ret);
    });
}

template <typename T>
void front_ring<T>::entries::free_index(unsigned id) {
    _ids.push(id);
    _available.signal();
}

future<> xenfront_net_device::queue_rx_packet() {

    auto rsp_cons = _rx_ring.rsp_cons;
    rmb();
    auto rsp_prod = _rx_ring._sring->rsp_prod;

    while (rsp_cons < rsp_prod) {
        auto rsp = _rx_ring[rsp_cons].rsp;
        auto& entry = _rx_ring.entries[rsp.id];

        rsp_cons++;
        _rx_ring.rsp_cons = rsp_cons;

        if (rsp.status < 0) {
            printf("Packet error: Handle it\n");
            continue;
        }
        auto rsp_size = rsp.status;

        packet p(static_cast<char *>(entry.page) + rsp.offset, rsp_size);
        _rx_stream.produce(std::move(p));

        _rx_ring._sring->rsp_event = rsp_cons + 1;

        rsp_prod = _rx_ring._sring->rsp_prod;

        _rx_refs->free_ref(entry);
        _rx_ring.entries.free_index(rsp.id);
    }

    // FIXME: Queue_rx maybe should not be a future then
    return make_ready_future<>();
}

void xenfront_net_device::alloc_one_rx_reference(unsigned index) {

    _rx_ring.entries[index] = _rx_refs->new_ref();

    // This is how the backend knows where to put data.
    auto req =  &_rx_ring._sring->_ring[index].req;
    req->id = index;
    req->gref = _rx_ring.entries[index].xen_id;
}

future<> xenfront_net_device::alloc_rx_references() {
    return _rx_ring.entries.get_index().then([this] (unsigned i) {
        auto req_prod = _rx_ring.req_prod_pvt;
        alloc_one_rx_reference(i);
        ++req_prod;
        _rx_ring.req_prod_pvt = req_prod;
        wmb();
        _rx_ring._sring->req_prod = req_prod;
        /* ready */
        _rx_evtchn.notify();
    });
}

future<> xenfront_net_device::handle_tx_completions() {
    auto prod = _tx_ring._sring->rsp_prod;
    rmb();

    for (unsigned i = _tx_ring.rsp_cons; i != prod; i++) {
        auto rsp = _tx_ring[i].rsp;

        if (rsp.status == 1) {
            continue;
        }

        if (rsp.status != 0) {
            printf("Packet error: Handle it\n");
            continue;
        }

        auto& entry = _tx_ring.entries[rsp.id];
        _tx_refs->free_ref(entry);
        _tx_ring.entries.free_index(rsp.id);
    }
    _tx_ring.rsp_cons = prod;
    _tx_ring._sring->rsp_event = prod + 1;
    return make_ready_future<>();
}

ethernet_address xenfront_net_device::hw_address() {
    return _hw_address;
}

net::hw_features xenfront_net_device::hw_features() {
    return _hw_features;
}

port xenfront_net_device::bind_tx_evtchn() {
    return _evtchn->bind();
}

port xenfront_net_device::bind_rx_evtchn() {

    auto split = _xenstore->read_or_default<int>(_backend + "/feature-split-event-channels");
    if (split) {
        return _evtchn->bind();
    }
    return _evtchn->bind(_tx_evtchn.number());
}

xenfront_net_device::xenfront_net_device(boost::program_options::variables_map opts, bool userspace)
    : _userspace(userspace)
    , _rx_stream()
    , _device_str("device/vif/" + std::to_string(opts["vif"].as<unsigned>()))
    , _otherend(_xenstore->read<int>(path("backend-id")))
    , _backend(_xenstore->read(path("backend")))
    , _gntalloc(gntalloc::instance(_userspace, _otherend))
    , _evtchn(evtchn::instance(_userspace, _otherend))
    , _tx_evtchn(bind_tx_evtchn())
    , _rx_evtchn(bind_rx_evtchn())
    , _tx_ring(_gntalloc->alloc_ref())
    , _rx_ring(_gntalloc->alloc_ref())
    , _tx_refs(_gntalloc->alloc_ref(front_ring<tx>::nr_ents))
    , _rx_refs(_gntalloc->alloc_ref(front_ring<rx>::nr_ents))
    , _hw_address(net::parse_ethernet_address(_xenstore->read(path("mac")))) {

    _rx_stream.started();

    auto all_features = _xenstore->ls(_backend);
    std::unordered_map<std::string, int> features_nack;

    for (auto&& feat : all_features) {
        if (feat.compare(0, 8, "feature-") == 0) {
            auto val = _xenstore->read<int>(_backend + "/" + feat);
            features_nack[feat] = val && _supported_features.count(feat);
        }
    }
    if (!opts["split-event-channels"].as<bool>()) {
        features_nack["feature-split-event-channels"] = 0;
    }

    _hw_features.rx_csum_offload = true;
    _hw_features.tx_csum_offload = true;

    for (auto&s : all_features) {
        auto value = _xenstore->read(_backend + "/" + s);
        _features.push_back(std::make_pair(s, value));
    }

    {
        auto t = xenstore::xenstore_transaction();

        for (auto&& f: features_nack) {
            _xenstore->write(path(f.first), f.second, t);
        }

        _xenstore->write<int>(path("event-channel-tx"), _tx_evtchn.number(), t);
        _xenstore->write<int>(path("event-channel-rx"), _rx_evtchn.number(), t);
        _xenstore->write<int>(path("tx-ring-ref"), _tx_ring.ref, t);
        _xenstore->write<int>(path("rx-ring-ref"), _rx_ring.ref, t);
        _xenstore->write<int>(path("state"), 4, t);
    }

    keep_doing([this] {
        return alloc_rx_references();
    });
    keep_doing([this] () {
        return _tx_evtchn.pending().then([this] {
            handle_tx_completions();
        });
    });
}

xenfront_net_device::~xenfront_net_device() {

    {
        auto t = xenstore::xenstore_transaction();

        for (auto& f: _features) {
            _xenstore->remove(path(f.first), t);
        }
        _xenstore->remove(path("event-channel-tx"), t);
        _xenstore->remove(path("event-channel-rx"), t);
        _xenstore->remove(path("tx-ring-ref"), t);
        _xenstore->remove(path("rx-ring-ref"), t);
        _xenstore->write<int>(path("state"), 6, t);
    }

    _xenstore->write<int>(path("state"), 1);
}

boost::program_options::options_description
get_xenfront_net_options_description() {

    boost::program_options::options_description opts(
            "xenfront net options");
    opts.add_options()
        ("vif",
                boost::program_options::value<unsigned>()->default_value(0),
                "vif number to hijack")
        ("split-event-channels",
                boost::program_options::value<bool>()->default_value(true),
                "Split event channel support")
        ;
    return opts;
}

std::unique_ptr<net::device> create_xenfront_net_device(boost::program_options::variables_map opts, bool userspace) {
    auto ptr = std::make_unique<xenfront_net_device>(opts, userspace);
    // This assumes only one device per cpu. Will need to be fixed when
    // this assumption will no longer hold.
    dev = ptr.get();
    return std::move(ptr);
}

}
<|endoftext|>


<commit_before>#ifndef TEST_NOTCH_IO_HPP
#define TEST_NOTCH_IO_HPP

#include <sstream>

#include "catch.hpp"
#include "notch_io.hpp"

using namespace std;

TEST_CASE("Array plain-text I/O", "[io]") {
    Array a = {0.5, 1.0, 2.0, 4.0};
    // output
    ostringstream sout;
    sout << a;
    CHECK(sout.str() == "0.5 1 2 4");
    // input
    Array b(4);
    istringstream sin(sout.str());
    sin >> b;
    REQUIRE(b.size() == a.size());
    for (size_t i = 0; i < a.size(); ++i) {
        CHECK(b[i] == a[i]);
    }
}

#endif
<commit_msg>tests for FANNReader and FANNFormat<commit_after>#ifndef TEST_NOTCH_IO_HPP
#define TEST_NOTCH_IO_HPP

#include <sstream>
#include <iterator>

#include "catch.hpp"
#include "notch_io.hpp"

using namespace std;

TEST_CASE("Array plain-text I/O", "[io]") {
    Array a = {0.5, 1.0, 2.0, 4.0};
    // output
    ostringstream sout;
    sout << a;
    CHECK(sout.str() == "0.5 1 2 4");
    // input
    Array b(4);
    istringstream sin(sout.str());
    sin >> b;
    REQUIRE(b.size() == a.size());
    for (size_t i = 0; i < a.size(); ++i) {
        CHECK(b[i] == a[i]);
    }
}

TEST_CASE("Dataset FANN-format reader", "[io]") {
    stringstream ss("4 2 1\n0.0 0\n0\n0.0 1.0\n1.0\n1.0 0.0\n1\n1 1\n0.0");
    LabeledDataset d = FANNReader::read(ss);
    CHECK(d.size() == 4);
    CHECK(d.inputDim() == 2);
    CHECK(d.outputDim() == 1);
    LabeledDataset good {{{0,0},{0}},
                         {{0,1},{1}},
                         {{1,0},{1}},
                         {{1,1},{0}}};
    auto d_it = begin(d);
    auto d_end = end(d);
    auto good_it = begin(good);
    auto good_end = end(good);
    for (; good_it != good_end; ++d_it, ++good_it) {
        for (size_t i = 0; i < good.inputDim(); ++i) {
            CHECK((*good_it).data[i] == (*d_it).data[i]);
        }
        for (size_t i = 0; i < good.outputDim(); ++i) {
            CHECK((*good_it).label[i] == (*d_it).label[i]);
        }
    }
}

TEST_CASE("Dataset FANN-format writer", "[io]") {
    LabeledDataset xorD {{{0,0},{0}}, {{0,1},{1}}, {{1,0},{1}}, {{1,1},{0}}};
    ostringstream ss;
    ss << FANNFormat(xorD);
    CHECK(ss.str() == "4 2 1\n0 0\n0\n0 1\n1\n1 0\n1\n1 1\n0\n");
}

#endif
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#include <iostream>
#include <fstream>
#include <stdexcept>
#include <mapnik/geom_util.hpp>

// boost
#include <boost/version.hpp>
#include <boost/format.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/filesystem/operations.hpp>

#if BOOST_VERSION < 103600
#include <boost/filesystem/convenience.hpp>
#endif

#include "shape_featureset.hpp"
#include "shape_index_featureset.hpp"
#include "shape.hpp"

DATASOURCE_PLUGIN(shape_datasource)

using mapnik::String;
using mapnik::Double;
using mapnik::Integer;
using mapnik::datasource_exception;
using mapnik::filter_in_box;
using mapnik::filter_at_point;
using mapnik::attribute_descriptor;

shape_datasource::shape_datasource(const parameters &params)
   : datasource (params),
     type_(datasource::Vector),
     file_length_(0),
     indexed_(false),
     desc_(*params.get<std::string>("type"), *params.get<std::string>("encoding","utf-8"))
{
   boost::optional<std::string> file = params.get<std::string>("file");
   if (!file) throw datasource_exception("missing <file> parameter");

   boost::optional<std::string> base = params.get<std::string>("base");
   if (base)
      shape_name_ = *base + "/" + *file;
   else
      shape_name_ = *file;

   boost::filesystem::path path(shape_name_);
#if BOOST_VERSION >= 103600
   path.replace_extension("");
#else
   path = boost::filesystem::change_extension(path,"");
#endif
   shape_name_ = path.string();

   if (!boost::filesystem::exists(shape_name_ + ".shp")) throw datasource_exception(shape_name_ + ".shp does not exist");

   try
   {
      shape_io shape(shape_name_);
      init(shape);
      for (int i=0;i<shape.dbf().num_fields();++i)
      {
         field_descriptor const& fd=shape.dbf().descriptor(i);
         std::string fld_name=fd.name_;
         switch (fd.type_)
         {
            case 'C':
            case 'D':
            case 'M':
            case 'L':
               desc_.add_descriptor(attribute_descriptor(fld_name, String));
               break;
            case 'N':
            case 'F':
            {
               if (fd.dec_>0)
               {
                  desc_.add_descriptor(attribute_descriptor(fld_name,Double,false,8));
               }
               else
               {
                  desc_.add_descriptor(attribute_descriptor(fld_name,Integer,false,4));
               }
               break;
            }
            default:
#ifdef MAPNIK_DEBUG
               std::clog << "unknown type "<<fd.type_<<"\n";
#endif
               break;
         }
      }
   }
   catch (datasource_exception& ex)
   {
      std::clog<<ex.what()<<std::endl;
      throw;
   }
   catch (...)
   {
      std::clog << " got exception ... \n";
      throw;
   }
}

shape_datasource::~shape_datasource() {}

const std::string shape_datasource::name_="shape";

void  shape_datasource::init(shape_io& shape)
{
   //first read header from *.shp
   int file_code=shape.shp().read_xdr_integer();
   if (file_code!=9994)
   {
       //invalid file code
       throw datasource_exception((boost::format("wrong file code : %d") % file_code).str());
   }

   shape.shp().skip(5*4);
   file_length_=shape.shp().read_xdr_integer();
   int version=shape.shp().read_ndr_integer();

   if (version!=1000)
   {
      //invalid version number
       throw datasource_exception((boost::format("invalid version number: %d") % version).str());
   }

#ifdef MAPNIK_DEBUG
   int shape_type = shape.shp().read_ndr_integer();
#else
   shape.shp().skip(4);
#endif

   shape.shp().read_envelope(extent_);
   shape.shp().skip(4*8);

   // check if we have an index file around
   std::string index_name(shape_name_+".index");
   std::ifstream file(index_name.c_str(),std::ios::in | std::ios::binary);
   if (file)
   {
      indexed_=true;
      file.close();
   }

#ifdef MAPNIK_DEBUG
   std::clog << extent_ << std::endl;
   std::clog << "file_length=" << file_length_ << std::endl;
   std::clog << "shape_type=" << shape_type << std::endl;
#endif

}

int shape_datasource::type() const
{
   return type_;
}

layer_descriptor shape_datasource::get_descriptor() const
{
   return desc_;
}

std::string shape_datasource::name()
{
   return name_;
}

featureset_ptr shape_datasource::features(const query& q) const
{
   filter_in_box filter(q.get_bbox());
   if (indexed_)
   {
      return featureset_ptr
         (new shape_index_featureset<filter_in_box>(filter,
                                                    shape_name_,
                                                    q.property_names(),
                                                    desc_.get_encoding()));
   }
   else
   {
      return featureset_ptr
         (new shape_featureset<filter_in_box>(filter,
                                              shape_name_,
                                              q.property_names(),
                                              desc_.get_encoding(),
                                              file_length_));
   }
}

featureset_ptr shape_datasource::features_at_point(coord2d const& pt) const
{
   filter_at_point filter(pt);
   // collect all attribute names
   std::vector<attribute_descriptor> const& desc_vector = desc_.get_descriptors();
   std::vector<attribute_descriptor>::const_iterator itr = desc_vector.begin();
   std::vector<attribute_descriptor>::const_iterator end = desc_vector.end();
   std::set<std::string> names;

   while (itr != end)
   {
      names.insert(itr->get_name());
      ++itr;
   }

   if (indexed_)
   {
      return featureset_ptr
         (new shape_index_featureset<filter_at_point>(filter,
                                                      shape_name_,
                                                      names,
                                                      desc_.get_encoding()));
   }
   else
   {
      return featureset_ptr
         (new shape_featureset<filter_at_point>(filter,
                                                shape_name_,
                                                names,
                                                desc_.get_encoding(),
                                                file_length_));
   }
}

Envelope<double> shape_datasource::envelope() const
{
   return extent_;
}
<commit_msg>shape plugin: only trim the '.shp' extension (restores behavior added in r1046 and later changed in r1170) - closes #413<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#include <iostream>
#include <fstream>
#include <stdexcept>
#include <mapnik/geom_util.hpp>

// boost
#include <boost/version.hpp>
#include <boost/format.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/filesystem/operations.hpp>

#include "shape_featureset.hpp"
#include "shape_index_featureset.hpp"
#include "shape.hpp"

DATASOURCE_PLUGIN(shape_datasource)

using mapnik::String;
using mapnik::Double;
using mapnik::Integer;
using mapnik::datasource_exception;
using mapnik::filter_in_box;
using mapnik::filter_at_point;
using mapnik::attribute_descriptor;

shape_datasource::shape_datasource(const parameters &params)
   : datasource (params),
     type_(datasource::Vector),
     file_length_(0),
     indexed_(false),
     desc_(*params.get<std::string>("type"), *params.get<std::string>("encoding","utf-8"))
{
   boost::optional<std::string> file = params.get<std::string>("file");
   if (!file) throw datasource_exception("missing <file> parameter");

   boost::optional<std::string> base = params.get<std::string>("base");
   if (base)
      shape_name_ = *base + "/" + *file;
   else
      shape_name_ = *file;

   boost::algorithm::ireplace_last(shape_name_,".shp","");

   if (!boost::filesystem::exists(shape_name_ + ".shp"))
   {
       throw datasource_exception(shape_name_ + " does not exist");
   }

   try
   {
      shape_io shape(shape_name_);
      init(shape);
      for (int i=0;i<shape.dbf().num_fields();++i)
      {
         field_descriptor const& fd=shape.dbf().descriptor(i);
         std::string fld_name=fd.name_;
         switch (fd.type_)
         {
            case 'C':
            case 'D':
            case 'M':
            case 'L':
               desc_.add_descriptor(attribute_descriptor(fld_name, String));
               break;
            case 'N':
            case 'F':
            {
               if (fd.dec_>0)
               {
                  desc_.add_descriptor(attribute_descriptor(fld_name,Double,false,8));
               }
               else
               {
                  desc_.add_descriptor(attribute_descriptor(fld_name,Integer,false,4));
               }
               break;
            }
            default:
#ifdef MAPNIK_DEBUG
               std::clog << "unknown type "<<fd.type_<<"\n";
#endif
               break;
         }
      }
   }
   catch (datasource_exception& ex)
   {
      std::clog<<ex.what()<<std::endl;
      throw;
   }
   catch (...)
   {
      std::clog << " got exception ... \n";
      throw;
   }
}

shape_datasource::~shape_datasource() {}

const std::string shape_datasource::name_="shape";

void  shape_datasource::init(shape_io& shape)
{
   //first read header from *.shp
   int file_code=shape.shp().read_xdr_integer();
   if (file_code!=9994)
   {
       //invalid file code
       throw datasource_exception((boost::format("wrong file code : %d") % file_code).str());
   }

   shape.shp().skip(5*4);
   file_length_=shape.shp().read_xdr_integer();
   int version=shape.shp().read_ndr_integer();

   if (version!=1000)
   {
      //invalid version number
       throw datasource_exception((boost::format("invalid version number: %d") % version).str());
   }

#ifdef MAPNIK_DEBUG
   int shape_type = shape.shp().read_ndr_integer();
#else
   shape.shp().skip(4);
#endif

   shape.shp().read_envelope(extent_);
   shape.shp().skip(4*8);

   // check if we have an index file around
   std::string index_name(shape_name_+".index");
   std::ifstream file(index_name.c_str(),std::ios::in | std::ios::binary);
   if (file)
   {
      indexed_=true;
      file.close();
   }

#ifdef MAPNIK_DEBUG
   std::clog << extent_ << std::endl;
   std::clog << "file_length=" << file_length_ << std::endl;
   std::clog << "shape_type=" << shape_type << std::endl;
#endif

}

int shape_datasource::type() const
{
   return type_;
}

layer_descriptor shape_datasource::get_descriptor() const
{
   return desc_;
}

std::string shape_datasource::name()
{
   return name_;
}

featureset_ptr shape_datasource::features(const query& q) const
{
   filter_in_box filter(q.get_bbox());
   if (indexed_)
   {
      return featureset_ptr
         (new shape_index_featureset<filter_in_box>(filter,
                                                    shape_name_,
                                                    q.property_names(),
                                                    desc_.get_encoding()));
   }
   else
   {
      return featureset_ptr
         (new shape_featureset<filter_in_box>(filter,
                                              shape_name_,
                                              q.property_names(),
                                              desc_.get_encoding(),
                                              file_length_));
   }
}

featureset_ptr shape_datasource::features_at_point(coord2d const& pt) const
{
   filter_at_point filter(pt);
   // collect all attribute names
   std::vector<attribute_descriptor> const& desc_vector = desc_.get_descriptors();
   std::vector<attribute_descriptor>::const_iterator itr = desc_vector.begin();
   std::vector<attribute_descriptor>::const_iterator end = desc_vector.end();
   std::set<std::string> names;

   while (itr != end)
   {
      names.insert(itr->get_name());
      ++itr;
   }

   if (indexed_)
   {
      return featureset_ptr
         (new shape_index_featureset<filter_at_point>(filter,
                                                      shape_name_,
                                                      names,
                                                      desc_.get_encoding()));
   }
   else
   {
      return featureset_ptr
         (new shape_featureset<filter_at_point>(filter,
                                                shape_name_,
                                                names,
                                                desc_.get_encoding(),
                                                file_length_));
   }
}

Envelope<double> shape_datasource::envelope() const
{
   return extent_;
}
<|endoftext|>


<commit_before>//-----------------------------------------------
//
//	This file is part of the Siv3D Engine.
//
//	Copyright (c) 2008-2021 Ryo Suzuki
//	Copyright (c) 2016-2021 OpenSiv3D Project
//
//	Licensed under the MIT License.
//
//-----------------------------------------------

# pragma once
# include <Siv3D/Common.hpp>
# include <Siv3D/Common/OpenGL.hpp>
# include <Siv3D/PointVector.hpp>
# include <Siv3D/ResizeMode.hpp>
# include <Siv3D/Scene.hpp>
# include <Siv3D/Graphics.hpp>
# include <Siv3D/FloatRect.hpp>
# include <Siv3D/Image.hpp>
# include <ThirdParty/EnumBitmask/EnumBitmask.hpp>
# include "GLES3InternalTexture2D.hpp"

namespace s3d
{
	enum class GLES3ClearTarget
	{
		BackBuffer = 1 << 0,

		Scene = 1 << 1,

		All = (BackBuffer | Scene),
	};
	DEFINE_BITMASK_OPERATORS(GLES3ClearTarget);

	class CRenderer2D_GLES3;

	class GLES3BackBuffer
	{
	private:

		CRenderer2D_GLES3* pRenderer2D	= nullptr;

		uint32 m_sampleCount			= Graphics::DefaultSampleCount;

		ResizeMode m_sceneResizeMode	= Scene::DefaultResizeMode;

		Size m_backBufferSize			= Window::DefaultClientSize;

		Size m_sceneSize				= Scene::DefaultSceneSize;

		struct SceneBuffer
		{
			std::unique_ptr<GLES3InternalTexture2D> scene;
			std::unique_ptr<GLES3InternalTexture2D> resolved;
		} m_sceneBuffers;

		ColorF m_letterboxColor				= Scene::DefaultLetterBoxColor;

		ColorF m_backgroundColor			= Scene::DefaultBackgroundColor;

		TextureFilter m_sceneTextureFilter	= Scene::DefaultTextureFilter;

		Image m_screenCaptureImage;

	public:

		GLES3BackBuffer();

		~GLES3BackBuffer();

		void clear(GLES3ClearTarget clearTargets);

		void bindSceneToContext(bool useDepth);

		void bindToScene(GLuint frameBuffer);

		void unbind();

		void updateFromSceneBuffer();

		void capture();

		const Image& getScreenCapture() const;

		//////////////////////////////////////////////////
		//
		//	LetterboxColor
		//
		//////////////////////////////////////////////////

		void setLetterboxColor(const ColorF& color) noexcept;

		[[nodiscard]]
		const ColorF& getLetterBoxColor() const noexcept;

		//////////////////////////////////////////////////
		//
		//	BackgroundColor
		//
		//////////////////////////////////////////////////

		void setBackgroundColor(const ColorF& color) noexcept;

		[[nodiscard]]
		const ColorF& getBackgroundColor() const noexcept;

		//////////////////////////////////////////////////
		//
		//	SceneTextureFilter
		//
		//////////////////////////////////////////////////

		void setSceneTextureFilter(TextureFilter textureFilter) noexcept;

		[[nodiscard]]
		TextureFilter getSceneTextureFilter() const noexcept;

		//////////////////////////////////////////////////
		//
		//	SceneResizeMode
		//
		//////////////////////////////////////////////////

		void setSceneResizeMode(ResizeMode resizeMode);

		[[nodiscard]]
		ResizeMode getSceneResizeMode() const noexcept;

		//////////////////////////////////////////////////
		//
		//	BackBuffer
		//
		//////////////////////////////////////////////////

		void setBackBufferSize(Size backBufferSize);

		[[nodiscard]]
		const Size& getBackBufferSize() const noexcept;

		void updateSceneSize();

		[[nodiscard]]
		std::pair<float, RectF> getLetterboxComposition() const noexcept;

		//////////////////////////////////////////////////
		//
		//	SceneBuffer
		//
		//////////////////////////////////////////////////

		void setSceneBufferSize(Size size);

		[[nodiscard]]
		const Size& getSceneBufferSize() const noexcept;

	};
}
<commit_msg>[Web] reduce scene buffer sampling number to 1<commit_after>//-----------------------------------------------
//
//	This file is part of the Siv3D Engine.
//
//	Copyright (c) 2008-2021 Ryo Suzuki
//	Copyright (c) 2016-2021 OpenSiv3D Project
//
//	Licensed under the MIT License.
//
//-----------------------------------------------

# pragma once
# include <Siv3D/Common.hpp>
# include <Siv3D/Common/OpenGL.hpp>
# include <Siv3D/PointVector.hpp>
# include <Siv3D/ResizeMode.hpp>
# include <Siv3D/Scene.hpp>
# include <Siv3D/Graphics.hpp>
# include <Siv3D/FloatRect.hpp>
# include <Siv3D/Image.hpp>
# include <ThirdParty/EnumBitmask/EnumBitmask.hpp>
# include "GLES3InternalTexture2D.hpp"

namespace s3d
{
	enum class GLES3ClearTarget
	{
		BackBuffer = 1 << 0,

		Scene = 1 << 1,

		All = (BackBuffer | Scene),
	};
	DEFINE_BITMASK_OPERATORS(GLES3ClearTarget);

	class CRenderer2D_GLES3;

	class GLES3BackBuffer
	{
	private:

		CRenderer2D_GLES3* pRenderer2D	= nullptr;

		uint32 m_sampleCount			= 1; // Graphics::DefaultSampleCount;

		ResizeMode m_sceneResizeMode	= Scene::DefaultResizeMode;

		Size m_backBufferSize			= Window::DefaultClientSize;

		Size m_sceneSize				= Scene::DefaultSceneSize;

		struct SceneBuffer
		{
			std::unique_ptr<GLES3InternalTexture2D> scene;
			std::unique_ptr<GLES3InternalTexture2D> resolved;
		} m_sceneBuffers;

		ColorF m_letterboxColor				= Scene::DefaultLetterBoxColor;

		ColorF m_backgroundColor			= Scene::DefaultBackgroundColor;

		TextureFilter m_sceneTextureFilter	= Scene::DefaultTextureFilter;

		Image m_screenCaptureImage;

	public:

		GLES3BackBuffer();

		~GLES3BackBuffer();

		void clear(GLES3ClearTarget clearTargets);

		void bindSceneToContext(bool useDepth);

		void bindToScene(GLuint frameBuffer);

		void unbind();

		void updateFromSceneBuffer();

		void capture();

		const Image& getScreenCapture() const;

		//////////////////////////////////////////////////
		//
		//	LetterboxColor
		//
		//////////////////////////////////////////////////

		void setLetterboxColor(const ColorF& color) noexcept;

		[[nodiscard]]
		const ColorF& getLetterBoxColor() const noexcept;

		//////////////////////////////////////////////////
		//
		//	BackgroundColor
		//
		//////////////////////////////////////////////////

		void setBackgroundColor(const ColorF& color) noexcept;

		[[nodiscard]]
		const ColorF& getBackgroundColor() const noexcept;

		//////////////////////////////////////////////////
		//
		//	SceneTextureFilter
		//
		//////////////////////////////////////////////////

		void setSceneTextureFilter(TextureFilter textureFilter) noexcept;

		[[nodiscard]]
		TextureFilter getSceneTextureFilter() const noexcept;

		//////////////////////////////////////////////////
		//
		//	SceneResizeMode
		//
		//////////////////////////////////////////////////

		void setSceneResizeMode(ResizeMode resizeMode);

		[[nodiscard]]
		ResizeMode getSceneResizeMode() const noexcept;

		//////////////////////////////////////////////////
		//
		//	BackBuffer
		//
		//////////////////////////////////////////////////

		void setBackBufferSize(Size backBufferSize);

		[[nodiscard]]
		const Size& getBackBufferSize() const noexcept;

		void updateSceneSize();

		[[nodiscard]]
		std::pair<float, RectF> getLetterboxComposition() const noexcept;

		//////////////////////////////////////////////////
		//
		//	SceneBuffer
		//
		//////////////////////////////////////////////////

		void setSceneBufferSize(Size size);

		[[nodiscard]]
		const Size& getSceneBufferSize() const noexcept;

	};
}
<|endoftext|>


<commit_before>#pragma once

#include "crow/core.hpp" // -lcrow
#include <map>
#include <stdexcept>
#include <string>

namespace Unicorn {

    namespace UnicornDetail {

        struct UnicodeVersionTable {
            std::map<Crow::Version, char32_t> table;
            UnicodeVersionTable();
        };

        const UnicodeVersionTable& unicode_version_table();

    }

    // Imports

    using Crow::basic_string;      // std::basic_string
    using Crow::string;            // std::string
    using Crow::u8string;          // std::string
    using Crow::u16string;         // std::u16string
    using Crow::u32string;         // std::u32string
    using Crow::wstring;           // std::wstring
    using Crow::ascii_whitespace;  // "\t\n\v\f\r "
    using Crow::npos;              // std::string::npos

    // Exceptions

    class EncodingError:
    public std::runtime_error {
    public:
        EncodingError():
            std::runtime_error(prefix({}, 0)), enc(), ofs(0) {}
        explicit EncodingError(const u8string& encoding, size_t offset = 0):
            std::runtime_error(prefix(encoding, offset)), enc(encoding), ofs(offset) {}
        template <typename C>
            EncodingError(const u8string& encoding, size_t offset, const C* ptr, size_t n = 1):
            std::runtime_error(prefix(encoding, offset) + hexcode(ptr, n)), enc(encoding), ofs(offset) {}
        u8string encoding() const { return enc; }
        size_t offset() const noexcept { return ofs; }
    private:
        u8string enc;
        size_t ofs;
        static u8string prefix(const u8string& encoding, size_t offset);
        template <typename C> static u8string hexcode(const C* ptr, size_t n);
    };

    template <typename C>
    u8string EncodingError::hexcode(const C* ptr, size_t n) {
        using utype = std::make_unsigned_t<C>;
        if (! ptr || ! n)
            return {};
        u8string s = "; hex";
        auto uptr = reinterpret_cast<const utype*>(ptr);
        for (size_t i = 0; i < n; ++i) {
            s += ' ';
            s += Crow::hex(uptr[i]);
        }
        return s;
    }

    // Basic character types

    #if defined(_XOPEN_SOURCE)
        using NativeCharacter = char;
    #else
        #define UNICORN_NATIVE_WCHAR 1
        using NativeCharacter = wchar_t;
    #endif

    #if WCHAR_MAX < 0x7fffffff
        #define UNICORN_WCHAR_UTF16 1
        using WcharEquivalent = char16_t;
    #else
        #define UNICORN_WCHAR_UTF32 1
        using WcharEquivalent = char32_t;
    #endif

    using NativeString = basic_string<NativeCharacter>;
    using WstringEquivalent = basic_string<WcharEquivalent>;

    namespace Literals {

        NativeString operator"" _nat(const char* s, size_t n);

    }

    // Version information

    Crow::Version unicorn_version() noexcept;
    Crow::Version unicode_version() noexcept;

}
<commit_msg>Change ldlib detection scheme<commit_after>#pragma once

#include "crow/core.hpp"
#include <map>
#include <stdexcept>
#include <string>

namespace Unicorn {

    namespace UnicornDetail {

        struct UnicodeVersionTable {
            std::map<Crow::Version, char32_t> table;
            UnicodeVersionTable();
        };

        const UnicodeVersionTable& unicode_version_table();

    }

    // Imports

    using Crow::basic_string;      // std::basic_string
    using Crow::string;            // std::string
    using Crow::u8string;          // std::string
    using Crow::u16string;         // std::u16string
    using Crow::u32string;         // std::u32string
    using Crow::wstring;           // std::wstring
    using Crow::ascii_whitespace;  // "\t\n\v\f\r "
    using Crow::npos;              // std::string::npos

    // Exceptions

    class EncodingError:
    public std::runtime_error {
    public:
        EncodingError():
            std::runtime_error(prefix({}, 0)), enc(), ofs(0) {}
        explicit EncodingError(const u8string& encoding, size_t offset = 0):
            std::runtime_error(prefix(encoding, offset)), enc(encoding), ofs(offset) {}
        template <typename C>
            EncodingError(const u8string& encoding, size_t offset, const C* ptr, size_t n = 1):
            std::runtime_error(prefix(encoding, offset) + hexcode(ptr, n)), enc(encoding), ofs(offset) {}
        u8string encoding() const { return enc; }
        size_t offset() const noexcept { return ofs; }
    private:
        u8string enc;
        size_t ofs;
        static u8string prefix(const u8string& encoding, size_t offset);
        template <typename C> static u8string hexcode(const C* ptr, size_t n);
    };

    template <typename C>
    u8string EncodingError::hexcode(const C* ptr, size_t n) {
        using utype = std::make_unsigned_t<C>;
        if (! ptr || ! n)
            return {};
        u8string s = "; hex";
        auto uptr = reinterpret_cast<const utype*>(ptr);
        for (size_t i = 0; i < n; ++i) {
            s += ' ';
            s += Crow::hex(uptr[i]);
        }
        return s;
    }

    // Basic character types

    #if defined(_XOPEN_SOURCE)
        using NativeCharacter = char;
    #else
        #define UNICORN_NATIVE_WCHAR 1
        using NativeCharacter = wchar_t;
    #endif

    #if WCHAR_MAX < 0x7fffffff
        #define UNICORN_WCHAR_UTF16 1
        using WcharEquivalent = char16_t;
    #else
        #define UNICORN_WCHAR_UTF32 1
        using WcharEquivalent = char32_t;
    #endif

    using NativeString = basic_string<NativeCharacter>;
    using WstringEquivalent = basic_string<WcharEquivalent>;

    namespace Literals {

        NativeString operator"" _nat(const char* s, size_t n);

    }

    // Version information

    Crow::Version unicorn_version() noexcept;
    Crow::Version unicode_version() noexcept;

}
<|endoftext|>


<commit_before>/* Copyright (c) 2014 Quanta Research Cambridge, Inc
 *
 * 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 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.
 */

#include <assert.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/mman.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/time.h>

#include "P4TopIndication.h"
#include "P4TopRequest.h"
#include "GeneratedTypes.h"
#include "utils.h"

#ifndef le32
#define le32    int32_t
#endif

#ifndef u32
#define u32     u_int32_t
#endif

#ifndef u16
#define u16     u_int16_t
#endif

#ifndef s32
#define s32     int32_t
#endif

#define DATA_WIDTH 128

struct pcap_file_header {
    u32 magic;
    u16 version_major;
    u16 version_minor;
    s32 thiszone; /* gmt to local correction */
    u32 sigfigs;  /* accuracy of timL1 cache bytes userspaceestamps */
    u32 snaplen;  /* max length saved portion of each pkt */
    u32 linktype; /* data link type (LINKTYPE_*) */
} __attribute__((packed));

struct pcap_pkthdr_ts {
    le32 hts_sec;
    le32 hts_usec;
}  __attribute__((packed));

struct pcap_pkthdr {
    struct  pcap_pkthdr_ts ts;  /* time stamp */
    le32 caplen;              /* length of portion present */
    le32 length;                  /* length this packet (off wire) */
}  __attribute__((packed));

void mem_copy(const void *buff, int length);

static P4TopRequestProxy *device = 0;

class P4TopIndication : public P4TopIndicationWrapper
{
public:
    virtual void sonic_read_version_resp(uint32_t a) {
        fprintf(stderr, "version %d\n", a);
    }
    virtual void cam_search_result(uint32_t a) {
        fprintf(stderr, "cam search %x\n", a);
    }
    virtual void read_setram_result(uint64_t a) {
        fprintf(stderr, "setram %lx\n", a);
    }
    virtual void match_table_resp(uint32_t a) {
    	fprintf(stderr, "match table");
    }
    virtual void matchTableResponse(uint32_t key, uint32_t value) {
        fprintf(stderr, "GET : key = %u  value = %u\n", key, value);
    }

    P4TopIndication(unsigned int id) : P4TopIndicationWrapper(id) {}
};

void mem_copy(const void *buff, int packet_size) {

    int i, sop, eop;
    uint64_t data[2];
    int numBeats;

    numBeats = packet_size / 8; // 16 bytes per beat for 128-bit datawidth;
    if (packet_size % 8) numBeats++;
    PRINT_INFO("nBeats=%d, packetSize=%d\n", numBeats, packet_size);
    for (i=0; i<numBeats; i++) {
        data[i%2] = *(static_cast<const uint64_t *>(buff) + i);
        sop = (i/2 == 0);
        eop = (i/2 == (numBeats-1)/2);
        if (i%2) {
            device->writePacketData(data, sop, eop);
            PRINT_INFO("%016lx %016lx %d %d\n", data[1], data[0], sop, eop);
        }

        // last beat, padding with zero
        if ((numBeats%2!=0) && (i==numBeats-1)) {
            sop = (i/2 == 0) ? 1 : 0;
            eop = 1;
            data[1] = 0;
            device->writePacketData(data, sop, eop);
            PRINT_INFO("%016lx %016lx %d %d\n", data[1], data[0], sop, eop);
        }
    }
}

/**
 * Send packet on quick_tx device
 * @param qtx       pointer to a quick_tx structure
 * @param buffer   full packet data starting at the ETH frame
 * @param length  length of packet (must be over 0)
 * @return           length of packet if it was successfully queued, QTX_E_EXIT if a critical error occurred
 *                  and close needs to be called
 */
static inline int quick_tx_send_packet(const void* buffer, int length) {
    assert(buffer);
    assert(length > 0);

#ifdef EXTRA_DEBUG
    printf("[quick_tx] Copying data from %p buffer, length = %d\n",
                (buffer, length);
#endif
    mem_copy(buffer, length);

    return length;
}

bool read_pcap_file(char* filename, void** buffer, long *length) {
    FILE *infile;
    long length_read;

    infile = fopen(filename, "r");
    if(infile == NULL) {
            printf("File does not exist!\n");
            return false;
        }

    fseek(infile, 0L, SEEK_END);
    *length = ftell(infile);
    fseek(infile, 0L, SEEK_SET);
    *buffer = (char*)calloc(*length, sizeof(char));

    /* memory error */
    if(*buffer == NULL) {
            printf("Could not allocate %ld bytes of memory!\n", *length);
            return false;
        }

    length_read = fread(*buffer, sizeof(char), *length, infile);
    *length = length_read;
    fclose(infile);

    return true;
}

void test_setram(P4TopRequestProxy *device) {
    device->writeSetRam(0x11, 0xff);
    device->readSetRam(0x11);
}

void test_bcam(P4TopRequestProxy *device) {
    device->camInsert(0x302, 0x24);
    device->camSearch(0x24);
    //device->camInsert(0x303, 0x24);
}

void test_matchtable(P4TopRequestProxy *device) {
    device->matchTableRequest(10, 15, 1); //PUT(10,15)
    device->matchTableRequest(10, 0, 0);  //GET(10) should print k=10 v=15
    device->matchTableRequest(10, 20, 2); //UPDATE(10,20)
    device->matchTableRequest(29, 0, 3);  //REMOVE(29)
    device->matchTableRequest(10, 0, 0);  //GET(10) should print k=10 v=20
    device->matchTableRequest(10, 0, 3);  //REMOVE(10)
    device->matchTableRequest(10, 0, 0);  //GET(10) should not print anything
    device->matchTableRequest(10, 30, 2); //UPDATE(10,30) should not update
    device->matchTableRequest(10, 0, 0);  //GET(10) should not print anything
    device->matchTableRequest(10, 45, 1); //PUT(10,45)
    device->matchTableRequest(10, 0, 0);  //GET(10) should print k=10 v=45

    device->matchTableRequest(20, 15, 1); //PUT(20,15)
    device->matchTableRequest(20, 0, 3);  //REMOVE(20)
    device->matchTableRequest(20, 0, 0);  //GET(20) should not print anyting

    device->matchTableRequest(20, 15, 1); //PUT(20,15)
    device->matchTableRequest(20, 0, 3);  //REMOVE(20)
    device->matchTableRequest(20, 60, 1); //PUT(20,15)
    device->matchTableRequest(20, 0, 0);  //GET(20) should print k=20 v=60
}

int main(int argc, char **argv)
{
    void *buffer;
    long length;
    struct pcap_pkthdr* pcap_hdr;
    int i;
    int loops = 1;

    P4TopIndication echoIndication(IfcNames_P4TopIndicationH2S);
    device = new P4TopRequestProxy(IfcNames_P4TopRequestS2H);

    device->sonic_read_version();

//    test_setram(device);
//  test_matchtable(device);
    test_bcam(device);

    while(1) sleep(1);

    fprintf(stderr, "Attempts to read pcap file %s\n", argv[1]);
    if (!read_pcap_file(argv[1], &buffer, &length)) {
        perror("Failed to read file!");
        exit(-1);
    }

    for (i = 0; i < loops; i++) {
        void* offset = static_cast<char *>(buffer) + sizeof(struct pcap_file_header);

        while(offset < static_cast<char *>(buffer) + length) {
            pcap_hdr = (struct pcap_pkthdr*) offset;
            offset = static_cast<char *>(offset) + sizeof(struct pcap_pkthdr);

            if ((quick_tx_send_packet((const void*)offset, pcap_hdr->caplen)) < 0) {
                printf("An error occurred while trying to send a packet\n");
                exit(-1);
            }

            offset = static_cast<char *>(offset) + pcap_hdr->caplen;
        }
    }

    return 0;
}
<commit_msg>update testcase<commit_after>/* Copyright (c) 2014 Quanta Research Cambridge, Inc
 *
 * 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 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.
 */

#include <assert.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/mman.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/time.h>

#include "P4TopIndication.h"
#include "P4TopRequest.h"
#include "GeneratedTypes.h"
#include "utils.h"

#ifndef le32
#define le32    int32_t
#endif

#ifndef u32
#define u32     u_int32_t
#endif

#ifndef u16
#define u16     u_int16_t
#endif

#ifndef s32
#define s32     int32_t
#endif

#define DATA_WIDTH 128

struct pcap_file_header {
    u32 magic;
    u16 version_major;
    u16 version_minor;
    s32 thiszone; /* gmt to local correction */
    u32 sigfigs;  /* accuracy of timL1 cache bytes userspaceestamps */
    u32 snaplen;  /* max length saved portion of each pkt */
    u32 linktype; /* data link type (LINKTYPE_*) */
} __attribute__((packed));

struct pcap_pkthdr_ts {
    le32 hts_sec;
    le32 hts_usec;
}  __attribute__((packed));

struct pcap_pkthdr {
    struct  pcap_pkthdr_ts ts;  /* time stamp */
    le32 caplen;              /* length of portion present */
    le32 length;                  /* length this packet (off wire) */
}  __attribute__((packed));

void mem_copy(const void *buff, int length);

static P4TopRequestProxy *device = 0;

class P4TopIndication : public P4TopIndicationWrapper
{
public:
    virtual void sonic_read_version_resp(uint32_t a) {
        fprintf(stderr, "version %d\n", a);
    }
    virtual void cam_search_result(uint32_t a) {
        fprintf(stderr, "cam search %x\n", a);
    }
    virtual void read_setram_result(uint64_t a) {
        fprintf(stderr, "setram %lx\n", a);
    }
    virtual void match_table_resp(uint32_t a) {
    	fprintf(stderr, "match table");
    }
    virtual void matchTableResponse(uint32_t key, uint32_t value) {
        fprintf(stderr, "GET : key = %u  value = %u\n", key, value);
    }

    P4TopIndication(unsigned int id) : P4TopIndicationWrapper(id) {}
};

void mem_copy(const void *buff, int packet_size) {

    int i, sop, eop;
    uint64_t data[2];
    int numBeats;

    numBeats = packet_size / 8; // 16 bytes per beat for 128-bit datawidth;
    if (packet_size % 8) numBeats++;
    PRINT_INFO("nBeats=%d, packetSize=%d\n", numBeats, packet_size);
    for (i=0; i<numBeats; i++) {
        data[i%2] = *(static_cast<const uint64_t *>(buff) + i);
        sop = (i/2 == 0);
        eop = (i/2 == (numBeats-1)/2);
        if (i%2) {
            device->writePacketData(data, sop, eop);
            PRINT_INFO("%016lx %016lx %d %d\n", data[1], data[0], sop, eop);
        }

        // last beat, padding with zero
        if ((numBeats%2!=0) && (i==numBeats-1)) {
            sop = (i/2 == 0) ? 1 : 0;
            eop = 1;
            data[1] = 0;
            device->writePacketData(data, sop, eop);
            PRINT_INFO("%016lx %016lx %d %d\n", data[1], data[0], sop, eop);
        }
    }
}

/**
 * Send packet on quick_tx device
 * @param qtx       pointer to a quick_tx structure
 * @param buffer   full packet data starting at the ETH frame
 * @param length  length of packet (must be over 0)
 * @return           length of packet if it was successfully queued, QTX_E_EXIT if a critical error occurred
 *                  and close needs to be called
 */
static inline int quick_tx_send_packet(const void* buffer, int length) {
    assert(buffer);
    assert(length > 0);

#ifdef EXTRA_DEBUG
    printf("[quick_tx] Copying data from %p buffer, length = %d\n",
                (buffer, length);
#endif
    mem_copy(buffer, length);

    return length;
}

bool read_pcap_file(char* filename, void** buffer, long *length) {
    FILE *infile;
    long length_read;

    infile = fopen(filename, "r");
    if(infile == NULL) {
            printf("File does not exist!\n");
            return false;
        }

    fseek(infile, 0L, SEEK_END);
    *length = ftell(infile);
    fseek(infile, 0L, SEEK_SET);
    *buffer = (char*)calloc(*length, sizeof(char));

    /* memory error */
    if(*buffer == NULL) {
            printf("Could not allocate %ld bytes of memory!\n", *length);
            return false;
        }

    length_read = fread(*buffer, sizeof(char), *length, infile);
    *length = length_read;
    fclose(infile);

    return true;
}

void test_setram(P4TopRequestProxy *device) {
    device->writeSetRam(0x11, 0xff);
    device->readSetRam(0x11);
}

void test_bcam(P4TopRequestProxy *device) {
    fprintf(stderr, "Insert CAM\n");
    device->camInsert(0x0, 0x0);
    device->camInsert(0x1, 0x1);
    device->camInsert(0x2, 0x2);
    device->camInsert(0x3, 0x3);
    device->camSearch(0x0);
    device->camSearch(0x1);
    device->camSearch(0x2);
    device->camSearch(0x3);
    //device->camInsert(0x303, 0x24);
}

void test_matchtable(P4TopRequestProxy *device) {
    device->matchTableRequest(10, 15, 1); //PUT(10,15)
    device->matchTableRequest(10, 0, 0);  //GET(10) should print k=10 v=15
    device->matchTableRequest(10, 20, 2); //UPDATE(10,20)
    device->matchTableRequest(29, 0, 3);  //REMOVE(29)
    device->matchTableRequest(10, 0, 0);  //GET(10) should print k=10 v=20
    device->matchTableRequest(10, 0, 3);  //REMOVE(10)
    device->matchTableRequest(10, 0, 0);  //GET(10) should not print anything
    device->matchTableRequest(10, 30, 2); //UPDATE(10,30) should not update
    device->matchTableRequest(10, 0, 0);  //GET(10) should not print anything
    device->matchTableRequest(10, 45, 1); //PUT(10,45)
    device->matchTableRequest(10, 0, 0);  //GET(10) should print k=10 v=45

    device->matchTableRequest(20, 15, 1); //PUT(20,15)
    device->matchTableRequest(20, 0, 3);  //REMOVE(20)
    device->matchTableRequest(20, 0, 0);  //GET(20) should not print anyting

    device->matchTableRequest(20, 15, 1); //PUT(20,15)
    device->matchTableRequest(20, 0, 3);  //REMOVE(20)
    device->matchTableRequest(20, 60, 1); //PUT(20,15)
    device->matchTableRequest(20, 0, 0);  //GET(20) should print k=20 v=60
}

int main(int argc, char **argv)
{
    void *buffer;
    long length;
    struct pcap_pkthdr* pcap_hdr;
    int i;
    int loops = 1;

    P4TopIndication echoIndication(IfcNames_P4TopIndicationH2S);
    device = new P4TopRequestProxy(IfcNames_P4TopRequestS2H);

    device->sonic_read_version();

//    test_setram(device);
//  test_matchtable(device);
    test_bcam(device);

    while(1) sleep(1);

    fprintf(stderr, "Attempts to read pcap file %s\n", argv[1]);
    if (!read_pcap_file(argv[1], &buffer, &length)) {
        perror("Failed to read file!");
        exit(-1);
    }

    for (i = 0; i < loops; i++) {
        void* offset = static_cast<char *>(buffer) + sizeof(struct pcap_file_header);

        while(offset < static_cast<char *>(buffer) + length) {
            pcap_hdr = (struct pcap_pkthdr*) offset;
            offset = static_cast<char *>(offset) + sizeof(struct pcap_pkthdr);

            if ((quick_tx_send_packet((const void*)offset, pcap_hdr->caplen)) < 0) {
                printf("An error occurred while trying to send a packet\n");
                exit(-1);
            }

            offset = static_cast<char *>(offset) + pcap_hdr->caplen;
        }
    }

    return 0;
}
<|endoftext|>