<commit_before>/*
  +----------------------------------------------------------------------+
  | PHP Version 5                                                        |
  +----------------------------------------------------------------------+
  | Copyright (c) 1997-2013 The PHP Group                                |
  +----------------------------------------------------------------------+
  | http://www.opensource.org/licenses/mit-license.php  MIT License      |
  +----------------------------------------------------------------------+
  | Author: Jani Taskinen <jani.taskinen@iki.fi>                         |
  | Author: Patrick Reilly <preilly@php.net>                             |
  +----------------------------------------------------------------------+
*/

/* $Id$ */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php_v8js_macros.h"

extern "C" {
#include "zend_exceptions.h"
}

/* Forward declarations */
void php_v8js_commonjs_normalise_identifier(char *base, char *identifier, char *normalised_path, char *module_name);

/* global.exit - terminate execution */
V8JS_METHOD(exit) /* {{{ */
{
	v8::V8::TerminateExecution();
}
/* }}} */

/* global.sleep - sleep for passed seconds */
V8JS_METHOD(sleep) /* {{{ */
{
	php_sleep(info[0]->Int32Value());
}
/* }}} */

/* global.print - php print() */
V8JS_METHOD(print) /* {{{ */
{
	int ret = 0;
	TSRMLS_FETCH();

	for (int i = 0; i < info.Length(); i++) {
		v8::String::Utf8Value str(info[i]);
		const char *cstr = ToCString(str);
		ret = PHPWRITE(cstr, strlen(cstr));
	}
	info.GetReturnValue().Set(V8JS_INT(ret));
}
/* }}} */

static void _php_v8js_dumper(v8::Local<v8::Value> var, int level TSRMLS_DC) /* {{{ */
{
	v8::String::Utf8Value str(var->ToDetailString());
	const char *valstr = ToCString(str);
	size_t valstr_len = (valstr) ? strlen(valstr) : 0;

	if (level > 1) {
		php_printf("%*c", (level - 1) * 2, ' ');
	}

	if (var->IsString())
	{
		php_printf("string(%zu) \"%s\"\n", valstr_len, valstr);
	}
	else if (var->IsBoolean())
	{
		php_printf("bool(%s)\n", valstr);
	}
	else if (var->IsInt32() || var->IsUint32())
	{
		php_printf("int(%s)\n", valstr);
	}
	else if (var->IsNumber())
	{
		php_printf("float(%s)\n", valstr);
	}
	else if (var->IsDate())
	{
		php_printf("Date(%s)\n", valstr);
	}
#if PHP_V8_API_VERSION >= 2003007
	else if (var->IsRegExp())
	{
		php_printf("RegExp(%s)\n", valstr);
	}
#endif
	else if (var->IsArray())
	{
		v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(var);
		uint32_t length = array->Length();

		php_printf("array(%d) {\n", length);

		for (unsigned i = 0; i < length; i++) {
			php_printf("%*c[%d] =>\n", level * 2, ' ', i);
			_php_v8js_dumper(array->Get(i), level + 1 TSRMLS_CC);
		}

		if (level > 1) {
			php_printf("%*c", (level - 1) * 2, ' ');
		}

		ZEND_PUTS("}\n");
	}
	else if (var->IsObject())
	{
		v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(var);
		V8JS_GET_CLASS_NAME(cname, object);

		if (var->IsFunction())
		{
			v8::String::Utf8Value csource(object->ToString());
			php_printf("object(%s)#%d {\n%*c%s\n", ToCString(cname), object->GetIdentityHash(), level * 2 + 2, ' ', ToCString(csource));
		}
		else
		{
			v8::Local<v8::Array> keys = object->GetPropertyNames();
			uint32_t length = keys->Length();

			php_printf("object(%s)#%d (%d) {\n", ToCString(cname), object->GetIdentityHash(), length);

			for (unsigned i = 0; i < length; i++) {
				v8::Local<v8::String> key = keys->Get(i)->ToString();
				v8::String::Utf8Value kname(key);
				php_printf("%*c[\"%s\"] =>\n", level * 2, ' ', ToCString(kname));
				_php_v8js_dumper(object->Get(key), level + 1 TSRMLS_CC);
			}
		}

		if (level > 1) {
			php_printf("%*c", (level - 1) * 2, ' ');
		}

		ZEND_PUTS("}\n");
	}
	else /* null, undefined, etc. */
	{
		php_printf("<%s>\n", valstr);
	}
}
/* }}} */

/* global.var_dump - Dump JS values */
V8JS_METHOD(var_dump) /* {{{ */
{
	TSRMLS_FETCH();

	for (int i = 0; i < info.Length(); i++) {
		_php_v8js_dumper(info[i], 1 TSRMLS_CC);
	}

	info.GetReturnValue().Set(V8JS_NULL);
}
/* }}} */

V8JS_METHOD(require)
{
	TSRMLS_FETCH();

	// Get the extension context
	v8::Handle<v8::External> data = v8::Handle<v8::External>::Cast(info.Data());
	php_v8js_ctx *c = static_cast<php_v8js_ctx*>(data->Value());

	// Check that we have a module loader
	if (c->module_loader == NULL) {
		info.GetReturnValue().Set(v8::ThrowException(v8::String::New("No module loader")));
		return;
	}

	v8::String::Utf8Value module_id_v8(info[0]);

	// Make sure to duplicate the module name string so it doesn't get freed by the V8 garbage collector
	char *module_id = estrdup(ToCString(module_id_v8));
	char *normalised_path = (char *)emalloc(PATH_MAX);
	char *module_name = (char *)emalloc(PATH_MAX);

	php_v8js_commonjs_normalise_identifier(c->modules_base.back(), module_id, normalised_path, module_name);
	efree(module_id);

	char *normalised_module_id = (char *)emalloc(strlen(module_id));
	*normalised_module_id = 0;

	if (strlen(normalised_path) > 0) {
		strcat(normalised_module_id, normalised_path);
		strcat(normalised_module_id, "/");
	}

	strcat(normalised_module_id, module_name);
	efree(module_name);

	// Check for module cyclic dependencies
	for (std::vector<char *>::iterator it = c->modules_stack.begin(); it != c->modules_stack.end(); ++it)
    {
    	if (!strcmp(*it, normalised_module_id)) {
    		efree(normalised_path);

		info.GetReturnValue().Set(v8::ThrowException(v8::String::New("Module cyclic dependency")));
		return;
    	}
    }

    // If we have already loaded and cached this module then use it
	if (V8JSG(modules_loaded).count(normalised_module_id) > 0) {
		efree(normalised_path);

		info.GetReturnValue().Set(V8JSG(modules_loaded)[normalised_module_id]);
		return;
	}

	// Callback to PHP to load the module code

	zval module_code;
	zval *normalised_path_zend;

	MAKE_STD_ZVAL(normalised_path_zend);
	ZVAL_STRING(normalised_path_zend, normalised_module_id, 1);
	zval* params[] = { normalised_path_zend };

	if (FAILURE == call_user_function(EG(function_table), NULL, c->module_loader, &module_code, 1, params TSRMLS_CC)) {
		efree(normalised_path);

		info.GetReturnValue().Set(v8::ThrowException(v8::String::New("Module loader callback failed")));
		return;
	}

	// Check if an exception was thrown
	if (EG(exception)) {
		efree(normalised_path);

		// Clear the PHP exception and throw it in V8 instead
		zend_clear_exception(TSRMLS_C);
		info.GetReturnValue().Set(v8::ThrowException(v8::String::New("Module loader callback exception")));
		return;
	}

	// Convert the return value to string
	if (Z_TYPE(module_code) != IS_STRING) {
    	convert_to_string(&module_code);
	}

	// Check that some code has been returned
	if (!strlen(Z_STRVAL(module_code))) {
		efree(normalised_path);

		info.GetReturnValue().Set(v8::ThrowException(v8::String::New("Module loader callback did not return code")));
		return;
	}

	// Create a template for the global object and set the built-in global functions
	v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
	global->Set(v8::String::New("print"), v8::FunctionTemplate::New(V8JS_MN(print)), v8::ReadOnly);
	global->Set(V8JS_SYM("sleep"), v8::FunctionTemplate::New(V8JS_MN(sleep)), v8::ReadOnly);
	global->Set(v8::String::New("require"), v8::FunctionTemplate::New(V8JS_MN(require), v8::External::New(c)), v8::ReadOnly);

	// Add the exports object in which the module can return its API
	v8::Handle<v8::ObjectTemplate> exports_template = v8::ObjectTemplate::New();
	v8::Handle<v8::Object> exports = exports_template->NewInstance();
	global->Set(v8::String::New("exports"), exports);

	// Add the module object in which the module can have more fine-grained control over what it can return
	v8::Handle<v8::ObjectTemplate> module_template = v8::ObjectTemplate::New();
	v8::Handle<v8::Object> module = module_template->NewInstance();
	module->Set(v8::String::New("id"), v8::String::New(normalised_module_id));
	global->Set(v8::String::New("module"), module);

	// Each module gets its own context so different modules do not affect each other
	v8::Local<v8::Context> context = v8::Local<v8::Context>::New(c->isolate, v8::Context::New(c->isolate, NULL, global));

	// Catch JS exceptions
	v8::TryCatch try_catch;

	v8::Locker locker(c->isolate);
	v8::Isolate::Scope isolate_scope(c->isolate);

	v8::HandleScope handle_scope(c->isolate);

	// Enter the module context
	v8::Context::Scope scope(context);
	// Set script identifier
	v8::Local<v8::String> sname = V8JS_SYM("require");

	v8::Local<v8::String> source = v8::String::New(Z_STRVAL(module_code));

	// Create and compile script
	v8::Local<v8::Script> script = v8::Script::New(source, sname);

	// The script will be empty if there are compile errors
	if (script.IsEmpty()) {
		efree(normalised_path);
		info.GetReturnValue().Set(v8::ThrowException(v8::String::New("Module script compile failed")));
		return;
	}

	// Add this module and path to the stack
	c->modules_stack.push_back(normalised_module_id);

	c->modules_base.push_back(normalised_path);

	// Run script
	v8::Local<v8::Value> result = script->Run();

	// Remove this module and path from the stack
	c->modules_stack.pop_back();
	c->modules_base.pop_back();

	efree(normalised_path);

	// Script possibly terminated, return immediately
	if (!try_catch.CanContinue()) {
		info.GetReturnValue().Set(v8::ThrowException(v8::String::New("Module script compile failed")));
		return;
	}

	// Handle runtime JS exceptions
	if (try_catch.HasCaught()) {
		// Rethrow the exception back to JS
		info.GetReturnValue().Set(try_catch.ReThrow());
		return;
	}

	// Cache the module so it doesn't need to be compiled and run again
	// Ensure compatibility with CommonJS implementations such as NodeJS by playing nicely with module.exports and exports
	if (module->Has(v8::String::New("exports")) && !module->Get(v8::String::New("exports"))->IsUndefined()) {
		// If module.exports has been set then we cache this arbitrary value...
		V8JSG(modules_loaded)[normalised_module_id] = handle_scope.Close(module->Get(v8::String::New("exports"))->ToObject());
	} else {
		// ...otherwise we cache the exports object itself
		V8JSG(modules_loaded)[normalised_module_id] = handle_scope.Close(exports);
	}

	info.GetReturnValue().Set(V8JSG(modules_loaded)[normalised_module_id]);
}

void php_v8js_register_methods(v8::Handle<v8::ObjectTemplate> global, php_v8js_ctx *c) /* {{{ */
{
	global->Set(V8JS_SYM("exit"), v8::FunctionTemplate::New(V8JS_MN(exit)), v8::ReadOnly);
	global->Set(V8JS_SYM("sleep"), v8::FunctionTemplate::New(V8JS_MN(sleep)), v8::ReadOnly);
	global->Set(V8JS_SYM("print"), v8::FunctionTemplate::New(V8JS_MN(print)), v8::ReadOnly);
	global->Set(V8JS_SYM("var_dump"), v8::FunctionTemplate::New(V8JS_MN(var_dump)), v8::ReadOnly);

	c->modules_base.push_back("");
	global->Set(V8JS_SYM("require"), v8::FunctionTemplate::New(V8JS_MN(require), v8::External::New(c)), v8::ReadOnly);
}
/* }}} */

/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 * vim600: noet sw=4 ts=4 fdm=marker
 * vim<600: noet sw=4 ts=4
 */
<commit_msg>Handle NULL in global.var_dump().<commit_after>/*
  +----------------------------------------------------------------------+
  | PHP Version 5                                                        |
  +----------------------------------------------------------------------+
  | Copyright (c) 1997-2013 The PHP Group                                |
  +----------------------------------------------------------------------+
  | http://www.opensource.org/licenses/mit-license.php  MIT License      |
  +----------------------------------------------------------------------+
  | Author: Jani Taskinen <jani.taskinen@iki.fi>                         |
  | Author: Patrick Reilly <preilly@php.net>                             |
  +----------------------------------------------------------------------+
*/

/* $Id$ */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php_v8js_macros.h"

extern "C" {
#include "zend_exceptions.h"
}

/* Forward declarations */
void php_v8js_commonjs_normalise_identifier(char *base, char *identifier, char *normalised_path, char *module_name);

/* global.exit - terminate execution */
V8JS_METHOD(exit) /* {{{ */
{
	v8::V8::TerminateExecution();
}
/* }}} */

/* global.sleep - sleep for passed seconds */
V8JS_METHOD(sleep) /* {{{ */
{
	php_sleep(info[0]->Int32Value());
}
/* }}} */

/* global.print - php print() */
V8JS_METHOD(print) /* {{{ */
{
	int ret = 0;
	TSRMLS_FETCH();

	for (int i = 0; i < info.Length(); i++) {
		v8::String::Utf8Value str(info[i]);
		const char *cstr = ToCString(str);
		ret = PHPWRITE(cstr, strlen(cstr));
	}
	info.GetReturnValue().Set(V8JS_INT(ret));
}
/* }}} */

static void _php_v8js_dumper(v8::Local<v8::Value> var, int level TSRMLS_DC) /* {{{ */
{
	if (level > 1) {
		php_printf("%*c", (level - 1) * 2, ' ');
	}

	if (var->IsNull())
	{
		php_printf("NULL\n");
		return;
	}

	v8::String::Utf8Value str(var->ToDetailString());
	const char *valstr = ToCString(str);
	size_t valstr_len = (valstr) ? strlen(valstr) : 0;

	if (var->IsString())
	{
		php_printf("string(%zu) \"%s\"\n", valstr_len, valstr);
	}
	else if (var->IsBoolean())
	{
		php_printf("bool(%s)\n", valstr);
	}
	else if (var->IsInt32() || var->IsUint32())
	{
		php_printf("int(%s)\n", valstr);
	}
	else if (var->IsNumber())
	{
		php_printf("float(%s)\n", valstr);
	}
	else if (var->IsDate())
	{
		php_printf("Date(%s)\n", valstr);
	}
#if PHP_V8_API_VERSION >= 2003007
	else if (var->IsRegExp())
	{
		php_printf("RegExp(%s)\n", valstr);
	}
#endif
	else if (var->IsArray())
	{
		v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(var);
		uint32_t length = array->Length();

		php_printf("array(%d) {\n", length);

		for (unsigned i = 0; i < length; i++) {
			php_printf("%*c[%d] =>\n", level * 2, ' ', i);
			_php_v8js_dumper(array->Get(i), level + 1 TSRMLS_CC);
		}

		if (level > 1) {
			php_printf("%*c", (level - 1) * 2, ' ');
		}

		ZEND_PUTS("}\n");
	}
	else if (var->IsObject())
	{
		v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(var);
		V8JS_GET_CLASS_NAME(cname, object);

		if (var->IsFunction())
		{
			v8::String::Utf8Value csource(object->ToString());
			php_printf("object(%s)#%d {\n%*c%s\n", ToCString(cname), object->GetIdentityHash(), level * 2 + 2, ' ', ToCString(csource));
		}
		else
		{
			v8::Local<v8::Array> keys = object->GetPropertyNames();
			uint32_t length = keys->Length();

			php_printf("object(%s)#%d (%d) {\n", ToCString(cname), object->GetIdentityHash(), length);

			for (unsigned i = 0; i < length; i++) {
				v8::Local<v8::String> key = keys->Get(i)->ToString();
				v8::String::Utf8Value kname(key);
				php_printf("%*c[\"%s\"] =>\n", level * 2, ' ', ToCString(kname));
				_php_v8js_dumper(object->Get(key), level + 1 TSRMLS_CC);
			}
		}

		if (level > 1) {
			php_printf("%*c", (level - 1) * 2, ' ');
		}

		ZEND_PUTS("}\n");
	}
	else /* null, undefined, etc. */
	{
		php_printf("<%s>\n", valstr);
	}
}
/* }}} */

/* global.var_dump - Dump JS values */
V8JS_METHOD(var_dump) /* {{{ */
{
	TSRMLS_FETCH();

	for (int i = 0; i < info.Length(); i++) {
		_php_v8js_dumper(info[i], 1 TSRMLS_CC);
	}

	info.GetReturnValue().Set(V8JS_NULL);
}
/* }}} */

V8JS_METHOD(require)
{
	TSRMLS_FETCH();

	// Get the extension context
	v8::Handle<v8::External> data = v8::Handle<v8::External>::Cast(info.Data());
	php_v8js_ctx *c = static_cast<php_v8js_ctx*>(data->Value());

	// Check that we have a module loader
	if (c->module_loader == NULL) {
		info.GetReturnValue().Set(v8::ThrowException(v8::String::New("No module loader")));
		return;
	}

	v8::String::Utf8Value module_id_v8(info[0]);

	// Make sure to duplicate the module name string so it doesn't get freed by the V8 garbage collector
	char *module_id = estrdup(ToCString(module_id_v8));
	char *normalised_path = (char *)emalloc(PATH_MAX);
	char *module_name = (char *)emalloc(PATH_MAX);

	php_v8js_commonjs_normalise_identifier(c->modules_base.back(), module_id, normalised_path, module_name);
	efree(module_id);

	char *normalised_module_id = (char *)emalloc(strlen(module_id));
	*normalised_module_id = 0;

	if (strlen(normalised_path) > 0) {
		strcat(normalised_module_id, normalised_path);
		strcat(normalised_module_id, "/");
	}

	strcat(normalised_module_id, module_name);
	efree(module_name);

	// Check for module cyclic dependencies
	for (std::vector<char *>::iterator it = c->modules_stack.begin(); it != c->modules_stack.end(); ++it)
    {
    	if (!strcmp(*it, normalised_module_id)) {
    		efree(normalised_path);

		info.GetReturnValue().Set(v8::ThrowException(v8::String::New("Module cyclic dependency")));
		return;
    	}
    }

    // If we have already loaded and cached this module then use it
	if (V8JSG(modules_loaded).count(normalised_module_id) > 0) {
		efree(normalised_path);

		info.GetReturnValue().Set(V8JSG(modules_loaded)[normalised_module_id]);
		return;
	}

	// Callback to PHP to load the module code

	zval module_code;
	zval *normalised_path_zend;

	MAKE_STD_ZVAL(normalised_path_zend);
	ZVAL_STRING(normalised_path_zend, normalised_module_id, 1);
	zval* params[] = { normalised_path_zend };

	if (FAILURE == call_user_function(EG(function_table), NULL, c->module_loader, &module_code, 1, params TSRMLS_CC)) {
		efree(normalised_path);

		info.GetReturnValue().Set(v8::ThrowException(v8::String::New("Module loader callback failed")));
		return;
	}

	// Check if an exception was thrown
	if (EG(exception)) {
		efree(normalised_path);

		// Clear the PHP exception and throw it in V8 instead
		zend_clear_exception(TSRMLS_C);
		info.GetReturnValue().Set(v8::ThrowException(v8::String::New("Module loader callback exception")));
		return;
	}

	// Convert the return value to string
	if (Z_TYPE(module_code) != IS_STRING) {
    	convert_to_string(&module_code);
	}

	// Check that some code has been returned
	if (!strlen(Z_STRVAL(module_code))) {
		efree(normalised_path);

		info.GetReturnValue().Set(v8::ThrowException(v8::String::New("Module loader callback did not return code")));
		return;
	}

	// Create a template for the global object and set the built-in global functions
	v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
	global->Set(v8::String::New("print"), v8::FunctionTemplate::New(V8JS_MN(print)), v8::ReadOnly);
	global->Set(V8JS_SYM("sleep"), v8::FunctionTemplate::New(V8JS_MN(sleep)), v8::ReadOnly);
	global->Set(v8::String::New("require"), v8::FunctionTemplate::New(V8JS_MN(require), v8::External::New(c)), v8::ReadOnly);

	// Add the exports object in which the module can return its API
	v8::Handle<v8::ObjectTemplate> exports_template = v8::ObjectTemplate::New();
	v8::Handle<v8::Object> exports = exports_template->NewInstance();
	global->Set(v8::String::New("exports"), exports);

	// Add the module object in which the module can have more fine-grained control over what it can return
	v8::Handle<v8::ObjectTemplate> module_template = v8::ObjectTemplate::New();
	v8::Handle<v8::Object> module = module_template->NewInstance();
	module->Set(v8::String::New("id"), v8::String::New(normalised_module_id));
	global->Set(v8::String::New("module"), module);

	// Each module gets its own context so different modules do not affect each other
	v8::Local<v8::Context> context = v8::Local<v8::Context>::New(c->isolate, v8::Context::New(c->isolate, NULL, global));

	// Catch JS exceptions
	v8::TryCatch try_catch;

	v8::Locker locker(c->isolate);
	v8::Isolate::Scope isolate_scope(c->isolate);

	v8::HandleScope handle_scope(c->isolate);

	// Enter the module context
	v8::Context::Scope scope(context);
	// Set script identifier
	v8::Local<v8::String> sname = V8JS_SYM("require");

	v8::Local<v8::String> source = v8::String::New(Z_STRVAL(module_code));

	// Create and compile script
	v8::Local<v8::Script> script = v8::Script::New(source, sname);

	// The script will be empty if there are compile errors
	if (script.IsEmpty()) {
		efree(normalised_path);
		info.GetReturnValue().Set(v8::ThrowException(v8::String::New("Module script compile failed")));
		return;
	}

	// Add this module and path to the stack
	c->modules_stack.push_back(normalised_module_id);

	c->modules_base.push_back(normalised_path);

	// Run script
	v8::Local<v8::Value> result = script->Run();

	// Remove this module and path from the stack
	c->modules_stack.pop_back();
	c->modules_base.pop_back();

	efree(normalised_path);

	// Script possibly terminated, return immediately
	if (!try_catch.CanContinue()) {
		info.GetReturnValue().Set(v8::ThrowException(v8::String::New("Module script compile failed")));
		return;
	}

	// Handle runtime JS exceptions
	if (try_catch.HasCaught()) {
		// Rethrow the exception back to JS
		info.GetReturnValue().Set(try_catch.ReThrow());
		return;
	}

	// Cache the module so it doesn't need to be compiled and run again
	// Ensure compatibility with CommonJS implementations such as NodeJS by playing nicely with module.exports and exports
	if (module->Has(v8::String::New("exports")) && !module->Get(v8::String::New("exports"))->IsUndefined()) {
		// If module.exports has been set then we cache this arbitrary value...
		V8JSG(modules_loaded)[normalised_module_id] = handle_scope.Close(module->Get(v8::String::New("exports"))->ToObject());
	} else {
		// ...otherwise we cache the exports object itself
		V8JSG(modules_loaded)[normalised_module_id] = handle_scope.Close(exports);
	}

	info.GetReturnValue().Set(V8JSG(modules_loaded)[normalised_module_id]);
}

void php_v8js_register_methods(v8::Handle<v8::ObjectTemplate> global, php_v8js_ctx *c) /* {{{ */
{
	global->Set(V8JS_SYM("exit"), v8::FunctionTemplate::New(V8JS_MN(exit)), v8::ReadOnly);
	global->Set(V8JS_SYM("sleep"), v8::FunctionTemplate::New(V8JS_MN(sleep)), v8::ReadOnly);
	global->Set(V8JS_SYM("print"), v8::FunctionTemplate::New(V8JS_MN(print)), v8::ReadOnly);
	global->Set(V8JS_SYM("var_dump"), v8::FunctionTemplate::New(V8JS_MN(var_dump)), v8::ReadOnly);

	c->modules_base.push_back("");
	global->Set(V8JS_SYM("require"), v8::FunctionTemplate::New(V8JS_MN(require), v8::External::New(c)), v8::ReadOnly);
}
/* }}} */

/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 * vim600: noet sw=4 ts=4 fdm=marker
 * vim<600: noet sw=4 ts=4
 */
<|endoftext|>


<commit_before>#include <iostream>

enum class Token
{
    Invalid = 0,
    Minus = 1,
    Plus = 2,
    Mul = 3,
    Div = 4,
    Number = 5,
    End = 6
};

// получение текущего токена
Token getToken(const char*& text, bool isShiftedAfterOperation = true, bool isShiftedAfterNumber = false)
{
    const  char* prev_text = text;

    while (const auto c = *text++)
    {
        switch (c) {
            case ' ':
                continue;
            case '-':
                if(!isShiftedAfterOperation)
                    text = prev_text;
                return Token::Minus;
            case '+':
                if(!isShiftedAfterOperation)
                    text = prev_text;
                return Token::Plus;
            case '/':
                if(!isShiftedAfterOperation)
                    text = prev_text;
                return Token::Div;
            case '*':
                if(!isShiftedAfterOperation)
                    text = prev_text;
                return Token::Mul;
        }

        if (c >= '0' && c <= '9') {
            for (auto c = *(text); c>= '0' && c<= '9';)
            {
                //skip digits
                ++text;
                c =  *text;
            }

            if(!isShiftedAfterNumber)
                text = prev_text;

            return Token::Number;
        }
        return Token::Invalid;
    }
    return Token ::End;
}

// вычисление числа с унарным минусом
int prim(const char*& text)
{

    bool isNegative = false;
    if(getToken(text) == Token::Minus)
    {
        isNegative = true;
    }

    int res  = 0;
    bool isNumber = false;
    for(;(*text >= '0' && *text <= '9') || *text == ' ' ; ++text)
    {
        if(*text == ' ')
            continue;

        res = res * 10 + (*text - '0');
        isNumber = true;
    }

    if(!isNumber)
        throw std::exception();

    if(isNegative)
        return -res;
    else
        return res;
}

//  вычисление терма в выражении
int term(const char*& text)
{
    int res = prim(text);

    Token tk = getToken(text);
    while (tk  == Token::Mul || tk == Token::Div)
    {
        if(tk == Token::Mul)
        {
           res *= prim(text);
        }

        if(tk == Token::Div)
        {
           res/= prim(text);
        }

        tk = getToken(text);
    }
    --text;

    return  res;
}

// сложение и вычитание термов
int expr(const char*& text)
{
    int res = term(text);

    Token tk;

    tk = getToken(text);
    for (;tk != Token::End; tk = getToken(text))
    {

          if(tk == Token::Invalid)
          {
              throw std::exception();
          }

          if(tk == Token::Plus)
          {
              res += term(text);
          }
          if(tk == Token::Minus)
          {
              res -= term(text);
          }
    }

    return  res;
}

int main(int argc, char* argv[])
{
    const char* text = "1 + 2/2 * 3 - -4*-1";

    if (argc == 1)
    {
      std::cout << "Empty input!"  << std::endl;
      return 2;
    }
    text = argv[1];

    if(getToken(text, false, false) == Token::End)
    {
       std::cout<<"Empty input!"<< std::endl;
       return 2;
    }

    try
    {
        int res = expr(text);
        std::cout<<res<<std::endl;
    }
    catch (std::exception ex)
    {
       std::cout<<"error in input!"<<std::endl;
    }

    return 0;
}
<commit_msg>hw2 update<commit_after>#include <iostream>

enum class Token
{
    Invalid = 0,
    Minus = 1,
    Plus = 2,
    Mul = 3,
    Div = 4,
    Number = 5,
    End = 6
};

// получение текущего токена
Token getToken(const char*& text, bool isShiftedAfterOperation = true, bool isShiftedAfterNumber = false)
{
    const  char* prev_text = text;

    while (const auto c = *text++)
    {
        switch (c) {
            case ' ':
                continue;
            case '-':
                if(!isShiftedAfterOperation)
                    text = prev_text;
                return Token::Minus;
            case '+':
                if(!isShiftedAfterOperation)
                    text = prev_text;
                return Token::Plus;
            case '/':
                if(!isShiftedAfterOperation)
                    text = prev_text;
                return Token::Div;
            case '*':
                if(!isShiftedAfterOperation)
                    text = prev_text;
                return Token::Mul;
        }

        if (c >= '0' && c <= '9') {
            for (auto c = *(text); c>= '0' && c<= '9';)
            {
                //skip digits
                ++text;
                c =  *text;
            }

            if(!isShiftedAfterNumber)
                text = prev_text;

            return Token::Number;
        }
        return Token::Invalid;
    }
    return Token ::End;
}

bool isNegativeNumber(const char*& text)
{
    const char* prev_text = text;

    if(getToken(text) == Token::Minus)
    {
        return true;
    }

    text = prev_text;
    return  false;
}

// вычисление числа с унарным минусом
int prim(const char*& text)
{

    bool isNegative = isNegativeNumber(text);

    int res  = 0;
    bool isNumber = false;

    for(;(*text >= '0' && *text <= '9') || *text == ' ' ; ++text)
    {
        if(*text == ' ')
            continue;

        res = res * 10 + (*text - '0');
        isNumber = true;
    }

    if(!isNumber)
        throw std::runtime_error("Error in number input!");

    if(isNegative)
        return -res;
    else
        return res;
}

//  вычисление терма в выражении
int term(const char*& text)
{
    int res = prim(text);

    Token tk = getToken(text);
    while (tk  == Token::Mul || tk == Token::Div)
    {
        if(tk == Token::Mul)
        {
           int pr = prim(text);
           res *=  pr;
        }

        if(tk == Token::Div)
        {
            int pr = prim(text);
            if(pr == 0)
            {
                throw std::runtime_error("Division by zero!");
            }

            res /=  pr;
        }

        tk = getToken(text);
    }
    --text;

    return  res;
}

// сложение и вычитание термов
int expr(const char*& text)
{
    int res = term(text);

    Token tk;

    tk = getToken(text);
    for (;tk != Token::End; tk = getToken(text))
    {

          if(tk == Token::Invalid)
          {
              throw std::runtime_error("Invalid character!");
          }

          if(tk == Token::Plus)
          {
              res += term(text);
          }
          if(tk == Token::Minus)
          {
              res -= term(text);
          }
    }

    return  res;
}

int main(int argc, char* argv[])
{
    const char* text = "";

    if (argc == 1)
    {
        std::cout << "Empty input!"  << std::endl;
        return -1;
    }
    text = argv[1];

    if(getToken(text, false, false) == Token::End)
    {
        std::cout<<"Empty input!"<< std::endl;
        return -1;
    }

    try
    {
        int res = expr(text);
        std::cout<<res<<std::endl;
    }
    catch (std::exception& ex)
    {
       std::cout<<ex.what()<<std::endl;
       return -1;
    }

    return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include "smc_compiler.h"
#include "gen.h"

using namespace std;

static void generate_state_map(state_map_t const& state_map, std::string const& package_name, std::string const& fsmclass, std::string const& class_name, std::set<string> const& action_set, transition_set_t const& transition_set);

void gen_swift(std::string const& package_name, std::string const& fsmclass, state_map_list_t const& state_map_list, std::string const& start_map, std::string const& start_state, transition_set_t const& transition_set, std::string const& class_name, std::set<string> const& action_set)
{
    string full_fsm_name = package_name + "_" + fsmclass;

    cout << "// -*- tab-width: 4; -*-\n";
    cout << "// -*- coding: utf-8 -*-\n";
    cout << "\n";
    cout << "//\n";
    cout << "// This file is automatically generated by State Machine Generator.\n";
    cout << "//\n";
    cout << "\n";

    cout
        << "import Foundation\n"
        << "\n"
        ;

    cout << "public protocol " << package_name << "_Action {\n";
    for (auto const& action : action_set) {
        cout << "    func " << action << "()\n";
    }
    cout << "}\n";

    cout << "public class " << class_name << " : " << package_name << "_Action {\n";
    for (auto const& action : action_set) {
        cout << "    public func " << action << "() {}\n";
    }
    cout << "}\n";

    cout
        << "\n"
        << "public class " << full_fsm_name << " {\n"
        << "\n"
        << "    private var currentState : " << package_name << "_ButtonStateMap_State?\n"
        << "    private var previousState : " << package_name << "_ButtonStateMap_State?\n"
        << "    public var debugMode = false\n"
        << "    let ctxt : " << class_name << "\n"
        << "\n"
        << "    public init(ctxt:" << class_name << ") {\n"
        << "        self.currentState = _" << package_name << "_" << start_map << "." << start_state << "()\n"
        << "        self.ctxt = ctxt\n"
        << "    }\n"
        << "\n"
        << "    public func enterStartState() {\n"
        << "        currentState!.Entry(self, ctxt: ctxt)\n"
        << "    }\n"
        << "\n"
        << "    private func setState(state:" << package_name << "_ButtonStateMap_State) {\n"
        << "        currentState = state;\n"
        << "        if (debugMode) {\n"
        << "            NSLog(\"ENTER STATE: %s\", state.getName())\n"
        << "        }\n"
        << "    }\n"
        ;

    for (auto&& transition_name : transition_set) {
        cout << "\n";
        cout << "    public func " << transition_name << "() {\n";
        cout << "        currentState!." << transition_name << "(self, ctxt: ctxt)\n";
        cout << "    }\n";
    }

    cout << "\n";
    cout << "}\n";
    cout << "\n";
    cout << "\n";
    cout << "\n";

    for (auto&& state_map : state_map_list) {
        generate_state_map(state_map, package_name, fsmclass, class_name, action_set, transition_set);
    }
}

static void generate_state_map(state_map_t const& state_map, std::string const& package_name, std::string const& fsmclass, std::string const& class_name, std::set<string> const& action_set, transition_set_t const& transition_set)
{
    string full_fsm_name = package_name + "_" + fsmclass;

    string const& state_map_name = package_name + "_" + state_map.get_state_map_name();
    state_list_t const& state_list = state_map.get_state_list();

    // カスタムアクションの出力とステート遷移の出力
    auto generate_transition = [&](transition_t const& transition, int indent)
    {
        intented_out out(cout, indent);

        // 遷移先のステートがある場合には Exit() を出力する。
        if ( !transition.get_next_state().empty()) {
            out << "fsm.currentState!.Exit(fsm, ctxt: ctxt)\n";
        }

        // 現在のステートをNULLにセットする。
        out << "fsm.previousState = fsm.currentState\n";

        // カスタムアクションを出力する。
        if ( !transition.get_action_list().empty()) {
            out << "fsm.currentState = nil\n";
            out << "//try {" << "\n";
            out << "// Custom action" << "\n";
        }

        for (auto const& action : transition.get_action_list()) {
            out << "ctxt." << action << "()\n";
        }

        // 次の遷移先への移動をfinally区の中に入れるかどうか
        int next_state_indent = 0;

        if ( !transition.get_action_list().empty()) {
            out << "//} finally {" << "\n";
            //next_state_indent++;
        }

        // 遷移先のステートがある場合には Entry() を出力する。
        if (transition.get_next_state().empty()) {
             out(next_state_indent) << "fsm.currentState = previousState\n";
        }
        else {
             out(next_state_indent) << "fsm.setState(" << state_map_name << "._" << transition.get_next_state() << ")\n";
             out(next_state_indent) << "fsm.currentState!.Entry(fsm, ctxt: ctxt)\n";
        }

        if ( !transition.get_action_list().empty()) {
            out << "//}" << "\n";
        }
    };

    cout << "private protocol " << state_map_name << "_State {\n";
    cout << "    func getName() -> String\n";
    cout << "    func Entry(fsm:" << full_fsm_name << ", ctxt:" << class_name << ")\n";
    cout << "    func Exit(fsm:" << full_fsm_name << ", ctxt:" << class_name << ")\n";
    for (auto&& transition_name : transition_set) {
        cout << "    func " << transition_name << "(fsm:" << full_fsm_name << ", ctxt:" << class_name << ")\n";
    }
    cout << "}\n";

    intented_out out(cout, 0);
    bool need_comma = false;
    out << "let " << state_map_name << " = _" << state_map_name << "()\n";
    cout << "\n";
    out << "public class _" << state_map_name << " {\n";
    for (auto const& state : state_list) {
        cout << "    let _" << state.get_state_name() << " = " << state.get_state_name() << "()\n";
    }

    cout << "\n";
    out(1) << "public class DefaultState : " << state_map_name << "_State {\n";
    out(2) << "public func getName() -> String { return \"DefaultState\" }\n\n";
    out(2) << "public func Entry(fsm:" << full_fsm_name << ", ctxt:" << class_name << ") {}\n";
    out(2) << "public func Exit(fsm:" << full_fsm_name << ", ctxt:" << class_name << ") {}\n";

    for (auto&& transition_name : transition_set) {
         out(2) << "public func " << transition_name << "(fsm:" << full_fsm_name << ", ctxt:" << class_name << ") {}\n";
    }
    out(1) << "}\n";
    cout << "\n";

    for (auto const& state : state_list) {
        if (need_comma) cout << "\n";

        cout << "\n";
        out(1) << "public class " << state.get_state_name() << " : DefaultState {\n";
        out(2) << "override public func getName() -> String { return \"" << state.get_state_name() << "\" }\n\n";
        out(2) << "override public func Entry(fsm:" << full_fsm_name << ", ctxt:" << class_name << ") {\n";

        for (auto&& action : state.get_entry()) {
             out(3) << "ctxt." << action << "()\n";
        }
        out(2) << "}\n";
        cout << "\n";
        out(2) << "override public func Exit(fsm:" << full_fsm_name << ", ctxt:" << class_name << ") {\n";
             ;
        for (auto const& action : state.get_exit()) {
             out(3) << "ctxt." << action << "()\n";
        }
        out(2) << "}\n";

        for (auto const& transition_name_list_pair : state.get_transitions()) {
            string const& transition_name = transition_name_list_pair.first;

            cout << "\n";
            out(2) << "override public func " << transition_name << "(fsm:" << full_fsm_name << ", ctxt:" << class_name << ") {\n";

            bool else_block = false;
            for (auto&& transition : transition_name_list_pair.second) {
                if ( !transition.get_guard().empty()) {
                    out(3) << (else_block ? "else if" : "if") << " (" << transition.get_guard() << ") {\n";

                    generate_transition(transition, 5);

                    out(3) << "}\n";
                    else_block = true;
                }
                else {
                    if (else_block) {
                        out(3) << "else {\n";
                    }

                    generate_transition(transition, else_block ? 4 : 3);

                    if (else_block) {
                        out(3) << "}\n";
                    }
                }
            }

            out(2) << "}\n";
        }

        cout << "\n";
        out(1) << "}\n"
             ;
        need_comma = true;
    }

    cout << "}" << endl;

}
<commit_msg>Swiftのコード生成を調整<commit_after>#include <iostream>
#include <string>
#include "smc_compiler.h"
#include "gen.h"

using namespace std;

static void generate_state_map(state_map_t const& state_map, std::string const& package_name, std::string const& fsmclass, std::string const& class_name, std::set<string> const& action_set, transition_set_t const& transition_set);

void gen_swift(std::string const& package_name, std::string const& fsmclass, state_map_list_t const& state_map_list, std::string const& start_map, std::string const& start_state, transition_set_t const& transition_set, std::string const& class_name, std::set<string> const& action_set)
{
    string full_fsm_name = package_name + "_" + fsmclass;

    cout << "// -*- tab-width: 4; -*-\n";
    cout << "// -*- coding: utf-8 -*-\n";
    cout << "\n";
    cout << "//\n";
    cout << "// This file is automatically generated by State Machine Generator.\n";
    cout << "//\n";
    cout << "\n";

    cout
        << "import Foundation\n"
        << "\n"
        ;

    cout << "public protocol " << package_name << "_Action {\n";
    for (auto const& action : action_set) {
        cout << "    func " << action << "()\n";
    }
    cout << "}\n";

    cout << "//public class " << class_name << " : " << package_name << "_Action {\n";
    for (auto const& action : action_set) {
        cout << "//    public func " << action << "() {}\n";
    }
    cout << "//}\n";

    cout
        << "\n"
        << "public class " << full_fsm_name << " {\n"
        << "\n"
        << "    private var currentState : " << package_name << "_ButtonStateMap_State?\n"
        << "    private var previousState : " << package_name << "_ButtonStateMap_State?\n"
        << "    public var debugMode = false\n"
        << "    let ctxt : " << class_name << "\n"
        << "\n"
        << "    public init(context:" << class_name << ") {\n"
        << "        self.currentState = _" << package_name << "_" << start_map << "._" << start_state << "\n"
        << "        self.ctxt = context\n"
        << "    }\n"
        << "\n"
        << "    public func enterStartState() {\n"
        << "        currentState!.Entry(self, ctxt: ctxt)\n"
        << "    }\n"
        << "\n"
        << "    private func setState(state:" << package_name << "_ButtonStateMap_State) {\n"
        << "        currentState = state;\n"
        << "        if (debugMode) {\n"
        << "            NSLog(\"ENTER STATE: %s\", state.getName())\n"
        << "        }\n"
        << "    }\n"
        ;

    for (auto&& transition_name : transition_set) {
        cout << "\n";
        cout << "    public func " << transition_name << "() {\n";
        cout << "        currentState!." << transition_name << "(self, ctxt: ctxt)\n";
        cout << "    }\n";
    }

    cout << "\n";
    cout << "}\n";
    cout << "\n";
    cout << "\n";
    cout << "\n";

    for (auto&& state_map : state_map_list) {
        generate_state_map(state_map, package_name, fsmclass, class_name, action_set, transition_set);
    }
}

static void generate_state_map(state_map_t const& state_map, std::string const& package_name, std::string const& fsmclass, std::string const& class_name, std::set<string> const& action_set, transition_set_t const& transition_set)
{
    string full_fsm_name = package_name + "_" + fsmclass;

    string const& state_map_name = package_name + "_" + state_map.get_state_map_name();
    state_list_t const& state_list = state_map.get_state_list();

    // カスタムアクションの出力とステート遷移の出力
    auto generate_transition = [&](transition_t const& transition, int indent)
    {
        intented_out out(cout, indent);

        // 遷移先のステートがある場合には Exit() を出力する。
        if ( !transition.get_next_state().empty()) {
            out << "fsm.currentState!.Exit(fsm, ctxt: ctxt)\n";
        }

        // 現在のステートをNULLにセットする。
        out << "fsm.previousState = fsm.currentState\n";

        // カスタムアクションを出力する。
        if ( !transition.get_action_list().empty()) {
            out << "fsm.currentState = nil\n";
            out << "//try {" << "\n";
            out << "// Custom action" << "\n";
        }

        for (auto const& action : transition.get_action_list()) {
            out << "ctxt." << action << "()\n";
        }

        // 次の遷移先への移動をfinally区の中に入れるかどうか
        int next_state_indent = 0;

        if ( !transition.get_action_list().empty()) {
            out << "//} finally {" << "\n";
            //next_state_indent++;
        }

        // 遷移先のステートがある場合には Entry() を出力する。
        if (transition.get_next_state().empty()) {
             out(next_state_indent) << "fsm.currentState = previousState\n";
        }
        else {
             out(next_state_indent) << "fsm.setState(" << state_map_name << "._" << transition.get_next_state() << ")\n";
             out(next_state_indent) << "fsm.currentState!.Entry(fsm, ctxt: ctxt)\n";
        }

        if ( !transition.get_action_list().empty()) {
            out << "//}" << "\n";
        }
    };

    cout << "private protocol " << state_map_name << "_State {\n";
    cout << "    func getName() -> String\n";
    cout << "    func Entry(fsm:" << full_fsm_name << ", ctxt:" << class_name << ")\n";
    cout << "    func Exit(fsm:" << full_fsm_name << ", ctxt:" << class_name << ")\n";
    for (auto&& transition_name : transition_set) {
        cout << "    func " << transition_name << "(fsm:" << full_fsm_name << ", ctxt:" << class_name << ")\n";
    }
    cout << "}\n";

    intented_out out(cout, 0);
    bool need_comma = false;
    out << "let " << state_map_name << " = _" << state_map_name << "()\n";
    cout << "\n";
    out << "public class _" << state_map_name << " {\n";
    for (auto const& state : state_list) {
        cout << "    let _" << state.get_state_name() << " = " << state.get_state_name() << "()\n";
    }

    cout << "\n";
    out(1) << "public class DefaultState : " << state_map_name << "_State {\n";
    out(2) << "public func getName() -> String { return \"DefaultState\" }\n\n";
    out(2) << "public func Entry(fsm:" << full_fsm_name << ", ctxt:" << class_name << ") {}\n";
    out(2) << "public func Exit(fsm:" << full_fsm_name << ", ctxt:" << class_name << ") {}\n";

    for (auto&& transition_name : transition_set) {
         out(2) << "public func " << transition_name << "(fsm:" << full_fsm_name << ", ctxt:" << class_name << ") {}\n";
    }
    out(1) << "}\n";
    cout << "\n";

    for (auto const& state : state_list) {
        if (need_comma) cout << "\n";

        cout << "\n";
        out(1) << "public class " << state.get_state_name() << " : DefaultState {\n";
        out(2) << "override public func getName() -> String { return \"" << state.get_state_name() << "\" }\n\n";
        out(2) << "override public func Entry(fsm:" << full_fsm_name << ", ctxt:" << class_name << ") {\n";

        for (auto&& action : state.get_entry()) {
             out(3) << "ctxt." << action << "()\n";
        }
        out(2) << "}\n";
        cout << "\n";
        out(2) << "override public func Exit(fsm:" << full_fsm_name << ", ctxt:" << class_name << ") {\n";
             ;
        for (auto const& action : state.get_exit()) {
             out(3) << "ctxt." << action << "()\n";
        }
        out(2) << "}\n";

        for (auto const& transition_name_list_pair : state.get_transitions()) {
            string const& transition_name = transition_name_list_pair.first;

            cout << "\n";
            out(2) << "override public func " << transition_name << "(fsm:" << full_fsm_name << ", ctxt:" << class_name << ") {\n";

            bool else_block = false;
            for (auto&& transition : transition_name_list_pair.second) {
                if ( !transition.get_guard().empty()) {
                    out(3) << (else_block ? "else if" : "if") << " (" << transition.get_guard() << ") {\n";

                    generate_transition(transition, 5);

                    out(3) << "}\n";
                    else_block = true;
                }
                else {
                    if (else_block) {
                        out(3) << "else {\n";
                    }

                    generate_transition(transition, else_block ? 4 : 3);

                    if (else_block) {
                        out(3) << "}\n";
                    }
                }
            }

            out(2) << "}\n";
        }

        cout << "\n";
        out(1) << "}\n"
             ;
        need_comma = true;
    }

    cout << "}" << endl;

}
<|endoftext|>


<commit_before>/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/**
 * Copyright (C) 2013 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * See COPYING for copyright and distribution information.
 */

#include "../c/util/crypto.h"
#include "../c/encoding/binary-xml-data.h"
#include "../encoding/binary-xml-encoder.hpp"
#include <ndn-cpp/sha256-with-rsa-signature.hpp>
#include "../util/logging.hpp"
#include <ndn-cpp/security/security-exception.hpp>
#include <ndn-cpp/security/policy/policy-manager.hpp>
#include <ndn-cpp/security/key-chain.hpp>

using namespace std;
using namespace ndn::ptr_lib;

namespace ndn {

#if 1
static uint8_t DEFAULT_PUBLIC_KEY_DER[] = {
0x30, 0x81, 0x9F, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81,
0x8D, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xE1, 0x7D, 0x30, 0xA7, 0xD8, 0x28, 0xAB, 0x1B, 0x84, 0x0B, 0x17,
0x54, 0x2D, 0xCA, 0xF6, 0x20, 0x7A, 0xFD, 0x22, 0x1E, 0x08, 0x6B, 0x2A, 0x60, 0xD1, 0x6C, 0xB7, 0xF5, 0x44, 0x48, 0xBA,
0x9F, 0x3F, 0x08, 0xBC, 0xD0, 0x99, 0xDB, 0x21, 0xDD, 0x16, 0x2A, 0x77, 0x9E, 0x61, 0xAA, 0x89, 0xEE, 0xE5, 0x54, 0xD3,
0xA4, 0x7D, 0xE2, 0x30, 0xBC, 0x7A, 0xC5, 0x90, 0xD5, 0x24, 0x06, 0x7C, 0x38, 0x98, 0xBB, 0xA6, 0xF5, 0xDC, 0x43, 0x60,
0xB8, 0x45, 0xED, 0xA4, 0x8C, 0xBD, 0x9C, 0xF1, 0x26, 0xA7, 0x23, 0x44, 0x5F, 0x0E, 0x19, 0x52, 0xD7, 0x32, 0x5A, 0x75,
0xFA, 0xF5, 0x56, 0x14, 0x4F, 0x9A, 0x98, 0xAF, 0x71, 0x86, 0xB0, 0x27, 0x86, 0x85, 0xB8, 0xE2, 0xC0, 0x8B, 0xEA, 0x87,
0x17, 0x1B, 0x4D, 0xEE, 0x58, 0x5C, 0x18, 0x28, 0x29, 0x5B, 0x53, 0x95, 0xEB, 0x4A, 0x17, 0x77, 0x9F, 0x02, 0x03, 0x01,
0x00, 01
};
#endif

KeyChain::KeyChain(const shared_ptr<IdentityManager>& identityManager, const shared_ptr<PolicyManager>& policyManager)
: identityManager_(identityManager), policyManager_(policyManager), face_(0), maxSteps_(100)
{
}

static bool
verifySignature(const Data& data /*, const Publickey& publickey */)
{
#if 0
  using namespace CryptoPP;

  Blob unsignedData(data.getSignedBlob()->signed_buf(), data.getSignedBlob()->signed_size());
  bool result = false;

  // Temporarily hardwire.  It should be assigned by Signature.getAlgorithm().
  DigestAlgorithm digestAlg = DIGEST_SHA256;
  // Temporarily hardwire.  It should be assigned by Publickey.getKeyType().
  KeyType keyType = KEY_TYPE_RSA;
  if (keyType == KEY_TYPE_RSA) {
    RSA::PublicKey pubKey;
    ByteQueue queue;

    queue.Put((const byte*)publickey.getKeyBlob ().buf (), publickey.getKeyBlob ().size ());
    pubKey.Load(queue);

    if (DIGEST_SHA256 == digestAlg) {
      Ptr<const signature::Sha256WithRsa> sigPtr = boost::dynamic_pointer_cast<const signature::Sha256WithRsa> (data.getSignature());
      const Blob & sigBits = sigPtr->getSignatureBits();

      RSASS<PKCS1v15, SHA256>::Verifier verifier (pubKey);
      result = verifier.VerifyMessage((const byte*) unsignedData.buf(), unsignedData.size(), (const byte*)sigBits.buf(), sigBits.size());
      _LOG_DEBUG("Signature verified? " << data.getName() << " " << boolalpha << result);
    }
  }

 return result;
#else
  const Sha256WithRsaSignature *signature = dynamic_cast<const Sha256WithRsaSignature*>(data.getSignature());
  if (!signature)
    throw SecurityException("signature is not Sha256WithRsaSignature.");

  if (signature->getDigestAlgorithm().size() != 0)
    // TODO: Allow a non-default digest algorithm.
    throw UnrecognizedDigestAlgorithmException("Cannot verify a data packet with a non-default digest algorithm.");
  if (!data.getDefaultWireEncoding())
     data.wireEncode();
 uint8_t signedPortionDigest[SHA256_DIGEST_LENGTH];
  ndn_digestSha256(data.getDefaultWireEncoding().signedBuf(), data.getDefaultWireEncoding().signedSize(), signedPortionDigest);

  // Verify the signedPortionDigest.
  // Use a temporary pointer since d2i updates it.
  const uint8_t *derPointer = DEFAULT_PUBLIC_KEY_DER;
  RSA *publicKey = d2i_RSA_PUBKEY(NULL, &derPointer, sizeof(DEFAULT_PUBLIC_KEY_DER));
  if (!publicKey)
    throw UnrecognizedKeyFormatException("Error decoding public key in d2i_RSAPublicKey");
  int success = RSA_verify
    (NID_sha256, signedPortionDigest, sizeof(signedPortionDigest), (uint8_t *)signature->getSignature().buf(),
     signature->getSignature().size(), publicKey);
  // Free the public key before checking for success.
  RSA_free(publicKey);

  return (success == 1);
#endif
}

void
KeyChain::sign(Data& data, const Name& certificateName, WireFormat& wireFormat)
{
  identityManager_->signByCertificate(data, certificateName, wireFormat);
}

shared_ptr<Signature>
KeyChain::sign(const uint8_t* buffer, size_t bufferLength, const Name& certificateName)
{
  return identityManager_->signByCertificate(buffer, bufferLength, certificateName);
}

void
KeyChain::signByIdentity(Data& data, const Name& identityName, WireFormat& wireFormat)
{
  Name signingCertificateName;

  if (identityName.getComponentCount() == 0) {
    Name inferredIdentity = policyManager_->inferSigningIdentity(data.getName());
    if (inferredIdentity.getComponentCount() == 0)
      signingCertificateName = identityManager_->getDefaultCertificateName();
    else
      signingCertificateName = identityManager_->getDefaultCertificateNameForIdentity(inferredIdentity);
  }
  else
    signingCertificateName = identityManager_->getDefaultCertificateNameForIdentity(identityName);

  if (signingCertificateName.getComponentCount() == 0)
    throw SecurityException("No qualified certificate name found!");

  if (!policyManager_->checkSigningPolicy(data.getName(), signingCertificateName))
    throw SecurityException("Signing Cert name does not comply with signing policy");

  identityManager_->signByCertificate(data, signingCertificateName);
}

  shared_ptr<Signature>
  KeyChain::signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName)
  {
    Name signingCertificateName = identityManager_->getDefaultCertificateNameForIdentity(identityName);

    if (signingCertificateName.size() == 0)
      throw SecurityException("No qualified certificate name found!");

    return identityManager_->signByCertificate(buffer, bufferLength, signingCertificateName);
  }

void
KeyChain::verifyData
  (const shared_ptr<Data>& data, const OnVerified& onVerified, const OnVerifyFailed& onVerifyFailed, int stepCount)
{
  _LOG_TRACE("Enter Verify");

#if 0
  if (m_policyManager->requireVerify(*dataPtr))
    stepVerify(dataPtr, true, maxStep_, onVerified, onVerifyFailed);
  else if(m_policyManager->skipVerify(*dataPtr))
#else
  if (verifySignature(*data))
#endif
    onVerified(data);
  else
    onVerifyFailed(data);
}

}
<commit_msg>code style: Fix indentation for KeyChain::signByIdentity.<commit_after>/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/**
 * Copyright (C) 2013 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * See COPYING for copyright and distribution information.
 */

#include "../c/util/crypto.h"
#include "../c/encoding/binary-xml-data.h"
#include "../encoding/binary-xml-encoder.hpp"
#include <ndn-cpp/sha256-with-rsa-signature.hpp>
#include "../util/logging.hpp"
#include <ndn-cpp/security/security-exception.hpp>
#include <ndn-cpp/security/policy/policy-manager.hpp>
#include <ndn-cpp/security/key-chain.hpp>

using namespace std;
using namespace ndn::ptr_lib;

namespace ndn {

#if 1
static uint8_t DEFAULT_PUBLIC_KEY_DER[] = {
0x30, 0x81, 0x9F, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81,
0x8D, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xE1, 0x7D, 0x30, 0xA7, 0xD8, 0x28, 0xAB, 0x1B, 0x84, 0x0B, 0x17,
0x54, 0x2D, 0xCA, 0xF6, 0x20, 0x7A, 0xFD, 0x22, 0x1E, 0x08, 0x6B, 0x2A, 0x60, 0xD1, 0x6C, 0xB7, 0xF5, 0x44, 0x48, 0xBA,
0x9F, 0x3F, 0x08, 0xBC, 0xD0, 0x99, 0xDB, 0x21, 0xDD, 0x16, 0x2A, 0x77, 0x9E, 0x61, 0xAA, 0x89, 0xEE, 0xE5, 0x54, 0xD3,
0xA4, 0x7D, 0xE2, 0x30, 0xBC, 0x7A, 0xC5, 0x90, 0xD5, 0x24, 0x06, 0x7C, 0x38, 0x98, 0xBB, 0xA6, 0xF5, 0xDC, 0x43, 0x60,
0xB8, 0x45, 0xED, 0xA4, 0x8C, 0xBD, 0x9C, 0xF1, 0x26, 0xA7, 0x23, 0x44, 0x5F, 0x0E, 0x19, 0x52, 0xD7, 0x32, 0x5A, 0x75,
0xFA, 0xF5, 0x56, 0x14, 0x4F, 0x9A, 0x98, 0xAF, 0x71, 0x86, 0xB0, 0x27, 0x86, 0x85, 0xB8, 0xE2, 0xC0, 0x8B, 0xEA, 0x87,
0x17, 0x1B, 0x4D, 0xEE, 0x58, 0x5C, 0x18, 0x28, 0x29, 0x5B, 0x53, 0x95, 0xEB, 0x4A, 0x17, 0x77, 0x9F, 0x02, 0x03, 0x01,
0x00, 01
};
#endif

KeyChain::KeyChain(const shared_ptr<IdentityManager>& identityManager, const shared_ptr<PolicyManager>& policyManager)
: identityManager_(identityManager), policyManager_(policyManager), face_(0), maxSteps_(100)
{
}

static bool
verifySignature(const Data& data /*, const Publickey& publickey */)
{
#if 0
  using namespace CryptoPP;

  Blob unsignedData(data.getSignedBlob()->signed_buf(), data.getSignedBlob()->signed_size());
  bool result = false;

  // Temporarily hardwire.  It should be assigned by Signature.getAlgorithm().
  DigestAlgorithm digestAlg = DIGEST_SHA256;
  // Temporarily hardwire.  It should be assigned by Publickey.getKeyType().
  KeyType keyType = KEY_TYPE_RSA;
  if (keyType == KEY_TYPE_RSA) {
    RSA::PublicKey pubKey;
    ByteQueue queue;

    queue.Put((const byte*)publickey.getKeyBlob ().buf (), publickey.getKeyBlob ().size ());
    pubKey.Load(queue);

    if (DIGEST_SHA256 == digestAlg) {
      Ptr<const signature::Sha256WithRsa> sigPtr = boost::dynamic_pointer_cast<const signature::Sha256WithRsa> (data.getSignature());
      const Blob & sigBits = sigPtr->getSignatureBits();

      RSASS<PKCS1v15, SHA256>::Verifier verifier (pubKey);
      result = verifier.VerifyMessage((const byte*) unsignedData.buf(), unsignedData.size(), (const byte*)sigBits.buf(), sigBits.size());
      _LOG_DEBUG("Signature verified? " << data.getName() << " " << boolalpha << result);
    }
  }

 return result;
#else
  const Sha256WithRsaSignature *signature = dynamic_cast<const Sha256WithRsaSignature*>(data.getSignature());
  if (!signature)
    throw SecurityException("signature is not Sha256WithRsaSignature.");

  if (signature->getDigestAlgorithm().size() != 0)
    // TODO: Allow a non-default digest algorithm.
    throw UnrecognizedDigestAlgorithmException("Cannot verify a data packet with a non-default digest algorithm.");
  if (!data.getDefaultWireEncoding())
     data.wireEncode();
 uint8_t signedPortionDigest[SHA256_DIGEST_LENGTH];
  ndn_digestSha256(data.getDefaultWireEncoding().signedBuf(), data.getDefaultWireEncoding().signedSize(), signedPortionDigest);

  // Verify the signedPortionDigest.
  // Use a temporary pointer since d2i updates it.
  const uint8_t *derPointer = DEFAULT_PUBLIC_KEY_DER;
  RSA *publicKey = d2i_RSA_PUBKEY(NULL, &derPointer, sizeof(DEFAULT_PUBLIC_KEY_DER));
  if (!publicKey)
    throw UnrecognizedKeyFormatException("Error decoding public key in d2i_RSAPublicKey");
  int success = RSA_verify
    (NID_sha256, signedPortionDigest, sizeof(signedPortionDigest), (uint8_t *)signature->getSignature().buf(),
     signature->getSignature().size(), publicKey);
  // Free the public key before checking for success.
  RSA_free(publicKey);

  return (success == 1);
#endif
}

void
KeyChain::sign(Data& data, const Name& certificateName, WireFormat& wireFormat)
{
  identityManager_->signByCertificate(data, certificateName, wireFormat);
}

shared_ptr<Signature>
KeyChain::sign(const uint8_t* buffer, size_t bufferLength, const Name& certificateName)
{
  return identityManager_->signByCertificate(buffer, bufferLength, certificateName);
}

void
KeyChain::signByIdentity(Data& data, const Name& identityName, WireFormat& wireFormat)
{
  Name signingCertificateName;

  if (identityName.getComponentCount() == 0) {
    Name inferredIdentity = policyManager_->inferSigningIdentity(data.getName());
    if (inferredIdentity.getComponentCount() == 0)
      signingCertificateName = identityManager_->getDefaultCertificateName();
    else
      signingCertificateName = identityManager_->getDefaultCertificateNameForIdentity(inferredIdentity);
  }
  else
    signingCertificateName = identityManager_->getDefaultCertificateNameForIdentity(identityName);

  if (signingCertificateName.getComponentCount() == 0)
    throw SecurityException("No qualified certificate name found!");

  if (!policyManager_->checkSigningPolicy(data.getName(), signingCertificateName))
    throw SecurityException("Signing Cert name does not comply with signing policy");

  identityManager_->signByCertificate(data, signingCertificateName);
}

shared_ptr<Signature>
KeyChain::signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName)
{
  Name signingCertificateName = identityManager_->getDefaultCertificateNameForIdentity(identityName);

  if (signingCertificateName.size() == 0)
    throw SecurityException("No qualified certificate name found!");

  return identityManager_->signByCertificate(buffer, bufferLength, signingCertificateName);
}

void
KeyChain::verifyData
  (const shared_ptr<Data>& data, const OnVerified& onVerified, const OnVerifyFailed& onVerifyFailed, int stepCount)
{
  _LOG_TRACE("Enter Verify");

#if 0
  if (m_policyManager->requireVerify(*dataPtr))
    stepVerify(dataPtr, true, maxStep_, onVerified, onVerifyFailed);
  else if(m_policyManager->skipVerify(*dataPtr))
#else
  if (verifySignature(*data))
#endif
    onVerified(data);
  else
    onVerifyFailed(data);
}

}
<|endoftext|>


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

#include "QUECTEL_BC95_CellularNetwork.h"

using namespace mbed;

QUECTEL_BC95_CellularNetwork::QUECTEL_BC95_CellularNetwork(ATHandler &atHandler) : AT_CellularNetwork(atHandler)
{
    _op_act = RAT_NB1;
}

QUECTEL_BC95_CellularNetwork::~QUECTEL_BC95_CellularNetwork()
{
}

AT_CellularNetwork::RegistrationMode QUECTEL_BC95_CellularNetwork::has_registration(RegistrationType reg_tech)
{
    return (reg_tech == C_EREG) ? RegistrationModeLAC : RegistrationModeDisable;
}

nsapi_error_t QUECTEL_BC95_CellularNetwork::set_access_technology_impl(RadioAccessTechnology opRat)
{
    if (opRat != RAT_NB1) {
        //TODO: Set as unknown or force to NB1?
        _op_act = RAT_UNKNOWN;
        return NSAPI_ERROR_UNSUPPORTED;
    }

    return NSAPI_ERROR_OK;
}
<commit_msg>Cellular: Fixed bc95 to accept only RAT_NB1 as it's only valid rat that modem supports.<commit_after>/*
 * Copyright (c) 2017, Arm Limited and affiliates.
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "QUECTEL_BC95_CellularNetwork.h"

using namespace mbed;

QUECTEL_BC95_CellularNetwork::QUECTEL_BC95_CellularNetwork(ATHandler &atHandler) : AT_CellularNetwork(atHandler)
{
    _op_act = RAT_NB1;
}

QUECTEL_BC95_CellularNetwork::~QUECTEL_BC95_CellularNetwork()
{
}

AT_CellularNetwork::RegistrationMode QUECTEL_BC95_CellularNetwork::has_registration(RegistrationType reg_tech)
{
    return (reg_tech == C_EREG) ? RegistrationModeLAC : RegistrationModeDisable;
}

nsapi_error_t QUECTEL_BC95_CellularNetwork::set_access_technology_impl(RadioAccessTechnology opRat)
{
    if (opRat != RAT_NB1) {
        // only rat that is supported by this modem
        _op_act = RAT_NB1;
        return NSAPI_ERROR_UNSUPPORTED;
    }

    return NSAPI_ERROR_OK;
}
<|endoftext|>


<commit_before>// Copyright (c) Timur Iskhakov.
// Distributed under the terms of the MIT License.

#include "core.hpp"

#include <algorithm>
#include <stdexcept>

template <class Real>
std::vector<Real> linear_system(const Matrix<Real> &M, const std::vector<Real> &b) {
    return lu_decomposition(M, b);
}

class LinearSystemException : public std::exception {
	virtual const char* what() const noexcept = 0;
};

class LinearSystemInfiniteSolutions : public LinearSystemException {
	const char* what() const noexcept override { return "infinite solutions"; }
};

class LinearSystemNoSolutions : public LinearSystemException {
	const char* what() const noexcept override { return "no solutions"; }
};

template <class ForwardIt>
ForwardIt max_absolute_element(ForwardIt, ForwardIt);

template <class Real>
std::vector<Real> solve_upper_triangular(const Matrix<Real> &M, const std::vector<Real> &b) {
    if (M.size() != b.size()) {
        throw std::invalid_argument("solve_upper_triangular: matrix size is not equal to vector");
    }

    size_t n = M.row_size();
    std::vector<Real> ret(n);

    for (ssize_t pos = n - 1; pos >= 0; --pos) {
        ret[pos] = b[pos];
        for (size_t i = pos + 1; i != n; ++i) {
            ret[pos] -= M[pos][i] * ret[i];
        }
        ret[pos] /= M[pos][pos];
    }

    return ret;
}

template <class Real>
std::vector<Real> solve_lower_triangular(const Matrix<Real> &_M, const std::vector<Real> &_b) {
    if (_M.size() != _b.size()) {
        throw std::invalid_argument("solve_lower_triangular: matrix size is not equal to vector");
    }

    auto M = _M;
    auto b = _b;

    std::reverse(M.matrix.begin(), M.matrix.end());
    for (auto &row : M.matrix) {
        std::reverse(row.begin(), row.end());
    }

    std::reverse(b.begin(), b.end());
    auto ret = solve_upper_triangular(M, b);
    std::reverse(ret.begin(), ret.end());

    return ret;
}

template <class Real>
bool is_linear_dependent(const std::vector<Real> &a, const std::vector<Real> &b) {
    if (a.size() != b.size()) {
        throw std::invalid_argument("is_linear_dependent vectors have different sizes");
    }

    for (size_t i = 1; i != a.size(); ++i) {
        if (!equal(a[i] * b[0], a[0] * b[i])) {
            return false;
        }
    }
    return true;
}

template <class Real>
void build_linear_basis(Matrix<Real> &M, std::vector<Real> &b) {
    if (M.size() != b.size()) {
        throw std::invalid_argument("build_linear_basis: matrix row size is not equal to vector");
    }

    size_t end = M.size();
    for (size_t i = 0; i != end; ++i) {
        for (size_t j = 0; j != i; ++j) {
            if (is_linear_dependent(M.get_row(i), M.get_row(j))) {
                if (!equal(b[i] * M[j][0], b[j] * M[i][0])) {
                    throw LinearSystemNoSolutions();
                }

                std::swap(M[i], M[end - 1]);
                std::swap(b[i], b[end - 1]);
                --end;
                --i;
                break;
            }
        }
    }
}

template <class Real>
std::vector<Real> gaussian_elimination(const Matrix<Real> &_M, const std::vector<Real> &_b) {
	if (_M.size() != _b.size()) {
		throw std::invalid_argument("gaussian_elimination: matrix size is not equal to vector");
	}

    auto M = _M;
    auto b = _b;

    build_linear_basis(M, b);

    size_t n = M.row_size();

    if (M.size() < n) {
        throw LinearSystemInfiniteSolutions();
    }

    for (size_t pos = 0; pos != n; ++pos) {
		auto column = M.get_column(pos);
        auto next = max_absolute_element(column.begin() + pos, column.end());
        if (equal(*next)) {
            throw LinearSystemInfiniteSolutions();
        }

        std::swap(M[next - column.begin()], M[pos]);
        std::swap(b[next - column.begin()], b[pos]);

        for (size_t i = pos + 1; i != n; ++i) {
            if (equal(M[i][pos])) {
                continue;
            }

            Real coef = M[i][pos] / M[pos][pos];

            M[i][pos] = 0.0;
            for (size_t j = pos + 1; j != n; ++j) {
                M[i][j] -= coef * M[pos][j];
            }
            b[i] -= coef * b[pos];
        }
    }

    return solve_upper_triangular(M, b);
}

template <class Real>
std::vector<Real> lu_decomposition(const Matrix<Real> &_M, const std::vector<Real> &_b) {
    if (_M.size() != _b.size()) {
        throw std::invalid_argument("lu_decomposition: matrix size is not equal to vector");
    }

    auto M = _M;
    auto b = _b;

    build_linear_basis(M, b);

    size_t n = M.row_size();

    if (M.size() < n) {
        throw LinearSystemInfiniteSolutions();
    }

    Matrix<Real> L(n, n), U(n, n);

    for (size_t pos = 0; pos != n; ++pos) {
        L[pos][pos] = 1.0;

        auto column = M.get_column(pos);
        auto next = max_absolute_element(column.begin() + pos, column.end());
        std::swap(M[next - column.begin()], M[pos]);
        std::swap(b[next - column.begin()], b[pos]);

        for (size_t i = 0; i != pos + 1; ++i) {
            U[i][pos] = M[i][pos];
            for (size_t j = 0; j != i; ++j) {
                U[i][pos] -= U[j][pos] * L[i][j];
            }

        }
        if (equal(U[pos][pos])) {
            throw LinearSystemInfiniteSolutions();
        }

        for (size_t i = pos; i != n; ++i) {
            L[i][pos] = M[i][pos];
            for (size_t j = 0; j != pos; ++j) {
                L[i][pos] -= U[j][pos] * L[i][j];
            }
            L[i][pos] /= U[pos][pos];
        }
        if (equal(L[pos][pos])) {
            throw LinearSystemInfiniteSolutions();
        }
    }

    auto sub_b = std::vector<Real>(b.begin(), b.begin() + n);
    return solve_upper_triangular(U, solve_lower_triangular(L, sub_b));
}

template <class Real>
std::vector<Real> tridiagonal_thomas(
    const std::vector<Real> &A,
    const std::vector<Real> &C,
    const std::vector<Real> &B,
    const std::vector<Real> &F)
{
    if (A.size() != C.size() || A.size() != B.size() || A.size() != F.size()) {
        throw std::invalid_argument("tridiagonal_thomas: invalid tridiagonal argument sizes");
    }

    size_t n = A.size();

    std::vector<Real> alpha(n), beta(n);
    alpha[0] = 0.0;
    beta[0] = 0.0;

    Real z;
    for (size_t i = 1; i != n; ++i) {
        z = (A[i - 1] * alpha[i - 1] + C[i - 1]);
        alpha[i] = -B[i - 1] / z;
        beta[i] = (F[i - 1] - A[i - 1] * beta[i - 1]) / z;
    }

    std::vector<Real> ret(n);
    ret[n - 1] = (F[n - 1] - A[n - 1] * beta[n - 1]) / (C[n - 1] + A[n - 1] * alpha[n - 1]);

    for (ssize_t i = n - 2; i >= 0; --i) {
        ret[i] = alpha[i + 1] * ret[i + 1] + beta[i + 1];
    }

    return ret;
}

template <class ForwardIt>
ForwardIt max_absolute_element(ForwardIt begin, ForwardIt end) {
    ForwardIt ret = begin;

    for (auto it = begin; it != end; ++it) {
        if (abs(*it) > abs(*ret)) {
            ret = it;
        }
    }

    return ret;
}

template std::vector<double> linear_system(const Matrix<double> &, const std::vector<double> &);
template std::vector<double> gaussian_elimination(const Matrix<double> &, const std::vector<double> &);
template std::vector<double> lu_decomposition(const Matrix<double> &, const std::vector<double> &);
template std::vector<double> tridiagonal_thomas(const std::vector<double> &, const std::vector<double> &,
    const std::vector<double> &, const std::vector<double> &);
<commit_msg>linear system bug fixed<commit_after>// Copyright (c) Timur Iskhakov.
// Distributed under the terms of the MIT License.

#include "core.hpp"

#include <algorithm>
#include <stdexcept>

template <class Real>
std::vector<Real> linear_system(const Matrix<Real> &M, const std::vector<Real> &b) {
    return lu_decomposition(M, b);
}

class LinearSystemException : public std::exception {
	virtual const char* what() const noexcept = 0;
};

class LinearSystemInfiniteSolutions : public LinearSystemException {
	const char* what() const noexcept override { return "infinite solutions"; }
};

class LinearSystemNoSolution : public LinearSystemException {
	const char* what() const noexcept override { return "no solution"; }
};

template <class ForwardIt>
ForwardIt max_absolute_element(ForwardIt, ForwardIt);

template <class Real>
std::vector<Real> solve_upper_triangular(const Matrix<Real> &M, const std::vector<Real> &b) {
    if (M.size() != b.size()) {
        throw std::invalid_argument("solve_upper_triangular: matrix size is not equal to vector");
    }

    size_t n = M.row_size();
    std::vector<Real> ret(n);

    for (ssize_t pos = n - 1; pos >= 0; --pos) {
        ret[pos] = b[pos];
        for (size_t i = pos + 1; i != n; ++i) {
            ret[pos] -= M[pos][i] * ret[i];
        }
        ret[pos] /= M[pos][pos];
    }

    return ret;
}

template <class Real>
std::vector<Real> solve_lower_triangular(const Matrix<Real> &_M, const std::vector<Real> &_b) {
    if (_M.size() != _b.size()) {
        throw std::invalid_argument("solve_lower_triangular: matrix size is not equal to vector");
    }

    auto M = _M;
    auto b = _b;

    std::reverse(M.matrix.begin(), M.matrix.end());
    for (auto &row : M.matrix) {
        std::reverse(row.begin(), row.end());
    }

    std::reverse(b.begin(), b.end());
    auto ret = solve_upper_triangular(M, b);
    std::reverse(ret.begin(), ret.end());

    return ret;
}

template <class Real>
std::vector<Real> gaussian_elimination(const Matrix<Real> &_M, const std::vector<Real> &_b) {
	if (_M.size() != _b.size()) {
		throw std::invalid_argument("gaussian_elimination: matrix size is not equal to vector");
	}

    auto M = _M;
    auto b = _b;

    size_t n = M.row_size(), m = M.size();

    if (M.size() < n) {
        throw LinearSystemInfiniteSolutions();
    }

    for (size_t pos = 0; pos != n; ++pos) {
		auto column = M.get_column(pos);
        auto next = max_absolute_element(column.begin() + pos, column.end());
        if (equal(*next)) {
            throw LinearSystemInfiniteSolutions();
        }

        std::swap(M[next - column.begin()], M[pos]);
        std::swap(b[next - column.begin()], b[pos]);

        for (size_t i = pos + 1; i != m; ++i) {
            if (equal(M[i][pos])) {
                continue;
            }

            Real coef = M[i][pos] / M[pos][pos];

            M[i][pos] = 0.0;
            for (size_t j = pos + 1; j != n; ++j) {
                M[i][j] -= coef * M[pos][j];
            }
            b[i] -= coef * b[pos];
        }
    }

    for (size_t i = n; i != m; ++i) {
        if (!equal(b[i])) {
            throw LinearSystemNoSolution();
        }
    }

    return solve_upper_triangular(M, b);
}

template <class Real>
std::vector<Real> lu_decomposition(const Matrix<Real> &_M, const std::vector<Real> &_b) {
    if (_M.size() != _b.size()) {
        throw std::invalid_argument("lu_decomposition: matrix size is not equal to vector");
    }

    if (_M.size() != _M.row_size()) {
        throw std::invalid_argument("lu_decomposition: only square matices are supported");
    }

    auto M = _M;
    auto b = _b;

    size_t n = M.row_size();

    Matrix<Real> L(n, n), U(n, n);

    for (size_t pos = 0; pos != n; ++pos) {
        auto column = M.get_column(pos);
        auto next = max_absolute_element(column.begin() + pos, column.end());
        std::swap(M[next - column.begin()], M[pos]);
        std::swap(b[next - column.begin()], b[pos]);
    }

    for (size_t pos = 0; pos != n; ++pos) {
        L[pos][pos] = 1.0;

        for (size_t i = 0; i != pos + 1; ++i) {
            U[i][pos] = M[i][pos];
            for (size_t j = 0; j != i; ++j) {
                U[i][pos] -= U[j][pos] * L[i][j];
            }
        }
        if (equal(U[pos][pos])) {
            throw LinearSystemInfiniteSolutions();
        }

        for (size_t i = pos; i != n; ++i) {
            L[i][pos] = M[i][pos];
            for (size_t j = 0; j != pos; ++j) {
                L[i][pos] -= U[j][pos] * L[i][j];
            }
            L[i][pos] /= U[pos][pos];
        }
    }

    auto sub_b = std::vector<Real>(b.begin(), b.begin() + n);
    return solve_upper_triangular(U, solve_lower_triangular(L, sub_b));
}

template <class Real>
std::vector<Real> tridiagonal_thomas(
    const std::vector<Real> &A,
    const std::vector<Real> &C,
    const std::vector<Real> &B,
    const std::vector<Real> &F)
{
    if (A.size() != C.size() || A.size() != B.size() || A.size() != F.size()) {
        throw std::invalid_argument("tridiagonal_thomas: invalid tridiagonal argument sizes");
    }

    size_t n = A.size();

    std::vector<Real> alpha(n), beta(n);
    alpha[0] = 0.0;
    beta[0] = 0.0;

    Real z;
    for (size_t i = 1; i != n; ++i) {
        z = (A[i - 1] * alpha[i - 1] + C[i - 1]);
        alpha[i] = -B[i - 1] / z;
        beta[i] = (F[i - 1] - A[i - 1] * beta[i - 1]) / z;
    }

    std::vector<Real> ret(n);
    ret[n - 1] = (F[n - 1] - A[n - 1] * beta[n - 1]) / (C[n - 1] + A[n - 1] * alpha[n - 1]);

    for (ssize_t i = n - 2; i >= 0; --i) {
        ret[i] = alpha[i + 1] * ret[i + 1] + beta[i + 1];
    }

    return ret;
}

template <class ForwardIt>
ForwardIt max_absolute_element(ForwardIt begin, ForwardIt end) {
    ForwardIt ret = begin;

    for (auto it = begin; it != end; ++it) {
        if (abs(*it) > abs(*ret)) {
            ret = it;
        }
    }

    return ret;
}

template std::vector<double> linear_system(const Matrix<double> &, const std::vector<double> &);
template std::vector<double> gaussian_elimination(const Matrix<double> &, const std::vector<double> &);
template std::vector<double> lu_decomposition(const Matrix<double> &, const std::vector<double> &);
template std::vector<double> tridiagonal_thomas(const std::vector<double> &, const std::vector<double> &,
    const std::vector<double> &, const std::vector<double> &);
<|endoftext|>


<commit_before>// Copyright (c) Timur Iskhakov.
// Distributed under the terms of the MIT License.

#include "core.hpp"

#include <algorithm>
#include <stdexcept>

template <class Real>
std::vector<Real> linear_system(const Matrix<Real> &M, const std::vector<Real> &b) {
    return lu_decomposition(M, b);
}

class LinearSystemException : public std::exception {
	virtual const char* what() const noexcept = 0;
};

class LinearSystemInfiniteSolutions : public LinearSystemException {
	const char* what() const noexcept override { return "infinite solutions"; }
};

class LinearSystemNoSolution : public LinearSystemException {
	const char* what() const noexcept override { return "no solution"; }
};

template <class ForwardIt>
ForwardIt max_absolute_element(ForwardIt, ForwardIt);

template <class Real>
std::vector<Real> solve_upper_triangular(const Matrix<Real> &M, const std::vector<Real> &b) {
    if (M.size() != b.size()) {
        throw std::invalid_argument("solve_upper_triangular: matrix size is not equal to vector");
    }

    size_t n = M.row_size();
    std::vector<Real> ret(n);

    for (ssize_t pos = n - 1; pos >= 0; --pos) {
        ret[pos] = b[pos];
        for (size_t i = pos + 1; i != n; ++i) {
            ret[pos] -= M[pos][i] * ret[i];
        }
        ret[pos] /= M[pos][pos];
    }

    return ret;
}

template <class Real>
std::vector<Real> solve_lower_triangular(const Matrix<Real> &_M, const std::vector<Real> &_b) {
    if (_M.size() != _b.size()) {
        throw std::invalid_argument("solve_lower_triangular: matrix size is not equal to vector");
    }

    auto M = _M;
    auto b = _b;

    std::reverse(M.matrix.begin(), M.matrix.end());
    for (auto &row : M.matrix) {
        std::reverse(row.begin(), row.end());
    }

    std::reverse(b.begin(), b.end());
    auto ret = solve_upper_triangular(M, b);
    std::reverse(ret.begin(), ret.end());

    return ret;
}

template <class Real>
std::vector<Real> gaussian_elimination(const Matrix<Real> &_M, const std::vector<Real> &_b) {
	if (_M.size() != _b.size()) {
		throw std::invalid_argument("gaussian_elimination: matrix size is not equal to vector");
	}

    auto M = _M;
    auto b = _b;

    size_t n = M.row_size(), m = M.size();

    if (M.size() < n) {
        throw LinearSystemInfiniteSolutions();
    }

    for (size_t pos = 0; pos != n; ++pos) {
		auto column = M.get_column(pos);
        auto next = max_absolute_element(column.begin() + pos, column.end());
        if (equal(*next)) {
            throw LinearSystemInfiniteSolutions();
        }

        std::swap(M[next - column.begin()], M[pos]);
        std::swap(b[next - column.begin()], b[pos]);

        for (size_t i = pos + 1; i != m; ++i) {
            if (equal(M[i][pos])) {
                continue;
            }

            Real coef = M[i][pos] / M[pos][pos];

            M[i][pos] = 0.0;
            for (size_t j = pos + 1; j != n; ++j) {
                M[i][j] -= coef * M[pos][j];
            }
            b[i] -= coef * b[pos];
        }
    }

    for (size_t i = n; i != m; ++i) {
        if (!equal(b[i])) {
            throw LinearSystemNoSolution();
        }
    }

    return solve_upper_triangular(M, b);
}

template <class Real>
std::vector<Real> lu_decomposition(const Matrix<Real> &_M, const std::vector<Real> &_b) {
    if (_M.size() != _b.size()) {
        throw std::invalid_argument("lu_decomposition: matrix size is not equal to vector");
    }

    if (_M.size() != _M.row_size()) {
        throw std::invalid_argument("lu_decomposition: only square matices are supported");
    }

    auto M = _M;
    auto b = _b;

    size_t n = M.row_size();

    Matrix<Real> L(n, n), U(n, n);

    for (size_t pos = 0; pos != n; ++pos) {
        auto column = M.get_column(pos);
        auto next = max_absolute_element(column.begin() + pos, column.end());
        std::swap(M[next - column.begin()], M[pos]);
        std::swap(b[next - column.begin()], b[pos]);
    }

    for (size_t pos = 0; pos != n; ++pos) {
        L[pos][pos] = 1.0;

        for (size_t i = 0; i != pos + 1; ++i) {
            U[i][pos] = M[i][pos];
            for (size_t j = 0; j != i; ++j) {
                U[i][pos] -= U[j][pos] * L[i][j];
            }
        }
        if (equal(U[pos][pos])) {
            throw LinearSystemInfiniteSolutions();
        }

        for (size_t i = pos; i != n; ++i) {
            L[i][pos] = M[i][pos];
            for (size_t j = 0; j != pos; ++j) {
                L[i][pos] -= U[j][pos] * L[i][j];
            }
            L[i][pos] /= U[pos][pos];
        }
    }

    auto sub_b = std::vector<Real>(b.begin(), b.begin() + n);
    return solve_upper_triangular(U, solve_lower_triangular(L, sub_b));
}

template <class Real>
std::vector<Real> tridiagonal_thomas(
    const std::vector<Real> &A,
    const std::vector<Real> &C,
    const std::vector<Real> &B,
    const std::vector<Real> &F)
{
    if (A.size() != C.size() || A.size() != B.size() || A.size() != F.size()) {
        throw std::invalid_argument("tridiagonal_thomas: invalid tridiagonal argument sizes");
    }

    size_t n = A.size();

    std::vector<Real> alpha(n), beta(n);
    alpha[0] = 0.0;
    beta[0] = 0.0;

    Real z;
    for (size_t i = 1; i != n; ++i) {
        z = (A[i - 1] * alpha[i - 1] + C[i - 1]);
        alpha[i] = -B[i - 1] / z;
        beta[i] = (F[i - 1] - A[i - 1] * beta[i - 1]) / z;
    }

    std::vector<Real> ret(n);
    ret[n - 1] = (F[n - 1] - A[n - 1] * beta[n - 1]) / (C[n - 1] + A[n - 1] * alpha[n - 1]);

    for (ssize_t i = n - 2; i >= 0; --i) {
        ret[i] = alpha[i + 1] * ret[i + 1] + beta[i + 1];
    }

    return ret;
}

template <class ForwardIt>
ForwardIt max_absolute_element(ForwardIt begin, ForwardIt end) {
    ForwardIt ret = begin;

    for (auto it = begin; it != end; ++it) {
        if (abs(*it) > abs(*ret)) {
            ret = it;
        }
    }

    return ret;
}

template std::vector<double> linear_system(const Matrix<double> &, const std::vector<double> &);
template std::vector<double> gaussian_elimination(const Matrix<double> &, const std::vector<double> &);
template std::vector<double> lu_decomposition(const Matrix<double> &, const std::vector<double> &);
template std::vector<double> tridiagonal_thomas(const std::vector<double> &, const std::vector<double> &,
    const std::vector<double> &, const std::vector<double> &);
<commit_msg>linear systems bug fix<commit_after>// Copyright (c) Timur Iskhakov.
// Distributed under the terms of the MIT License.

#include "core.hpp"

#include <algorithm>
#include <stdexcept>

template <class Real>
std::vector<Real> linear_system(const Matrix<Real> &M, const std::vector<Real> &b) {
    return lu_decomposition(M, b);
}

class LinearSystemException : public std::exception {
	virtual const char* what() const noexcept = 0;
};

class LinearSystemInfiniteSolutions : public LinearSystemException {
	const char* what() const noexcept override { return "infinite solutions"; }
};

class LinearSystemNoSolution : public LinearSystemException {
	const char* what() const noexcept override { return "no solution"; }
};

template <class ForwardIt>
ForwardIt max_absolute_element(ForwardIt, ForwardIt);

template <class Real>
std::vector<Real> solve_upper_triangular(const Matrix<Real> &M, const std::vector<Real> &b) {
    if (M.size() != b.size()) {
        throw std::invalid_argument("solve_upper_triangular: matrix size is not equal to vector");
    }

    size_t n = M.row_size();
    std::vector<Real> ret(n);

    for (ssize_t pos = n - 1; pos >= 0; --pos) {
        ret[pos] = b[pos];
        for (size_t i = pos + 1; i != n; ++i) {
            ret[pos] -= M[pos][i] * ret[i];
        }
        ret[pos] /= M[pos][pos];
    }

    return ret;
}

template <class Real>
std::vector<Real> solve_lower_triangular(const Matrix<Real> &_M, const std::vector<Real> &_b) {
    if (_M.size() != _b.size()) {
        throw std::invalid_argument("solve_lower_triangular: matrix size is not equal to vector");
    }

    auto M = _M;
    auto b = _b;

    std::reverse(M.matrix.begin(), M.matrix.end());
    for (auto &row : M.matrix) {
        std::reverse(row.begin(), row.end());
    }

    std::reverse(b.begin(), b.end());
    auto ret = solve_upper_triangular(M, b);
    std::reverse(ret.begin(), ret.end());

    return ret;
}

template <class Real>
std::vector<Real> gaussian_elimination(const Matrix<Real> &_M, const std::vector<Real> &_b) {
	if (_M.size() != _b.size()) {
		throw std::invalid_argument("gaussian_elimination: matrix size is not equal to vector");
	}

    auto M = _M;
    auto b = _b;

    size_t n = M.row_size(), m = M.size();

    if (M.size() < n) {
        throw LinearSystemInfiniteSolutions();
    }

    for (size_t pos = 0; pos != n; ++pos) {
		auto column = M.get_column(pos);
        auto next = max_absolute_element(column.begin() + pos, column.end());

        if (equal(*next)) {
            throw LinearSystemInfiniteSolutions();
        }

        std::swap(M[next - column.begin()], M[pos]);
        std::swap(b[next - column.begin()], b[pos]);

        for (size_t i = pos + 1; i != m; ++i) {
            if (equal(M[i][pos])) {
                continue;
            }

            Real coef = M[i][pos] / M[pos][pos];

            M[i][pos] = 0.0;
            for (size_t j = pos + 1; j != n; ++j) {
                M[i][j] -= coef * M[pos][j];
            }
            b[i] -= coef * b[pos];
        }
    }

    for (size_t i = n; i != m; ++i) {
        if (!equal(b[i])) {
            throw LinearSystemNoSolution();
        }
    }

    return solve_upper_triangular(M, b);
}

template <class Real>
void pivot_doolittle(Matrix<Real> &_M, std::vector<Real> &_b) {
    if (_M.size() != _b.size()) {
        throw std::invalid_argument("pivot_doolittle: matrix size is not equal to vector");
    }

    if (_M.size() != _M.row_size()) {
        throw std::invalid_argument("pivot_doolittle: only square matices are supported");
    }

    size_t n = _M.size();

    std::vector<size_t> perm(n);
    for (size_t i = 0; i != n; ++i) {
        perm[i] = i;
    }

    for (size_t pos = 0; pos != n; ++pos) {
        auto column = _M.get_column(pos);
        auto next = max_absolute_element(column.begin() + pos, column.end());

        if (next - column.begin() != static_cast<ssize_t>(pos)) {
            std::swap(perm[next - column.begin()], perm[pos]);
        }
    }

    auto M = _M;
    auto b = _b;

    for (size_t i = 0; i != n; ++i) {
        M[i] = _M[perm[i]];
        b[i] = _b[perm[i]];
    }

    _M = M;
    _b = b;
}

template <class Real>
std::vector<Real> lu_decomposition(const Matrix<Real> &_M, const std::vector<Real> &_b) {
    if (_M.size() != _b.size()) {
        throw std::invalid_argument("lu_decomposition: matrix size is not equal to vector");
    }

    if (_M.size() != _M.row_size()) {
        throw std::invalid_argument("lu_decomposition: only square matices are supported");
    }

    auto M = _M;
    auto b = _b;

    size_t n = M.row_size();

    Matrix<Real> L(n, n), U(n, n);
    pivot_doolittle(M, b);

    for (size_t pos = 0; pos != n; ++pos) {
        L[pos][pos] = 1.0;

        for (size_t i = 0; i != pos + 1; ++i) {
            U[i][pos] = M[i][pos];
            for (size_t j = 0; j != i; ++j) {
                U[i][pos] -= U[j][pos] * L[i][j];
            }
        }
        if (equal(U[pos][pos])) {
            throw LinearSystemInfiniteSolutions();
        }

        for (size_t i = pos; i != n; ++i) {
            L[i][pos] = M[i][pos];
            for (size_t j = 0; j != pos; ++j) {
                L[i][pos] -= U[j][pos] * L[i][j];
            }
            L[i][pos] /= U[pos][pos];
        }
    }

    return solve_upper_triangular(U, solve_lower_triangular(L, b));
}

template <class Real>
std::vector<Real> tridiagonal_thomas(
    const std::vector<Real> &A,
    const std::vector<Real> &C,
    const std::vector<Real> &B,
    const std::vector<Real> &F)
{
    if (A.size() != C.size() || A.size() != B.size() || A.size() != F.size()) {
        throw std::invalid_argument("tridiagonal_thomas: invalid tridiagonal argument sizes");
    }

    size_t n = A.size();

    std::vector<Real> alpha(n), beta(n);
    alpha[0] = 0.0;
    beta[0] = 0.0;

    Real z;
    for (size_t i = 1; i != n; ++i) {
        z = (A[i - 1] * alpha[i - 1] + C[i - 1]);
        alpha[i] = -B[i - 1] / z;
        beta[i] = (F[i - 1] - A[i - 1] * beta[i - 1]) / z;
    }

    std::vector<Real> ret(n);
    ret[n - 1] = (F[n - 1] - A[n - 1] * beta[n - 1]) / (C[n - 1] + A[n - 1] * alpha[n - 1]);

    for (ssize_t i = n - 2; i >= 0; --i) {
        ret[i] = alpha[i + 1] * ret[i + 1] + beta[i + 1];
    }

    return ret;
}

template <class ForwardIt>
ForwardIt max_absolute_element(ForwardIt begin, ForwardIt end) {
    ForwardIt ret = begin;

    for (auto it = std::next(begin); it != end; ++it) {
        if (std::abs(*it) > std::abs(*ret)) {
            ret = it;
        }
    }

    return ret;
}

template std::vector<double> linear_system(const Matrix<double> &, const std::vector<double> &);
template std::vector<double> gaussian_elimination(const Matrix<double> &, const std::vector<double> &);
template std::vector<double> lu_decomposition(const Matrix<double> &, const std::vector<double> &);
template std::vector<double> tridiagonal_thomas(const std::vector<double> &, const std::vector<double> &,
    const std::vector<double> &, const std::vector<double> &);
<|endoftext|>


<commit_before>/**
 *  Hashidsxx (c) 2014 Toon Schoenmakers
 *
 *  https://github.com/schoentoon/hashidsxx
 *  hashidsxx may be freely distributed under the MIT license.
 */

#include <getopt.h>
#include <string.h>

#include "hashids.h"

#include <iostream>
#include <list>

static const struct option g_LongOpts[] = {
  { "help", no_argument, 0, 'h' },
  { "salt", required_argument, 0, 's' },
  { "alphabet", required_argument, 0, 'a' },
  { "min", required_argument, 0, 'm' },
  { "input", required_argument, 0, 'i' },
  { 0, 0, 0, 0 }
};

static int usage(const char *prog) {
  std::cerr << "USAGE: [encode|decode]" << prog << " [options]" << std::endl
            << "-h, --help      Show this help message" << std::endl
            << "-s, --salt      The salt to use for the encryption" << std::endl
            << "-a, --alphabet  A custom alphabet to use" << std::endl
            << "-m, --min       The minimum amount of characters to use, only "
               "useful when encoding" << std::endl
            << "-i, --input     Input numbers, in case of encode repeat this "
               "for multiple input numbers" << std::endl;
  return 1;
};

int main(int argc, char **argv) {
  if (argc == 1)
    return usage(argv[0]);

  std::string salt;
  std::string alphabet(DEFAULT_ALPHABET);
  unsigned int min_length = 0;

  bool encode = (strcmp(argv[1], "encode") == 0);
  if (encode == false && strcmp(argv[1], "decode") != 0)
    return usage(argv[0]); // we must make sure we were at least decode or
                           // encode you know

  std::list<uint32_t> encode_input;
  std::string decode_input;

  int arg, optindex;
  while ((arg = getopt_long(argc, argv, "hs:a:m:i:", g_LongOpts, &optindex)) !=
         -1) {
    switch (arg) {
    case 'h':
      return usage(argv[0]);
    case 's':
      salt = std::string(optarg);
      break;
    case 'a':
      alphabet = std::string(optarg);
      break;
    case 'm':
      min_length = std::stoi(std::string(optarg));
      break;
    case 'i':
      if (encode)
        encode_input.push_back(std::stoi(std::string(optarg)));
      else
        decode_input = std::string(optarg);
      break;
    }
  }

  try {
    hashidsxx::Hashids hash(salt, min_length, alphabet);

    if (encode)
      std::cout << hash.encode(encode_input.begin(), encode_input.end())
                << std::endl;
    else {
      for (uint32_t number : hash.decode(decode_input))
        std::cout << number << std::endl;
    }
  }
  catch (const std::runtime_error &error) {
    std::cerr << error.what() << std::endl;
    return 1;
  };

  return 0;
};
<commit_msg>Added support for encode and decode hex<commit_after>/**
 *  Hashidsxx (c) 2014 Toon Schoenmakers
 *
 *  https://github.com/schoentoon/hashidsxx
 *  hashidsxx may be freely distributed under the MIT license.
 */

#include <getopt.h>
#include <string.h>

#include "hashids.h"

#include <iostream>
#include <list>

static const struct option g_LongOpts[] = {
  { "help", no_argument, 0, 'h' },
  { "salt", required_argument, 0, 's' },
  { "alphabet", required_argument, 0, 'a' },
  { "min", required_argument, 0, 'm' },
  { "input", required_argument, 0, 'i' },
  { 0, 0, 0, 0 }
};

static int usage(const char *prog) {
  std::cerr << "USAGE: [encode|decode|encodeHex|decodeHex]" << prog
            << " [options]" << std::endl
            << "-h, --help      Show this help message" << std::endl
            << "-s, --salt      The salt to use for the encryption" << std::endl
            << "-a, --alphabet  A custom alphabet to use" << std::endl
            << "-m, --min       The minimum amount of characters to use, only "
               "useful when encoding" << std::endl
            << "-i, --input     Input numbers, in case of encode repeat this "
               "for multiple input numbers" << std::endl;
  return 1;
};

int main(int argc, char **argv) {
  if (argc == 1)
    return usage(argv[0]);

  std::string salt;
  std::string alphabet(DEFAULT_ALPHABET);
  unsigned int min_length = 0;

  std::string mode(argv[1]);

  if (mode != "encode" && mode != "encodeHex" && mode != "decode" &&
      mode != "decodeHex")
    return usage(argv[0]);

  bool encode = mode.compare(0, 6, "encode") == 0;
  bool hex = mode.compare(6, 3, "Hex") == 0;

  std::list<uint32_t> encode_input;
  std::string decode_input;
  std::string hexInput;

  int arg, optindex;
  while ((arg = getopt_long(argc, argv, "hs:a:m:i:", g_LongOpts, &optindex)) !=
         -1) {
    switch (arg) {
    case 'h':
      return usage(argv[0]);
    case 's':
      salt = std::string(optarg);
      break;
    case 'a':
      alphabet = std::string(optarg);
      break;
    case 'm':
      min_length = std::stoi(std::string(optarg));
      break;
    case 'i':
      if (hex)
        hexInput = std::string(optarg);
      else if (encode)
        encode_input.push_back(std::stoi(std::string(optarg)));
      else
        decode_input = std::string(optarg);
      break;
    }
  }

  try {
    hashidsxx::Hashids hash(salt, min_length, alphabet);

    if (hex) {
      if (encode)
        std::cout << hash.encodeHex(hexInput) << std::endl;
      else
        std::cout << hash.decodeHex(hexInput) << std::endl;
    } else {
      if (encode)
        std::cout << hash.encode(encode_input.begin(), encode_input.end())
                  << std::endl;
      else {
        for (uint32_t number : hash.decode(decode_input))
          std::cout << number << std::endl;
      }
    }
  }
  catch (const std::runtime_error &error) {
    std::cerr << error.what() << std::endl;
    return 1;
  };

  return 0;
};<|endoftext|>


<commit_before>#ifndef OM_ALLOCATOR_HPP_
#define OM_ALLOCATOR_HPP_

#include <Om/AllocationSite.hpp>
#include <Om/Bytes.hpp>
#include <Om/Cell.hpp>
#include <Om/Context.hpp>
#include <Om/Heap.hpp>
#include <Om/Maybe.hpp>
#include <Om/Object.hpp>
#include <Om/RawAllocator.hpp>

namespace Om {
namespace Mm {

struct ObjectTemplate {
	Size slotCount_;
};

struct AllocationRequest {
	ObjectTemplate objectTemplate_;
};

struct Allocation {
	Maybe<Object*> object_;
};

class MemoryContext {
	// TODO(rwy0717) nothing
};

class ObjectAllocator {
public:
	template <GcSafe gcSafe = GcSafe::yes>
	inline auto allocate(Context& cx, const AllocationRequest& site) -> Maybe<Ref<Object>> {
		auto alloc = Maybe<Ref<Object>>{rawAllocator_.allocate<gcSafe>(cx, mib(32))};
	}

	inline constexpr auto raw() -> RawAllocator& {
		return rawAllocator_;
	}

private:
	RawAllocator rawAllocator_;
};

}  // namespace Mm
}  // namespace Om

#endif  // OM_ALLOCATOR_HPP_<commit_msg>Remove constexpr member in non-literal type<commit_after>#ifndef OM_ALLOCATOR_HPP_
#define OM_ALLOCATOR_HPP_

#include <Om/AllocationSite.hpp>
#include <Om/Bytes.hpp>
#include <Om/Cell.hpp>
#include <Om/Context.hpp>
#include <Om/Heap.hpp>
#include <Om/Maybe.hpp>
#include <Om/Object.hpp>
#include <Om/RawAllocator.hpp>

namespace Om {
namespace Mm {

struct ObjectTemplate {
	Size slotCount_;
};

struct AllocationRequest {
	ObjectTemplate objectTemplate_;
};

struct Allocation {
	Maybe<Object*> object_;
};

class MemoryContext {
	// TODO(rwy0717) nothing
};

class ObjectAllocator {
public:
	template <GcSafe gcSafe = GcSafe::yes>
	inline auto allocate(Context& cx, const AllocationRequest& site) -> Maybe<Ref<Object>> {
		auto alloc = Maybe<Ref<Object>>{rawAllocator_.allocate<gcSafe>(cx, mib(32))};
	}

	inline auto raw() -> RawAllocator& {
		return rawAllocator_;
	}

private:
	RawAllocator rawAllocator_;
};

}  // namespace Mm
}  // namespace Om

#endif  // OM_ALLOCATOR_HPP_<|endoftext|>