<commit_before>#include <gtksourceview/gtksourceview.h>
#include <gtksourceview/gtksource.h>
#include <cstdio>
#include <string>
#include <iostream>
#include "Gtk.hpp"
using namespace Jazz;

GtkWidget* window 	= nullptr;
GtkWidget* toolbar 	= nullptr;
GtkWidget* swin 	= nullptr;
GtkWidget* source_view 	= nullptr;
GtkWidget* hbox 	= nullptr;
GtkWidget* notebook = nullptr;
//GtkWidget* frame	= nullptr;
//GtkWidget* label	= nullptr;
int tab_num = 1;
char bufferf[32];
char bufferl[32];
GtkSourceLanguageManager* language_manager = nullptr;

struct _Data
{
   GtkTextBuffer *buffer;
   GtkWindow     *parent;
};
typedef struct _Data Data;

static void close_tab(GtkButton* button, GtkWidget* child_obj)
{
	gint pagenum = gtk_notebook_page_num(GTK_NOTEBOOK(notebook), child_obj);

	gtk_notebook_remove_page(GTK_NOTEBOOK(notebook), pagenum);
}

GtkWidget* new_tab_label(const std::string& title, GtkWidget* child_held)
{
	std::string shortname = "";
	if(title.find("\\")!=std::string::npos)
		shortname = title.substr(title.find_last_of("\\")+1);
	else
		shortname = title;
	// Create widgets that go in the new tab
	auto image = gtk_image_new_from_icon_name("window-close",GTK_ICON_SIZE_SMALL_TOOLBAR);
	auto box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
	auto tab_close_button = gtk_button_new();
	auto tab_label = gtk_label_new(shortname.c_str());
	// making close button
	gtk_button_set_relief(GTK_BUTTON(tab_close_button),GTK_RELIEF_NONE);
	gtk_button_set_focus_on_click(GTK_BUTTON(tab_close_button), false);
	gtk_button_set_image(GTK_BUTTON(tab_close_button), image);
	// pack the label on the left, and the button
	gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(tab_label), TRUE, TRUE, 0);
	gtk_box_pack_end(GTK_BOX(box), tab_close_button, TRUE, TRUE, 0);
	//
	g_signal_connect (tab_close_button, "clicked", G_CALLBACK(close_tab), child_held);//tab_label);
	// the box shows its widgets
	gtk_widget_show_all(GTK_WIDGET(box));

	return box;
}

GtkWidget* new_sourceview(bool scrollable = true)
{
	Gtk::SourceView source_view;

	if(scrollable)
	{
		Gtk::ScrolledWindow scrolled_window;

		scrolled_window.Add(source_view);
		scrolled_window.ShowAll();

		return scrolled_window.Object();
	}
	return source_view.Object();
}

static void new_file(GtkToolItem *button, void*)
{
	std::string str = "Page ";
	str += std::to_string(tab_num); //char* str = "Page";

	auto new_source_view = new_sourceview();
	auto new_tab_thing = new_tab_label(str, new_source_view);

	gtk_notebook_append_page(GTK_NOTEBOOK(notebook), new_source_view, new_tab_thing); //scrolled_win, box);//tab_label);//new_source_view, new_tab_thing);

	gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), -1);

	gtk_widget_show_all(notebook);
	//std::cout << tab_num << std::endl;
	tab_num++;
}
static void load_file(GtkToolItem *button, void*)
{
	static GtkWidget *dialog = gtk_file_chooser_dialog_new("Open File",	GTK_WINDOW(window), GTK_FILE_CHOOSER_ACTION_OPEN,
			"_Open", GTK_RESPONSE_ACCEPT, "_Cancel", GTK_RESPONSE_CANCEL, NULL);

	if( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
	{
		gchar *filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( dialog ) );
		gchar *text_data;
		printf("Open: %s\n", filename);
		g_file_get_contents( filename, &text_data, NULL, NULL );

		auto s_lang = gtk_source_language_manager_guess_language(
			language_manager,
			filename,
			nullptr);

		// the pointer is to a scrolled window containing a sourceview because we didnt pass false
		auto new_sview = new_sourceview();
		// Append new page
		auto tab_label = new_tab_label(filename, new_sview);

		auto source = gtk_bin_get_child (GTK_BIN(new_sview));

		auto buff = gtk_text_view_get_buffer(GTK_TEXT_VIEW( source ));
		gtk_text_buffer_set_text( buff, text_data, -1 );

		gtk_source_buffer_set_language(GTK_SOURCE_BUFFER(buff), s_lang);

		gtk_notebook_append_page(GTK_NOTEBOOK(notebook), new_sview, tab_label);

		gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), -1);

		gtk_widget_show_all(notebook);

		g_free( filename );
		g_free( text_data );
		tab_num++;
	}
	//gtk_widget_hide(dialog);
	gtk_widget_destroy(dialog);
}
static void save_file(GtkToolItem *button, void*)
{
	static GtkWidget *dialog = gtk_file_chooser_dialog_new("Save file", GTK_WINDOW(window), GTK_FILE_CHOOSER_ACTION_SAVE,
			"_Save", GTK_RESPONSE_ACCEPT, "_Cancel", GTK_RESPONSE_CANCEL, NULL);

	if( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
	{
		gchar *filename;
		gchar *text_data;

		Gtk::Notebook the_notebook(notebook);

		//gint page_num = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
		GtkWidget* page = the_notebook.CurrentPage().Object();//gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page_num);
		GtkWidget* label = gtk_notebook_get_tab_label(GTK_NOTEBOOK(notebook), page);

		GtkWidget* the_child = the_notebook.CurrentPage().Object();
		GtkSourceView* the_sourceview = nullptr;

		if(GTK_IS_SCROLLED_WINDOW(the_child))
			the_sourceview = GTK_SOURCE_VIEW(gtk_bin_get_child(GTK_BIN(the_child)));
		else
			the_sourceview = GTK_SOURCE_VIEW(the_child);

		Gtk::SourceView sourceview(GTK_WIDGET(the_sourceview));

		Gtk::Buffer the_buffer = sourceview.GetBuffer();

		//Gtk::Buffer the_buffer(the_notebook.CurrentPage());

		g_object_get( G_OBJECT( the_buffer.Object() ), "text",
			&text_data, NULL);

		filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER( dialog ));

		std::string filenm = filename;

		std::string shortname = filenm.substr(filenm.find_last_of("\\")+1);

		GList* children = gtk_container_get_children(GTK_CONTAINER(label));

		GList* label_child = g_list_first(children);

		gtk_label_set_text(GTK_LABEL(label_child->data), shortname.c_str()); //children->data, shortname);

		g_file_set_contents( filename, text_data, -1, NULL);
		g_free( filename );
		g_free( text_data );
	}
	//gtk_widget_hide(dialog);
	gtk_widget_destroy(dialog);
}
static void activate(GtkApplication* app, gpointer user_data)
{
	// initialize
	notebook = gtk_notebook_new();
	//data = g_slice_new(Data);
	window = gtk_application_window_new(app);
	toolbar = gtk_toolbar_new();
	hbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 1);
	//
	language_manager = gtk_source_language_manager_get_default ();
	//
	GtkToolItem* new_button = gtk_tool_button_new(nullptr, nullptr);
	gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(new_button), "document-new");
	//
	GtkToolItem* open_button = gtk_tool_button_new(nullptr, nullptr);
	gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(open_button), "document-open");
	//
	GtkToolItem* save_button = gtk_tool_button_new(nullptr, nullptr);
	gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(save_button), "document-save");
	//
	GtkToolItem* seperator = gtk_separator_tool_item_new();
	//
	GtkToolItem* compile_button = gtk_tool_button_new(nullptr, nullptr);
	gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(compile_button), "system-run");
	//
	// signal connect
	g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK( gtk_main_quit ), NULL);
	g_signal_connect (save_button, "clicked", G_CALLBACK(save_file), nullptr);
	g_signal_connect (open_button, "clicked", G_CALLBACK(load_file), nullptr);
	g_signal_connect (new_button, "clicked", G_CALLBACK(new_file), nullptr);
	// position
	gtk_box_pack_start(GTK_BOX(hbox), toolbar, FALSE, FALSE, 0);
	gtk_notebook_set_tab_pos (GTK_NOTEBOOK(notebook), GTK_POS_TOP);
	gtk_box_pack_end( GTK_BOX( hbox ), notebook, TRUE, TRUE, 0 );
	// insert toolbar items
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), new_button, -1);
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), open_button, -1);
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), save_button, -1);
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), seperator, -1);
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), compile_button, -1);
	// window set
	gtk_window_set_title(GTK_WINDOW(window), "Window");
	gtk_window_set_default_size(GTK_WINDOW(window), 600, 500);
	// connections
	gtk_container_add(GTK_CONTAINER(window), hbox);

	gtk_widget_show_all(window);
}

int main(int argc, char** argv)
{
	GtkApplication* app;

	app = gtk_application_new("ca.chr.gtk.jazz", G_APPLICATION_FLAGS_NONE);
	g_signal_connect(app, "activate", G_CALLBACK(activate), 0);
	int status = g_application_run(G_APPLICATION(app), argc, argv);
	g_object_unref(app);

	return status;
}
<commit_msg>implemented new loading method based on sourcefileloader<commit_after>#include <gtksourceview/gtksourceview.h>
#include <gtksourceview/gtksource.h>
#include <cstdio>
#include <string>
#include <iostream>
#include "Gtk.hpp"
using namespace Jazz;

GtkWidget* window 	= nullptr;
GtkWidget* toolbar 	= nullptr;
GtkWidget* swin 	= nullptr;
GtkWidget* source_view 	= nullptr;
GtkWidget* hbox 	= nullptr;
GtkWidget* notebook = nullptr;
//GtkWidget* frame	= nullptr;
//GtkWidget* label	= nullptr;
int tab_num = 1;
char bufferf[32];
char bufferl[32];
GtkSourceLanguageManager* language_manager = nullptr;

struct _Data
{
   GtkTextBuffer *buffer;
   GtkWindow     *parent;
};
typedef struct _Data Data;

static void close_tab(GtkButton* button, GtkWidget* child_obj)
{
	gint pagenum = gtk_notebook_page_num(GTK_NOTEBOOK(notebook), child_obj);

	gtk_notebook_remove_page(GTK_NOTEBOOK(notebook), pagenum);
}

GtkWidget* new_tab_label(const std::string& title, GtkWidget* child_held)
{
	std::string shortname = "";
	if(title.find("\\")!=std::string::npos)
		shortname = title.substr(title.find_last_of("\\")+1);
	else
		shortname = title;
	// Create widgets that go in the new tab
	auto image = gtk_image_new_from_icon_name("window-close",GTK_ICON_SIZE_SMALL_TOOLBAR);
	auto box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
	auto tab_close_button = gtk_button_new();
	auto tab_label = gtk_label_new(shortname.c_str());
	// making close button
	gtk_button_set_relief(GTK_BUTTON(tab_close_button),GTK_RELIEF_NONE);
	gtk_button_set_focus_on_click(GTK_BUTTON(tab_close_button), false);
	gtk_button_set_image(GTK_BUTTON(tab_close_button), image);
	// pack the label on the left, and the button
	gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(tab_label), TRUE, TRUE, 0);
	gtk_box_pack_end(GTK_BOX(box), tab_close_button, TRUE, TRUE, 0);
	//
	g_signal_connect (tab_close_button, "clicked", G_CALLBACK(close_tab), child_held);//tab_label);
	// the box shows its widgets
	gtk_widget_show_all(GTK_WIDGET(box));

	return box;
}

GtkWidget* new_sourceview(bool scrollable = true)
{
	Gtk::SourceView source_view;

	if(scrollable)
	{
		Gtk::ScrolledWindow scrolled_window;

		scrolled_window.Add(source_view);
		scrolled_window.ShowAll();

		return scrolled_window.Object();
	}
	return source_view.Object();
}

static void new_file(GtkToolItem *button, void*)
{
	std::string str = "Page ";
	str += std::to_string(tab_num); //char* str = "Page";

	auto new_source_view = new_sourceview();
	auto new_tab_thing = new_tab_label(str, new_source_view);

	gtk_notebook_append_page(GTK_NOTEBOOK(notebook), new_source_view, new_tab_thing); //scrolled_win, box);//tab_label);//new_source_view, new_tab_thing);

	gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), -1);

	gtk_widget_show_all(notebook);
	//std::cout << tab_num << std::endl;
	tab_num++;
}
static void load_file(GtkToolItem *button, void*)
{
	GtkWidget* dialog = gtk_file_chooser_dialog_new("Open File",	GTK_WINDOW(window), GTK_FILE_CHOOSER_ACTION_OPEN,
			"_Open", GTK_RESPONSE_ACCEPT, "_Cancel", GTK_RESPONSE_CANCEL, NULL);

	if( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
	{
		gchar* filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( dialog ) );
		printf("Open: %s\n", filename);

		// Construct the new text view, the pointer is to a scrolled
		// window containing a sourceview because we didnt pass false
		auto new_sview = new_sourceview();
		auto tab_label = new_tab_label(filename, new_sview);
		auto source = gtk_bin_get_child (GTK_BIN(new_sview));
		auto buff = gtk_text_view_get_buffer(GTK_TEXT_VIEW( source ));

		GFile* new_file = g_file_new_for_path(filename);
		GtkSourceFile* new_source_file = gtk_source_file_new();

		gtk_source_file_set_location(new_source_file, new_file);

		GtkSourceFileLoader* loader = gtk_source_file_loader_new(
			GTK_SOURCE_BUFFER(buff), new_source_file);

		auto s_lang = gtk_source_language_manager_guess_language(
			language_manager,
			filename,
			nullptr);

		gtk_source_file_loader_load_async(
			loader, G_PRIORITY_DEFAULT, NULL, NULL, NULL,	NULL,
			[](GObject* source_obj, GAsyncResult* res, gpointer loader) -> void {
				GError* error = nullptr;
				gboolean success = gtk_source_file_loader_load_finish(
					(GtkSourceFileLoader*)loader, res, &error);
				if(success)
					puts("Successfully opened file");
				else
					printf("Failed to open file: %i, %s\n",
						error->code,error->message);
			},
			// Pass the loader as the user data, so that we can just keep
			// the lambda function as is
			(gpointer)loader);

		//gtk_text_buffer_set_text( buff, text_data, -1 );

		gtk_source_buffer_set_language(GTK_SOURCE_BUFFER(buff), s_lang);

		gtk_notebook_append_page(GTK_NOTEBOOK(notebook), new_sview, tab_label);

		gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), -1);

		gtk_widget_show_all(notebook);

		g_free( filename );
		g_object_unref(new_file);
		//g_free( text_data );
		tab_num++;
	}
	//gtk_widget_hide(dialog);
	gtk_widget_destroy(dialog);
}
static void save_file(GtkToolItem *button, void*)
{
	static GtkWidget *dialog = gtk_file_chooser_dialog_new("Save file", GTK_WINDOW(window), GTK_FILE_CHOOSER_ACTION_SAVE,
			"_Save", GTK_RESPONSE_ACCEPT, "_Cancel", GTK_RESPONSE_CANCEL, NULL);

	if( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
	{
		gchar *filename;
		gchar *text_data;

		Gtk::Notebook the_notebook(notebook);

		//gint page_num = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
		GtkWidget* page = the_notebook.CurrentPage().Object();//gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page_num);
		GtkWidget* label = gtk_notebook_get_tab_label(GTK_NOTEBOOK(notebook), page);

		GtkWidget* the_child = the_notebook.CurrentPage().Object();
		GtkSourceView* the_sourceview = nullptr;

		if(GTK_IS_SCROLLED_WINDOW(the_child))
			the_sourceview = GTK_SOURCE_VIEW(gtk_bin_get_child(GTK_BIN(the_child)));
		else
			the_sourceview = GTK_SOURCE_VIEW(the_child);

		Gtk::SourceView sourceview(GTK_WIDGET(the_sourceview));

		Gtk::Buffer the_buffer = sourceview.GetBuffer();

		//Gtk::Buffer the_buffer(the_notebook.CurrentPage());

		g_object_get( G_OBJECT( the_buffer.Object() ), "text",
			&text_data, NULL);

		filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER( dialog ));

		std::string filenm = filename;

		std::string shortname = filenm.substr(filenm.find_last_of("\\")+1);

		GList* children = gtk_container_get_children(GTK_CONTAINER(label));

		GList* label_child = g_list_first(children);

		gtk_label_set_text(GTK_LABEL(label_child->data), shortname.c_str()); //children->data, shortname);

		g_file_set_contents( filename, text_data, -1, NULL);
		g_free( filename );
		g_free( text_data );
	}
	//gtk_widget_hide(dialog);
	gtk_widget_destroy(dialog);
}
static void activate(GtkApplication* app, gpointer user_data)
{
	// initialize
	notebook = gtk_notebook_new();
	//data = g_slice_new(Data);
	window = gtk_application_window_new(app);
	toolbar = gtk_toolbar_new();
	hbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 1);
	//
	language_manager = gtk_source_language_manager_get_default ();
	//
	GtkToolItem* new_button = gtk_tool_button_new(nullptr, nullptr);
	gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(new_button), "document-new");
	//
	GtkToolItem* open_button = gtk_tool_button_new(nullptr, nullptr);
	gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(open_button), "document-open");
	//
	GtkToolItem* save_button = gtk_tool_button_new(nullptr, nullptr);
	gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(save_button), "document-save");
	//
	GtkToolItem* seperator = gtk_separator_tool_item_new();
	//
	GtkToolItem* compile_button = gtk_tool_button_new(nullptr, nullptr);
	gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(compile_button), "system-run");
	//
	// signal connect
	g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK( gtk_main_quit ), NULL);
	g_signal_connect (save_button, "clicked", G_CALLBACK(save_file), nullptr);
	g_signal_connect (open_button, "clicked", G_CALLBACK(load_file), nullptr);
	g_signal_connect (new_button, "clicked", G_CALLBACK(new_file), nullptr);
	// position
	gtk_box_pack_start(GTK_BOX(hbox), toolbar, FALSE, FALSE, 0);
	gtk_notebook_set_tab_pos (GTK_NOTEBOOK(notebook), GTK_POS_TOP);
	gtk_box_pack_end( GTK_BOX( hbox ), notebook, TRUE, TRUE, 0 );
	// insert toolbar items
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), new_button, -1);
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), open_button, -1);
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), save_button, -1);
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), seperator, -1);
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), compile_button, -1);
	// window set
	gtk_window_set_title(GTK_WINDOW(window), "Window");
	gtk_window_set_default_size(GTK_WINDOW(window), 600, 500);
	// connections
	gtk_container_add(GTK_CONTAINER(window), hbox);

	gtk_widget_show_all(window);
}

int main(int argc, char** argv)
{
	GtkApplication* app;

	app = gtk_application_new("ca.chr.gtk.jazz", G_APPLICATION_FLAGS_NONE);
	g_signal_connect(app, "activate", G_CALLBACK(activate), 0);
	int status = g_application_run(G_APPLICATION(app), argc, argv);
	g_object_unref(app);

	return status;
}
<|endoftext|>


<commit_before>#include "amfobject.hpp"

#include "deserializationcontext.hpp"
#include "deserializer.hpp"
#include "types/amfinteger.hpp"
#include "types/amfstring.hpp"

namespace amf {

bool AmfObject::operator==(const AmfItem& other) const {
	const AmfObject* p = dynamic_cast<const AmfObject*>(&other);

	if (p == nullptr)
		return false;

	if (traits != p->traits)
		return false;

	if (traits.dynamic && dynamicProperties != p->dynamicProperties)
		return false;

	if (sealedProperties != p->sealedProperties)
		return false;

	if (traits.externalizable && externalizer(this) != p->externalizer(p))
		return false;

	return true;
}

std::vector<u8> AmfObject::serialize() const {
	/* AmfObject is defined as
	 * object-marker
	 * (
	 *   U29O-ref |
	 *   (U29O-traits-ext class-name *(U8)) |
	 *   U29O-traits-ref |
	 *   (U29O-traits class-name *(UTF-8-vr) *(value-type) *(dynamic-member))
	 * )
	 */

	std::vector<u8> buf = { AMF_OBJECT };

	AmfString className(traits.className);
	// serialized class name with AmfString marker
	std::vector<u8> name(className.serialize());

	if (traits.externalizable) {
		// U29O-traits-ext = 0b0111 = 0x07
		buf.push_back(0x07);
		// class-name
		buf.insert(buf.end(), name.begin() + 1, name.end());

		// externalized value = *(U8)
		// note: this may throw if externalizer is not properly initialized
		std::vector<u8> externalized(externalizer(this));
		buf.insert(buf.end(), externalized.begin(), externalized.end());
		return buf;
	}

	// U29-traits = 0b0011 = 0x03
	size_t traitMarker = traits.attributes.size() << 4 | 0x03;
	// dynamic marker = 0b1000 = 0x08
	if (traits.dynamic) traitMarker |= 0x08;

	std::vector<u8> marker(AmfInteger(traitMarker).serialize());
	buf.insert(buf.end(), marker.begin() + 1, marker.end());

	// class-name, skip the AmfString marker
	buf.insert(buf.end(), name.begin() + 1, name.end());

	// sealed property names = *(UTF-8-vr)
	for (const std::string& attribute : traits.attributes) {
		std::vector<u8> attr(AmfString(attribute).serialize());
		// skip AmfString marker
		buf.insert(buf.end(), attr.begin() + 1, attr.end());
	}

	// sealed property values = *(value-type)
	for (const std::string& attribute : traits.attributes) {
		auto s = sealedProperties.at(attribute)->serialize();
		buf.insert(buf.end(), s.begin(), s.end());
	}

	// only encode *(dynamic-member) (including the end marker) if the object
	// is actually dynamic
	if (traits.dynamic) {
		// dynamic-members = UTF-8-vr value-type
		for (const auto& it : dynamicProperties) {
			AmfString attribute(it.first);
			const std::vector<u8> name(attribute.serialize());

			// skip AmfString marker again
			buf.insert(buf.end(), name.begin() + 1, name.end());

			auto s = it.second->serialize();
			buf.insert(buf.end(), s.begin(), s.end());
		}

		// final dynamic member = UTF-8-empty
		buf.push_back(0x01);
	}

	return buf;
}

AmfItemPtr AmfObject::deserializePtr(v8::const_iterator& it, v8::const_iterator end, DeserializationContext& ctx) {
	if (it == end || *it++ != AMF_OBJECT)
		throw std::invalid_argument("AmfObject: Invalid type marker");

	int type = AmfInteger::deserializeValue(it, end);
	if ((type & 0x01) == 0x00) {
		// 0b...0 == U29O-ref
		return ctx.getPointer<AmfObject>(type >> 1);
	}

	AmfObjectTraits traits("", false, false);
	if ((type & 0x03) == 0x01) {
		// 0b..01 == U29O-traits-ref
		traits = ctx.getTraits(type >> 2);
	} else {
		if ((type & 0x07) == 0x07) {
			// 0b.111 == U29O-traits-ext
			traits.externalizable = true;
			traits.className = AmfString::deserializeValue(it, end, ctx);
		} else if ((type & 0x07) == 0x03) {
			// 0b.011 == U29O-traits
			traits.dynamic = ((type & 0x08) == 0x08);
			traits.className = AmfString::deserializeValue(it, end, ctx);
			int numSealed = type >> 4;
			for (int i = 0; i < numSealed; ++i)
				traits.attributes.insert(AmfString::deserializeValue(it, end, ctx));
		}

		ctx.addTraits(traits);
	}

	AmfItemPtr ptr(new AmfObject(traits));
	AmfObject & ret = ptr.as<AmfObject>();
	ctx.addPointer(ptr);

	if (traits.externalizable) {
		auto deserializer = Deserializer::externalDeserializers.at(traits.className);
		return deserializer(it, end, ctx);
	}

	for (auto name : traits.attributes) {
		AmfItemPtr val = Deserializer::deserialize(it, end, ctx);
		ret.sealedProperties[name] = val;
	}

	if (traits.dynamic) {
		while (true) {
			std::string name = AmfString::deserializeValue(it, end, ctx);
			if (name == "") break;

			AmfItemPtr val = Deserializer::deserialize(it, end, ctx);
			ret.dynamicProperties[name] = val;
		}
	}

	return ptr;
}

AmfObject AmfObject::deserialize(v8::const_iterator& it, v8::const_iterator end, DeserializationContext& ctx) {
	return deserializePtr(it, end, ctx).as<AmfObject>();
}

} // namespace amf
<commit_msg>Revert incorrect refactoring.<commit_after>#include "amfobject.hpp"

#include "deserializationcontext.hpp"
#include "deserializer.hpp"
#include "types/amfinteger.hpp"
#include "types/amfstring.hpp"

namespace amf {

bool AmfObject::operator==(const AmfItem& other) const {
	const AmfObject* p = dynamic_cast<const AmfObject*>(&other);

	if (p == nullptr)
		return false;

	if (traits != p->traits)
		return false;

	if (traits.dynamic && dynamicProperties != p->dynamicProperties)
		return false;

	if (sealedProperties != p->sealedProperties)
		return false;

	if (traits.externalizable && externalizer(this) != p->externalizer(p))
		return false;

	return true;
}

std::vector<u8> AmfObject::serialize() const {
	/* AmfObject is defined as
	 * object-marker
	 * (
	 *   U29O-ref |
	 *   (U29O-traits-ext class-name *(U8)) |
	 *   U29O-traits-ref |
	 *   (U29O-traits class-name *(UTF-8-vr) *(value-type) *(dynamic-member))
	 * )
	 */

	std::vector<u8> buf = { AMF_OBJECT };

	AmfString className(traits.className);
	// serialized class name with AmfString marker
	std::vector<u8> name(className.serialize());

	if (traits.externalizable) {
		// U29O-traits-ext = 0b0111 = 0x07
		buf.push_back(0x07);
		// class-name
		buf.insert(buf.end(), name.begin() + 1, name.end());

		// externalized value = *(U8)
		// note: this may throw if externalizer is not properly initialized
		std::vector<u8> externalized(externalizer(this));
		buf.insert(buf.end(), externalized.begin(), externalized.end());
		return buf;
	}

	// U29-traits = 0b0011 = 0x03
	size_t traitMarker = traits.attributes.size() << 4 | 0x03;
	// dynamic marker = 0b1000 = 0x08
	if (traits.dynamic) traitMarker |= 0x08;

	std::vector<u8> marker(AmfInteger(traitMarker).serialize());
	buf.insert(buf.end(), marker.begin() + 1, marker.end());

	// class-name, skip the AmfString marker
	buf.insert(buf.end(), name.begin() + 1, name.end());

	// sealed property names = *(UTF-8-vr)
	for (const std::string& attribute : traits.attributes) {
		std::vector<u8> attr(AmfString(attribute).serialize());
		// skip AmfString marker
		buf.insert(buf.end(), attr.begin() + 1, attr.end());
	}

	// sealed property values = *(value-type)
	for (const std::string& attribute : traits.attributes) {
		auto s = sealedProperties.at(attribute)->serialize();
		buf.insert(buf.end(), s.begin(), s.end());
	}

	// only encode *(dynamic-member) (including the end marker) if the object
	// is actually dynamic
	if (traits.dynamic) {
		// dynamic-members = UTF-8-vr value-type
		for (const auto& it : dynamicProperties) {
			AmfString attribute(it.first);
			const std::vector<u8> name(attribute.serialize());

			// skip AmfString marker again
			buf.insert(buf.end(), name.begin() + 1, name.end());

			auto s = it.second->serialize();
			buf.insert(buf.end(), s.begin(), s.end());
		}

		// final dynamic member = UTF-8-empty
		buf.push_back(0x01);
	}

	return buf;
}

AmfItemPtr AmfObject::deserializePtr(v8::const_iterator& it, v8::const_iterator end, DeserializationContext& ctx) {
	if (it == end || *it++ != AMF_OBJECT)
		throw std::invalid_argument("AmfObject: Invalid type marker");

	int type = AmfInteger::deserializeValue(it, end);
	if ((type & 0x01) == 0x00) {
		// 0b...0 == U29O-ref
		return ctx.getPointer<AmfObject>(type >> 1);
	}

	AmfObjectTraits traits("", false, false);
	if ((type & 0x03) == 0x01) {
		// 0b..01 == U29O-traits-ref
		traits = ctx.getTraits(type >> 2);
	} else {
		if ((type & 0x07) == 0x07) {
			// 0b.111 == U29O-traits-ext
			traits.externalizable = true;
			traits.className = AmfString::deserializeValue(it, end, ctx);
		} else if ((type & 0x07) == 0x03) {
			// 0b.011 == U29O-traits
			traits.dynamic = ((type & 0x08) == 0x08);
			traits.className = AmfString::deserializeValue(it, end, ctx);
			int numSealed = type >> 4;
			for (int i = 0; i < numSealed; ++i)
				traits.attributes.insert(AmfString::deserializeValue(it, end, ctx));
		}

		ctx.addTraits(traits);
	}

	AmfItemPtr ptr(new AmfObject(traits));
	AmfObject & ret = ptr.as<AmfObject>();
	ctx.addPointer(ptr);

	if (traits.externalizable) {
		ret = Deserializer::externalDeserializers.at(traits.className)(it, end, ctx);
		return ptr;
	}

	for (auto name : traits.attributes) {
		AmfItemPtr val = Deserializer::deserialize(it, end, ctx);
		ret.sealedProperties[name] = val;
	}

	if (traits.dynamic) {
		while (true) {
			std::string name = AmfString::deserializeValue(it, end, ctx);
			if (name == "") break;

			AmfItemPtr val = Deserializer::deserialize(it, end, ctx);
			ret.dynamicProperties[name] = val;
		}
	}

	return ptr;
}

AmfObject AmfObject::deserialize(v8::const_iterator& it, v8::const_iterator end, DeserializationContext& ctx) {
	return deserializePtr(it, end, ctx).as<AmfObject>();
}

} // namespace amf
<|endoftext|>


<commit_before>#ifndef SILICIUM_SILICIUM_CONFIG_HPP
#define SILICIUM_SILICIUM_CONFIG_HPP

#include <memory>
#include <stdexcept>
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
#include <boost/version.hpp>
#include <boost/preprocessor/if.hpp>

#ifdef _MSC_VER
#	define SILICIUM_COMPILER_CXX11 1
#	define SILICIUM_COMPILER_CXX14 1
#elif __cplusplus > 201103L
#	define SILICIUM_COMPILER_CXX11 1
#	define SILICIUM_COMPILER_CXX14 1
#elif __cplusplus >= 201103L
#	define SILICIUM_COMPILER_CXX11 1
#	define SILICIUM_COMPILER_CXX14 1 /* actually 0, assume 1 for now */
#else
#	define SILICIUM_COMPILER_CXX11 0
#	define SILICIUM_COMPILER_CXX14 0
#endif

#ifdef NDEBUG
#	ifdef _MSC_VER
#		define SILICIUM_UNREACHABLE() __assume(false)
#	else
#		define SILICIUM_UNREACHABLE() __builtin_unreachable()
#	endif
#else
#	define SILICIUM_UNREACHABLE() throw ::std::logic_error("unreachable " __FILE__ ":" BOOST_STRINGIZE(__LINE__))
#endif

#if (defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 408)) || defined(__clang__)
#	define SILICIUM_COMPILER_GENERATES_MOVES 1
#else
#	define SILICIUM_COMPILER_GENERATES_MOVES 0
#endif

#if defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 408) || defined(__clang__)
#	define SILICIUM_COMPILER_HAS_WORKING_NOEXCEPT 1
#else
#	define SILICIUM_COMPILER_HAS_WORKING_NOEXCEPT 0
#endif

#ifdef _MSC_VER
#	define SILICIUM_NORETURN __declspec(noreturn)
#else
//	GCC
#	define SILICIUM_NORETURN __attribute__ ((__noreturn__))
#endif

#if (defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 408)) || defined(__clang__) || (defined(_MSC_VER) && (_MSC_VER >= 1900))
#	define SILICIUM_COMPILER_HAS_RVALUE_THIS_QUALIFIER 1
#else
#	define SILICIUM_COMPILER_HAS_RVALUE_THIS_QUALIFIER 0
#endif

#if (defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 408) && SILICIUM_COMPILER_CXX14) || defined(__clang__)
#	define SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE 1
#else
#	define SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE 0
#endif

#if defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 408) || defined(__clang__) || (defined(_MSC_VER) && (_MSC_VER >= 1900))
#	define SILICIUM_COMPILER_HAS_EXTENDED_CAPTURE 1
#else
#	define SILICIUM_COMPILER_HAS_EXTENDED_CAPTURE 0
#endif

#if defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 407) || defined(__clang__) || defined(_MSC_VER)
#	define SILICIUM_COMPILER_HAS_VARIADIC_PACK_EXPANSION 1
#else
#	define SILICIUM_COMPILER_HAS_VARIADIC_PACK_EXPANSION 0
#endif

#if defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 407) || defined(__clang__) || (defined(_MSC_VER) && (_MSC_VER != 1900)) //VS 2015 has a buggy variadic template using
#	define SILICIUM_COMPILER_HAS_USING 1
#else
#	define SILICIUM_COMPILER_HAS_USING 0
#endif

#ifdef _MSC_VER
#	define SILICIUM_COMPILER_HAS_CXX11_UNION 0
#else
#	define SILICIUM_COMPILER_HAS_CXX11_UNION 1
#endif

#ifdef BOOST_DELETED_FUNCTION
#	define SILICIUM_DELETED_FUNCTION BOOST_DELETED_FUNCTION
#else
#	define SILICIUM_DELETED_FUNCTION(f) private: f;
#endif

#define SILICIUM_DISABLE_COPY(struct_name) \
	SILICIUM_DELETED_FUNCTION(struct_name(struct_name const &)) \
	SILICIUM_DELETED_FUNCTION(struct_name &operator = (struct_name const &))

#define SILICIUM_DEFAULT_NOEXCEPT_MOVE(struct_name) \
	struct_name(struct_name &&) BOOST_NOEXCEPT = default; \
	struct_name &operator = (struct_name &&) BOOST_NOEXCEPT = default;

#define SILICIUM_DEFAULT_MOVE(struct_name) \
	struct_name(struct_name &&) = default; \
	struct_name &operator = (struct_name &&) = default;

#define SILICIUM_DEFAULT_COPY(struct_name) \
	struct_name(struct_name const &) = default; \
	struct_name &operator = (struct_name const &) = default;

#ifdef _MSC_VER
#	define SILICIUM_DEPRECATED __declspec(deprecated)
#else
#	define SILICIUM_DEPRECATED __attribute__((deprecated))
#endif

#if defined(__GNUC__) && (__GNUC__ <= 4) && (__GNUC__ < 4 || __GNUC_MINOR__ <= 6)
#	define SILICIUM_OVERRIDE
#	define SILICIUM_FINAL
#else
#	define SILICIUM_OVERRIDE override
#	define SILICIUM_FINAL final
#endif

#ifdef _MSC_VER
#	define SILICIUM_USE_RESULT _Check_return_
#else
#	define SILICIUM_USE_RESULT __attribute__((warn_unused_result))
#endif

//TODO
#define SILICIUM_CXX14_CONSTEXPR

#define SILICIUM_IF(condition, value) BOOST_PP_IF(condition, value, BOOST_PP_EMPTY())
#define SILICIUM_IF_NOT(condition, value) BOOST_PP_IF(condition, BOOST_PP_EMPTY(), value)

#define SILICIUM_MOVE_IF_COMPILER_LACKS_RVALUE_QUALIFIERS(should_be_rvalue) BOOST_PP_IF(SILICIUM_COMPILER_HAS_RVALUE_THIS_QUALIFIER, (should_be_rvalue), std::move((should_be_rvalue)))

namespace Si
{
	struct nothing
	{
		BOOST_CONSTEXPR nothing() BOOST_NOEXCEPT
		{
		}
	};

	inline bool operator == (nothing const &, nothing const &)
	{
		return true;
	}

	template <class T, class ...Args>
	auto make_unique(Args &&...args) -> std::unique_ptr<T>
	{
		return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
	}

	template <class To, class From>
	To function_ptr_cast(From from)
	{
		//TODO: check that the cast makes sense
#ifdef __GNUC__
		//silence Warnung: ISO C++ forbids casting between pointer-to-function and pointer-to-object [enabled by default]
		__extension__
#endif
		To result = reinterpret_cast<To>(from);
		return result;
	}

#if defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 407) || defined(__clang__)
#define SILICIUM_HAS_PROPER_COPY_TRAITS 1
}
#include <type_traits>
namespace Si
{
	using std::is_copy_constructible;
	using std::is_copy_assignable;
#elif BOOST_VERSION >= 105500 //1.55
#define SILICIUM_HAS_PROPER_COPY_TRAITS 1
}
#include <boost/type_traits/is_copy_constructible.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <future>
namespace Si
{
	using boost::is_copy_constructible;
	template <class T>
	struct is_copy_constructible<std::future<T>> : std::false_type
	{
	};
	template <class T>
	struct is_copy_assignable : std::true_type
	{
	};
	template <class T>
	struct is_copy_assignable<std::future<T>> : std::false_type
	{
	};
	template <class T, class D>
	struct is_copy_assignable<std::unique_ptr<T, D>> : std::false_type
	{
	};
#else
#define SILICIUM_HAS_PROPER_COPY_TRAITS 0
	template <class T>
	struct is_copy_constructible : std::true_type
	{
	};
	template <class T>
	struct is_copy_assignable : std::true_type
	{
	};
#endif

#if defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 407) || defined(__clang__) || defined(_MSC_VER)
}
#include <type_traits>
namespace Si
{
	using std::is_default_constructible;
	using std::is_move_assignable;
	using std::is_nothrow_default_constructible;
	using std::is_nothrow_move_constructible;
	using std::is_nothrow_move_assignable;
#else
	template <class T>
	struct is_default_constructible : std::false_type
	{
	};
	template <class T>
	struct is_move_assignable : std::false_type
	{
	};
	template <class T>
	struct is_nothrow_default_constructible : std::true_type
	{
	};
	template <class T>
	struct is_nothrow_move_constructible : std::true_type
	{
	};
	template <class T>
	struct is_nothrow_move_assignable : std::true_type
	{
	};
#endif

#if BOOST_VERSION == 105400
	//uintptr_t is somehow missing from Boost 1.54
	typedef std::uintptr_t uintptr_t;
#else
	typedef boost::uintptr_t uintptr_t;
#endif
}

#endif
<commit_msg>enable C++14 deduced return types for VC++ 2015<commit_after>#ifndef SILICIUM_SILICIUM_CONFIG_HPP
#define SILICIUM_SILICIUM_CONFIG_HPP

#include <memory>
#include <stdexcept>
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
#include <boost/version.hpp>
#include <boost/preprocessor/if.hpp>

#ifdef _MSC_VER
#	define SILICIUM_COMPILER_CXX11 1
#	define SILICIUM_COMPILER_CXX14 1
#elif __cplusplus > 201103L
#	define SILICIUM_COMPILER_CXX11 1
#	define SILICIUM_COMPILER_CXX14 1
#elif __cplusplus >= 201103L
#	define SILICIUM_COMPILER_CXX11 1
#	define SILICIUM_COMPILER_CXX14 1 /* actually 0, assume 1 for now */
#else
#	define SILICIUM_COMPILER_CXX11 0
#	define SILICIUM_COMPILER_CXX14 0
#endif

#ifdef NDEBUG
#	ifdef _MSC_VER
#		define SILICIUM_UNREACHABLE() __assume(false)
#	else
#		define SILICIUM_UNREACHABLE() __builtin_unreachable()
#	endif
#else
#	define SILICIUM_UNREACHABLE() throw ::std::logic_error("unreachable " __FILE__ ":" BOOST_STRINGIZE(__LINE__))
#endif

#if (defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 408)) || defined(__clang__)
#	define SILICIUM_COMPILER_GENERATES_MOVES 1
#else
#	define SILICIUM_COMPILER_GENERATES_MOVES 0
#endif

#if defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 408) || defined(__clang__)
#	define SILICIUM_COMPILER_HAS_WORKING_NOEXCEPT 1
#else
#	define SILICIUM_COMPILER_HAS_WORKING_NOEXCEPT 0
#endif

#ifdef _MSC_VER
#	define SILICIUM_NORETURN __declspec(noreturn)
#else
//	GCC
#	define SILICIUM_NORETURN __attribute__ ((__noreturn__))
#endif

#if (defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 408)) || defined(__clang__) || (defined(_MSC_VER) && (_MSC_VER >= 1900))
#	define SILICIUM_COMPILER_HAS_RVALUE_THIS_QUALIFIER 1
#else
#	define SILICIUM_COMPILER_HAS_RVALUE_THIS_QUALIFIER 0
#endif

#if (defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 408) && SILICIUM_COMPILER_CXX14) || defined(__clang__) || (defined(_MSC_VER) && (_MSC_VER >= 1900))
#	define SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE 1
#else
#	define SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE 0
#endif

#if defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 408) || defined(__clang__) || (defined(_MSC_VER) && (_MSC_VER >= 1900))
#	define SILICIUM_COMPILER_HAS_EXTENDED_CAPTURE 1
#else
#	define SILICIUM_COMPILER_HAS_EXTENDED_CAPTURE 0
#endif

#if defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 407) || defined(__clang__) || defined(_MSC_VER)
#	define SILICIUM_COMPILER_HAS_VARIADIC_PACK_EXPANSION 1
#else
#	define SILICIUM_COMPILER_HAS_VARIADIC_PACK_EXPANSION 0
#endif

#if defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 407) || defined(__clang__) || (defined(_MSC_VER) && (_MSC_VER != 1900)) //VS 2015 has a buggy variadic template using
#	define SILICIUM_COMPILER_HAS_USING 1
#else
#	define SILICIUM_COMPILER_HAS_USING 0
#endif

#ifdef _MSC_VER
#	define SILICIUM_COMPILER_HAS_CXX11_UNION 0
#else
#	define SILICIUM_COMPILER_HAS_CXX11_UNION 1
#endif

#ifdef BOOST_DELETED_FUNCTION
#	define SILICIUM_DELETED_FUNCTION BOOST_DELETED_FUNCTION
#else
#	define SILICIUM_DELETED_FUNCTION(f) private: f;
#endif

#define SILICIUM_DISABLE_COPY(struct_name) \
	SILICIUM_DELETED_FUNCTION(struct_name(struct_name const &)) \
	SILICIUM_DELETED_FUNCTION(struct_name &operator = (struct_name const &))

#define SILICIUM_DEFAULT_NOEXCEPT_MOVE(struct_name) \
	struct_name(struct_name &&) BOOST_NOEXCEPT = default; \
	struct_name &operator = (struct_name &&) BOOST_NOEXCEPT = default;

#define SILICIUM_DEFAULT_MOVE(struct_name) \
	struct_name(struct_name &&) = default; \
	struct_name &operator = (struct_name &&) = default;

#define SILICIUM_DEFAULT_COPY(struct_name) \
	struct_name(struct_name const &) = default; \
	struct_name &operator = (struct_name const &) = default;

#ifdef _MSC_VER
#	define SILICIUM_DEPRECATED __declspec(deprecated)
#else
#	define SILICIUM_DEPRECATED __attribute__((deprecated))
#endif

#if defined(__GNUC__) && (__GNUC__ <= 4) && (__GNUC__ < 4 || __GNUC_MINOR__ <= 6)
#	define SILICIUM_OVERRIDE
#	define SILICIUM_FINAL
#else
#	define SILICIUM_OVERRIDE override
#	define SILICIUM_FINAL final
#endif

#ifdef _MSC_VER
#	define SILICIUM_USE_RESULT _Check_return_
#else
#	define SILICIUM_USE_RESULT __attribute__((warn_unused_result))
#endif

//TODO
#define SILICIUM_CXX14_CONSTEXPR

#define SILICIUM_IF(condition, value) BOOST_PP_IF(condition, value, BOOST_PP_EMPTY())
#define SILICIUM_IF_NOT(condition, value) BOOST_PP_IF(condition, BOOST_PP_EMPTY(), value)

#define SILICIUM_MOVE_IF_COMPILER_LACKS_RVALUE_QUALIFIERS(should_be_rvalue) BOOST_PP_IF(SILICIUM_COMPILER_HAS_RVALUE_THIS_QUALIFIER, (should_be_rvalue), std::move((should_be_rvalue)))

namespace Si
{
	struct nothing
	{
		BOOST_CONSTEXPR nothing() BOOST_NOEXCEPT
		{
		}
	};

	inline bool operator == (nothing const &, nothing const &)
	{
		return true;
	}

	template <class T, class ...Args>
	auto make_unique(Args &&...args) -> std::unique_ptr<T>
	{
		return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
	}

	template <class To, class From>
	To function_ptr_cast(From from)
	{
		//TODO: check that the cast makes sense
#ifdef __GNUC__
		//silence Warnung: ISO C++ forbids casting between pointer-to-function and pointer-to-object [enabled by default]
		__extension__
#endif
		To result = reinterpret_cast<To>(from);
		return result;
	}

#if defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 407) || defined(__clang__)
#define SILICIUM_HAS_PROPER_COPY_TRAITS 1
}
#include <type_traits>
namespace Si
{
	using std::is_copy_constructible;
	using std::is_copy_assignable;
#elif BOOST_VERSION >= 105500 //1.55
#define SILICIUM_HAS_PROPER_COPY_TRAITS 1
}
#include <boost/type_traits/is_copy_constructible.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <future>
namespace Si
{
	using boost::is_copy_constructible;
	template <class T>
	struct is_copy_constructible<std::future<T>> : std::false_type
	{
	};
	template <class T>
	struct is_copy_assignable : std::true_type
	{
	};
	template <class T>
	struct is_copy_assignable<std::future<T>> : std::false_type
	{
	};
	template <class T, class D>
	struct is_copy_assignable<std::unique_ptr<T, D>> : std::false_type
	{
	};
#else
#define SILICIUM_HAS_PROPER_COPY_TRAITS 0
	template <class T>
	struct is_copy_constructible : std::true_type
	{
	};
	template <class T>
	struct is_copy_assignable : std::true_type
	{
	};
#endif

#if defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 407) || defined(__clang__) || defined(_MSC_VER)
}
#include <type_traits>
namespace Si
{
	using std::is_default_constructible;
	using std::is_move_assignable;
	using std::is_nothrow_default_constructible;
	using std::is_nothrow_move_constructible;
	using std::is_nothrow_move_assignable;
#else
	template <class T>
	struct is_default_constructible : std::false_type
	{
	};
	template <class T>
	struct is_move_assignable : std::false_type
	{
	};
	template <class T>
	struct is_nothrow_default_constructible : std::true_type
	{
	};
	template <class T>
	struct is_nothrow_move_constructible : std::true_type
	{
	};
	template <class T>
	struct is_nothrow_move_assignable : std::true_type
	{
	};
#endif

#if BOOST_VERSION == 105400
	//uintptr_t is somehow missing from Boost 1.54
	typedef std::uintptr_t uintptr_t;
#else
	typedef boost::uintptr_t uintptr_t;
#endif
}

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include <string>
#include <cstdlib>
#include <cmath>
#include <boost/optional.hpp>
#include <nix/util/dataAccess.hpp>
#include <algorithm>

using namespace std;

namespace nix {
namespace util {

int positionToIndex(double position, const string &unit, const SampledDimension &dimension) {
    int index;
    boost::optional<string> dim_unit = dimension.unit();
    double scaling = 1.0;
    if ((!dim_unit && unit.length() > 0) || (dim_unit && unit.length() == 0)) {
        throw nix::IncompatibleDimensions("Units of position and SampledDimension must both be given!", "nix::util::positionToIndex");
    }
    if ((dimension.offset() && position < *dimension.offset()) || (!dimension.offset() && position < 0.0)) {
        throw nix::OutOfBounds("Position is out of bounds in SampledDimension.", (int)position);
    }
    if (dim_unit) {
        try {
            scaling = util::getSIScaling(unit, *dim_unit);
        } catch (...) {
            throw nix::IncompatibleDimensions("Cannot apply a position with unit to a SetDimension", "nix::util::positionToIndex");
        }
    }
    index = (int)round(position * scaling / dimension.samplingInterval());
    return index;
}

int positionToIndex(double position, const string &unit, const SetDimension &dimension) {
    int index;
    index = (int) round(position);
    if (unit.length() > 0) {
        throw nix::IncompatibleDimensions("Cannot apply a position with unit to a SetDimension", "nix::util::positionToIndex");
    }
    if (index >= 0 && (size_t)index < dimension.labels().size()){
        return index;
    } else {
        throw nix::OutOfBounds("Position is out of bounds in setDimension.", (int)position);
    }
    return index;
}

int positionToIndex(double position, const string &unit, const RangeDimension &dimension) {
    int index;
    boost::optional<string> dim_unit = dimension.unit();
    if ((!dim_unit && unit.length() > 0) || (dim_unit && unit.length() == 0)) {
        throw nix::IncompatibleDimensions("Units of position and RangeDimension must both be given!", "nix::util::positionToIndex");
    }
    vector<double> ticks = dimension.ticks();
    vector<double>::iterator low = std::lower_bound (ticks.begin(), ticks.end(), position);
    if (*low == position) {
        return low - ticks.begin();
    }
    if (low != ticks.begin() && *low != position) {
        double diff_low, diff_before;
        diff_low = abs(*low - position);
        diff_before = abs(*(std::prev(low)) - position);
        if (diff_low < diff_before) {
            index = low - ticks.begin();
        } else {
            index = low - ticks.begin() - 1;
        }
        return index;
    } else {
        return low - ticks.begin();
    }
}

} // namespace util
} // namespace nix
<commit_msg>enabled using scaled units in positionToIndex for RangeDimensions<commit_after>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include <string>
#include <cstdlib>
#include <cmath>
#include <boost/optional.hpp>
#include <nix/util/dataAccess.hpp>
#include <algorithm>

using namespace std;

namespace nix {
namespace util {

int positionToIndex(double position, const string &unit, const SampledDimension &dimension) {
    int index;
    boost::optional<string> dim_unit = dimension.unit();
    double scaling = 1.0;
    if ((!dim_unit && unit.length() > 0) || (dim_unit && unit.length() == 0)) {
        throw nix::IncompatibleDimensions("Units of position and SampledDimension must both be given!", "nix::util::positionToIndex");
    }
    if ((dimension.offset() && position < *dimension.offset()) || (!dimension.offset() && position < 0.0)) {
        throw nix::OutOfBounds("Position is out of bounds in SampledDimension.", (int)position);
    }
    if (dim_unit) {
        try {
            scaling = util::getSIScaling(unit, *dim_unit);
        } catch (...) {
            throw nix::IncompatibleDimensions("Cannot apply a position with unit to a SetDimension", "nix::util::positionToIndex");
        }
    }
    index = (int)round(position * scaling / dimension.samplingInterval());
    return index;
}

int positionToIndex(double position, const string &unit, const SetDimension &dimension) {
    int index;
    index = (int) round(position);
    if (unit.length() > 0) {
        throw nix::IncompatibleDimensions("Cannot apply a position with unit to a SetDimension", "nix::util::positionToIndex");
    }
    if (index >= 0 && (size_t)index < dimension.labels().size()){
        return index;
    } else {
        throw nix::OutOfBounds("Position is out of bounds in setDimension.", (int)position);
    }
    return index;
}

int positionToIndex(double position, const string &unit, const RangeDimension &dimension) {
    int index;
    boost::optional<string> dim_unit = dimension.unit();
    double scaling = 1.0;

    if ((!dim_unit && unit.length() > 0) || (dim_unit && unit.length() == 0)) {
        throw nix::IncompatibleDimensions("Units of position and RangeDimension must both be given!", "nix::util::positionToIndex");
    }
    if (dim_unit) {
        try {
            scaling = util::getSIScaling(unit, *dim_unit);
        } catch (...) {
            throw nix::IncompatibleDimensions("Cannot apply a position with unit to a SetDimension", "nix::util::positionToIndex");
        }
    }
    vector<double> ticks = dimension.ticks();
    vector<double>::iterator low = std::lower_bound (ticks.begin(), ticks.end(), position * scaling);
    if (*low == position) {
        return low - ticks.begin();
    }
    if (low != ticks.begin() && *low != position * scaling) {
        double diff_low, diff_before;
        diff_low = abs(*low - position);
        diff_before = abs(*(std::prev(low)) - position * scaling);
        if (diff_low < diff_before) {
            index = low - ticks.begin();
        } else {
            index = low - ticks.begin() - 1;
        }
        return index;
    } else {
        return low - ticks.begin();
    }
}

} // namespace util
} // namespace nix
<|endoftext|>


<commit_before>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include <string>
#include <cstdlib>
#include <cmath>
#include <boost/optional.hpp>
#include <nix/util/dataAccess.hpp>
#include <algorithm>

using namespace std;

namespace nix {
namespace util {

//TODO maybe a relaxed handling of units would be better, e.g. if none given, take the one from the dimension...
int positionToIndex(double position, const string &unit, const Dimension &dimension) {
    if (dimension.dimensionType() == nix::DimensionType::Sample) {
        SampledDimension dim;
        dim = dimension;
        return positionToIndex(position, unit, dim);
    } else if (dimension.dimensionType() == nix::DimensionType::Set) {
        SetDimension dim;
        dim = dimension;
        return positionToIndex(position, unit, dim);
    } else {
        RangeDimension dim;
        dim = dimension;
        return positionToIndex(position, unit, dim);
    }
}

size_t positionToIndex(double position, const string &unit, const SampledDimension &dimension) {
    size_t index;
    boost::optional<string> dim_unit = dimension.unit();
    double scaling = 1.0;

    if (!dim_unit && unit != "none") {
        throw nix::IncompatibleDimensions("Units of position and SampledDimension must both be given!", "nix::util::positionToIndex");
    }
    if ((dimension.offset() && position < *dimension.offset()) || (!dimension.offset() && position < 0.0)) {
        throw nix::OutOfBounds("Position is out of bounds in SampledDimension.", static_cast<int>(position));
    }
    if (dim_unit && unit != "none") {
        try {
            scaling = util::getSIScaling(unit, *dim_unit);
        } catch (...) {
            throw nix::IncompatibleDimensions("Cannot apply a position with unit to a SetDimension", "nix::util::positionToIndex");
        }
    }
    index = static_cast<size_t>(round(position * scaling / dimension.samplingInterval()));
    return index;
}

size_t positionToIndex(double position, const string &unit, const SetDimension &dimension) {
    size_t index;
    index = static_cast<size_t>(round(position));
    if (unit.length() > 0 && unit != "none") {
        throw nix::IncompatibleDimensions("Cannot apply a position with unit to a SetDimension", "nix::util::positionToIndex");
    }
    if (static_cast<size_t>(index) < dimension.labels().size()){
        return index;
    } else {
        throw nix::OutOfBounds("Position is out of bounds in setDimension.", static_cast<int>(position));
    }
}

size_t positionToIndex(double position, const string &unit, const RangeDimension &dimension) {
    size_t index;
    boost::optional<string> dim_unit = dimension.unit();
    double scaling = 1.0;

    if (dim_unit && unit != "none") {
        try {
            scaling = util::getSIScaling(unit, *dim_unit);
        } catch (...) {
            throw nix::IncompatibleDimensions("Provided units are not scalable!", "nix::util::positionToIndex");
        }
    }
    vector<double> ticks = dimension.ticks();
    if (position*scaling < *ticks.begin()) {
        return 0;
    } else if (position*scaling > *prev(ticks.end())) {
        return prev(ticks.end()) - ticks.begin();
    }
    vector<double>::iterator low = std::lower_bound (ticks.begin(), ticks.end(), position * scaling);
    if (*low == position) {
        return low - ticks.begin();
    }
    if (low != ticks.begin() && *low != position * scaling) {
        double diff_low, diff_before;
        diff_low = fabs(*low - position);
        diff_before = fabs(*(std::prev(low)) - position * scaling);
        if (diff_low < diff_before) {
            index = low - ticks.begin();
        } else {
            index = low - ticks.begin() - 1;
        }
        return index;
    } else {
        return low - ticks.begin();
    }
}

void getOffsetAndCount(const SimpleTag &tag, const DataArray &array, NDSize &offset, NDSize &count) {
    vector<double> position = tag.position();
    vector<double> extent = tag.extent();
    vector<string> units = tag.units();
    NDSize temp_offset(position.size());
    NDSize temp_count(position.size(), 1);

    if (array.dimensionCount() != position.size() || (extent.size() > 0 && extent.size() != array.dimensionCount())) {
        throw std::runtime_error("Dimensionality of position or extent vector does not match dimensionality of data!");
    }
    for (size_t i = 0; i < position.size(); ++i) {
        Dimension dim = array.getDimension(i+1);
        temp_offset[i] = positionToIndex(position[i], i > units.size() ? "none" : units[i], dim);
        if (i < extent.size()) {
            temp_count[i] = 1 + positionToIndex(position[i] + extent[i], i > units.size() ? "none" : units[i], dim) - temp_offset[i];
        }
    }
    offset = temp_offset;
    count = temp_count;
}

void getOffsetAndCount(const DataTag &tag, const DataArray &array, size_t index, NDSize &offsets, NDSize &counts) {
    DataArray positions = tag.positions();
    DataArray extents = tag.extents();
    NDSize position_extent = positions.dataExtent();
    NDSize extent_extent = extents.dataExtent();
    size_t dimension_count = array.dimensionCount();

    if (index >= position_extent[0] || index >= extent_extent[0]) {
        throw nix::OutOfBounds("Index out of bounds of positions or extents!", 0);
    }
    if (position_extent[1] > dimension_count || extent_extent[1] > dimension_count) {
        throw nix::IncompatibleDimensions("Number of dimensions in position or extent do not match dimensionality of data","util::getOffsetAndCount");
    }
    NDSize temp_offset = NDSize{static_cast<NDSize::value_type>(index), static_cast<NDSize::value_type>(0)};
    NDSize temp_count{static_cast<NDSize::value_type>(1), static_cast<NDSize::value_type>(dimension_count)};
    NDArray offset(positions.dataType(), temp_count);
    NDArray extent(extents.dataType(), temp_count);
    positions.getData(offset, temp_count, temp_offset);
    extents.getData(extent, temp_count, temp_offset);

    NDSize data_offset(dimension_count, static_cast<size_t>(0));
    NDSize data_count(dimension_count, static_cast<size_t>(0));
    vector<string> units = tag.units();

    for (size_t i = 0; i < offset.num_elements(); ++i) {
        Dimension dimension = array.getDimension(i+1);
        string unit = "none";
        if (i <= units.size() && units.size() > 0) {
            unit = units[i];
        }
        /*
        if (dimension.dimensionType() == nix::DimensionType::Sample) {
            SampledDimension dim;
            dim = dimension;
            unit = dim.unit() ? *dim.unit() : "none";
        } else if (dimension.dimensionType() == nix::DimensionType::Range) {
            RangeDimension dim;
            dim = dimension;
            unit = dim.unit() ? *dim.unit() : "none";
        }
        */
        data_offset[i] = positionToIndex(offset.get<double>(i), unit, dimension);

        if (i < extent.num_elements()) {
            data_count[i] = 1 + positionToIndex(offset.get<double>(i) + extent.get<double>(i), unit, dimension) - data_offset[i];
        }
    }
    offsets = data_offset;
    counts = data_count;
}

bool positionInData(const DataArray &data, const NDSize &position) {
    NDSize data_size = data.dataExtent();
    bool valid = true;

    if (!(data_size.size() == position.size())) {
        return false;
    }
    for (size_t i = 0; i < data_size.size(); i++) {
        valid &= position[i] < data_size[i];
    }
    return valid;
}

bool positionAndExtentInData(const DataArray &data, const NDSize &position, const NDSize &count) {
    NDSize pos = position + count;
    pos -= 1;
    return positionInData(data, pos);
}

NDArray retrieveData(const DataTag &tag, size_t position_index, size_t reference_index) {
    DataArray positions = tag.positions();
    DataArray extents = tag.extents();
    vector<DataArray> refs = tag.references();
    if (refs.size() == 0) {
        throw nix::OutOfBounds("There are no references in this tag!", 0);
    }
    if (position_index >= positions.dataExtent()[0] ||
        (extents && position_index >= extents.dataExtent()[0])) {
        throw nix::OutOfBounds("Index out of bounds of positions or extents!", 0);
    }
    if (!(reference_index < tag.referenceCount())) {
        throw nix::OutOfBounds("Reference index out of bounds.", 0);
    }
    size_t dimension_count = refs[reference_index].dimensionCount();
    if (positions.dataExtent()[1] > dimension_count ||
        (extents &&extents.dataExtent()[1] > dimension_count)) {
        throw nix::IncompatibleDimensions("Number of dimensions in position or extent do not match dimensionality of data","util::retrieveData");
    }

    NDSize offset, count;
    getOffsetAndCount(tag, refs[reference_index], position_index, offset, count);
    if (!positionAndExtentInData(refs[reference_index], offset, count)) {
        throw nix::OutOfBounds("References data slice out of the extent of the DataArray!", 0);
    }
    NDArray data(refs[reference_index].dataType(), count);
    refs[reference_index].getData(data, count, offset);
    return data;
}

NDArray retrieveData(const SimpleTag &tag, size_t reference_index) {
    vector<double> positions = tag.position();
    vector<double> extents = tag.extent();
    vector<DataArray> refs = tag.references();
    if (refs.size() == 0) {
        throw nix::OutOfBounds("There are no references in this tag!", 0);
    }
    if (!(reference_index < tag.referenceCount())) {
        throw nix::OutOfBounds("Reference index out of bounds.", 0);
    }
    size_t dimension_count = refs[reference_index].dimensionCount();
    if (positions.size() != dimension_count || (extents.size() > 0 && extents.size() != dimension_count)) {
        throw nix::IncompatibleDimensions("Number of dimensions in position or extent do not match dimensionality of data","util::retrieveData");
    }

    NDSize offset, count;
    getOffsetAndCount(tag, refs[reference_index], offset, count);
    if (!positionAndExtentInData(refs[reference_index], offset, count)) {
        throw nix::OutOfBounds("Referenced data slice out of the extent of the DataArray!", 0);
    }
    NDArray data(refs[reference_index].dataType(), count);
    refs[reference_index].getData(data, count, offset);
    return data;
}

} // namespace util
} // namespace nix
<commit_msg>improve getOffsetAndCount to handle optional extents and units<commit_after>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include <string>
#include <cstdlib>
#include <cmath>
#include <boost/optional.hpp>
#include <nix/util/dataAccess.hpp>
#include <algorithm>

using namespace std;

namespace nix {
namespace util {

//TODO maybe a relaxed handling of units would be better, e.g. if none given, take the one from the dimension...
int positionToIndex(double position, const string &unit, const Dimension &dimension) {
    if (dimension.dimensionType() == nix::DimensionType::Sample) {
        SampledDimension dim;
        dim = dimension;
        return positionToIndex(position, unit, dim);
    } else if (dimension.dimensionType() == nix::DimensionType::Set) {
        SetDimension dim;
        dim = dimension;
        return positionToIndex(position, unit, dim);
    } else {
        RangeDimension dim;
        dim = dimension;
        return positionToIndex(position, unit, dim);
    }
}

size_t positionToIndex(double position, const string &unit, const SampledDimension &dimension) {
    size_t index;
    boost::optional<string> dim_unit = dimension.unit();
    double scaling = 1.0;

    if (!dim_unit && unit != "none") {
        throw nix::IncompatibleDimensions("Units of position and SampledDimension must both be given!", "nix::util::positionToIndex");
    }
    if ((dimension.offset() && position < *dimension.offset()) || (!dimension.offset() && position < 0.0)) {
        throw nix::OutOfBounds("Position is out of bounds in SampledDimension.", static_cast<int>(position));
    }
    if (dim_unit && unit != "none") {
        try {
            scaling = util::getSIScaling(unit, *dim_unit);
        } catch (...) {
            throw nix::IncompatibleDimensions("Cannot apply a position with unit to a SetDimension", "nix::util::positionToIndex");
        }
    }
    index = static_cast<size_t>(round(position * scaling / dimension.samplingInterval()));
    return index;
}

size_t positionToIndex(double position, const string &unit, const SetDimension &dimension) {
    size_t index;
    index = static_cast<size_t>(round(position));
    if (unit.length() > 0 && unit != "none") {
        throw nix::IncompatibleDimensions("Cannot apply a position with unit to a SetDimension", "nix::util::positionToIndex");
    }
    if (static_cast<size_t>(index) < dimension.labels().size()){
        return index;
    } else {
        throw nix::OutOfBounds("Position is out of bounds in setDimension.", static_cast<int>(position));
    }
}

size_t positionToIndex(double position, const string &unit, const RangeDimension &dimension) {
    size_t index;
    boost::optional<string> dim_unit = dimension.unit();
    double scaling = 1.0;

    if (dim_unit && unit != "none") {
        try {
            scaling = util::getSIScaling(unit, *dim_unit);
        } catch (...) {
            throw nix::IncompatibleDimensions("Provided units are not scalable!", "nix::util::positionToIndex");
        }
    }
    vector<double> ticks = dimension.ticks();
    if (position*scaling < *ticks.begin()) {
        return 0;
    } else if (position*scaling > *prev(ticks.end())) {
        return prev(ticks.end()) - ticks.begin();
    }
    vector<double>::iterator low = std::lower_bound (ticks.begin(), ticks.end(), position * scaling);
    if (*low == position) {
        return low - ticks.begin();
    }
    if (low != ticks.begin() && *low != position * scaling) {
        double diff_low, diff_before;
        diff_low = fabs(*low - position);
        diff_before = fabs(*(std::prev(low)) - position * scaling);
        if (diff_low < diff_before) {
            index = low - ticks.begin();
        } else {
            index = low - ticks.begin() - 1;
        }
        return index;
    } else {
        return low - ticks.begin();
    }
}

void getOffsetAndCount(const SimpleTag &tag, const DataArray &array, NDSize &offset, NDSize &count) {
    vector<double> position = tag.position();
    vector<double> extent = tag.extent();
    vector<string> units = tag.units();
    NDSize temp_offset(position.size());
    NDSize temp_count(position.size(), 1);

    if (array.dimensionCount() != position.size() || (extent.size() > 0 && extent.size() != array.dimensionCount())) {
        throw std::runtime_error("Dimensionality of position or extent vector does not match dimensionality of data!");
    }
    for (size_t i = 0; i < position.size(); ++i) {
        Dimension dim = array.getDimension(i+1);
        temp_offset[i] = positionToIndex(position[i], i > units.size() ? "none" : units[i], dim);
        if (i < extent.size()) {
            temp_count[i] = 1 + positionToIndex(position[i] + extent[i], i > units.size() ? "none" : units[i], dim) - temp_offset[i];
        }
    }
    offset = temp_offset;
    count = temp_count;
}

void getOffsetAndCount(const DataTag &tag, const DataArray &array, size_t index, NDSize &offsets, NDSize &counts) {
    DataArray positions = tag.positions();
    DataArray extents = tag.extents();
    NDSize position_size, extent_size;
    size_t dimension_count = array.dimensionCount();

    if (positions) {
        position_size = positions.dataExtent();
    }
    if (extents) {
        extent_size = extents.dataExtent();
    }
    if (!positions || index >= position_size[0]) {
        throw nix::OutOfBounds("Index out of bounds of positions!", 0);
    }
    if (extents && index >= extent_size[0]) {
        throw nix::OutOfBounds("Index out of bounds of positions or extents!", 0);
    }
    if (position_size[1] > dimension_count) {
        throw nix::IncompatibleDimensions("Number of dimensions in positions do not match dimensionality of data","util::getOffsetAndCount");
    }
    if(extents && extent_size[1] > dimension_count) {
        throw nix::IncompatibleDimensions("Number of dimensions in extents do not match dimensionality of data","util::getOffsetAndCount");
    }

    NDSize temp_offset = NDSize{static_cast<NDSize::value_type>(index), static_cast<NDSize::value_type>(0)};
    NDSize temp_count{static_cast<NDSize::value_type>(1), static_cast<NDSize::value_type>(dimension_count)};
    NDArray offset(positions.dataType(), temp_count);
    positions.getData(offset, temp_count, temp_offset);

    NDSize data_offset(dimension_count, static_cast<size_t>(0));
    NDSize data_count(dimension_count, static_cast<size_t>(1));
    vector<string> units = tag.units();

    for (size_t i = 0; i < offset.num_elements(); ++i) {
        Dimension dimension = array.getDimension(i+1);
        string unit = "none";
        if (i <= units.size() && units.size() > 0) {
            unit = units[i];
        }
        data_offset[i] = positionToIndex(offset.get<double>(i), unit, dimension);
    }

    if(extents) {
        NDArray extent(extents.dataType(), temp_count);
        extents.getData(extent, temp_count, temp_offset);
        for (size_t i = 0; i < offset.num_elements(); ++i) {
            Dimension dimension = array.getDimension(i+1);
            string unit = "none";
            if (i <= units.size() && units.size() > 0) {
                unit = units[i];
            }
            if (i < extent.num_elements()) {
                data_count[i] = 1 + positionToIndex(offset.get<double>(i) + extent.get<double>(i), unit, dimension) - data_offset[i];
            }
        }
    }
    offsets = data_offset;
    counts = data_count;
}

bool positionInData(const DataArray &data, const NDSize &position) {
    NDSize data_size = data.dataExtent();
    bool valid = true;

    if (!(data_size.size() == position.size())) {
        return false;
    }
    for (size_t i = 0; i < data_size.size(); i++) {
        valid &= position[i] < data_size[i];
    }
    return valid;
}

bool positionAndExtentInData(const DataArray &data, const NDSize &position, const NDSize &count) {
    NDSize pos = position + count;
    pos -= 1;
    return positionInData(data, pos);
}

NDArray retrieveData(const DataTag &tag, size_t position_index, size_t reference_index) {
    DataArray positions = tag.positions();
    DataArray extents = tag.extents();
    vector<DataArray> refs = tag.references();

    if (refs.size() == 0) {
        throw nix::OutOfBounds("There are no references in this tag!", 0);
    }
    if (position_index >= positions.dataExtent()[0] ||
        (extents && position_index >= extents.dataExtent()[0])) {
        throw nix::OutOfBounds("Index out of bounds of positions or extents!", 0);
    }
    if (!(reference_index < tag.referenceCount())) {
        throw nix::OutOfBounds("Reference index out of bounds.", 0);
    }

    size_t dimension_count = refs[reference_index].dimensionCount();
    if (positions.dataExtent()[1] > dimension_count ||
        (extents &&extents.dataExtent()[1] > dimension_count)) {
        throw nix::IncompatibleDimensions("Number of dimensions in position or extent do not match dimensionality of data","util::retrieveData");
    }

    NDSize offset, count;
    getOffsetAndCount(tag, refs[reference_index], position_index, offset, count);
    if (!positionAndExtentInData(refs[reference_index], offset, count)) {
        throw nix::OutOfBounds("References data slice out of the extent of the DataArray!", 0);
    }
    NDArray data(refs[reference_index].dataType(), count);
    refs[reference_index].getData(data, count, offset);
    return data;
}

NDArray retrieveData(const SimpleTag &tag, size_t reference_index) {
    vector<double> positions = tag.position();
    vector<double> extents = tag.extent();
    vector<DataArray> refs = tag.references();
    if (refs.size() == 0) {
        throw nix::OutOfBounds("There are no references in this tag!", 0);
    }
    if (!(reference_index < tag.referenceCount())) {
        throw nix::OutOfBounds("Reference index out of bounds.", 0);
    }
    size_t dimension_count = refs[reference_index].dimensionCount();
    if (positions.size() != dimension_count || (extents.size() > 0 && extents.size() != dimension_count)) {
        throw nix::IncompatibleDimensions("Number of dimensions in position or extent do not match dimensionality of data","util::retrieveData");
    }

    NDSize offset, count;
    getOffsetAndCount(tag, refs[reference_index], offset, count);
    if (!positionAndExtentInData(refs[reference_index], offset, count)) {
        throw nix::OutOfBounds("Referenced data slice out of the extent of the DataArray!", 0);
    }
    NDArray data(refs[reference_index].dataType(), count);
    refs[reference_index].getData(data, count, offset);
    return data;
}

} // namespace util
} // namespace nix
<|endoftext|>


<commit_before>/*
 * Copyright 2011 Intel Corporation.
 *
 * This program is licensed under the terms and conditions of the
 * Apache License, version 2.0.  The full text of the Apache License is at
 * http://www.apache.org/licenses/LICENSE-2.0
 */

#include <QApplication>
#include <QDBusConnection>
#include <QDBusError>
#include <QDBusInterface>
#include <QDeclarativeEngine>
#include <QDeclarativeView>
#include <QGraphicsItem>
#include <QDeclarativeContext>
#include <QDeclarativeNetworkAccessManagerFactory>
#include <QDesktopWidget>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QGLFormat>
#include <QLibraryInfo>
#include <QNetworkAccessManager>
#include <QNetworkDiskCache>
#include <QNetworkProxy>
#include <QResizeEvent>
#include <QSettings>
#include <QTimer>
#include <QTextStream>
#include <QTranslator>
#include <QVariant>
#include <QX11Info>
#include <MGConfItem>
#include <QInputContext>

#include "launcherwindow.h"
#include "launcheratoms.h"
#include "launcherapp.h"

#include <QX11Info>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <unistd.h>

class NetworkAccessManagerFactory : public QDeclarativeNetworkAccessManagerFactory
{
public:
    virtual QNetworkAccessManager *create(QObject *parent);
};

QNetworkAccessManager *NetworkAccessManagerFactory::create(QObject *parent)
{
    QUrl httpProxy(getenv("http_proxy"));
    QNetworkAccessManager *nam = new QNetworkAccessManager(parent);
    if (!httpProxy.isEmpty())
    {
        QNetworkProxy proxy(QNetworkProxy::HttpCachingProxy,
                            httpProxy.host(),
                            httpProxy.port());
        nam->setProxy(proxy);
    }

    QNetworkDiskCache *cache = new QNetworkDiskCache();
    cache->setCacheDirectory(QDir::homePath() + "/.cache/" + qApp->applicationName());
    nam->setCache(cache);

    return nam;
}

LauncherWindow::LauncherWindow(bool fullscreen, int width, int height, bool opengl, bool setSource, QWidget *parent) :
    QWidget(parent),
    m_inhibitScreenSaver(false)
{
    LauncherApp *app = static_cast<LauncherApp *>(qApp);

    setWindowTitle(app->applicationName());
    setWindowIconText(app->applicationName());

    int screenWidth;
    int screenHeight;
    if (fullscreen)
    {
        screenWidth = qApp->desktop()->rect().width();
        screenHeight = qApp->desktop()->rect().height();
        setWindowFlags(Qt::FramelessWindowHint);
    }
    else
    {
        screenWidth = width;
        screenHeight = height;
    }

    view = new QDeclarativeView(this);
    view->engine()->setNetworkAccessManagerFactory(new NetworkAccessManagerFactory);
    connect(view->engine(), SIGNAL(quit()), qApp, SLOT(closeAllWindows()));
    connect((const QObject*)qApp->inputContext(), SIGNAL(inputMethodAreaChanged(QRect)),
            this, SLOT(handleInputMethodAreaChanged(QRect)));
    connect(qApp, SIGNAL(dismissKeyboard()), this, SLOT(dismissKeyboard()));

    QDeclarativeContext *context = view->rootContext();
    context->setContextProperty("screenWidth", screenWidth);
    context->setContextProperty("screenHeight", screenHeight);
    context->setContextProperty("qApp", qApp);
    context->setContextProperty("mainWindow", this);
    context->setContextProperty("theme_name", MGConfItem("/meego/ux/theme").value().toString());
    foreach (QString key, app->themeConfig->allKeys())
    {
        if (key.contains("Size") || key.contains("Padding") ||
            key.contains("Width") ||key.contains("Height") ||
            key.contains("Margin") || key.contains("Thickness"))
        {
            context->setContextProperty("theme_" + key, app->themeConfig->value(key).toInt());
        }
        else if (key.contains("Opacity"))
        {
            context->setContextProperty("theme_" + key, app->themeConfig->value(key).toDouble());
        }
        else
        {
            context->setContextProperty("theme_" + key, app->themeConfig->value(key));
        }
    }

    if (setSource) {
      sharePath = QString("/usr/share/") + app->applicationName() + "/";
      if (!QFile::exists(sharePath + "main.qml"))
      {
        qFatal("%s does not exist!", sharePath.toUtf8().data());
      }
    }

    loadTranslators();
    connect(app, SIGNAL(localeSettingsChanged()), this, SLOT(loadTranslators()));

    // Qt will search each translator for a string translation, starting with
    // the last translator installed working back to the first translator.
    // The first translation found wins.
    app->installTranslator(&qtTranslator);     // General Qt translations
    app->installTranslator(&commonTranslator); // Common Components translations
    app->installTranslator(&mediaTranslator);  // Common Media translations
    app->installTranslator(&appTranslator);    // App specific translations

    if (setSource)
    {
      view->setSource(QUrl(sharePath + "main.qml"));
    }

    if (opengl)
    {
        QGLFormat format = QGLFormat::defaultFormat();
        format.setSampleBuffers(false);
        view->setViewport(new QGLWidget(format));
    }

    setGeometry(QRect(0, 0, screenWidth, screenHeight));
}

LauncherWindow::~LauncherWindow()
{
}

void LauncherWindow::loadTranslators()
{
    LauncherApp *app = static_cast<LauncherApp *>(qApp);

    qtTranslator.load("qt_" + QLocale::system().name() + ".qm",
                      QLibraryInfo::location(QLibraryInfo::TranslationsPath));
    commonTranslator.load("meegolabs-ux-components_" + QLocale::system().name() + ".qm",
                          QLibraryInfo::location(QLibraryInfo::TranslationsPath));
    mediaTranslator.load("meego-ux-media-qml_" + QLocale::system().name() + ".qm",
                         QLibraryInfo::location(QLibraryInfo::TranslationsPath));
    appTranslator.load(app->applicationName() + "_" + QLocale::system().name() + ".qm",
                       QLibraryInfo::location(QLibraryInfo::TranslationsPath));
}

void LauncherWindow::triggerSystemUIMenu()
{
    QDBusInterface iface("com.nokia.systemui","/statusindicatormenu","com.meego.core.MStatusIndicatorMenu");
    if(iface.isValid()) iface.call("open");
}

void LauncherWindow::goHome()
{
    setWindowState(windowState() ^ Qt::WindowMinimized);
}

// Called by LauncherApplication when it wants to dismiss the
// keyboard.  hideOnFocusOut() is a slot on MInputContext, that seems
// to be required, it doesn't get it right if you just drop the focus
// (bug in MInputContext?)
void LauncherWindow::dismissKeyboard()
{
    if(view->scene() && view->scene()->focusItem()) {
        view->scene()->focusItem()->clearFocus();
        QMetaObject::invokeMethod(qApp->inputContext(), "hideOnFocusOut");
    }
}

void LauncherWindow::forwardCall(const QStringList& parameters)
{
    emit call(parameters);
}

void LauncherWindow::setActualOrientation(int orientation)
{
    m_actualOrientation = orientation;

    if (!winId())
    {
        return;
    }

    Atom orientationAtom = XInternAtom(QX11Info::display(), "_MEEGO_ORIENTATION", false);
    XChangeProperty(QX11Info::display(), winId(), orientationAtom, XA_CARDINAL, 32,
                    PropModeReplace, (unsigned char*)&m_actualOrientation, 1);
}

bool LauncherWindow::event (QEvent * event)
{
    if (event->type() == QEvent::Show)
    {
        setActualOrientation(m_actualOrientation);
    }
    return QWidget::event(event);
}

void LauncherWindow::setInhibitScreenSaver(bool inhibit)
{
    m_inhibitScreenSaver = inhibit;

    Atom inhibitAtom = XInternAtom(QX11Info::display(), "_MEEGO_INHIBIT_SCREENSAVER", false);
    XChangeProperty(QX11Info::display(), winId(), inhibitAtom, XA_CARDINAL, 32,
                    PropModeReplace, (unsigned char*)&m_inhibitScreenSaver, 1);
}
<commit_msg>tweak the inhibit screen saver handling to add or delete the window property<commit_after>/*
 * Copyright 2011 Intel Corporation.
 *
 * This program is licensed under the terms and conditions of the
 * Apache License, version 2.0.  The full text of the Apache License is at
 * http://www.apache.org/licenses/LICENSE-2.0
 */

#include <QApplication>
#include <QDBusConnection>
#include <QDBusError>
#include <QDBusInterface>
#include <QDeclarativeEngine>
#include <QDeclarativeView>
#include <QGraphicsItem>
#include <QDeclarativeContext>
#include <QDeclarativeNetworkAccessManagerFactory>
#include <QDesktopWidget>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QGLFormat>
#include <QLibraryInfo>
#include <QNetworkAccessManager>
#include <QNetworkDiskCache>
#include <QNetworkProxy>
#include <QResizeEvent>
#include <QSettings>
#include <QTimer>
#include <QTextStream>
#include <QTranslator>
#include <QVariant>
#include <QX11Info>
#include <MGConfItem>
#include <QInputContext>

#include "launcherwindow.h"
#include "launcheratoms.h"
#include "launcherapp.h"

#include <QX11Info>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <unistd.h>

class NetworkAccessManagerFactory : public QDeclarativeNetworkAccessManagerFactory
{
public:
    virtual QNetworkAccessManager *create(QObject *parent);
};

QNetworkAccessManager *NetworkAccessManagerFactory::create(QObject *parent)
{
    QUrl httpProxy(getenv("http_proxy"));
    QNetworkAccessManager *nam = new QNetworkAccessManager(parent);
    if (!httpProxy.isEmpty())
    {
        QNetworkProxy proxy(QNetworkProxy::HttpCachingProxy,
                            httpProxy.host(),
                            httpProxy.port());
        nam->setProxy(proxy);
    }

    QNetworkDiskCache *cache = new QNetworkDiskCache();
    cache->setCacheDirectory(QDir::homePath() + "/.cache/" + qApp->applicationName());
    nam->setCache(cache);

    return nam;
}

LauncherWindow::LauncherWindow(bool fullscreen, int width, int height, bool opengl, bool setSource, QWidget *parent) :
    QWidget(parent),
    m_inhibitScreenSaver(false)
{
    LauncherApp *app = static_cast<LauncherApp *>(qApp);

    setWindowTitle(app->applicationName());
    setWindowIconText(app->applicationName());

    int screenWidth;
    int screenHeight;
    if (fullscreen)
    {
        screenWidth = qApp->desktop()->rect().width();
        screenHeight = qApp->desktop()->rect().height();
        setWindowFlags(Qt::FramelessWindowHint);
    }
    else
    {
        screenWidth = width;
        screenHeight = height;
    }

    view = new QDeclarativeView(this);
    view->engine()->setNetworkAccessManagerFactory(new NetworkAccessManagerFactory);
    connect(view->engine(), SIGNAL(quit()), qApp, SLOT(closeAllWindows()));
    connect((const QObject*)qApp->inputContext(), SIGNAL(inputMethodAreaChanged(QRect)),
            this, SLOT(handleInputMethodAreaChanged(QRect)));
    connect(qApp, SIGNAL(dismissKeyboard()), this, SLOT(dismissKeyboard()));

    QDeclarativeContext *context = view->rootContext();
    context->setContextProperty("screenWidth", screenWidth);
    context->setContextProperty("screenHeight", screenHeight);
    context->setContextProperty("qApp", qApp);
    context->setContextProperty("mainWindow", this);
    context->setContextProperty("theme_name", MGConfItem("/meego/ux/theme").value().toString());
    foreach (QString key, app->themeConfig->allKeys())
    {
        if (key.contains("Size") || key.contains("Padding") ||
            key.contains("Width") ||key.contains("Height") ||
            key.contains("Margin") || key.contains("Thickness"))
        {
            context->setContextProperty("theme_" + key, app->themeConfig->value(key).toInt());
        }
        else if (key.contains("Opacity"))
        {
            context->setContextProperty("theme_" + key, app->themeConfig->value(key).toDouble());
        }
        else
        {
            context->setContextProperty("theme_" + key, app->themeConfig->value(key));
        }
    }

    if (setSource) {
      sharePath = QString("/usr/share/") + app->applicationName() + "/";
      if (!QFile::exists(sharePath + "main.qml"))
      {
        qFatal("%s does not exist!", sharePath.toUtf8().data());
      }
    }

    loadTranslators();
    connect(app, SIGNAL(localeSettingsChanged()), this, SLOT(loadTranslators()));

    // Qt will search each translator for a string translation, starting with
    // the last translator installed working back to the first translator.
    // The first translation found wins.
    app->installTranslator(&qtTranslator);     // General Qt translations
    app->installTranslator(&commonTranslator); // Common Components translations
    app->installTranslator(&mediaTranslator);  // Common Media translations
    app->installTranslator(&appTranslator);    // App specific translations

    if (setSource)
    {
      view->setSource(QUrl(sharePath + "main.qml"));
    }

    if (opengl)
    {
        QGLFormat format = QGLFormat::defaultFormat();
        format.setSampleBuffers(false);
        view->setViewport(new QGLWidget(format));
    }

    setGeometry(QRect(0, 0, screenWidth, screenHeight));
}

LauncherWindow::~LauncherWindow()
{
}

void LauncherWindow::loadTranslators()
{
    LauncherApp *app = static_cast<LauncherApp *>(qApp);

    qtTranslator.load("qt_" + QLocale::system().name() + ".qm",
                      QLibraryInfo::location(QLibraryInfo::TranslationsPath));
    commonTranslator.load("meegolabs-ux-components_" + QLocale::system().name() + ".qm",
                          QLibraryInfo::location(QLibraryInfo::TranslationsPath));
    mediaTranslator.load("meego-ux-media-qml_" + QLocale::system().name() + ".qm",
                         QLibraryInfo::location(QLibraryInfo::TranslationsPath));
    appTranslator.load(app->applicationName() + "_" + QLocale::system().name() + ".qm",
                       QLibraryInfo::location(QLibraryInfo::TranslationsPath));
}

void LauncherWindow::triggerSystemUIMenu()
{
    QDBusInterface iface("com.nokia.systemui","/statusindicatormenu","com.meego.core.MStatusIndicatorMenu");
    if(iface.isValid()) iface.call("open");
}

void LauncherWindow::goHome()
{
    setWindowState(windowState() ^ Qt::WindowMinimized);
}

// Called by LauncherApplication when it wants to dismiss the
// keyboard.  hideOnFocusOut() is a slot on MInputContext, that seems
// to be required, it doesn't get it right if you just drop the focus
// (bug in MInputContext?)
void LauncherWindow::dismissKeyboard()
{
    if(view->scene() && view->scene()->focusItem()) {
        view->scene()->focusItem()->clearFocus();
        QMetaObject::invokeMethod(qApp->inputContext(), "hideOnFocusOut");
    }
}

void LauncherWindow::forwardCall(const QStringList& parameters)
{
    emit call(parameters);
}

void LauncherWindow::setActualOrientation(int orientation)
{
    m_actualOrientation = orientation;

    if (!winId())
    {
        return;
    }

    Atom orientationAtom = XInternAtom(QX11Info::display(), "_MEEGO_ORIENTATION", false);
    XChangeProperty(QX11Info::display(), winId(), orientationAtom, XA_CARDINAL, 32,
                    PropModeReplace, (unsigned char*)&m_actualOrientation, 1);
}

bool LauncherWindow::event (QEvent * event)
{
    if (event->type() == QEvent::Show)
    {
        setActualOrientation(m_actualOrientation);
    }
    return QWidget::event(event);
}

void LauncherWindow::setInhibitScreenSaver(bool inhibit)
{
    m_inhibitScreenSaver = inhibit;

    Atom inhibitAtom = XInternAtom(QX11Info::display(), "_MEEGO_INHIBIT_SCREENSAVER", false);
    if (inhibit)
    {
        XChangeProperty(QX11Info::display(), winId(), inhibitAtom, XA_CARDINAL, 32,
                        PropModeReplace, (unsigned char*)&m_inhibitScreenSaver, 1);
    }
    else
    {
        XDeleteProperty(QX11Info::display(), winId(), inhibitAtom);
    }
}
<|endoftext|>


<commit_before>/*
 * This file is part of the IAN project - https://github.com/Meoo/IAN
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <ws/WsAcceptor.hpp>

#include <bin-common/AsioPool.hpp>
#include <bin-common/Cluster.hpp>
#include <bin-common/config/Config.hpp>
#include <bin-common/config/ConfigValue.hpp>
#include <common/EasyProfiler.hpp>
#include <common/Log.hpp>
#include <common/Platform.hpp>

#include <boost/asio/io_context.hpp>

#include <csignal>
#include <cstdlib>
#include <thread>

namespace signals
{
bool should_stop   = false;
bool should_reload = false;
AsioPool * asio_pool;

extern "C" void sig_stop(int)
{
  should_stop = true;
  asio_pool->stop();
}

extern "C" void sig_reload(int)
{
  should_reload = true;
  asio_pool->stop();
}
} // namespace signals

int main(int argc, char ** argv)
{
  EASY_MAIN_THREAD;
  plat::set_thread_name("Front main");

  // Init logger
  spdlog::set_async_mode(256);
  auto logger = spdlog::stdout_color_mt("front");
  std::atexit(spdlog::drop_all);

#ifndef NDEBUG
  spdlog::set_level(spdlog::level::debug);
#endif

  // Load config file
  if (!config::load())
  {
    IAN_CRITICAL(logger, "Failed to read config file");
    spdlog::drop_all();
    return 1;
  }

  // ASIO & listener
  AsioPool asio_pool(logger);
  boost::asio::io_context & asio =
      asio_pool.createAsio("front", ConfigIntValue("front.threads", 2));

  // Cluster
  {
    auto clusterlogger =
        spdlog::create("front.cluster", logger->sinks().begin(), logger->sinks().end());
    cluster::init(clusterlogger, asio_pool, ConfigGroup("cluster"));
  }

  // Websocket
  {
    auto wslogger = spdlog::create("front.ws", logger->sinks().begin(), logger->sinks().end());

    for (auto & group : config::get_childs("front.ws.listen"))
    {
      auto acceptor = std::make_shared<WsAcceptor>(wslogger, asio, group);
      acceptor->run();
    }
  }

  // Install signal handlers
  signals::asio_pool = &asio_pool;

  std::signal(SIGINT, signals::sig_stop);
  std::signal(SIGTERM, signals::sig_stop);
#ifdef SIGHUP
  std::signal(SIGHUP, signals::sig_reload);
#endif

  // Loop when reloading configuration
  for (;;)
  {
    asio_pool.run();

    if (signals::should_stop)
    {
      IAN_INFO(logger, "Received stop signal");
      break;
    }

    if (signals::should_reload)
    {
      if (!config::load())
      {
        IAN_CRITICAL(logger, "Failed to reload config file");
        return 1;
      }

      IAN_INFO(logger, "Config reloaded");
      signals::should_reload = false;
      continue;
    }

    IAN_CRITICAL(logger, "Asio stopped without signal");
    return 1;
  }

  IAN_INFO(logger, "Shutting down");
  return 0;
}
<commit_msg>Remove main thread name<commit_after>/*
 * This file is part of the IAN project - https://github.com/Meoo/IAN
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <ws/WsAcceptor.hpp>

#include <bin-common/AsioPool.hpp>
#include <bin-common/Cluster.hpp>
#include <bin-common/config/Config.hpp>
#include <bin-common/config/ConfigValue.hpp>
#include <common/EasyProfiler.hpp>
#include <common/Log.hpp>

#include <boost/asio/io_context.hpp>

#include <csignal>
#include <cstdlib>
#include <thread>

namespace signals
{
bool should_stop   = false;
bool should_reload = false;
AsioPool * asio_pool;

extern "C" void sig_stop(int)
{
  should_stop = true;
  asio_pool->stop();
}

extern "C" void sig_reload(int)
{
  should_reload = true;
  asio_pool->stop();
}
} // namespace signals

int main(int argc, char ** argv)
{
  EASY_MAIN_THREAD;

  // Init logger
  spdlog::set_async_mode(256);
  auto logger = spdlog::stdout_color_mt("front");
  std::atexit(spdlog::drop_all);

#ifndef NDEBUG
  spdlog::set_level(spdlog::level::debug);
#endif

  // Load config file
  if (!config::load())
  {
    IAN_CRITICAL(logger, "Failed to read config file");
    spdlog::drop_all();
    return 1;
  }

  // ASIO & listener
  AsioPool asio_pool(logger);
  boost::asio::io_context & asio =
      asio_pool.createAsio("front", ConfigIntValue("front.threads", 2));

  // Cluster
  {
    auto clusterlogger =
        spdlog::create("front.cluster", logger->sinks().begin(), logger->sinks().end());
    cluster::init(clusterlogger, asio_pool, ConfigGroup("cluster"));
  }

  // Websocket
  {
    auto wslogger = spdlog::create("front.ws", logger->sinks().begin(), logger->sinks().end());

    for (auto & group : config::get_childs("front.ws.listen"))
    {
      auto acceptor = std::make_shared<WsAcceptor>(wslogger, asio, group);
      acceptor->run();
    }
  }

  // Install signal handlers
  signals::asio_pool = &asio_pool;

  std::signal(SIGINT, signals::sig_stop);
  std::signal(SIGTERM, signals::sig_stop);
#ifdef SIGHUP
  std::signal(SIGHUP, signals::sig_reload);
#endif

  // Loop when reloading configuration
  for (;;)
  {
    asio_pool.run();

    if (signals::should_stop)
    {
      IAN_INFO(logger, "Received stop signal");
      break;
    }

    if (signals::should_reload)
    {
      if (!config::load())
      {
        IAN_CRITICAL(logger, "Failed to reload config file");
        return 1;
      }

      IAN_INFO(logger, "Config reloaded");
      signals::should_reload = false;
      continue;
    }

    IAN_CRITICAL(logger, "Asio stopped without signal");
    return 1;
  }

  IAN_INFO(logger, "Shutting down");
  return 0;
}
<|endoftext|>


<commit_before>/*
Runs a read/write test to confirm communications integrity.
*/

#include <iostream>
#include <sstream>
#include <iomanip>
#include <random>
#include <functional>
#include <chrono>
#include <vector>

#include "libaps2.h"
#include "../C++/helpers.h"

using std::cout;
using std::endl;
using std::string;
using std::vector;

// N-wide hex output with 0x
template <unsigned int N>
std::ostream& hexn(std::ostream& out)
{
    return out << "0x" << std::hex << std::setw(N) << std::setfill('0');
}

int main(int argc, char const *argv[])
{

	//Poll for which device to test
	string deviceSerial = get_device_id();
	if (deviceSerial.empty()){
		cout << concol::RED << "No APS2 devices connected! Exiting..." << concol::RESET << endl;
		return 0;
	}

	set_logging_level(logDEBUG1);

	connect_APS(deviceSerial.c_str());
	stop(deviceSerial.c_str());

	// force initialize device
	initAPS(deviceSerial.c_str(), 1);

	//Generate a random 128MB vector to write
	std::default_random_engine generator;
	std::uniform_int_distribution<uint32_t> wordDistribution;

	size_t testLength = 1048576; //test size in 32 bit words
	vector<uint32_t> testVec(testLength);
	for (size_t ct=0; ct < (testLength); ct++){
		testVec.push_back(wordDistribution(generator));
	}

	//Choose a random starting point in the lower half of sequence memory
	std::uniform_int_distribution<uint32_t> addrDistribution(0, 0x20000000U);
	uint32_t startAddr = addrDistribution(generator);
	startAddr &= ~(0x3); //align address to 32 bit word

	cout << endl << endl;
	cout << concol::RED << "Testing sequence memory:" << concol::RESET << endl;
	cout << concol::RED << "writing " << 4*testLength/1048576 << " MB starting at " << hexn<8> << startAddr << " ..... ";
	cout.flush();
	auto start = std::chrono::steady_clock::now();
	write_memory(deviceSerial.c_str(), startAddr, testVec.data(), testVec.size());
	auto stop = std::chrono::steady_clock::now();
	auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop-start).count();
	cout << " at " << 4.0*testLength/duration << " MB/s." << concol::RESET << endl;

	//Check a few 256 count entries for correctness
	addrDistribution = std::uniform_int_distribution<uint32_t>(startAddr, startAddr+4*testLength-1024);
	for (size_t ct=0; ct < 10; ct++){
		vector<uint32_t> checkVec(256);
		uint32_t checkAddr = addrDistribution(generator);
		checkAddr &= ~(0x3); //align address to 32 bit word
		cout << concol::RED << "reading 1 kB starting at " << hexn<8> << checkAddr << " ..... " << concol::RESET;
		read_memory(deviceSerial.c_str(), checkAddr, checkVec.data(), 256);
		bool passed = true;
		for (auto val : checkVec){
			if (val != testVec[(checkAddr-startAddr)/4]) {
				passed &= false;
			}
			checkAddr += 4;
		}
		if (passed) {
			cout << concol::GREEN << " passed" << concol::RESET << endl;
		}
		else {
			cout << concol::RED << " failed" << concol::RESET << endl;
		}
	}

	disconnect_APS(deviceSerial.c_str());

	return 0;
}
<commit_msg>Make a subfunction and fill out all memory except CSR.<commit_after>/*
Runs a read/write test to confirm communications integrity.
*/

#include <iostream>
#include <sstream>
#include <iomanip>
#include <random>
#include <functional>
#include <chrono>
#include <vector>

#include "libaps2.h"
#include "../C++/helpers.h"

using std::cout;
using std::endl;
using std::string;
using std::vector;

// N-wide hex output with 0x
template <unsigned int N>
std::ostream& hexn(std::ostream& out)
{
    return out << "0x" << std::hex << std::setw(N) << std::setfill('0');
}

void run_test(string deviceSerial, string memArea, uint32_t memStartAddr, uint32_t memHighAddr, size_t testLength){
	//Generate a random vector to write
	std::default_random_engine generator;
	std::uniform_int_distribution<uint32_t> wordDistribution;

	vector<uint32_t> testVec(testLength/4);
	for (size_t ct=0; ct < (testLength/4); ct++){
		testVec[ct] = wordDistribution(generator);
	}

	//Choose a random starting point
	std::uniform_int_distribution<uint32_t> addrDistribution(memStartAddr, memHighAddr-testLength );
	uint32_t testStartAddr = addrDistribution(generator);
	testStartAddr &= ~(0x3); //align address to 32 bit word

	cout << endl << endl;
	cout << concol::RED << "Testing " << memArea << " memory:" << concol::RESET << endl;
	cout << concol::RED << "writing " << testLength/1024 << " kB starting at " << hexn<8> << testStartAddr << " ..... ";
	cout.flush();
	auto start = std::chrono::steady_clock::now();
	write_memory(deviceSerial.c_str(), testStartAddr, testVec.data(), testVec.size());
	auto stop = std::chrono::steady_clock::now();
	auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop-start).count();
	cout << " at " << static_cast<double>(testLength)/duration << " MB/s." << concol::RESET << endl;

	//Check a few 1kB count entries for correctness
	addrDistribution = std::uniform_int_distribution<uint32_t>(testStartAddr, testStartAddr+testLength-1024);
	for (size_t ct=0; ct < 10; ct++){
		vector<uint32_t> checkVec(256);
		uint32_t checkAddr = addrDistribution(generator);
		checkAddr &= ~(0x3); //align address to 32 bit word
		cout << concol::RED << "reading 1 kB starting at " << hexn<8> << checkAddr << " ..... " << concol::RESET;
		read_memory(deviceSerial.c_str(), checkAddr, checkVec.data(), 256);
		bool passed = true;
		for (auto val : checkVec){
			if (val != testVec[(checkAddr-testStartAddr)/4]) {
				passed &= false;
			}
			checkAddr += 4;
		}
		if (passed) {
			cout << concol::GREEN << " passed" << concol::RESET << endl;
		}
		else {
			cout << concol::RED << " failed" << concol::RESET << endl;
		}
	}

}

int main(int argc, char const *argv[])
{

	//Poll for which device to test
	string deviceSerial = get_device_id();
	if (deviceSerial.empty()){
		cout << concol::RED << "No APS2 devices connected! Exiting..." << concol::RESET << endl;
		return 0;
	}

	set_logging_level(logDEBUG1);

	connect_APS(deviceSerial.c_str());
	stop(deviceSerial.c_str());

	// force initialize device
	initAPS(deviceSerial.c_str(), 1);

	run_test(deviceSerial, "sequence", 0, 0x1FFFFFFFu, 4*(1<<20));
	run_test(deviceSerial, "waveform", 0x20000000u, 0x3FFFFFFFu, 4*(1<<20));
	run_test(deviceSerial, "sequence cache", 0xC2000000u, 0xC2007FFF, 8*(1<<10));
	run_test(deviceSerial, "waveform A cache", 0xC4000000u, 0xC403FFFF, 64*(1<<10));
	run_test(deviceSerial, "waveform B cache", 0xC6000000u, 0xC603FFFF, 64*(1<<10));

	disconnect_APS(deviceSerial.c_str());

	return 0;
}
<|endoftext|>