<commit_before>#include <v8.h>
#include <node.h>
#include <node_buffer.h>

#include <sstream>
#include <cstring>
#include <string>

#include "BoyerMoore.h"

using namespace v8;
using namespace node;

namespace {

// this is an application of the Curiously Recurring Template Pattern
template <class Derived> struct UnaryAction {
	Handle<Value> apply(Handle<Object>& buffer, const Arguments& args, HandleScope& scope);

	Handle<Value> operator()(const Arguments& args) {
		HandleScope scope;

		Local<Object> self = args.This();
		if (!Buffer::HasInstance(self)) {
			return ThrowException(Exception::TypeError(String::New(
					"Argument should be a buffer object.")));
		}

		return static_cast<Derived*>(this)->apply(self, args, scope);
	}
};

template <class Derived> struct BinaryAction {
	Handle<Value> apply(Handle<Object>& buffer, const char* data, size_t size, const Arguments& args, HandleScope& scope);

	Handle<Value> operator()(const Arguments& args) {
		HandleScope scope;

		Local<Object> self = args.This();
		if (!Buffer::HasInstance(self)) {
			return ThrowException(Exception::TypeError(String::New(
					"Argument should be a buffer object.")));
		}

		if (args[0]->IsString()) {
			String::Utf8Value s(args[0]->ToString());
			return static_cast<Derived*>(this)->apply(self, *s, s.length(), args, scope);
		}
		if (Buffer::HasInstance(args[0])) {
			Local<Object> other = args[0]->ToObject();
			return static_cast<Derived*>(this)->apply(
					self, Buffer::Data(other), Buffer::Length(other), args, scope);
		}

		static Persistent<String> illegalArgumentException = Persistent<String>::New(String::New(
				"Second argument must be a string or a buffer."));
		return ThrowException(Exception::TypeError(illegalArgumentException));
	}
};

//
// helper functions
//
Handle<Value> clear(Handle<Object>& buffer, int c) {
	size_t length = Buffer::Length(buffer);
	char* data = Buffer::Data(buffer);
	memset(data, c, length);
	return buffer;
}

Handle<Value> fill(Handle<Object>& buffer, void* pattern, size_t size) {
	size_t length = Buffer::Length(buffer);
	char* data = Buffer::Data(buffer);

	if (size >= length) {
		memcpy(data, pattern, length);
	} else {
		const int n_copies = length / size;
		const int remainder = length % size;
		for (int i = 0; i < n_copies; i++) {
			memcpy(data + size * i, pattern, size);
		}
		memcpy(data + size * n_copies, pattern, remainder);
	}

	return buffer;
}

int compare(Handle<Object>& buffer, const char* data2, size_t length2) {
	size_t length = Buffer::Length(buffer);
	if (length != length2) {
		return length > length2 ? 1 : -1;
	}

	char* data = Buffer::Data(buffer);
	return memcmp(data, data2, length);
}

//
// actions
//
struct ClearAction: UnaryAction<ClearAction> {
	Handle<Value> apply(Handle<Object>& buffer, const Arguments& args, HandleScope& scope) {
		return clear(buffer, 0);
	}
};

struct FillAction: UnaryAction<FillAction> {
	Handle<Value> apply(Handle<Object>& buffer, const Arguments& args, HandleScope& scope) {
		if (args[0]->IsInt32()) {
			int c = args[0]->ToInt32()->Int32Value();
			return clear(buffer, c);
		}

		if (args[0]->IsString()) {
			String::Utf8Value s(args[0]->ToString());
			return fill(buffer, *s, s.length());
		}

		if (Buffer::HasInstance(args[0])) {
			Handle<Object> other = args[0]->ToObject();
			size_t length = Buffer::Length(other);
			char* data = Buffer::Data(other);
			return fill(buffer, data, length);
		}

		static Persistent<String> illegalArgumentException = Persistent<String>::New(String::New(
				"Second argument should be either a string, a buffer or an integer."));
		return ThrowException(Exception::TypeError(illegalArgumentException));
	}
};

struct ReverseAction: UnaryAction<ReverseAction> {
	// O(n/2) for all cases which is okay, might be optimized some more with whole-word swaps
	// XXX won't this trash the L1 cache something awful?
	Handle<Value> apply(Handle<Object>& buffer, const Arguments& args, HandleScope& scope) {
		char* head = Buffer::Data(buffer);
		char* tail = head + Buffer::Length(buffer) - 1;

		// xor swap, just because I can
		while (head < tail) *head ^= *tail, *tail ^= *head, *head ^= *tail, ++head, --tail;

		return buffer;
	}
};

struct EqualsAction: BinaryAction<EqualsAction> {
	Handle<Value> apply(Handle<Object>& buffer, const char* data, size_t size, const Arguments& args, HandleScope& scope) {
		return compare(buffer, data, size) == 0 ? True() : False();
	}
};

struct CompareAction: BinaryAction<CompareAction> {
	Handle<Value> apply(Handle<Object>& buffer, const char* data, size_t size, const Arguments& args, HandleScope& scope) {
		return scope.Close(Integer::New(compare(buffer, data, size)));
	}
};

struct IndexOfAction: BinaryAction<IndexOfAction> {
	Handle<Value> apply(Handle<Object>& buffer, const char* data2, size_t size2, const Arguments& args, HandleScope& scope) {
		const char* data = Buffer::Data(buffer);
		size_t size = Buffer::Length(buffer);

		const char* p = boyermoore_search(data, size, data2, size2);
		const ptrdiff_t offset = p ? (p - data) : -1;

		return scope.Close(Integer::New(offset));
	}
};

static char toHexTable[] = "0123456789abcdef";

// CHECKME is this cache efficient?
static char fromHexTable[] = {
		-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
		-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,-1,
		10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
		10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
		-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
		-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
		-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
		-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
};

inline Handle<Value> decodeHex(const char* data, size_t size, const Arguments& args, HandleScope& scope) {
	if (size & 1) {
		return ThrowException(Exception::Error(String::New(
				"Odd string length, this is not hexadecimal data.")));
	}

	if (size == 0) {
		return String::Empty();
	}

	Handle<Object>& buffer = Buffer::New(size / 2)->handle_;
	for (char* s = Buffer::Data(buffer); size > 0; size -= 2) {
		int a = fromHexTable[*data++];
		int b = fromHexTable[*data++];

		if (a == -1 || b == -1) {
			return ThrowException(Exception::Error(String::New(
					"This is not hexadecimal data.")));
		}

		*s++ = b | (a << 4);
	}

	return buffer;
}

struct FromHexAction: UnaryAction<FromHexAction> {
	Handle<Value> apply(Handle<Object>& buffer, const Arguments& args, HandleScope& scope) {
		const char* data = Buffer::Data(buffer);
		size_t length = Buffer::Length(buffer);
		return decodeHex(data, length, args, scope);
	}
};

struct ToHexAction: UnaryAction<ToHexAction> {
	Handle<Value> apply(Handle<Object>& buffer, const Arguments& args, HandleScope& scope) {
		const size_t size = Buffer::Length(buffer);
		const char* data = Buffer::Data(buffer);

		if (size == 0) {
			return String::Empty();
		}

		std::string s(size * 2, 0);
		for (size_t i = 0; i < size; ++i) {
			const int c = data[i];
			s[i * 2] = toHexTable[c >> 4];
			s[i * 2 + 1] = toHexTable[c & 15];
		}

		return scope.Close(String::New(s.c_str(), s.size()));
	}
};

//
// V8 function callbacks
//
Handle<Value> Clear(const Arguments& args) {
	return ClearAction()(args);
}

Handle<Value> Fill(const Arguments& args) {
	return FillAction()(args);
}

Handle<Value> Reverse(const Arguments& args) {
	return ReverseAction()(args);
}

Handle<Value> Equals(const Arguments& args) {
	return EqualsAction()(args);
}

Handle<Value> Compare(const Arguments& args) {
	return CompareAction()(args);
}

Handle<Value> IndexOf(const Arguments& args) {
	return IndexOfAction()(args);
}

Handle<Value> FromHex(const Arguments& args) {
	return FromHexAction()(args);
}

Handle<Value> ToHex(const Arguments& args) {
	return ToHexAction()(args);
}

Handle<Value> Concat(const Arguments& args) {
	HandleScope scope;

	size_t size = 0;
	for (int index = 0, length = args.Length(); index < length; ++index) {
		Local<Value> arg = args[index];
		if (arg->IsString()) {
			// Utf8Length() because we need the length in bytes, not characters
			size += arg->ToString()->Utf8Length();
		}
		else if (Buffer::HasInstance(arg)) {
			size += Buffer::Length(arg->ToObject());
		}
		else {
			std::stringstream s;
			s << "Argument #" << index << " is neither a string nor a buffer object.";
			const char* message = s.str().c_str();
			return ThrowException(Exception::TypeError(String::New(message)));
		}
	}

	Buffer& dst = *Buffer::New(size);
	char* s = Buffer::Data(dst.handle_);

	for (int index = 0, length = args.Length(); index < length; ++index) {
		Local<Value> arg = args[index];
		if (arg->IsString()) {
			String::Utf8Value v(arg->ToString());
			memcpy(s, *v, v.length());
			s += v.length();
		}
		else if (Buffer::HasInstance(arg)) {
			Local<Object> b = arg->ToObject();
			const char* data = Buffer::Data(b);
			size_t length = Buffer::Length(b);
			memcpy(s, data, length);
			s += length;
		}
		else {
			return ThrowException(Exception::Error(String::New(
					"Congratulations! You have run into a bug: argument is neither a string nor a buffer object. "
					"Please make the world a better place and report it.")));
		}
	}

	return scope.Close(dst.handle_);
}

extern "C" void init(Handle<Object> target) {
	target->Set(String::NewSymbol("concat"),  FunctionTemplate::New(Concat)->GetFunction());
	target->Set(String::NewSymbol("fill"),    FunctionTemplate::New(Fill)->GetFunction());
	target->Set(String::NewSymbol("clear"),   FunctionTemplate::New(Clear)->GetFunction());
	target->Set(String::NewSymbol("reverse"), FunctionTemplate::New(Reverse)->GetFunction());
	target->Set(String::NewSymbol("equals"),  FunctionTemplate::New(Equals)->GetFunction());
	target->Set(String::NewSymbol("compare"), FunctionTemplate::New(Compare)->GetFunction());
	target->Set(String::NewSymbol("indexOf"), FunctionTemplate::New(IndexOf)->GetFunction());
	target->Set(String::NewSymbol("fromHex"), FunctionTemplate::New(FromHex)->GetFunction());
	target->Set(String::NewSymbol("toHex"),   FunctionTemplate::New(ToHex)->GetFunction());
}

}
<commit_msg>Register module with NODE_MODULE.<commit_after>#include <v8.h>
#include <node.h>
#include <node_buffer.h>

#include <sstream>
#include <cstring>
#include <string>

#include "BoyerMoore.h"

using namespace v8;
using namespace node;

namespace {

// this is an application of the Curiously Recurring Template Pattern
template <class Derived> struct UnaryAction {
	Handle<Value> apply(Handle<Object>& buffer, const Arguments& args, HandleScope& scope);

	Handle<Value> operator()(const Arguments& args) {
		HandleScope scope;

		Local<Object> self = args.This();
		if (!Buffer::HasInstance(self)) {
			return ThrowException(Exception::TypeError(String::New(
					"Argument should be a buffer object.")));
		}

		return static_cast<Derived*>(this)->apply(self, args, scope);
	}
};

template <class Derived> struct BinaryAction {
	Handle<Value> apply(Handle<Object>& buffer, const char* data, size_t size, const Arguments& args, HandleScope& scope);

	Handle<Value> operator()(const Arguments& args) {
		HandleScope scope;

		Local<Object> self = args.This();
		if (!Buffer::HasInstance(self)) {
			return ThrowException(Exception::TypeError(String::New(
					"Argument should be a buffer object.")));
		}

		if (args[0]->IsString()) {
			String::Utf8Value s(args[0]->ToString());
			return static_cast<Derived*>(this)->apply(self, *s, s.length(), args, scope);
		}
		if (Buffer::HasInstance(args[0])) {
			Local<Object> other = args[0]->ToObject();
			return static_cast<Derived*>(this)->apply(
					self, Buffer::Data(other), Buffer::Length(other), args, scope);
		}

		static Persistent<String> illegalArgumentException = Persistent<String>::New(String::New(
				"Second argument must be a string or a buffer."));
		return ThrowException(Exception::TypeError(illegalArgumentException));
	}
};

//
// helper functions
//
Handle<Value> clear(Handle<Object>& buffer, int c) {
	size_t length = Buffer::Length(buffer);
	char* data = Buffer::Data(buffer);
	memset(data, c, length);
	return buffer;
}

Handle<Value> fill(Handle<Object>& buffer, void* pattern, size_t size) {
	size_t length = Buffer::Length(buffer);
	char* data = Buffer::Data(buffer);

	if (size >= length) {
		memcpy(data, pattern, length);
	} else {
		const int n_copies = length / size;
		const int remainder = length % size;
		for (int i = 0; i < n_copies; i++) {
			memcpy(data + size * i, pattern, size);
		}
		memcpy(data + size * n_copies, pattern, remainder);
	}

	return buffer;
}

int compare(Handle<Object>& buffer, const char* data2, size_t length2) {
	size_t length = Buffer::Length(buffer);
	if (length != length2) {
		return length > length2 ? 1 : -1;
	}

	char* data = Buffer::Data(buffer);
	return memcmp(data, data2, length);
}

//
// actions
//
struct ClearAction: UnaryAction<ClearAction> {
	Handle<Value> apply(Handle<Object>& buffer, const Arguments& args, HandleScope& scope) {
		return clear(buffer, 0);
	}
};

struct FillAction: UnaryAction<FillAction> {
	Handle<Value> apply(Handle<Object>& buffer, const Arguments& args, HandleScope& scope) {
		if (args[0]->IsInt32()) {
			int c = args[0]->ToInt32()->Int32Value();
			return clear(buffer, c);
		}

		if (args[0]->IsString()) {
			String::Utf8Value s(args[0]->ToString());
			return fill(buffer, *s, s.length());
		}

		if (Buffer::HasInstance(args[0])) {
			Handle<Object> other = args[0]->ToObject();
			size_t length = Buffer::Length(other);
			char* data = Buffer::Data(other);
			return fill(buffer, data, length);
		}

		static Persistent<String> illegalArgumentException = Persistent<String>::New(String::New(
				"Second argument should be either a string, a buffer or an integer."));
		return ThrowException(Exception::TypeError(illegalArgumentException));
	}
};

struct ReverseAction: UnaryAction<ReverseAction> {
	// O(n/2) for all cases which is okay, might be optimized some more with whole-word swaps
	// XXX won't this trash the L1 cache something awful?
	Handle<Value> apply(Handle<Object>& buffer, const Arguments& args, HandleScope& scope) {
		char* head = Buffer::Data(buffer);
		char* tail = head + Buffer::Length(buffer) - 1;

		// xor swap, just because I can
		while (head < tail) *head ^= *tail, *tail ^= *head, *head ^= *tail, ++head, --tail;

		return buffer;
	}
};

struct EqualsAction: BinaryAction<EqualsAction> {
	Handle<Value> apply(Handle<Object>& buffer, const char* data, size_t size, const Arguments& args, HandleScope& scope) {
		return compare(buffer, data, size) == 0 ? True() : False();
	}
};

struct CompareAction: BinaryAction<CompareAction> {
	Handle<Value> apply(Handle<Object>& buffer, const char* data, size_t size, const Arguments& args, HandleScope& scope) {
		return scope.Close(Integer::New(compare(buffer, data, size)));
	}
};

struct IndexOfAction: BinaryAction<IndexOfAction> {
	Handle<Value> apply(Handle<Object>& buffer, const char* data2, size_t size2, const Arguments& args, HandleScope& scope) {
		const char* data = Buffer::Data(buffer);
		size_t size = Buffer::Length(buffer);

		const char* p = boyermoore_search(data, size, data2, size2);
		const ptrdiff_t offset = p ? (p - data) : -1;

		return scope.Close(Integer::New(offset));
	}
};

static char toHexTable[] = "0123456789abcdef";

// CHECKME is this cache efficient?
static char fromHexTable[] = {
		-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
		-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,-1,
		10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
		10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
		-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
		-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
		-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
		-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
};

inline Handle<Value> decodeHex(const char* data, size_t size, const Arguments& args, HandleScope& scope) {
	if (size & 1) {
		return ThrowException(Exception::Error(String::New(
				"Odd string length, this is not hexadecimal data.")));
	}

	if (size == 0) {
		return String::Empty();
	}

	Handle<Object>& buffer = Buffer::New(size / 2)->handle_;
	for (char* s = Buffer::Data(buffer); size > 0; size -= 2) {
		int a = fromHexTable[*data++];
		int b = fromHexTable[*data++];

		if (a == -1 || b == -1) {
			return ThrowException(Exception::Error(String::New(
					"This is not hexadecimal data.")));
		}

		*s++ = b | (a << 4);
	}

	return buffer;
}

struct FromHexAction: UnaryAction<FromHexAction> {
	Handle<Value> apply(Handle<Object>& buffer, const Arguments& args, HandleScope& scope) {
		const char* data = Buffer::Data(buffer);
		size_t length = Buffer::Length(buffer);
		return decodeHex(data, length, args, scope);
	}
};

struct ToHexAction: UnaryAction<ToHexAction> {
	Handle<Value> apply(Handle<Object>& buffer, const Arguments& args, HandleScope& scope) {
		const size_t size = Buffer::Length(buffer);
		const char* data = Buffer::Data(buffer);

		if (size == 0) {
			return String::Empty();
		}

		std::string s(size * 2, 0);
		for (size_t i = 0; i < size; ++i) {
			const int c = data[i];
			s[i * 2] = toHexTable[c >> 4];
			s[i * 2 + 1] = toHexTable[c & 15];
		}

		return scope.Close(String::New(s.c_str(), s.size()));
	}
};

//
// V8 function callbacks
//
Handle<Value> Clear(const Arguments& args) {
	return ClearAction()(args);
}

Handle<Value> Fill(const Arguments& args) {
	return FillAction()(args);
}

Handle<Value> Reverse(const Arguments& args) {
	return ReverseAction()(args);
}

Handle<Value> Equals(const Arguments& args) {
	return EqualsAction()(args);
}

Handle<Value> Compare(const Arguments& args) {
	return CompareAction()(args);
}

Handle<Value> IndexOf(const Arguments& args) {
	return IndexOfAction()(args);
}

Handle<Value> FromHex(const Arguments& args) {
	return FromHexAction()(args);
}

Handle<Value> ToHex(const Arguments& args) {
	return ToHexAction()(args);
}

Handle<Value> Concat(const Arguments& args) {
	HandleScope scope;

	size_t size = 0;
	for (int index = 0, length = args.Length(); index < length; ++index) {
		Local<Value> arg = args[index];
		if (arg->IsString()) {
			// Utf8Length() because we need the length in bytes, not characters
			size += arg->ToString()->Utf8Length();
		}
		else if (Buffer::HasInstance(arg)) {
			size += Buffer::Length(arg->ToObject());
		}
		else {
			std::stringstream s;
			s << "Argument #" << index << " is neither a string nor a buffer object.";
			const char* message = s.str().c_str();
			return ThrowException(Exception::TypeError(String::New(message)));
		}
	}

	Buffer& dst = *Buffer::New(size);
	char* s = Buffer::Data(dst.handle_);

	for (int index = 0, length = args.Length(); index < length; ++index) {
		Local<Value> arg = args[index];
		if (arg->IsString()) {
			String::Utf8Value v(arg->ToString());
			memcpy(s, *v, v.length());
			s += v.length();
		}
		else if (Buffer::HasInstance(arg)) {
			Local<Object> b = arg->ToObject();
			const char* data = Buffer::Data(b);
			size_t length = Buffer::Length(b);
			memcpy(s, data, length);
			s += length;
		}
		else {
			return ThrowException(Exception::Error(String::New(
					"Congratulations! You have run into a bug: argument is neither a string nor a buffer object. "
					"Please make the world a better place and report it.")));
		}
	}

	return scope.Close(dst.handle_);
}

void RegisterModule(Handle<Object> target) {
	target->Set(String::NewSymbol("concat"),  FunctionTemplate::New(Concat)->GetFunction());
	target->Set(String::NewSymbol("fill"),    FunctionTemplate::New(Fill)->GetFunction());
	target->Set(String::NewSymbol("clear"),   FunctionTemplate::New(Clear)->GetFunction());
	target->Set(String::NewSymbol("reverse"), FunctionTemplate::New(Reverse)->GetFunction());
	target->Set(String::NewSymbol("equals"),  FunctionTemplate::New(Equals)->GetFunction());
	target->Set(String::NewSymbol("compare"), FunctionTemplate::New(Compare)->GetFunction());
	target->Set(String::NewSymbol("indexOf"), FunctionTemplate::New(IndexOf)->GetFunction());
	target->Set(String::NewSymbol("fromHex"), FunctionTemplate::New(FromHex)->GetFunction());
	target->Set(String::NewSymbol("toHex"),   FunctionTemplate::New(ToHex)->GetFunction());
}

} // anonymous namespace

NODE_MODULE(buffertools, RegisterModule);
<|endoftext|>


<commit_before>//===- WebAssemblyTargetMachine.cpp - Define TargetMachine for WebAssembly -==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief This file defines the WebAssembly-specific subclass of TargetMachine.
///
//===----------------------------------------------------------------------===//

#include "WebAssembly.h"
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
#include "WebAssemblyTargetMachine.h"
#include "WebAssemblyTargetObjectFile.h"
#include "WebAssemblyTargetTransformInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Transforms/Scalar.h"
using namespace llvm;

#define DEBUG_TYPE "wasm"

extern "C" void LLVMInitializeWebAssemblyTarget() {
  // Register the target.
  RegisterTargetMachine<WebAssemblyTargetMachine> X(TheWebAssemblyTarget32);
  RegisterTargetMachine<WebAssemblyTargetMachine> Y(TheWebAssemblyTarget64);
}

//===----------------------------------------------------------------------===//
// WebAssembly Lowering public interface.
//===----------------------------------------------------------------------===//

/// Create an WebAssembly architecture model.
///
WebAssemblyTargetMachine::WebAssemblyTargetMachine(
    const Target &T, const Triple &TT, StringRef CPU, StringRef FS,
    const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM,
    CodeGenOpt::Level OL)
    : LLVMTargetMachine(T, TT.isArch64Bit()
                               ? "e-p:64:64-i64:64-v128:8:128-n32:64-S128"
                               : "e-p:32:32-i64:64-v128:8:128-n32:64-S128",
                        TT, CPU, FS, Options, RM, CM, OL),
      TLOF(make_unique<WebAssemblyTargetObjectFile>()) {
  initAsmInfo();

  // We need a reducible CFG, so disable some optimizations which tend to
  // introduce irreducibility.
  setRequiresStructuredCFG(true);
}

WebAssemblyTargetMachine::~WebAssemblyTargetMachine() {}

const WebAssemblySubtarget *
WebAssemblyTargetMachine::getSubtargetImpl(const Function &F) const {
  Attribute CPUAttr = F.getFnAttribute("target-cpu");
  Attribute FSAttr = F.getFnAttribute("target-features");

  std::string CPU = !CPUAttr.hasAttribute(Attribute::None)
                        ? CPUAttr.getValueAsString().str()
                        : TargetCPU;
  std::string FS = !FSAttr.hasAttribute(Attribute::None)
                       ? FSAttr.getValueAsString().str()
                       : TargetFS;

  auto &I = SubtargetMap[CPU + FS];
  if (!I) {
    // This needs to be done before we create a new subtarget since any
    // creation will depend on the TM and the code generation flags on the
    // function that reside in TargetOptions.
    resetTargetOptions(F);
    I = make_unique<WebAssemblySubtarget>(TargetTriple, CPU, FS, *this);
  }
  return I.get();
}

namespace {
/// WebAssembly Code Generator Pass Configuration Options.
class WebAssemblyPassConfig final : public TargetPassConfig {
public:
  WebAssemblyPassConfig(WebAssemblyTargetMachine *TM, PassManagerBase &PM)
      : TargetPassConfig(TM, PM) {}

  WebAssemblyTargetMachine &getWebAssemblyTargetMachine() const {
    return getTM<WebAssemblyTargetMachine>();
  }

  FunctionPass *createTargetRegisterAllocator(bool) override;
  void addFastRegAlloc(FunctionPass *RegAllocPass) override;
  void addOptimizedRegAlloc(FunctionPass *RegAllocPass) override;

  void addIRPasses() override;
  bool addPreISel() override;
  bool addInstSelector() override;
  bool addILPOpts() override;
  void addPreRegAlloc() override;
  void addRegAllocPasses(bool Optimized);
  void addPostRegAlloc() override;
  void addPreSched2() override;
  void addPreEmitPass() override;
};
} // end anonymous namespace

TargetIRAnalysis WebAssemblyTargetMachine::getTargetIRAnalysis() {
  return TargetIRAnalysis([this](Function &F) {
    return TargetTransformInfo(WebAssemblyTTIImpl(this, F));
  });
}

TargetPassConfig *
WebAssemblyTargetMachine::createPassConfig(PassManagerBase &PM) {
  return new WebAssemblyPassConfig(this, PM);
}

FunctionPass *WebAssemblyPassConfig::createTargetRegisterAllocator(bool) {
  return nullptr; // No reg alloc
}

void WebAssemblyPassConfig::addFastRegAlloc(FunctionPass *RegAllocPass) {
  assert(!RegAllocPass && "WebAssembly uses no regalloc!");
  addRegAllocPasses(false);
}

void WebAssemblyPassConfig::addOptimizedRegAlloc(FunctionPass *RegAllocPass) {
  assert(!RegAllocPass && "WebAssembly uses no regalloc!");
  addRegAllocPasses(true);
}

//===----------------------------------------------------------------------===//
// The following functions are called from lib/CodeGen/Passes.cpp to modify
// the CodeGen pass sequence.
//===----------------------------------------------------------------------===//

void WebAssemblyPassConfig::addIRPasses() {
  // FIXME: the default for this option is currently POSIX, whereas
  // WebAssembly's MVP should default to Single.
  if (TM->Options.ThreadModel == ThreadModel::Single)
    addPass(createLowerAtomicPass());
  else
    // Expand some atomic operations. WebAssemblyTargetLowering has hooks which
    // control specifically what gets lowered.
    addPass(createAtomicExpandPass(TM));

  TargetPassConfig::addIRPasses();
}

bool WebAssemblyPassConfig::addPreISel() { return false; }

bool WebAssemblyPassConfig::addInstSelector() {
  addPass(
      createWebAssemblyISelDag(getWebAssemblyTargetMachine(), getOptLevel()));
  return false;
}

bool WebAssemblyPassConfig::addILPOpts() { return true; }

void WebAssemblyPassConfig::addPreRegAlloc() {}

void WebAssemblyPassConfig::addRegAllocPasses(bool Optimized) {}

void WebAssemblyPassConfig::addPostRegAlloc() {
  // FIXME: the following passes dislike virtual registers. Disable them for now
  //        so that basic tests can pass. Future patches will remedy this.
  //
  // Fails with: Regalloc must assign all vregs.
  disablePass(&PrologEpilogCodeInserterID);
  // Fails with: should be run after register allocation.
  disablePass(&MachineCopyPropagationID);
}

void WebAssemblyPassConfig::addPreSched2() {}

void WebAssemblyPassConfig::addPreEmitPass() {}
<commit_msg>Use llvm::make_unique to fix the MSVC build.<commit_after>//===- WebAssemblyTargetMachine.cpp - Define TargetMachine for WebAssembly -==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief This file defines the WebAssembly-specific subclass of TargetMachine.
///
//===----------------------------------------------------------------------===//

#include "WebAssembly.h"
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
#include "WebAssemblyTargetMachine.h"
#include "WebAssemblyTargetObjectFile.h"
#include "WebAssemblyTargetTransformInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Transforms/Scalar.h"
using namespace llvm;

#define DEBUG_TYPE "wasm"

extern "C" void LLVMInitializeWebAssemblyTarget() {
  // Register the target.
  RegisterTargetMachine<WebAssemblyTargetMachine> X(TheWebAssemblyTarget32);
  RegisterTargetMachine<WebAssemblyTargetMachine> Y(TheWebAssemblyTarget64);
}

//===----------------------------------------------------------------------===//
// WebAssembly Lowering public interface.
//===----------------------------------------------------------------------===//

/// Create an WebAssembly architecture model.
///
WebAssemblyTargetMachine::WebAssemblyTargetMachine(
    const Target &T, const Triple &TT, StringRef CPU, StringRef FS,
    const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM,
    CodeGenOpt::Level OL)
    : LLVMTargetMachine(T, TT.isArch64Bit()
                               ? "e-p:64:64-i64:64-v128:8:128-n32:64-S128"
                               : "e-p:32:32-i64:64-v128:8:128-n32:64-S128",
                        TT, CPU, FS, Options, RM, CM, OL),
      TLOF(make_unique<WebAssemblyTargetObjectFile>()) {
  initAsmInfo();

  // We need a reducible CFG, so disable some optimizations which tend to
  // introduce irreducibility.
  setRequiresStructuredCFG(true);
}

WebAssemblyTargetMachine::~WebAssemblyTargetMachine() {}

const WebAssemblySubtarget *
WebAssemblyTargetMachine::getSubtargetImpl(const Function &F) const {
  Attribute CPUAttr = F.getFnAttribute("target-cpu");
  Attribute FSAttr = F.getFnAttribute("target-features");

  std::string CPU = !CPUAttr.hasAttribute(Attribute::None)
                        ? CPUAttr.getValueAsString().str()
                        : TargetCPU;
  std::string FS = !FSAttr.hasAttribute(Attribute::None)
                       ? FSAttr.getValueAsString().str()
                       : TargetFS;

  auto &I = SubtargetMap[CPU + FS];
  if (!I) {
    // This needs to be done before we create a new subtarget since any
    // creation will depend on the TM and the code generation flags on the
    // function that reside in TargetOptions.
    resetTargetOptions(F);
    I = llvm::make_unique<WebAssemblySubtarget>(TargetTriple, CPU, FS, *this);
  }
  return I.get();
}

namespace {
/// WebAssembly Code Generator Pass Configuration Options.
class WebAssemblyPassConfig final : public TargetPassConfig {
public:
  WebAssemblyPassConfig(WebAssemblyTargetMachine *TM, PassManagerBase &PM)
      : TargetPassConfig(TM, PM) {}

  WebAssemblyTargetMachine &getWebAssemblyTargetMachine() const {
    return getTM<WebAssemblyTargetMachine>();
  }

  FunctionPass *createTargetRegisterAllocator(bool) override;
  void addFastRegAlloc(FunctionPass *RegAllocPass) override;
  void addOptimizedRegAlloc(FunctionPass *RegAllocPass) override;

  void addIRPasses() override;
  bool addPreISel() override;
  bool addInstSelector() override;
  bool addILPOpts() override;
  void addPreRegAlloc() override;
  void addRegAllocPasses(bool Optimized);
  void addPostRegAlloc() override;
  void addPreSched2() override;
  void addPreEmitPass() override;
};
} // end anonymous namespace

TargetIRAnalysis WebAssemblyTargetMachine::getTargetIRAnalysis() {
  return TargetIRAnalysis([this](Function &F) {
    return TargetTransformInfo(WebAssemblyTTIImpl(this, F));
  });
}

TargetPassConfig *
WebAssemblyTargetMachine::createPassConfig(PassManagerBase &PM) {
  return new WebAssemblyPassConfig(this, PM);
}

FunctionPass *WebAssemblyPassConfig::createTargetRegisterAllocator(bool) {
  return nullptr; // No reg alloc
}

void WebAssemblyPassConfig::addFastRegAlloc(FunctionPass *RegAllocPass) {
  assert(!RegAllocPass && "WebAssembly uses no regalloc!");
  addRegAllocPasses(false);
}

void WebAssemblyPassConfig::addOptimizedRegAlloc(FunctionPass *RegAllocPass) {
  assert(!RegAllocPass && "WebAssembly uses no regalloc!");
  addRegAllocPasses(true);
}

//===----------------------------------------------------------------------===//
// The following functions are called from lib/CodeGen/Passes.cpp to modify
// the CodeGen pass sequence.
//===----------------------------------------------------------------------===//

void WebAssemblyPassConfig::addIRPasses() {
  // FIXME: the default for this option is currently POSIX, whereas
  // WebAssembly's MVP should default to Single.
  if (TM->Options.ThreadModel == ThreadModel::Single)
    addPass(createLowerAtomicPass());
  else
    // Expand some atomic operations. WebAssemblyTargetLowering has hooks which
    // control specifically what gets lowered.
    addPass(createAtomicExpandPass(TM));

  TargetPassConfig::addIRPasses();
}

bool WebAssemblyPassConfig::addPreISel() { return false; }

bool WebAssemblyPassConfig::addInstSelector() {
  addPass(
      createWebAssemblyISelDag(getWebAssemblyTargetMachine(), getOptLevel()));
  return false;
}

bool WebAssemblyPassConfig::addILPOpts() { return true; }

void WebAssemblyPassConfig::addPreRegAlloc() {}

void WebAssemblyPassConfig::addRegAllocPasses(bool Optimized) {}

void WebAssemblyPassConfig::addPostRegAlloc() {
  // FIXME: the following passes dislike virtual registers. Disable them for now
  //        so that basic tests can pass. Future patches will remedy this.
  //
  // Fails with: Regalloc must assign all vregs.
  disablePass(&PrologEpilogCodeInserterID);
  // Fails with: should be run after register allocation.
  disablePass(&MachineCopyPropagationID);
}

void WebAssemblyPassConfig::addPreSched2() {}

void WebAssemblyPassConfig::addPreEmitPass() {}
<|endoftext|>


<commit_before>#include <v8.h>
#include <node.h>
#include <node_buffer.h>

#include <cstring>

using namespace v8;
using namespace node;

namespace {

// this is an application of the Curiously Recurring Template Pattern
template <class T> struct UnaryAction {
	Handle<Value> apply(Buffer& buffer, const Arguments& args);

	Handle<Value> operator()(const Arguments& args) {
		if (args[0]->IsObject()) {
			Local<Object> object = args[0]->ToObject();
			if (Buffer::HasInstance(object)) {
				Buffer& buffer = *ObjectWrap::Unwrap<Buffer>(object);
				return static_cast<T*>(this)->apply(buffer, args);
			}
		}
		static Persistent<String> illegalArgumentException = Persistent<String>::New(String::New("First argument should be a buffer."));
		return ThrowException(Exception::TypeError(illegalArgumentException));
	}
};

template <class T> struct BinaryAction {
	Handle<Value> apply(Buffer& a, Buffer& b, const Arguments& args);

	Handle<Value> operator()(const Arguments& args) {
		if (args[0]->IsObject() && args[1]->IsObject()) {
			Local<Object> arg0 = args[0]->ToObject();
			Local<Object> arg1 = args[0]->ToObject();
			if (Buffer::HasInstance(arg0) && Buffer::HasInstance(arg1)) {
				Buffer& a = *ObjectWrap::Unwrap<Buffer>(arg0);
				Buffer& b = *ObjectWrap::Unwrap<Buffer>(arg1);
				return static_cast<T*>(this)->apply(a, b, args);
			}
		}
		static Persistent<String> illegalArgumentException = Persistent<String>::New(String::New("First and second argument should be a buffer."));
		return ThrowException(Exception::TypeError(illegalArgumentException));
	}
};

//
// helper functions
//
Handle<Value> clear(Buffer& buffer, int c) {
	memset(buffer.data(), c, buffer.length());
	return buffer.handle_;
}

Handle<Value> fill(Buffer& buffer, void* pattern, size_t size) {
	if (size >= buffer.length()) {
		memcpy(buffer.data(), pattern, buffer.length());
	} else {
		const int n_copies = buffer.length() / size;
		const int remainder = buffer.length() % size;
		for (int i = 0; i < n_copies; i++) {
			memcpy(buffer.data() + size * i, pattern, size);
		}
		memcpy(buffer.data() + size * n_copies, pattern, remainder);
	}
	return buffer.handle_;
}

int compare(Buffer& a, Buffer& b) {
	if (a.length() != b.length()) {
		return a.length() > b.length() ? 1 : -1;
	}
	return memcmp(a.data(), b.data(), a.length());
}

//
// actions
//
struct ClearAction: UnaryAction<ClearAction> {
	Handle<Value> apply(Buffer& buffer, const Arguments& args) {
		const int c = args[1]->IsInt32() ? args[1]->ToInt32()->Int32Value() : 0;
		return clear(buffer, c);
	}
};

struct FillAction: UnaryAction<FillAction> {
	Handle<Value> apply(Buffer& buffer, const Arguments& args) {
		if (args[1]->IsInt32()) {
			int c = args[1]->ToInt32()->Int32Value();
			return clear(buffer, c);
		}
		if (args[1]->IsString()) {
			String::AsciiValue s(args[1]->ToString());
			return fill(buffer, *s, s.length());
		}
		if (args[1]->IsObject()) {
			Local<Object> o = args[1]->ToObject();
			if (Buffer::HasInstance(o)) {
				Buffer& src = *Buffer::Unwrap<Buffer>(o);
				return fill(buffer, src.data(), src.length());
			}
		}
		static Persistent<String> illegalArgumentException = Persistent<String>::New(String::New(
				"Second argument should be either a string, a buffer or an integer."));
		return ThrowException(Exception::TypeError(illegalArgumentException));
	}
};

struct EqualsAction: BinaryAction<EqualsAction> {
	Handle<Value> apply(Buffer& a, Buffer& b, const Arguments& args) {
		HandleScope scope;
		return scope.Close(Boolean::New(compare(a, b)));
	}
};

struct CompareAction: BinaryAction<CompareAction> {
	Handle<Value> apply(Buffer& a, Buffer& b, const Arguments& args) {
		HandleScope scope;
		return scope.Close(Integer::New(compare(a, b)));
	}
};

//
// V8 function callbacks
//
Handle<Value> Clear(const Arguments& args) {
	return ClearAction()(args);
}

Handle<Value> Fill(const Arguments& args) {
	return FillAction()(args);
}

Handle<Value> Equals(const Arguments& args) {
	return CompareAction()(args);
}

Handle<Value> Compare(const Arguments& args) {
	return CompareAction()(args);
}

extern "C" void init(Handle<Object> target) {
	HandleScope scope;
	target->Set(String::New("fill"), FunctionTemplate::New(Fill)->GetFunction());
	target->Set(String::New("clear"), FunctionTemplate::New(Clear)->GetFunction());
	target->Set(String::New("equals"), FunctionTemplate::New(Equals)->GetFunction());
	target->Set(String::New("compare"), FunctionTemplate::New(Compare)->GetFunction());
}

}
<commit_msg>Bug fix: Equals() should of course invoke EqualsAction, not CompareAction.<commit_after>#include <v8.h>
#include <node.h>
#include <node_buffer.h>

#include <cstring>

using namespace v8;
using namespace node;

namespace {

// this is an application of the Curiously Recurring Template Pattern
template <class T> struct UnaryAction {
	Handle<Value> apply(Buffer& buffer, const Arguments& args);

	Handle<Value> operator()(const Arguments& args) {
		if (args[0]->IsObject()) {
			Local<Object> object = args[0]->ToObject();
			if (Buffer::HasInstance(object)) {
				Buffer& buffer = *ObjectWrap::Unwrap<Buffer>(object);
				return static_cast<T*>(this)->apply(buffer, args);
			}
		}
		static Persistent<String> illegalArgumentException = Persistent<String>::New(String::New("First argument should be a buffer."));
		return ThrowException(Exception::TypeError(illegalArgumentException));
	}
};

template <class T> struct BinaryAction {
	Handle<Value> apply(Buffer& a, Buffer& b, const Arguments& args);

	Handle<Value> operator()(const Arguments& args) {
		if (args[0]->IsObject() && args[1]->IsObject()) {
			Local<Object> arg0 = args[0]->ToObject();
			Local<Object> arg1 = args[0]->ToObject();
			if (Buffer::HasInstance(arg0) && Buffer::HasInstance(arg1)) {
				Buffer& a = *ObjectWrap::Unwrap<Buffer>(arg0);
				Buffer& b = *ObjectWrap::Unwrap<Buffer>(arg1);
				return static_cast<T*>(this)->apply(a, b, args);
			}
		}
		static Persistent<String> illegalArgumentException = Persistent<String>::New(String::New("First and second argument should be a buffer."));
		return ThrowException(Exception::TypeError(illegalArgumentException));
	}
};

//
// helper functions
//
Handle<Value> clear(Buffer& buffer, int c) {
	memset(buffer.data(), c, buffer.length());
	return buffer.handle_;
}

Handle<Value> fill(Buffer& buffer, void* pattern, size_t size) {
	if (size >= buffer.length()) {
		memcpy(buffer.data(), pattern, buffer.length());
	} else {
		const int n_copies = buffer.length() / size;
		const int remainder = buffer.length() % size;
		for (int i = 0; i < n_copies; i++) {
			memcpy(buffer.data() + size * i, pattern, size);
		}
		memcpy(buffer.data() + size * n_copies, pattern, remainder);
	}
	return buffer.handle_;
}

int compare(Buffer& a, Buffer& b) {
	if (a.length() != b.length()) {
		return a.length() > b.length() ? 1 : -1;
	}
	return memcmp(a.data(), b.data(), a.length());
}

//
// actions
//
struct ClearAction: UnaryAction<ClearAction> {
	Handle<Value> apply(Buffer& buffer, const Arguments& args) {
		const int c = args[1]->IsInt32() ? args[1]->ToInt32()->Int32Value() : 0;
		return clear(buffer, c);
	}
};

struct FillAction: UnaryAction<FillAction> {
	Handle<Value> apply(Buffer& buffer, const Arguments& args) {
		if (args[1]->IsInt32()) {
			int c = args[1]->ToInt32()->Int32Value();
			return clear(buffer, c);
		}
		if (args[1]->IsString()) {
			String::AsciiValue s(args[1]->ToString());
			return fill(buffer, *s, s.length());
		}
		if (args[1]->IsObject()) {
			Local<Object> o = args[1]->ToObject();
			if (Buffer::HasInstance(o)) {
				Buffer& src = *Buffer::Unwrap<Buffer>(o);
				return fill(buffer, src.data(), src.length());
			}
		}
		static Persistent<String> illegalArgumentException = Persistent<String>::New(String::New(
				"Second argument should be either a string, a buffer or an integer."));
		return ThrowException(Exception::TypeError(illegalArgumentException));
	}
};

struct EqualsAction: BinaryAction<EqualsAction> {
	Handle<Value> apply(Buffer& a, Buffer& b, const Arguments& args) {
		return compare(a, b) == 0 ? True() : False();
	}
};

struct CompareAction: BinaryAction<CompareAction> {
	Handle<Value> apply(Buffer& a, Buffer& b, const Arguments& args) {
		HandleScope scope;
		return scope.Close(Integer::New(compare(a, b)));
	}
};

//
// V8 function callbacks
//
Handle<Value> Clear(const Arguments& args) {
	return ClearAction()(args);
}

Handle<Value> Fill(const Arguments& args) {
	return FillAction()(args);
}

Handle<Value> Equals(const Arguments& args) {
	return EqualsAction()(args);
}

Handle<Value> Compare(const Arguments& args) {
	return CompareAction()(args);
}

extern "C" void init(Handle<Object> target) {
	HandleScope scope;
	target->Set(String::New("fill"), FunctionTemplate::New(Fill)->GetFunction());
	target->Set(String::New("clear"), FunctionTemplate::New(Clear)->GetFunction());
	target->Set(String::New("equals"), FunctionTemplate::New(Equals)->GetFunction());
	target->Set(String::New("compare"), FunctionTemplate::New(Compare)->GetFunction());
}

}
<|endoftext|>


<commit_before>#include "platform/tizen/TizenApplication.h"

using namespace Tizen::Graphics::Opengl;

namespace lime {

	int gFixedOrientation = -1;
	int mSingleTouchID;
	FrameCreationCallback sgCallback;
	unsigned int sgFlags;
	int sgHeight;
	const char *sgTitle;
	TizenFrame *sgTizenFrame;
	int sgWidth;

	enum { NO_TOUCH = -1 };

	void CreateMainFrame (FrameCreationCallback inOnFrame, int inWidth, int inHeight, unsigned int inFlags, const char *inTitle, Surface *inIcon) {

		sgCallback = inOnFrame;
		sgWidth = inWidth;
		sgHeight = inHeight;
		sgFlags = inFlags;
		sgTitle = inTitle;

		mSingleTouchID = NO_TOUCH;

		//if (sgWidth == 0 && sgHeight == 0) {

			// Hard-code screen size for now

			sgWidth = 720;
			sgHeight = 1280;

		//}

		// For now, swap the width/height for proper EGL initialization, when landscape

		if (gFixedOrientation == 3 || gFixedOrientation == 4) {

			int temp = sgWidth;
			sgWidth = sgHeight;
			sgHeight = temp;

		}

		Tizen::Base::Collection::ArrayList args (Tizen::Base::Collection::SingleObjectDeleter);
		args.Construct ();
		result r = Tizen::App::Application::Execute (TizenApplication::CreateInstance, &args);

	}

	void StartAnimation () {}
	void PauseAnimation () {}
	void ResumeAnimation () {}
	void StopAnimation () {}

	TizenApplication::TizenApplication (void) {

		mEGLDisplay = EGL_NO_DISPLAY;
		mEGLSurface = EGL_NO_SURFACE;
		mEGLConfig = null;
		mEGLContext = EGL_NO_CONTEXT;
		mForm = null;
		mTimer = null;

	}

	TizenApplication::~TizenApplication (void) {}

	void TizenApplication::Cleanup (void) {

		if (mTimer != null) {

			mTimer->Cancel ();
			delete mTimer;
			mTimer = null;

		}

		Event close (etQuit);
		sgTizenFrame->HandleEvent (close);

		Event lostFocus (etLostInputFocus);
		sgTizenFrame->HandleEvent (lostFocus);

		Event deactivate (etDeactivate);
		sgTizenFrame->HandleEvent (deactivate);

		Event kill (etDestroyHandler);
		sgTizenFrame->HandleEvent (kill);

	}

	Tizen::App::Application* TizenApplication::CreateInstance (void) {

		return new (std::nothrow) TizenApplication ();

	}

	bool TizenApplication::OnAppInitializing (Tizen::App::AppRegistry& appRegistry) {

		Tizen::Ui::Controls::Frame* appFrame = new (std::nothrow) Tizen::Ui::Controls::Frame ();
		appFrame->Construct ();
		this->AddFrame (*appFrame);

		mForm = new (std::nothrow) TizenForm (this);
		mForm->Construct (Tizen::Ui::Controls::FORM_STYLE_NORMAL);

		if (gFixedOrientation == 3 || gFixedOrientation == 4) {

			mForm->SetOrientation (Tizen::Ui::ORIENTATION_LANDSCAPE);

		}

		GetAppFrame ()->GetFrame ()->AddControl (mForm);

		mForm->AddKeyEventListener (*this);
		mForm->AddTouchEventListener (*this);
		mForm->SetMultipointTouchEnabled (true);

		bool ok = limeEGLCreate (mForm, sgWidth, sgHeight, 2, (sgFlags & wfDepthBuffer) ? 16 : 0, (sgFlags & wfStencilBuffer) ? 8 : 0, 0);

		mTimer = new (std::nothrow) Tizen::Base::Runtime::Timer;
		mTimer->Construct (*this);

		Tizen::System::PowerManager::AddScreenEventListener (*this);

		sgTizenFrame = new TizenFrame (sgWidth, sgHeight);
		sgCallback (sgTizenFrame);

		return true;

	}

	bool TizenApplication::OnAppTerminating (Tizen::App::AppRegistry& appRegistry, bool forcedTermination) {

		Cleanup ();

		return true;

	}

	void TizenApplication::OnBackground (void) {

		if (mTimer != null) {

			mTimer->Cancel ();

		}

		Event lostFocus (etLostInputFocus);
		sgTizenFrame->HandleEvent (lostFocus);

		Event deactivate (etDeactivate);
		sgTizenFrame->HandleEvent (deactivate);

	}

	void TizenApplication::OnBatteryLevelChanged (Tizen::System::BatteryLevel batteryLevel) {}

	void TizenApplication::OnForeground (void) {

		Event activate (etActivate);
		sgTizenFrame->HandleEvent (activate);

		Event gotFocus (etGotInputFocus);
		sgTizenFrame->HandleEvent (gotFocus);

		Event poll (etPoll);
		sgTizenFrame->HandleEvent (poll);

		double next = sgTizenFrame->GetStage ()->GetNextWake () - GetTimeStamp ();

		if (mTimer != null) {

			if (next > 0) {

				mTimer->Start (next * 1000.0);

			} else {

				mTimer->Start (10);

			}

		}

	}

	void TizenApplication::OnKeyLongPressed (const Tizen::Ui::Control& source, Tizen::Ui::KeyCode keyCode) {}

	void TizenApplication::OnKeyPressed (const Tizen::Ui::Control& source, Tizen::Ui::KeyCode keyCode) {

	}

	void TizenApplication::OnKeyReleased (const Tizen::Ui::Control& source, Tizen::Ui::KeyCode keyCode) {

		if (keyCode == Tizen::Ui::KEY_BACK || keyCode == Tizen::Ui::KEY_ESC) {

			Terminate ();

		}

	}

	void TizenApplication::OnLowMemory (void) {}
	void TizenApplication::OnScreenOn (void) {}
	void TizenApplication::OnScreenOff (void) {}

	void TizenApplication::OnTimerExpired (Tizen::Base::Runtime::Timer& timer) {

		if (mTimer == null) {

			return;

		}

		Event poll (etPoll);
		sgTizenFrame->HandleEvent (poll);

		double next = sgTizenFrame->GetStage ()->GetNextWake () - GetTimeStamp ();

		if (next > 0) {

			mTimer->Start (next * 1000.0);

		} else {

			mTimer->Start (10);

		}

	}

	void TizenApplication::OnTouchCanceled (const Tizen::Ui::Control &source, const Tizen::Graphics::Point &currentPosition, const Tizen::Ui::TouchEventInfo &touchInfo) {}
	void TizenApplication::OnTouchFocusIn (const Tizen::Ui::Control &source, const Tizen::Graphics::Point &currentPosition, const Tizen::Ui::TouchEventInfo &touchInfo) {}
	void TizenApplication::OnTouchFocusOut (const Tizen::Ui::Control &source, const Tizen::Graphics::Point &currentPosition, const Tizen::Ui::TouchEventInfo &touchInfo) {}

	void TizenApplication::OnTouchMoved (const Tizen::Ui::Control &source, const Tizen::Graphics::Point &currentPosition, const Tizen::Ui::TouchEventInfo &touchInfo) {

		Event mouse (etTouchMove, currentPosition.x, currentPosition.y);
		mouse.value = touchInfo.GetPointId ();

		if (mSingleTouchID == NO_TOUCH || mouse.value == mSingleTouchID) {

			mouse.flags |= efPrimaryTouch;

		}

		sgTizenFrame->HandleEvent (mouse);

	}

	void TizenApplication::OnTouchPressed (const Tizen::Ui::Control &source, const Tizen::Graphics::Point &currentPosition, const Tizen::Ui::TouchEventInfo &touchInfo) {

		Event mouse (etTouchBegin, currentPosition.x, currentPosition.y);
		mouse.value = touchInfo.GetPointId ();

		if (mSingleTouchID == NO_TOUCH || mouse.value == mSingleTouchID) {

			mouse.flags |= efPrimaryTouch;

		}

		sgTizenFrame->HandleEvent (mouse);

	}

	void TizenApplication::OnTouchReleased (const Tizen::Ui::Control &source, const Tizen::Graphics::Point &currentPosition, const Tizen::Ui::TouchEventInfo &touchInfo) {

		Event mouse (etTouchEnd, currentPosition.x, currentPosition.y);
		mouse.value = touchInfo.GetPointId ();

		if (mSingleTouchID == NO_TOUCH || mouse.value == mSingleTouchID) {

			mouse.flags |= efPrimaryTouch;

		}

		if (mSingleTouchID == mouse.value) {

			mSingleTouchID = NO_TOUCH;

		}

		sgTizenFrame->HandleEvent (mouse);

	}

}
<commit_msg>Adjustments to timer<commit_after>#include "platform/tizen/TizenApplication.h"

using namespace Tizen::Graphics::Opengl;

namespace lime {

	int gFixedOrientation = -1;
	int mSingleTouchID;
	FrameCreationCallback sgCallback;
	unsigned int sgFlags;
	int sgHeight;
	const char *sgTitle;
	TizenFrame *sgTizenFrame;
	int sgWidth;

	enum { NO_TOUCH = -1 };

	void CreateMainFrame (FrameCreationCallback inOnFrame, int inWidth, int inHeight, unsigned int inFlags, const char *inTitle, Surface *inIcon) {

		sgCallback = inOnFrame;
		sgWidth = inWidth;
		sgHeight = inHeight;
		sgFlags = inFlags;
		sgTitle = inTitle;

		mSingleTouchID = NO_TOUCH;

		//if (sgWidth == 0 && sgHeight == 0) {

			// Hard-code screen size for now

			sgWidth = 720;
			sgHeight = 1280;

		//}

		// For now, swap the width/height for proper EGL initialization, when landscape

		if (gFixedOrientation == 3 || gFixedOrientation == 4) {

			int temp = sgWidth;
			sgWidth = sgHeight;
			sgHeight = temp;

		}

		Tizen::Base::Collection::ArrayList args (Tizen::Base::Collection::SingleObjectDeleter);
		args.Construct ();
		result r = Tizen::App::Application::Execute (TizenApplication::CreateInstance, &args);

	}

	void StartAnimation () {}
	void PauseAnimation () {}
	void ResumeAnimation () {}
	void StopAnimation () {}

	TizenApplication::TizenApplication (void) {

		mEGLDisplay = EGL_NO_DISPLAY;
		mEGLSurface = EGL_NO_SURFACE;
		mEGLConfig = null;
		mEGLContext = EGL_NO_CONTEXT;
		mForm = null;
		mTimer = null;

	}

	TizenApplication::~TizenApplication (void) {}

	void TizenApplication::Cleanup (void) {

		if (mTimer != null) {

			mTimer->Cancel ();
			delete mTimer;
			mTimer = null;

		}

		Event close (etQuit);
		sgTizenFrame->HandleEvent (close);

		Event lostFocus (etLostInputFocus);
		sgTizenFrame->HandleEvent (lostFocus);

		Event deactivate (etDeactivate);
		sgTizenFrame->HandleEvent (deactivate);

		Event kill (etDestroyHandler);
		sgTizenFrame->HandleEvent (kill);

	}

	Tizen::App::Application* TizenApplication::CreateInstance (void) {

		return new (std::nothrow) TizenApplication ();

	}

	bool TizenApplication::OnAppInitializing (Tizen::App::AppRegistry& appRegistry) {

		Tizen::Ui::Controls::Frame* appFrame = new (std::nothrow) Tizen::Ui::Controls::Frame ();
		appFrame->Construct ();
		this->AddFrame (*appFrame);

		mForm = new (std::nothrow) TizenForm (this);
		mForm->Construct (Tizen::Ui::Controls::FORM_STYLE_NORMAL);

		if (gFixedOrientation == 3 || gFixedOrientation == 4) {

			mForm->SetOrientation (Tizen::Ui::ORIENTATION_LANDSCAPE);

		}

		GetAppFrame ()->GetFrame ()->AddControl (mForm);

		mForm->AddKeyEventListener (*this);
		mForm->AddTouchEventListener (*this);
		mForm->SetMultipointTouchEnabled (true);

		bool ok = limeEGLCreate (mForm, sgWidth, sgHeight, 2, (sgFlags & wfDepthBuffer) ? 16 : 0, (sgFlags & wfStencilBuffer) ? 8 : 0, 0);

		mTimer = new (std::nothrow) Tizen::Base::Runtime::Timer;
		mTimer->Construct (*this);

		Tizen::System::PowerManager::AddScreenEventListener (*this);

		sgTizenFrame = new TizenFrame (sgWidth, sgHeight);
		sgCallback (sgTizenFrame);

		return true;

	}

	bool TizenApplication::OnAppTerminating (Tizen::App::AppRegistry& appRegistry, bool forcedTermination) {

		Cleanup ();

		return true;

	}

	void TizenApplication::OnBackground (void) {

		if (mTimer != null) {

			mTimer->Cancel ();

		}

		Event lostFocus (etLostInputFocus);
		sgTizenFrame->HandleEvent (lostFocus);

		Event deactivate (etDeactivate);
		sgTizenFrame->HandleEvent (deactivate);

	}

	void TizenApplication::OnBatteryLevelChanged (Tizen::System::BatteryLevel batteryLevel) {}

	void TizenApplication::OnForeground (void) {

		Event activate (etActivate);
		sgTizenFrame->HandleEvent (activate);

		Event gotFocus (etGotInputFocus);
		sgTizenFrame->HandleEvent (gotFocus);

		Event poll (etPoll);
		sgTizenFrame->HandleEvent (poll);

		double next = sgTizenFrame->GetStage ()->GetNextWake () - GetTimeStamp ();

		if (mTimer != null) {

			if (next > 0.001) {

				mTimer->Start (next * 1000.0);

			} else {

				mTimer->Start (1);

			}

		}

	}

	void TizenApplication::OnKeyLongPressed (const Tizen::Ui::Control& source, Tizen::Ui::KeyCode keyCode) {}

	void TizenApplication::OnKeyPressed (const Tizen::Ui::Control& source, Tizen::Ui::KeyCode keyCode) {

	}

	void TizenApplication::OnKeyReleased (const Tizen::Ui::Control& source, Tizen::Ui::KeyCode keyCode) {

		if (keyCode == Tizen::Ui::KEY_BACK || keyCode == Tizen::Ui::KEY_ESC) {

			Terminate ();

		}

	}

	void TizenApplication::OnLowMemory (void) {}
	void TizenApplication::OnScreenOn (void) {}
	void TizenApplication::OnScreenOff (void) {}

	void TizenApplication::OnTimerExpired (Tizen::Base::Runtime::Timer& timer) {

		if (mTimer == null) {

			return;

		}

		Event poll (etPoll);
		sgTizenFrame->HandleEvent (poll);

		double next = sgTizenFrame->GetStage ()->GetNextWake () - GetTimeStamp ();

		if (next > 0.001) {

			mTimer->Start (next * 1000.0);

		} else {

			mTimer->Start (1);

		}

	}

	void TizenApplication::OnTouchCanceled (const Tizen::Ui::Control &source, const Tizen::Graphics::Point &currentPosition, const Tizen::Ui::TouchEventInfo &touchInfo) {}
	void TizenApplication::OnTouchFocusIn (const Tizen::Ui::Control &source, const Tizen::Graphics::Point &currentPosition, const Tizen::Ui::TouchEventInfo &touchInfo) {}
	void TizenApplication::OnTouchFocusOut (const Tizen::Ui::Control &source, const Tizen::Graphics::Point &currentPosition, const Tizen::Ui::TouchEventInfo &touchInfo) {}

	void TizenApplication::OnTouchMoved (const Tizen::Ui::Control &source, const Tizen::Graphics::Point &currentPosition, const Tizen::Ui::TouchEventInfo &touchInfo) {

		Event mouse (etTouchMove, currentPosition.x, currentPosition.y);
		mouse.value = touchInfo.GetPointId ();

		if (mSingleTouchID == NO_TOUCH || mouse.value == mSingleTouchID) {

			mouse.flags |= efPrimaryTouch;

		}

		sgTizenFrame->HandleEvent (mouse);

	}

	void TizenApplication::OnTouchPressed (const Tizen::Ui::Control &source, const Tizen::Graphics::Point &currentPosition, const Tizen::Ui::TouchEventInfo &touchInfo) {

		Event mouse (etTouchBegin, currentPosition.x, currentPosition.y);
		mouse.value = touchInfo.GetPointId ();

		if (mSingleTouchID == NO_TOUCH || mouse.value == mSingleTouchID) {

			mouse.flags |= efPrimaryTouch;

		}

		sgTizenFrame->HandleEvent (mouse);

	}

	void TizenApplication::OnTouchReleased (const Tizen::Ui::Control &source, const Tizen::Graphics::Point &currentPosition, const Tizen::Ui::TouchEventInfo &touchInfo) {

		Event mouse (etTouchEnd, currentPosition.x, currentPosition.y);
		mouse.value = touchInfo.GetPointId ();

		if (mSingleTouchID == NO_TOUCH || mouse.value == mSingleTouchID) {

			mouse.flags |= efPrimaryTouch;

		}

		if (mSingleTouchID == mouse.value) {

			mSingleTouchID = NO_TOUCH;

		}

		sgTizenFrame->HandleEvent (mouse);

	}

}
<|endoftext|>


<commit_before>#include "Script.hpp"

/* Assets */
#include "../ResourceManager/AssetManager.hpp"

/* Logger */
#include "../Logger/Logger.hpp"

/* GUI */
#include "../GUI/Window.hpp"

#include "../GUI/Containers/Column.hpp"
#include "../GUI/Containers/Row.hpp"

#include "../GUI/Widgets/Button.hpp"
#include "../GUI/Widgets/Label.hpp"
#include "../GUI/Widgets/Slider.hpp"
#include "../GUI/Widgets/Spacer.hpp"
#include "../GUI/Widgets/TextBox.hpp"
#include "../GUI/Widgets/Toggle.hpp"

/* EntitySystem */
#include "../EntitySystem/Entity.hpp"

#include "../World/World.hpp"

namespace swift
{
	sf::RenderWindow* Script::window = nullptr;
	AssetManager* Script::assets = nullptr;
	sf::Clock* Script::clock = nullptr;
	Settings* Script::settings = nullptr;
	Logger* Script::log = nullptr;

	Script::Script()
			:	gui(nullptr),
				keyboard(nullptr),
				stateReturn(nullptr),
				world(nullptr)
	{
		deleteMe = false;

		// We don't want to give the scripts access to os commands or file writing abilities
		luaState.OpenLib("base", luaopen_base);
		luaState.OpenLib("math", luaopen_math);
		luaState.OpenLib("string", luaopen_string);
		luaState.OpenLib("table", luaopen_table);

		addVariables();
		addClasses();
		addFunctions();
	}

	Script::~Script()
	{
	}

	bool Script::loadFromFile(const std::string& file)
	{
		bool r = luaState.Load(file);	// r will be false if errors, true otherwise

		return r;
	}

	void Script::start()
	{
		luaState["Start"]();

		if(static_cast<bool>(luaState["Done"]) == true)
		{
			deleteMe = true;
		}
	}

	void Script::run()
	{
		luaState["Update"]();

		if(static_cast<bool>(luaState["Done"]) == true)
		{
			deleteMe = true;
		}
	}

	bool Script::toDelete()
	{
		return deleteMe;
	}

	void Script::setWindow(sf::RenderWindow& win)
	{
		window = &win;
	}

	void Script::setAssetManager(AssetManager& am)
	{
		assets = &am;
	}

	void Script::setClock(sf::Clock& c)
	{
		clock = &c;
	}

	void Script::setSettings(Settings& s)
	{
		settings = &s;
	}

	void Script::setLogger(Logger& l)
	{
		log = &l;
	}

	void Script::setGUI(cstr::Window& ui)
	{
		gui = &ui;
	}

	void Script::setKeyboard(KeyboardManager& k)
	{
		keyboard = &k;
	}

	void Script::setStateReturn(State::Type& t)
	{
		stateReturn = &t;
	}

	void Script::setWorld(World& w)
	{
		world = &w;
	}

	void Script::addVariables()
	{
		luaState["states"]["MainMenu"] = 0;
		luaState["states"]["Settings"] = 1;
		luaState["states"]["Play"] = 2;
		luaState["states"]["Exit"] = 3;
	}

	void Script::addClasses()
	{
		// vectors
		luaState["Vector2f"].SetClass<sf::Vector2f>("x", &sf::Vector2f::x, "y", &sf::Vector2f::y);
		luaState["Vector2i"].SetClass<sf::Vector2i>("x", &sf::Vector2i::x, "y", &sf::Vector2i::y);
		luaState["Vector2u"].SetClass<sf::Vector2u>("x", &sf::Vector2u::x, "y", &sf::Vector2u::y);

		// ECS
		luaState["Entity"].SetClass<Entity>("add", static_cast<bool (Entity::*)(std::string)>(&Entity::add),
											"remove", static_cast<bool (Entity::*)(std::string)>(&Entity::remove),
											"has", static_cast<bool (Entity::*)(std::string) const>(&Entity::has),
											"getDrawable", static_cast<Drawable* (Entity::*)()>(&Entity::get<Drawable>),
											"getMovable", static_cast<Movable* (Entity::*)()>(&Entity::get<Movable>),
											"getPhysical", static_cast<Physical* (Entity::*)()>(&Entity::get<Physical>),
											"getName", static_cast<Name* (Entity::*)()>(&Entity::get<Name>));

		// each Component type
		luaState["Drawable"].SetClass<Drawable>();
		luaState["Movable"].SetClass<Movable>();
		luaState["Physical"].SetClass<Physical>();
		luaState["Name"].SetClass<Name>();

		// GUI
		/*luaState["Column"].SetClass<cstr::Column>();
		luaState["Row"].SetClass<cstr::Row>();

		luaState["Button"].SetClass<cstr::Button>();
		luaState["Label"].SetClass<cstr::Label>();
		luaState["Slider"].SetClass<cstr::Slider>();
		luaState["Spacer"].SetClass<cstr::Spacer>();
		luaState["TextBox"].SetClass<cstr::TextBox>();
		luaState["Toggle"].SetClass<cstr::Toggle>();*/
	}

	void Script::addFunctions()
	{
		/* utility functions */
		luaState["getWindowSize"] = [&]()
		{
			if(window)
				return std::make_tuple(window->getSize().x, window->getSize().y);
			else
				return std::make_tuple(0u, 0u);
		};

		luaState["getTime"] = [&]()
		{
			if(clock)
				return clock->getElapsedTime().asSeconds();
			else
				return 0.f;
		};

		luaState["doKeypress"] = [&](std::string k)
		{
			if(keyboard)
				keyboard->call(k);
		};

		luaState["log"] = [&](std::string m)
		{
			if(log)
				*log << m;
		};

		/* EntitySystem */
		// World
		luaState["newEntity"] = [&]() -> Entity*
		{
			if(world)
				return world->addEntity();
			else
				return nullptr;
		};

		luaState["getTotalEntities"] = [&]()
		{
			if(world)
				return static_cast<unsigned>(world->getEntities().size());
			else
				return 0u;
		};

		luaState["getEntity"] = [&](unsigned e) -> Entity*
		{
			if(world && e < world->getEntities().size())
				return world->getEntities()[e];
			else
				return nullptr;
		};

		// Drawable
		luaState["setTexture"] = [&](Drawable* d, std::string t)
		{
			if(d)
			{
				d->sprite.setTexture(assets->getTexture(t));
				return true;
			}
			else
				return false;
		};

		luaState["setTextureRect"] = [&](Drawable* d, int x, int y, int w, int h)
		{
			if(d)
				d->sprite.setTextureRect({x, y, w, h});
		};

		luaState["getSpriteSize"] = [&](Drawable* d)
		{
			if(d)
				return std::make_tuple(d->sprite.getGlobalBounds().width, d->sprite.getGlobalBounds().height);
			else
				return std::make_tuple(0.f, 0.f);
		};

		luaState["setScale"] = [&](Drawable* d, float x, float y)
		{
			if(d)
				d->sprite.setScale(x, y);
		};

		// Movable
		luaState["setMoveVelocity"] = [&](Movable* m, float v)
		{
			if(m)
			{
				m->moveVelocity = v;
			}
		};

		luaState["getVelocity"] = [&](Movable* m)
		{
			if(m)
				return std::make_tuple(m->velocity.x, m->velocity.y);
			else
				return std::make_tuple(0.f, 0.f);
		};

		// Physical
		luaState["setPosition"] = [&](Physical* p, float x, float y)
		{
			if(p)
				p->position = {x, y};
			else if(p)
				p->position = {0, 0};
		};

		luaState["getPosition"] = [&](Physical* p)
		{
			if(p)
				return std::make_tuple(p->position.x, p->position.y);
			else
				return std::make_tuple(0.f, 0.f);
		};

		luaState["setSize"] = [&](Physical* p, unsigned x, unsigned y)
		{
			if(p)
				p->size = {x, y};
			else if(p)
				p->size = {0, 0};
		};

		luaState["getSize"] = [&](Physical* p)
		{
			if(p)
				return std::make_tuple(p->size.x, p->size.y);
			else
				return std::make_tuple(0u, 0u);
		};

		// Name
		luaState["setName"] = [&](Name* n, std::string s)
		{
			if(n)
				n->name = s;
		};

		luaState["getName"] = [&](Name* n) -> std::string
		{
			if(n)
				return n->name;
			else
				return "null";
		};

		/* gui functions */

		/* State */
		luaState["setStateReturn"] = [&](unsigned s)
		{
			*stateReturn = static_cast<State::Type>(s);
		};

		/* Settings */
		luaState["getSettingStr"] = [&](std::string n)
		{
			std::string v;
			return std::make_tuple(settings->get(n, v), v);
		};

		luaState["setSettingStr"] = [&](std::string n, std::string v)
		{
			return settings->set(n, v);
		};

		luaState["getSettingBool"] = [&](std::string n)
		{
			bool v;
			return std::make_tuple(settings->get(n, v), v);
		};

		luaState["setSettingBool"] = [&](std::string n, bool v)
		{
			return settings->set(n, v);
		};

		luaState["getSettingNum"] = [&](std::string n)
		{
			int v;
			return std::make_tuple(settings->get(n, v), v);
		};

		luaState["setSettingNum"] = [&](std::string n, int v)
		{
			return settings->set(n, v);
		};
	}
}<commit_msg>Added Lua functions for getting Entities around a point in the world<commit_after>#include "Script.hpp"

/* Assets */
#include "../ResourceManager/AssetManager.hpp"

/* Logger */
#include "../Logger/Logger.hpp"

/* GUI */
#include "../GUI/Window.hpp"

#include "../GUI/Containers/Column.hpp"
#include "../GUI/Containers/Row.hpp"

#include "../GUI/Widgets/Button.hpp"
#include "../GUI/Widgets/Label.hpp"
#include "../GUI/Widgets/Slider.hpp"
#include "../GUI/Widgets/Spacer.hpp"
#include "../GUI/Widgets/TextBox.hpp"
#include "../GUI/Widgets/Toggle.hpp"

/* EntitySystem */
#include "../EntitySystem/Entity.hpp"

#include "../World/World.hpp"

namespace swift
{
	sf::RenderWindow* Script::window = nullptr;
	AssetManager* Script::assets = nullptr;
	sf::Clock* Script::clock = nullptr;
	Settings* Script::settings = nullptr;
	Logger* Script::log = nullptr;

	Script::Script()
			:	gui(nullptr),
				keyboard(nullptr),
				stateReturn(nullptr),
				world(nullptr)
	{
		deleteMe = false;

		// We don't want to give the scripts access to os commands or file writing abilities
		luaState.OpenLib("base", luaopen_base);
		luaState.OpenLib("math", luaopen_math);
		luaState.OpenLib("string", luaopen_string);
		luaState.OpenLib("table", luaopen_table);

		addVariables();
		addClasses();
		addFunctions();
	}

	Script::~Script()
	{
	}

	bool Script::loadFromFile(const std::string& file)
	{
		bool r = luaState.Load(file);	// r will be false if errors, true otherwise

		return r;
	}

	void Script::start()
	{
		luaState["Start"]();

		if(static_cast<bool>(luaState["Done"]) == true)
		{
			deleteMe = true;
		}
	}

	void Script::run()
	{
		luaState["Update"]();

		if(static_cast<bool>(luaState["Done"]) == true)
		{
			deleteMe = true;
		}
	}

	bool Script::toDelete()
	{
		return deleteMe;
	}

	void Script::setWindow(sf::RenderWindow& win)
	{
		window = &win;
	}

	void Script::setAssetManager(AssetManager& am)
	{
		assets = &am;
	}

	void Script::setClock(sf::Clock& c)
	{
		clock = &c;
	}

	void Script::setSettings(Settings& s)
	{
		settings = &s;
	}

	void Script::setLogger(Logger& l)
	{
		log = &l;
	}

	void Script::setGUI(cstr::Window& ui)
	{
		gui = &ui;
	}

	void Script::setKeyboard(KeyboardManager& k)
	{
		keyboard = &k;
	}

	void Script::setStateReturn(State::Type& t)
	{
		stateReturn = &t;
	}

	void Script::setWorld(World& w)
	{
		world = &w;
	}

	void Script::addVariables()
	{
		luaState["states"]["MainMenu"] = 0;
		luaState["states"]["Settings"] = 1;
		luaState["states"]["Play"] = 2;
		luaState["states"]["Exit"] = 3;
	}

	void Script::addClasses()
	{
		// vectors
		luaState["Vector2f"].SetClass<sf::Vector2f>("x", &sf::Vector2f::x, "y", &sf::Vector2f::y);
		luaState["Vector2i"].SetClass<sf::Vector2i>("x", &sf::Vector2i::x, "y", &sf::Vector2i::y);
		luaState["Vector2u"].SetClass<sf::Vector2u>("x", &sf::Vector2u::x, "y", &sf::Vector2u::y);

		// c++ containers
		luaState["entityList"].SetClass<std::vector<Entity*>>();

		// ECS
		luaState["Entity"].SetClass<Entity>("add", static_cast<bool (Entity::*)(std::string)>(&Entity::add),
											"remove", static_cast<bool (Entity::*)(std::string)>(&Entity::remove),
											"has", static_cast<bool (Entity::*)(std::string) const>(&Entity::has),
											"getDrawable", static_cast<Drawable* (Entity::*)()>(&Entity::get<Drawable>),
											"getMovable", static_cast<Movable* (Entity::*)()>(&Entity::get<Movable>),
											"getPhysical", static_cast<Physical* (Entity::*)()>(&Entity::get<Physical>),
											"getName", static_cast<Name* (Entity::*)()>(&Entity::get<Name>));

		// each Component type
		luaState["Drawable"].SetClass<Drawable>();
		luaState["Movable"].SetClass<Movable>();
		luaState["Physical"].SetClass<Physical>();
		luaState["Name"].SetClass<Name>();

		// GUI
		/*luaState["Column"].SetClass<cstr::Column>();
		luaState["Row"].SetClass<cstr::Row>();

		luaState["Button"].SetClass<cstr::Button>();
		luaState["Label"].SetClass<cstr::Label>();
		luaState["Slider"].SetClass<cstr::Slider>();
		luaState["Spacer"].SetClass<cstr::Spacer>();
		luaState["TextBox"].SetClass<cstr::TextBox>();
		luaState["Toggle"].SetClass<cstr::Toggle>();*/
	}

	void Script::addFunctions()
	{
		/* utility functions */
		luaState["getWindowSize"] = [&]()
		{
			if(window)
				return std::make_tuple(window->getSize().x, window->getSize().y);
			else
				return std::make_tuple(0u, 0u);
		};

		luaState["getTime"] = [&]()
		{
			if(clock)
				return clock->getElapsedTime().asSeconds();
			else
				return 0.f;
		};

		luaState["doKeypress"] = [&](std::string k)
		{
			if(keyboard)
				keyboard->call(k);
		};

		luaState["log"] = [&](std::string m)
		{
			if(log)
				*log << m;
		};

		/* EntitySystem */
		// World
		luaState["newEntity"] = [&]() -> Entity*
		{
			if(world)
				return world->addEntity();
			else
				return nullptr;
		};

		luaState["getTotalEntities"] = [&]()
		{
			if(world)
				return static_cast<unsigned>(world->getEntities().size());
			else
				return 0u;
		};

		luaState["getEntity"] = [&](unsigned e) -> Entity*
		{
			if(world && e < world->getEntities().size())
				return world->getEntities()[e];
			else
				return nullptr;
		};

		luaState["calculateEntitiesAround"] = [&](float x, float y, float radius)
		{
			if(world)
				world->calculateEntitiesAround({x, y}, radius);
		};

		luaState["getTotalEntitiesAround"] = [&]()
		{
			if(world)
				return static_cast<unsigned>(world->getEntitiesAround().size());
			else
				return 0u;
		};

		luaState["getEntityAround"] = [&](unsigned e) -> Entity*
		{
			if(world && e < world->getEntitiesAround().size())
				return world->getEntities()[e];
			else
				return nullptr;
		};

		// Drawable
		luaState["setTexture"] = [&](Drawable* d, std::string t)
		{
			if(d)
			{
				d->sprite.setTexture(assets->getTexture(t));
				return true;
			}
			else
				return false;
		};

		luaState["setTextureRect"] = [&](Drawable* d, int x, int y, int w, int h)
		{
			if(d)
				d->sprite.setTextureRect({x, y, w, h});
		};

		luaState["getSpriteSize"] = [&](Drawable* d)
		{
			if(d)
				return std::make_tuple(d->sprite.getGlobalBounds().width, d->sprite.getGlobalBounds().height);
			else
				return std::make_tuple(0.f, 0.f);
		};

		luaState["setScale"] = [&](Drawable* d, float x, float y)
		{
			if(d)
				d->sprite.setScale(x, y);
		};

		// Movable
		luaState["setMoveVelocity"] = [&](Movable* m, float v)
		{
			if(m)
			{
				m->moveVelocity = v;
			}
		};

		luaState["getVelocity"] = [&](Movable* m)
		{
			if(m)
				return std::make_tuple(m->velocity.x, m->velocity.y);
			else
				return std::make_tuple(0.f, 0.f);
		};

		// Physical
		luaState["setPosition"] = [&](Physical* p, float x, float y)
		{
			if(p)
				p->position = {x, y};
			else if(p)
				p->position = {0, 0};
		};

		luaState["getPosition"] = [&](Physical* p)
		{
			if(p)
				return std::make_tuple(p->position.x, p->position.y);
			else
				return std::make_tuple(0.f, 0.f);
		};

		luaState["setSize"] = [&](Physical* p, unsigned x, unsigned y)
		{
			if(p)
				p->size = {x, y};
			else if(p)
				p->size = {0, 0};
		};

		luaState["getSize"] = [&](Physical* p)
		{
			if(p)
				return std::make_tuple(p->size.x, p->size.y);
			else
				return std::make_tuple(0u, 0u);
		};

		// Name
		luaState["setName"] = [&](Name* n, std::string s)
		{
			if(n)
				n->name = s;
		};

		luaState["getName"] = [&](Name* n) -> std::string
		{
			if(n)
				return n->name;
			else
				return "null";
		};

		/* gui functions */

		/* State */
		luaState["setStateReturn"] = [&](unsigned s)
		{
			*stateReturn = static_cast<State::Type>(s);
		};

		/* Settings */
		luaState["getSettingStr"] = [&](std::string n)
		{
			std::string v;
			return std::make_tuple(settings->get(n, v), v);
		};

		luaState["setSettingStr"] = [&](std::string n, std::string v)
		{
			return settings->set(n, v);
		};

		luaState["getSettingBool"] = [&](std::string n)
		{
			bool v;
			return std::make_tuple(settings->get(n, v), v);
		};

		luaState["setSettingBool"] = [&](std::string n, bool v)
		{
			return settings->set(n, v);
		};

		luaState["getSettingNum"] = [&](std::string n)
		{
			int v;
			return std::make_tuple(settings->get(n, v), v);
		};

		luaState["setSettingNum"] = [&](std::string n, int v)
		{
			return settings->set(n, v);
		};
	}
}<|endoftext|>


<commit_before>class tup_seatraffic_factions {
        title = "    Enable Ambient Air Factions";
        values[]= {0,1,2};
        texts[]= {"All Factions","Civilian Only","None"};
        default = 1;
};
class tup_seatraffic_amount {
        title = "    Enable Ambient Sea Traffic";
        values[]= {0,1};
        texts[]= {"Full","Reduced"};
        default = 1;
};
class tup_seatraffic_ROE {
        title = "        Ambient Sea Traffic Rules of Engagement";
       values[]= {1,2,3,4,5};
       texts[]= {"Never fire","Hold fire - defend only","Hold fire, engage at will","Fire at will","Fire at will, engage at will"};
       default = 2;
};
class tup_seatraffic_LHD {
        title = "        Ambient LHD Helicopter Dock";
       values[]= {0,1,2};
       texts[]= {"Never","Always","Random"};
       default = 2;
};
<commit_msg>[TUP_SEATRAFFIC] - Typo in params<commit_after>class tup_seatraffic_factions {
        title = "    Enable Ambient Sea Factions";
        values[]= {0,1,2};
        texts[]= {"All Factions","Civilian Only","None"};
        default = 1;
};
class tup_seatraffic_amount {
        title = "    Enable Ambient Sea Traffic";
        values[]= {0,1};
        texts[]= {"Full","Reduced"};
        default = 1;
};
class tup_seatraffic_ROE {
        title = "        Ambient Sea Traffic Rules of Engagement";
       values[]= {1,2,3,4,5};
       texts[]= {"Never fire","Hold fire - defend only","Hold fire, engage at will","Fire at will","Fire at will, engage at will"};
       default = 2;
};
class tup_seatraffic_LHD {
        title = "        Ambient LHD Helicopter Dock";
       values[]= {0,1,2};
       texts[]= {"Never","Always","Random"};
       default = 2;
};
<|endoftext|>


<commit_before>#include "blinkyBlocksVM.h"
#include "blinkyBlocksBlock.h"
#include "blinkyBlocksBlockCode.h"
#include <boost/asio/io_service.hpp>
#include <sys/wait.h>
#include <stdio.h>
#include <boost/bind.hpp>
#include "trace.h"
#include <stdexcept>
#include <string.h>
#include "events.h"
#include "blinkyBlocksEvents.h"
#include "openglViewer.h"

#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>

using namespace boost;
using asio::ip::tcp;

namespace BlinkyBlocks {

boost::asio::io_service *BlinkyBlocksVM::ios = NULL;
boost::interprocess::interprocess_mutex BlinkyBlocksVM::mutex_ios;
tcp::acceptor *BlinkyBlocksVM::acceptor = NULL;
string BlinkyBlocksVM::vmPath;
string BlinkyBlocksVM::programPath;
bool BlinkyBlocksVM::debugging = false;

BlinkyBlocksVM::BlinkyBlocksVM(BlinkyBlocksBlock* bb){
   int ret;
   boost::system::error_code error;
   stringstream vmLogFile;

	assert(ios != NULL && acceptor != NULL);
	hostBlock = bb;
   vmLogFile << "VM" << hostBlock->blockId << ".log";

	OUTPUT << "VM "<< hostBlock->blockId << " constructor" << endl;
	// Start the VM
	pid = 0;
   mutex_ios.lock();
	ios->notify_fork(boost::asio::io_service::fork_prepare);
	pid = fork();
	if(pid < 0) {ERRPUT << "Error when starting the VM" << endl;}
    if(pid == 0) {
		ios->notify_fork(boost::asio::io_service::fork_child);
      mutex_ios.unlock();
      acceptor->close();
      getWorld()->closeAllSockets();
#ifdef LOGFILE
      log_file.close();
#endif
		int fd = open(vmLogFile.str().c_str(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
		dup2(fd, 1);
		dup2(fd, 2);
		close(fd);
		if (debugging) {
			//./meld -f  /home/ubuntu/Bureau/CMU/meld/examples/ends.m -c sl -D SIM
		  char* cmd[] = {(char*)vmPath.c_str(), /*(char*)"-a", (char*)"bbsim",*/ (char*)"-f", (char*)programPath.c_str(), (char*)"-c", (char*) "sl", (char*) "-D", (char*) "SIM", NULL };
			ret = execv(vmPath.c_str(), const_cast<char**>(cmd));
		} else {
			//./meld -f  /home/ubuntu/Bureau/CMU/meld/examples/ends.m -c sl
		  char* cmd[] = {(char*)vmPath.c_str(), /*(char*)"-a", (char*)"bbsim",*/ (char*)"-f", (char*)programPath.c_str(), (char*)"-c", (char*) "sl", NULL };
			ret = execv(vmPath.c_str(), const_cast<char**>(cmd));
		}
      if(ret == -1) {
         cerr << "Error: VM executable, " << vmPath.c_str()  << ", does not exist or is not executable" << endl;
         exit(EXIT_FAILURE);
      }
	}
	ios->notify_fork(boost::asio::io_service::fork_parent);
   mutex_ios.unlock();
	socket = boost::shared_ptr<tcp::socket>(new tcp::socket(*ios));
   if (hostBlock->blockId == 1) {
      bool connected = false;

      acceptor->async_accept(*(socket.get()), boost::bind(&BlinkyBlocksVM::asyncAcceptHandler, this, error , &connected));
      while(!connected &&  (pid != waitpid(pid, NULL, WNOHANG))) {
         	if (!BlinkyBlocksVM::isInDebuggingMode()) { // In debugging mode the scheduler thread is looking for connections
               checkForReceivedVMCommands(); // it is actually check for connection
               usleep(10000);
            }
      }
      if(!connected) {
         ifstream file (vmLogFile.str().c_str());
         string line;
         cerr << "VisibleSim error: unable to connect to the VM" << endl;
         cerr << vmLogFile.str() << ":" << endl;
         if (file.is_open()) {
            while (!file.eof()) {
               getline(file,line);
               cerr << line;
            }
         cerr << endl;
         file.close();
         }
         acceptor->close();
         exit(EXIT_FAILURE);
      }
   } else {
      acceptor->accept(*(socket.get()));
   }
   idSent = false;
	deterministicSet = false;
	nbSentCommands = 0;
	asyncReadCommand();
}

void BlinkyBlocksVM::asyncAcceptHandler(boost::system::error_code& error, bool* connected) {
 if (error) {
   *connected = false;
 } else {
   *connected = true;
 }
}

BlinkyBlocksVM::~BlinkyBlocksVM() {
	closeSocket();
	killProcess();
}

void BlinkyBlocksVM::terminate() {
	waitpid(pid, NULL, 0);
}

void BlinkyBlocksVM::killProcess() {
	kill(pid, SIGTERM);
	waitpid(pid, NULL, 0);
}

void BlinkyBlocksVM::closeSocket() {
	if (socket != NULL) {
		socket->cancel();
		socket->close();
		socket.reset();
	}
}

void BlinkyBlocksVM::asyncReadCommandHandler(const boost::system::error_code& error, std::size_t bytes_transferred) {
	if(error) {
		ERRPUT << "An error occurred while receiving a tcp command from VM " << hostBlock->blockId << " (socket closed ?) " <<endl;
		return;
	}
    try {
		memset(inBuffer+1, 0, inBuffer[0]);
		boost::asio::read(getSocket(),boost::asio::buffer((void*)(inBuffer + 1), inBuffer[0]) );
	} catch (std::exception& e) {
		ERRPUT << "Connection to the VM "<< hostBlock->blockId << " lost" << endl;
	}
	handleInBuffer();
	while (socket->available()) {
		try {
			boost::asio::read(getSocket(), boost::asio::buffer(inBuffer, sizeof(commandType)));
			boost::asio::read(getSocket(),boost::asio::buffer((void*)(inBuffer + 1), inBuffer[0]));
		}  catch (std::exception& e) {
			ERRPUT << "Connection to the VM "<< hostBlock->blockId << " lost" << endl;
		}
		handleInBuffer();
	}
    this->asyncReadCommand();
}

void BlinkyBlocksVM::handleInBuffer() {
	BlinkyBlocksBlockCode *bbc = (BlinkyBlocksBlockCode*)hostBlock->blockCode;
	VMCommand command(inBuffer);
	bbc->handleCommand(command);
}

void BlinkyBlocksVM::asyncReadCommand() {
	if (socket == NULL) {
		ERRPUT << "Simulator is not connected to the VM "<< hostBlock->blockId << endl;
		return;
	}
	try {
	inBuffer[0] = 0;
	boost::asio::async_read(getSocket(),
		boost::asio::buffer(inBuffer, sizeof(commandType)),
		boost::bind(&BlinkyBlocksVM::asyncReadCommandHandler, this, boost::asio::placeholders::error,
		boost::asio::placeholders::bytes_transferred));
	} catch (std::exception& e) {
		ERRPUT << "Connection to the VM "<< hostBlock->blockId << " lost" << endl;
	}
}

int BlinkyBlocksVM::sendCommand(VMCommand &command){
	if (socket == NULL) {
		ERRPUT << "Simulator is not connected to the VM "<< hostBlock->blockId << endl;
		return 0;
	}
	if (command.getType() != VM_COMMAND_DEBUG) {
		nbSentCommands++;
		((BlinkyBlocksBlockCode*)hostBlock->blockCode)->handleDeterministicMode(command);
	}
	try {
		boost::asio::write(getSocket(), boost::asio::buffer(command.getData(), command.getSize()));
      //boost::asio::async_write(getSocket(), boost::asio::buffer(command.getData(), command.getSize()), boost::bind(&BlinkyBlocksVM::handle_write, this,
      //      boost::asio::placeholders::error));
   } catch (std::exception& e) {
		ERRPUT << "Connection to the VM "<< hostBlock->blockId << " lost" << endl;
		return 0;
	}
	return 1;
}

  void BlinkyBlocksVM::handle_write(const boost::system::error_code& error)
  {
    if (!error)
    {
     cout << "ok" << endl;
    }
  }

void BlinkyBlocksVM::checkForReceivedCommands() {
	if (ios != NULL) {
      mutex_ios.lock();
      try {
         ios->poll();
         ios->reset();
      } catch (boost::exception& e) {
      }
      mutex_ios.unlock();
		}
}

void BlinkyBlocksVM::waitForOneCommand() {
	if (ios != NULL) {
		mutex_ios.lock();
      try {
      ios->run_one();
		ios->reset();
      } catch (boost::exception& e) {
      }
      mutex_ios.unlock();
	}
	checkForReceivedCommands();
}

void BlinkyBlocksVM::setConfiguration(string v, string p, bool d) {
	vmPath = v;
	programPath = p;
	debugging = d;
}

void BlinkyBlocksVM::createServer(int p) {
	assert(ios == NULL);
	ios = new boost::asio::io_service();
	acceptor =  new tcp::acceptor(*ios, tcp::endpoint(tcp::v4(), p));
}

void BlinkyBlocksVM::deleteServer() {
	ios->stop();
	delete acceptor;
	delete ios;
	ios = NULL; acceptor = NULL;
}

}
<commit_msg>use -a parameter<commit_after>#include "blinkyBlocksVM.h"
#include "blinkyBlocksBlock.h"
#include "blinkyBlocksBlockCode.h"
#include <boost/asio/io_service.hpp>
#include <sys/wait.h>
#include <stdio.h>
#include <boost/bind.hpp>
#include "trace.h"
#include <stdexcept>
#include <string.h>
#include "events.h"
#include "blinkyBlocksEvents.h"
#include "openglViewer.h"

#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>

using namespace boost;
using asio::ip::tcp;

namespace BlinkyBlocks {

boost::asio::io_service *BlinkyBlocksVM::ios = NULL;
boost::interprocess::interprocess_mutex BlinkyBlocksVM::mutex_ios;
tcp::acceptor *BlinkyBlocksVM::acceptor = NULL;
string BlinkyBlocksVM::vmPath;
string BlinkyBlocksVM::programPath;
bool BlinkyBlocksVM::debugging = false;

BlinkyBlocksVM::BlinkyBlocksVM(BlinkyBlocksBlock* bb){
   int ret;
   boost::system::error_code error;
   stringstream vmLogFile;

	assert(ios != NULL && acceptor != NULL);
	hostBlock = bb;
   vmLogFile << "VM" << hostBlock->blockId << ".log";

	OUTPUT << "VM "<< hostBlock->blockId << " constructor" << endl;
	// Start the VM
	pid = 0;
   mutex_ios.lock();
	ios->notify_fork(boost::asio::io_service::fork_prepare);
	pid = fork();
	if(pid < 0) {ERRPUT << "Error when starting the VM" << endl;}
    if(pid == 0) {
		ios->notify_fork(boost::asio::io_service::fork_child);
      mutex_ios.unlock();
      acceptor->close();
      getWorld()->closeAllSockets();
#ifdef LOGFILE
      log_file.close();
#endif
		int fd = open(vmLogFile.str().c_str(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
		dup2(fd, 1);
		dup2(fd, 2);
		close(fd);
		if (debugging) {
			//./meld -f  /home/ubuntu/Bureau/CMU/meld/examples/ends.m -c sl -D SIM
		  char* cmd[] = {(char*)vmPath.c_str(), (char*)"-a", (char*)"bbsim", (char*)"-f", (char*)programPath.c_str(), (char*)"-c", (char*) "sl", (char*) "-D", (char*) "SIM", NULL };
			ret = execv(vmPath.c_str(), const_cast<char**>(cmd));
		} else {
			//./meld -f  /home/ubuntu/Bureau/CMU/meld/examples/ends.m -c sl
		  char* cmd[] = {(char*)vmPath.c_str(), (char*)"-a", (char*)"bbsim", (char*)"-f", (char*)programPath.c_str(), (char*)"-c", (char*) "sl", NULL };
			ret = execv(vmPath.c_str(), const_cast<char**>(cmd));
		}
      if(ret == -1) {
         cerr << "Error: VM executable, " << vmPath.c_str()  << ", does not exist or is not executable" << endl;
         exit(EXIT_FAILURE);
      }
	}
	ios->notify_fork(boost::asio::io_service::fork_parent);
   mutex_ios.unlock();
	socket = boost::shared_ptr<tcp::socket>(new tcp::socket(*ios));
   if (hostBlock->blockId == 1) {
      bool connected = false;

      acceptor->async_accept(*(socket.get()), boost::bind(&BlinkyBlocksVM::asyncAcceptHandler, this, error , &connected));
      while(!connected &&  (pid != waitpid(pid, NULL, WNOHANG))) {
         	if (!BlinkyBlocksVM::isInDebuggingMode()) { // In debugging mode the scheduler thread is looking for connections
               checkForReceivedVMCommands(); // it is actually check for connection
               usleep(10000);
            }
      }
      if(!connected) {
         ifstream file (vmLogFile.str().c_str());
         string line;
         cerr << "VisibleSim error: unable to connect to the VM" << endl;
         cerr << vmLogFile.str() << ":" << endl;
         if (file.is_open()) {
            while (!file.eof()) {
               getline(file,line);
               cerr << line;
            }
         cerr << endl;
         file.close();
         }
         acceptor->close();
         exit(EXIT_FAILURE);
      }
   } else {
      acceptor->accept(*(socket.get()));
   }
   idSent = false;
	deterministicSet = false;
	nbSentCommands = 0;
	asyncReadCommand();
}

void BlinkyBlocksVM::asyncAcceptHandler(boost::system::error_code& error, bool* connected) {
 if (error) {
   *connected = false;
 } else {
   *connected = true;
 }
}

BlinkyBlocksVM::~BlinkyBlocksVM() {
	closeSocket();
	killProcess();
}

void BlinkyBlocksVM::terminate() {
	waitpid(pid, NULL, 0);
}

void BlinkyBlocksVM::killProcess() {
	kill(pid, SIGTERM);
	waitpid(pid, NULL, 0);
}

void BlinkyBlocksVM::closeSocket() {
	if (socket != NULL) {
		socket->cancel();
		socket->close();
		socket.reset();
	}
}

void BlinkyBlocksVM::asyncReadCommandHandler(const boost::system::error_code& error, std::size_t bytes_transferred) {
	if(error) {
		ERRPUT << "An error occurred while receiving a tcp command from VM " << hostBlock->blockId << " (socket closed ?) " <<endl;
		return;
	}
    try {
		memset(inBuffer+1, 0, inBuffer[0]);
		boost::asio::read(getSocket(),boost::asio::buffer((void*)(inBuffer + 1), inBuffer[0]) );
	} catch (std::exception& e) {
		ERRPUT << "Connection to the VM "<< hostBlock->blockId << " lost" << endl;
	}
	handleInBuffer();
	while (socket->available()) {
		try {
			boost::asio::read(getSocket(), boost::asio::buffer(inBuffer, sizeof(commandType)));
			boost::asio::read(getSocket(),boost::asio::buffer((void*)(inBuffer + 1), inBuffer[0]));
		}  catch (std::exception& e) {
			ERRPUT << "Connection to the VM "<< hostBlock->blockId << " lost" << endl;
		}
		handleInBuffer();
	}
    this->asyncReadCommand();
}

void BlinkyBlocksVM::handleInBuffer() {
	BlinkyBlocksBlockCode *bbc = (BlinkyBlocksBlockCode*)hostBlock->blockCode;
	VMCommand command(inBuffer);
	bbc->handleCommand(command);
}

void BlinkyBlocksVM::asyncReadCommand() {
	if (socket == NULL) {
		ERRPUT << "Simulator is not connected to the VM "<< hostBlock->blockId << endl;
		return;
	}
	try {
	inBuffer[0] = 0;
	boost::asio::async_read(getSocket(),
		boost::asio::buffer(inBuffer, sizeof(commandType)),
		boost::bind(&BlinkyBlocksVM::asyncReadCommandHandler, this, boost::asio::placeholders::error,
		boost::asio::placeholders::bytes_transferred));
	} catch (std::exception& e) {
		ERRPUT << "Connection to the VM "<< hostBlock->blockId << " lost" << endl;
	}
}

int BlinkyBlocksVM::sendCommand(VMCommand &command){
	if (socket == NULL) {
		ERRPUT << "Simulator is not connected to the VM "<< hostBlock->blockId << endl;
		return 0;
	}
	if (command.getType() != VM_COMMAND_DEBUG) {
		nbSentCommands++;
		((BlinkyBlocksBlockCode*)hostBlock->blockCode)->handleDeterministicMode(command);
	}
	try {
		boost::asio::write(getSocket(), boost::asio::buffer(command.getData(), command.getSize()));
      //boost::asio::async_write(getSocket(), boost::asio::buffer(command.getData(), command.getSize()), boost::bind(&BlinkyBlocksVM::handle_write, this,
      //      boost::asio::placeholders::error));
   } catch (std::exception& e) {
		ERRPUT << "Connection to the VM "<< hostBlock->blockId << " lost" << endl;
		return 0;
	}
	return 1;
}

  void BlinkyBlocksVM::handle_write(const boost::system::error_code& error)
  {
    if (!error)
    {
     cout << "ok" << endl;
    }
  }

void BlinkyBlocksVM::checkForReceivedCommands() {
	if (ios != NULL) {
      mutex_ios.lock();
      try {
         ios->poll();
         ios->reset();
      } catch (boost::exception& e) {
      }
      mutex_ios.unlock();
		}
}

void BlinkyBlocksVM::waitForOneCommand() {
	if (ios != NULL) {
		mutex_ios.lock();
      try {
      ios->run_one();
		ios->reset();
      } catch (boost::exception& e) {
      }
      mutex_ios.unlock();
	}
	checkForReceivedCommands();
}

void BlinkyBlocksVM::setConfiguration(string v, string p, bool d) {
	vmPath = v;
	programPath = p;
	debugging = d;
}

void BlinkyBlocksVM::createServer(int p) {
	assert(ios == NULL);
	ios = new boost::asio::io_service();
	acceptor =  new tcp::acceptor(*ios, tcp::endpoint(tcp::v4(), p));
}

void BlinkyBlocksVM::deleteServer() {
	ios->stop();
	delete acceptor;
	delete ios;
	ios = NULL; acceptor = NULL;
}

}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "CommandSpecs.h"

CommandSpecs::CommandSpecs()
{
}

CommandSpecs::~CommandSpecs()
{
}

bool CommandSpecs::ShouldRunThisCommand(ParsedCommand * Parsed)
{
	return (Parsed->Words->at(0) == "specs");
}

void CommandSpecs::Run(ParsedCommand* Parsed)
{
	this->GetOSInfo();
	this->GetProcessorInfo();
}

string* CommandSpecs::GetName()
{
	return new string("Specs");
}

string* CommandSpecs::GetHelp()
{
	return new string("Writes to the console some detailed information about your computer.");
}

void CommandSpecs::GetOSInfo()
{
	__int64 major = 0;
	__int64 minor = 0;
	__int64 serviceMajor = 0;

	//Determine major version number.
	while (IsWindowsVersionOrGreater(major, minor, serviceMajor))
	{
		++major;
	}
	--major;

	//Determine minor version number.
	while (IsWindowsVersionOrGreater(major, minor, serviceMajor))
	{
		++minor;
	}
	--minor;

	//Determine service pack major version number.
	while (IsWindowsVersionOrGreater(major, minor, serviceMajor))
	{
		serviceMajor++;
	}
	serviceMajor--;

	Console->WriteLine("OS Info: ");
	Console->WriteLine(&("Major: " + to_string(major)));
	Console->WriteLine(&("Minor: " + to_string(minor)));
	Console->WriteLine(&("Service: " + to_string(serviceMajor)));
}

void CommandSpecs::GetProcessorInfo()
{
	Console->WriteLine("\r\n");
	Console->WriteLine("Processor Information: ");
	Console->WriteLine("\r\n");
	SYSTEM_INFO SysInfo;
	GetSystemInfo(&SysInfo);
	//SysInfo->dwNumberOfProcessors
	_PROCESSOR_POWER_INFORMATION* ProcessorInformations = new _PROCESSOR_POWER_INFORMATION[SysInfo.dwNumberOfProcessors];
	CallNtPowerInformation(POWER_INFORMATION_LEVEL::ProcessorInformation, NULL, NULL, ProcessorInformations, (sizeof(_PROCESSOR_POWER_INFORMATION) * SysInfo.dwNumberOfProcessors));

	__int8 i = 0;

	while (i != SysInfo.dwNumberOfProcessors)
	{
		Console->WriteLine(&("Processor " + to_string(ProcessorInformations[i].Number)));
		//Console->WriteLine(&("Current Mhz: " + to_string(ProcessorInformations[i].CurrentMhz)));
		Console->WriteLine(&("Max Mhz: " + to_string(ProcessorInformations[i].MaxMhz)));
		//Console->WriteLine(&("Mhz Limit: " + to_string(ProcessorInformations[i].MhzLimit)));
		Console->WriteLine("\r\n");
		++i;
	}
}
<commit_msg>Added back some things.<commit_after>#include "stdafx.h"
#include "CommandSpecs.h"

CommandSpecs::CommandSpecs()
{
}

CommandSpecs::~CommandSpecs()
{
}

bool CommandSpecs::ShouldRunThisCommand(ParsedCommand * Parsed)
{
	return (Parsed->Words->at(0) == "specs");
}

void CommandSpecs::Run(ParsedCommand* Parsed)
{
	this->GetOSInfo();
	this->GetProcessorInfo();
}

string* CommandSpecs::GetName()
{
	return new string("Specs");
}

string* CommandSpecs::GetHelp()
{
	return new string("Writes to the console some detailed information about your computer.");
}

void CommandSpecs::GetOSInfo()
{
	__int64 major = 0;
	__int64 minor = 0;
	__int64 serviceMajor = 0;

	//Determine major version number.
	while (IsWindowsVersionOrGreater(major, minor, serviceMajor))
	{
		++major;
	}
	--major;

	//Determine minor version number.
	while (IsWindowsVersionOrGreater(major, minor, serviceMajor))
	{
		++minor;
	}
	--minor;

	//Determine service pack major version number.
	while (IsWindowsVersionOrGreater(major, minor, serviceMajor))
	{
		serviceMajor++;
	}
	serviceMajor--;

	Console->WriteLine("OS Info: ");
	Console->WriteLine(&("Major: " + to_string(major)));
	Console->WriteLine(&("Minor: " + to_string(minor)));
	Console->WriteLine(&("Service: " + to_string(serviceMajor)));
}

void CommandSpecs::GetProcessorInfo()
{
	Console->WriteLine("\r\n");
	Console->WriteLine("Processor Information: ");
	Console->WriteLine("\r\n");
	SYSTEM_INFO SysInfo;
	GetSystemInfo(&SysInfo);
	//SysInfo->dwNumberOfProcessors
	_PROCESSOR_POWER_INFORMATION* ProcessorInformations = new _PROCESSOR_POWER_INFORMATION[SysInfo.dwNumberOfProcessors];
	CallNtPowerInformation(POWER_INFORMATION_LEVEL::ProcessorInformation, NULL, NULL, ProcessorInformations, (sizeof(_PROCESSOR_POWER_INFORMATION) * SysInfo.dwNumberOfProcessors));

	__int8 i = 0;

	while (i != SysInfo.dwNumberOfProcessors)
	{
		Console->WriteLine(&("Processor " + to_string(ProcessorInformations[i].Number)));
		Console->WriteLine(&("Current Mhz: " + to_string(ProcessorInformations[i].CurrentMhz)));
		Console->WriteLine(&("Max Mhz: " + to_string(ProcessorInformations[i].MaxMhz)));
		Console->WriteLine(&("Mhz Limit: " + to_string(ProcessorInformations[i].MhzLimit)));
		Console->WriteLine("\r\n");
		++i;
	}
}
<|endoftext|>