<commit_before>// Copyright (c) 2018 ASMlover. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include <iostream>
#include <boost/python.hpp>

const char* greet(void) {
  return "Hello, PyBoost";
}

class World {
  std::string message_;

  World(const World&) = delete;
  World& operator=(const World&) = delete;
public:
  World(void) = default;
  ~World(void) = default;

  World(const char* msg)
    : message_(msg) {
  }

  void set_msg(const std::string& message) {
    message_ = message;
  }

  std::string get_msg(void) const {
    return message_;
  }
};

class WorldWrapper : public World {
  PyObject* self_{};
public:
  WorldWrapper(PyObject* self)
    : self_(self) {
    boost::python::xincref(self_);
  }

  WorldWrapper(PyObject* self, const char* msg)
    : World(msg)
    , self_(self) {
    boost::python::xincref(self_);
  }

  ~WorldWrapper(void) {
    boost::python::xdecref(self_);
  }
};

struct Var {
  std::string name;
  float value{};

  Var(const char* n = "")
    : name(n) {
  }
};

class VarWrapper : public Var {
  PyObject* self_{};
public:
  VarWrapper(PyObject* self)
    : self_(self) {
    boost::python::xincref(self_);
  }

  VarWrapper(PyObject* self, const char* name)
    : Var(name)
    , self_(self) {
  }

  ~VarWrapper(void) {
    boost::python::xdecref(self_);
  }
};

class Num {
  float value_{};

  Num(const Num&) = delete;
  Num& operator=(const Num&) = delete;
public:
  Num(void) = default;
  ~Num(void) = default;

  void set(float value) {
    value_ = value;
  }

  float get(void) const {
    return value_;
  }
};

class NumWrapper : public Num {
  PyObject* self_{};
public:
  NumWrapper(PyObject* self)
    : self_(self) {
    boost::python::xincref(self_);
  }

  ~NumWrapper(void) {
    boost::python::xdecref(self_);
  }
};

struct Base {
  virtual ~Base(void) {}
  virtual std::string get_name(void) const {
    return "Base";
  }
};

struct Derived : public Base {
  virtual std::string get_name(void) const override {
    return "Derived";
  }
};

static void print_base(Base* b) {
  std::cout << "Base name: " << b->get_name() << std::endl;
}

static void print_derived(Derived* d) {
  std::cout << "Derived name: " << d->get_name() << std::endl;
}

Base* base_factory(void) {
  return new Derived();
}

struct VirtualBase {
  virtual ~VirtualBase(void) {}
  virtual int get_value(void) const {
    return 0;
  }
};

struct VirtualBaseWrap
  : public VirtualBase, public boost::python::wrapper<VirtualBase> {
  virtual int get_value(void) const override {
    if (boost::python::override f = get_override("get_value"))
      return f();
    return VirtualBase::get_value();
  }

  int default_get_value(void) const {
    return VirtualBase::get_value();
  }
};

BOOST_PYTHON_MODULE(pyboost) {
  boost::python::def("greet", greet);

  boost::python::class_<World,
    std::shared_ptr<WorldWrapper>, boost::noncopyable>("World")
    .def(boost::python::init<const char*>())
    .def("set_msg", &World::set_msg)
    .def("get_msg", &World::get_msg);

  boost::python::class_<Var,
    std::shared_ptr<VarWrapper>, boost::noncopyable>("Var")
    .def(boost::python::init<const char*>())
    .def_readonly("name", &Var::name)
    .def_readwrite("value", &Var::value);

  boost::python::class_<Num,
    std::shared_ptr<NumWrapper>, boost::noncopyable>("Num")
    .add_property("rvalue", &Num::get)
    .add_property("value", &Num::get, &Num::set);

  boost::python::class_<Base>("Base")
    .def("get_name", &Base::get_name);
  boost::python::class_<Derived, boost::python::bases<Base>>("Derived")
    .def("get_name", &Derived::get_name);
  boost::python::def("print_base", print_base);
  boost::python::def("print_derived", print_derived);
  boost::python::def("base_factory", base_factory,
      boost::python::return_value_policy<boost::python::manage_new_object>());

  boost::python::class_<VirtualBaseWrap, boost::noncopyable>("VirtualBase")
    .def("get_value",
        &VirtualBase::get_value, &VirtualBaseWrap::default_get_value);
}
<commit_msg>:construction: chore(pyboost): add unit base demo for pyboost<commit_after>// Copyright (c) 2018 ASMlover. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include <iostream>
#include <boost/python.hpp>

const char* greet(void) {
  return "Hello, PyBoost";
}

struct UnitBase {
  std::string basename;

  UnitBase(void) {
  }

  UnitBase(const char* name)
    : basename(name) {
  }

  virtual ~UnitBase(void) {
  }

  std::string get_name(void) const {
    return basename;
  }
};

class World {
  std::string message_;

  World(const World&) = delete;
  World& operator=(const World&) = delete;
public:
  World(void) = default;
  ~World(void) = default;

  World(const char* msg)
    : message_(msg) {
  }

  void set_msg(const std::string& message) {
    message_ = message;
  }

  std::string get_msg(void) const {
    return message_;
  }
};

class WorldWrapper : public World {
  PyObject* self_{};
public:
  WorldWrapper(PyObject* self)
    : self_(self) {
    boost::python::xincref(self_);
  }

  WorldWrapper(PyObject* self, const char* msg)
    : World(msg)
    , self_(self) {
    boost::python::xincref(self_);
  }

  ~WorldWrapper(void) {
    boost::python::xdecref(self_);
  }
};

struct Var {
  std::string name;
  float value{};

  Var(const char* n = "")
    : name(n) {
  }
};

class VarWrapper : public Var {
  PyObject* self_{};
public:
  VarWrapper(PyObject* self)
    : self_(self) {
    boost::python::xincref(self_);
  }

  VarWrapper(PyObject* self, const char* name)
    : Var(name)
    , self_(self) {
  }

  ~VarWrapper(void) {
    boost::python::xdecref(self_);
  }
};

class Num {
  float value_{};

  Num(const Num&) = delete;
  Num& operator=(const Num&) = delete;
public:
  Num(void) = default;
  ~Num(void) = default;

  void set(float value) {
    value_ = value;
  }

  float get(void) const {
    return value_;
  }
};

class NumWrapper : public Num {
  PyObject* self_{};
public:
  NumWrapper(PyObject* self)
    : self_(self) {
    boost::python::xincref(self_);
  }

  ~NumWrapper(void) {
    boost::python::xdecref(self_);
  }
};

struct Base {
  virtual ~Base(void) {}
  virtual std::string get_name(void) const {
    return "Base";
  }
};

struct Derived : public Base {
  virtual std::string get_name(void) const override {
    return "Derived";
  }
};

static void print_base(Base* b) {
  std::cout << "Base name: " << b->get_name() << std::endl;
}

static void print_derived(Derived* d) {
  std::cout << "Derived name: " << d->get_name() << std::endl;
}

Base* base_factory(void) {
  return new Derived();
}

struct VirtualBase {
  virtual ~VirtualBase(void) {}
  virtual int get_value(void) const {
    return 0;
  }
};

struct VirtualBaseWrap
  : public VirtualBase, public boost::python::wrapper<VirtualBase> {
  virtual int get_value(void) const override {
    if (boost::python::override f = get_override("get_value"))
      return f();
    return VirtualBase::get_value();
  }

  int default_get_value(void) const {
    return VirtualBase::get_value();
  }
};

BOOST_PYTHON_MODULE(pyboost) {
  boost::python::def("greet", greet);

  boost::python::class_<UnitBase>("UnitBase")
    .def(boost::python::init<const char*>())
    .def_readwrite("basename", &UnitBase::basename)
    .def("get_name", &UnitBase::get_name);

  boost::python::class_<World,
    std::shared_ptr<WorldWrapper>, boost::noncopyable>("World")
    .def(boost::python::init<const char*>())
    .def("set_msg", &World::set_msg)
    .def("get_msg", &World::get_msg);

  boost::python::class_<Var,
    std::shared_ptr<VarWrapper>, boost::noncopyable>("Var")
    .def(boost::python::init<const char*>())
    .def_readonly("name", &Var::name)
    .def_readwrite("value", &Var::value);

  boost::python::class_<Num,
    std::shared_ptr<NumWrapper>, boost::noncopyable>("Num")
    .add_property("rvalue", &Num::get)
    .add_property("value", &Num::get, &Num::set);

  boost::python::class_<Base>("Base")
    .def("get_name", &Base::get_name);
  boost::python::class_<Derived, boost::python::bases<Base>>("Derived")
    .def("get_name", &Derived::get_name);
  boost::python::def("print_base", print_base);
  boost::python::def("print_derived", print_derived);
  boost::python::def("base_factory", base_factory,
      boost::python::return_value_policy<boost::python::manage_new_object>());

  boost::python::class_<VirtualBaseWrap, boost::noncopyable>("VirtualBase")
    .def("get_value",
        &VirtualBase::get_value, &VirtualBaseWrap::default_get_value);
}
<|endoftext|>


<commit_before>#include "catch2/catch.hpp"
#include "ApprovalTests.hpp"

#include "GildedRose.h"

TEST_CASE("Foo") {

    vector<Item> items;
    items.push_back(Item("foo", 0, 0));
    GildedRose app(items);
    app.updateQuality();
    REQUIRE("fixme" == app.items[0].name);

}
<commit_msg>starting position should include item printer<commit_after>#include <catch2/catch.hpp>
#include "ApprovalTests.hpp"

#include "GildedRose.h"

std::ostream& operator<<(std::ostream& os, const Item& obj)
{
    return os
            << "name: " << obj.name
            << ", sellIn: " << obj.sellIn
            << ", quality: " << obj.quality;
}

TEST_CASE("UpdateQuality") {

    vector<Item> items;
    items.push_back(Item("foo", 0, 0));
    GildedRose app(items);
    app.updateQuality();
    REQUIRE("foo" == app.items[0].name);
}
<|endoftext|>


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

#include "editor_plugin_settings.h"

#include "core/io/config_file.h"
#include "core/os/file_access.h"
#include "core/os/main_loop.h"
#include "core/project_settings.h"
#include "editor_node.h"
#include "editor_scale.h"
#include "scene/gui/margin_container.h"

void EditorPluginSettings::_notification(int p_what) {

	if (p_what == MainLoop::NOTIFICATION_WM_FOCUS_IN) {
		update_plugins();
	} else if (p_what == Node::NOTIFICATION_READY) {
		plugin_config_dialog->connect("plugin_ready", EditorNode::get_singleton(), "_on_plugin_ready");
		plugin_list->connect("button_pressed", this, "_cell_button_pressed");
	}
}

void EditorPluginSettings::update_plugins() {

	plugin_list->clear();

	DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
	Error err = da->change_dir("res://addons");
	if (err != OK) {
		memdelete(da);
		return;
	}

	updating = true;

	TreeItem *root = plugin_list->create_item();

	da->list_dir_begin();

	String d = da->get_next();

	Vector<String> plugins;

	while (d != String()) {

		bool dir = da->current_is_dir();
		String path = "res://addons/" + d + "/plugin.cfg";

		if (dir && FileAccess::exists(path)) {

			plugins.push_back(d);
		}

		d = da->get_next();
	}

	da->list_dir_end();
	memdelete(da);

	plugins.sort();

	for (int i = 0; i < plugins.size(); i++) {

		Ref<ConfigFile> cf;
		cf.instance();
		String path = "res://addons/" + plugins[i] + "/plugin.cfg";

		Error err2 = cf->load(path);

		if (err2 != OK) {
			WARN_PRINTS("Can't load plugin config: " + path);
		} else {
			bool key_missing = false;

			if (!cf->has_section_key("plugin", "name")) {
				WARN_PRINTS("Plugin config misses \"plugin/name\" key: " + path);
				key_missing = true;
			}
			if (!cf->has_section_key("plugin", "author")) {
				WARN_PRINTS("Plugin config misses \"plugin/author\" key: " + path);
				key_missing = true;
			}
			if (!cf->has_section_key("plugin", "version")) {
				WARN_PRINTS("Plugin config misses \"plugin/version\" key: " + path);
				key_missing = true;
			}
			if (!cf->has_section_key("plugin", "description")) {
				WARN_PRINTS("Plugin config misses \"plugin/description\" key: " + path);
				key_missing = true;
			}
			if (!cf->has_section_key("plugin", "script")) {
				WARN_PRINTS("Plugin config misses \"plugin/script\" key: " + path);
				key_missing = true;
			}

			if (!key_missing) {
				String d2 = plugins[i];
				String name = cf->get_value("plugin", "name");
				String author = cf->get_value("plugin", "author");
				String version = cf->get_value("plugin", "version");
				String description = cf->get_value("plugin", "description");
				String script = cf->get_value("plugin", "script");

				TreeItem *item = plugin_list->create_item(root);
				item->set_text(0, name);
				item->set_tooltip(0, TTR("Name:") + " " + name + "\n" + TTR("Path:") + " " + path + "\n" + TTR("Main Script:") + " " + script + "\n" + TTR("Description:") + " " + description);
				item->set_metadata(0, d2);
				item->set_text(1, version);
				item->set_metadata(1, script);
				item->set_text(2, author);
				item->set_metadata(2, description);
				item->set_cell_mode(3, TreeItem::CELL_MODE_RANGE);
				item->set_range_config(3, 0, 1, 1);
				item->set_text(3, "Inactive,Active");
				item->set_editable(3, true);
				item->add_button(4, get_icon("Edit", "EditorIcons"), BUTTON_PLUGIN_EDIT, false, TTR("Edit Plugin"));

				if (EditorNode::get_singleton()->is_addon_plugin_enabled(d2)) {
					item->set_custom_color(3, get_color("success_color", "Editor"));
					item->set_range(3, 1);
				} else {
					item->set_custom_color(3, get_color("disabled_font_color", "Editor"));
					item->set_range(3, 0);
				}
			}
		}
	}

	updating = false;
}

void EditorPluginSettings::_plugin_activity_changed() {

	if (updating)
		return;

	TreeItem *ti = plugin_list->get_edited();
	ERR_FAIL_COND(!ti);
	bool active = ti->get_range(3);
	String name = ti->get_metadata(0);

	EditorNode::get_singleton()->set_addon_plugin_enabled(name, active, true);

	bool is_active = EditorNode::get_singleton()->is_addon_plugin_enabled(name);

	if (is_active != active) {
		updating = true;
		ti->set_range(3, is_active ? 1 : 0);
		updating = false;
	}

	if (is_active)
		ti->set_custom_color(3, get_color("success_color", "Editor"));
	else
		ti->set_custom_color(3, get_color("disabled_font_color", "Editor"));
}

void EditorPluginSettings::_create_clicked() {
	plugin_config_dialog->config("");
	plugin_config_dialog->popup_centered();
}

void EditorPluginSettings::_cell_button_pressed(Object *p_item, int p_column, int p_id) {
	TreeItem *item = Object::cast_to<TreeItem>(p_item);
	if (!item)
		return;
	if (p_id == BUTTON_PLUGIN_EDIT) {
		if (p_column == 4) {
			String dir = item->get_metadata(0);
			plugin_config_dialog->config("res://addons/" + dir + "/plugin.cfg");
			plugin_config_dialog->popup_centered();
		}
	}
}

void EditorPluginSettings::_bind_methods() {

	ClassDB::bind_method("update_plugins", &EditorPluginSettings::update_plugins);
	ClassDB::bind_method("_create_clicked", &EditorPluginSettings::_create_clicked);
	ClassDB::bind_method("_plugin_activity_changed", &EditorPluginSettings::_plugin_activity_changed);
	ClassDB::bind_method("_cell_button_pressed", &EditorPluginSettings::_cell_button_pressed);
}

EditorPluginSettings::EditorPluginSettings() {

	plugin_config_dialog = memnew(PluginConfigDialog);
	plugin_config_dialog->config("");
	add_child(plugin_config_dialog);

	HBoxContainer *title_hb = memnew(HBoxContainer);
	title_hb->add_child(memnew(Label(TTR("Installed Plugins:"))));
	title_hb->add_spacer();
	create_plugin = memnew(Button(TTR("Create")));
	create_plugin->connect("pressed", this, "_create_clicked");
	title_hb->add_child(create_plugin);
	update_list = memnew(Button(TTR("Update")));
	update_list->connect("pressed", this, "update_plugins");
	title_hb->add_child(update_list);
	add_child(title_hb);

	plugin_list = memnew(Tree);
	plugin_list->set_v_size_flags(SIZE_EXPAND_FILL);
	plugin_list->set_columns(5);
	plugin_list->set_column_titles_visible(true);
	plugin_list->set_column_title(0, TTR("Name:"));
	plugin_list->set_column_title(1, TTR("Version:"));
	plugin_list->set_column_title(2, TTR("Author:"));
	plugin_list->set_column_title(3, TTR("Status:"));
	plugin_list->set_column_title(4, TTR("Edit:"));
	plugin_list->set_column_expand(0, true);
	plugin_list->set_column_expand(1, false);
	plugin_list->set_column_expand(2, false);
	plugin_list->set_column_expand(3, false);
	plugin_list->set_column_expand(4, false);
	plugin_list->set_column_min_width(1, 100 * EDSCALE);
	plugin_list->set_column_min_width(2, 250 * EDSCALE);
	plugin_list->set_column_min_width(3, 80 * EDSCALE);
	plugin_list->set_column_min_width(4, 40 * EDSCALE);
	plugin_list->set_hide_root(true);
	plugin_list->connect("item_edited", this, "_plugin_activity_changed");

	VBoxContainer *mc = memnew(VBoxContainer);
	mc->add_child(plugin_list);
	mc->set_v_size_flags(SIZE_EXPAND_FILL);
	mc->set_h_size_flags(SIZE_EXPAND_FILL);

	add_child(mc);

	updating = false;
}
<commit_msg>Use checkbox for plugin status instead of option list<commit_after>/*************************************************************************/
/*  editor_plugin_settings.cpp                                           */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "editor_plugin_settings.h"

#include "core/io/config_file.h"
#include "core/os/file_access.h"
#include "core/os/main_loop.h"
#include "core/project_settings.h"
#include "editor_node.h"
#include "editor_scale.h"
#include "scene/gui/margin_container.h"

void EditorPluginSettings::_notification(int p_what) {

	if (p_what == MainLoop::NOTIFICATION_WM_FOCUS_IN) {
		update_plugins();
	} else if (p_what == Node::NOTIFICATION_READY) {
		plugin_config_dialog->connect("plugin_ready", EditorNode::get_singleton(), "_on_plugin_ready");
		plugin_list->connect("button_pressed", this, "_cell_button_pressed");
	}
}

void EditorPluginSettings::update_plugins() {

	plugin_list->clear();

	DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
	Error err = da->change_dir("res://addons");
	if (err != OK) {
		memdelete(da);
		return;
	}

	updating = true;

	TreeItem *root = plugin_list->create_item();

	da->list_dir_begin();

	String d = da->get_next();

	Vector<String> plugins;

	while (d != String()) {

		bool dir = da->current_is_dir();
		String path = "res://addons/" + d + "/plugin.cfg";

		if (dir && FileAccess::exists(path)) {

			plugins.push_back(d);
		}

		d = da->get_next();
	}

	da->list_dir_end();
	memdelete(da);

	plugins.sort();

	for (int i = 0; i < plugins.size(); i++) {

		Ref<ConfigFile> cf;
		cf.instance();
		String path = "res://addons/" + plugins[i] + "/plugin.cfg";

		Error err2 = cf->load(path);

		if (err2 != OK) {
			WARN_PRINTS("Can't load plugin config: " + path);
		} else {
			bool key_missing = false;

			if (!cf->has_section_key("plugin", "name")) {
				WARN_PRINTS("Plugin config misses \"plugin/name\" key: " + path);
				key_missing = true;
			}
			if (!cf->has_section_key("plugin", "author")) {
				WARN_PRINTS("Plugin config misses \"plugin/author\" key: " + path);
				key_missing = true;
			}
			if (!cf->has_section_key("plugin", "version")) {
				WARN_PRINTS("Plugin config misses \"plugin/version\" key: " + path);
				key_missing = true;
			}
			if (!cf->has_section_key("plugin", "description")) {
				WARN_PRINTS("Plugin config misses \"plugin/description\" key: " + path);
				key_missing = true;
			}
			if (!cf->has_section_key("plugin", "script")) {
				WARN_PRINTS("Plugin config misses \"plugin/script\" key: " + path);
				key_missing = true;
			}

			if (!key_missing) {
				String d2 = plugins[i];
				String name = cf->get_value("plugin", "name");
				String author = cf->get_value("plugin", "author");
				String version = cf->get_value("plugin", "version");
				String description = cf->get_value("plugin", "description");
				String script = cf->get_value("plugin", "script");

				TreeItem *item = plugin_list->create_item(root);
				item->set_text(0, name);
				item->set_tooltip(0, TTR("Name:") + " " + name + "\n" + TTR("Path:") + " " + path + "\n" + TTR("Main Script:") + " " + script + "\n" + TTR("Description:") + " " + description);
				item->set_metadata(0, d2);
				item->set_text(1, version);
				item->set_metadata(1, script);
				item->set_text(2, author);
				item->set_metadata(2, description);
				item->set_cell_mode(3, TreeItem::CELL_MODE_CHECK);
				item->set_text(3, TTR("Enable"));
				bool is_active = EditorNode::get_singleton()->is_addon_plugin_enabled(d2);
				item->set_checked(3, is_active);
				item->set_editable(3, true);
				item->add_button(4, get_icon("Edit", "EditorIcons"), BUTTON_PLUGIN_EDIT, false, TTR("Edit Plugin"));
			}
		}
	}

	updating = false;
}

void EditorPluginSettings::_plugin_activity_changed() {

	if (updating)
		return;

	TreeItem *ti = plugin_list->get_edited();
	ERR_FAIL_COND(!ti);
	bool active = ti->is_checked(3);
	String name = ti->get_metadata(0);

	EditorNode::get_singleton()->set_addon_plugin_enabled(name, active, true);

	bool is_active = EditorNode::get_singleton()->is_addon_plugin_enabled(name);

	if (is_active != active) {
		updating = true;
		ti->set_checked(3, is_active);
		updating = false;
	}
}

void EditorPluginSettings::_create_clicked() {
	plugin_config_dialog->config("");
	plugin_config_dialog->popup_centered();
}

void EditorPluginSettings::_cell_button_pressed(Object *p_item, int p_column, int p_id) {
	TreeItem *item = Object::cast_to<TreeItem>(p_item);
	if (!item)
		return;
	if (p_id == BUTTON_PLUGIN_EDIT) {
		if (p_column == 4) {
			String dir = item->get_metadata(0);
			plugin_config_dialog->config("res://addons/" + dir + "/plugin.cfg");
			plugin_config_dialog->popup_centered();
		}
	}
}

void EditorPluginSettings::_bind_methods() {

	ClassDB::bind_method("update_plugins", &EditorPluginSettings::update_plugins);
	ClassDB::bind_method("_create_clicked", &EditorPluginSettings::_create_clicked);
	ClassDB::bind_method("_plugin_activity_changed", &EditorPluginSettings::_plugin_activity_changed);
	ClassDB::bind_method("_cell_button_pressed", &EditorPluginSettings::_cell_button_pressed);
}

EditorPluginSettings::EditorPluginSettings() {

	plugin_config_dialog = memnew(PluginConfigDialog);
	plugin_config_dialog->config("");
	add_child(plugin_config_dialog);

	HBoxContainer *title_hb = memnew(HBoxContainer);
	title_hb->add_child(memnew(Label(TTR("Installed Plugins:"))));
	title_hb->add_spacer();
	create_plugin = memnew(Button(TTR("Create")));
	create_plugin->connect("pressed", this, "_create_clicked");
	title_hb->add_child(create_plugin);
	update_list = memnew(Button(TTR("Update")));
	update_list->connect("pressed", this, "update_plugins");
	title_hb->add_child(update_list);
	add_child(title_hb);

	plugin_list = memnew(Tree);
	plugin_list->set_v_size_flags(SIZE_EXPAND_FILL);
	plugin_list->set_columns(5);
	plugin_list->set_column_titles_visible(true);
	plugin_list->set_column_title(0, TTR("Name:"));
	plugin_list->set_column_title(1, TTR("Version:"));
	plugin_list->set_column_title(2, TTR("Author:"));
	plugin_list->set_column_title(3, TTR("Status:"));
	plugin_list->set_column_title(4, TTR("Edit:"));
	plugin_list->set_column_expand(0, true);
	plugin_list->set_column_expand(1, false);
	plugin_list->set_column_expand(2, false);
	plugin_list->set_column_expand(3, false);
	plugin_list->set_column_expand(4, false);
	plugin_list->set_column_min_width(1, 100 * EDSCALE);
	plugin_list->set_column_min_width(2, 250 * EDSCALE);
	plugin_list->set_column_min_width(3, 80 * EDSCALE);
	plugin_list->set_column_min_width(4, 40 * EDSCALE);
	plugin_list->set_hide_root(true);
	plugin_list->connect("item_edited", this, "_plugin_activity_changed");

	VBoxContainer *mc = memnew(VBoxContainer);
	mc->add_child(plugin_list);
	mc->set_v_size_flags(SIZE_EXPAND_FILL);
	mc->set_h_size_flags(SIZE_EXPAND_FILL);

	add_child(mc);

	updating = false;
}
<|endoftext|>


<commit_before>/* TrainingData.cpp
 *
 * Kubo Ryosuke
 */

#include "learn/training_data/TrainingData.hpp"
#include "core/record/Record.hpp"
#include "core/record/CsaReader.hpp"
#include "common/file_system/Directory.hpp"
#include <cstring>

namespace sunfish {

bool TrainingDataGenerator::writeToFile(const char* path) const {
  std::ofstream file(path, std::ios::out | std::ios::binary);
  if (!file) {
    LOG(error) << "could not open a file: " << path;
    return false;
  }

  for (auto ite = trainingData_.begin(); ite != trainingData_.end(); ite++) {
    char sfenSize = static_cast<char>(ite->sfen.size());
    file.write(&sfenSize, sizeof(sfenSize));
    file.write(ite->sfen.c_str(), ite->sfen.size());
    uint16_t move = ite->move.serialize16();
    file.write(reinterpret_cast<char*>(&move), sizeof(move));
  }
  file.close();

  return true;
}

bool TrainingDataGenerator::loadCsaFiles(const char* dir) {
  Directory directory(dir);
  auto files = directory.files("*.csa");

  if (files.size() == 0) {
    LOG(error) << ".csa files not found";
    return false;
  }

  for (auto ite = files.begin(); ite != files.end(); ite++) {
    std::ifstream file(*ite);
    if (!file) {
      LOG(error) << "could not open a file: " << *ite;
      continue;
    }
    Record record;
    CsaReader::read(file, record);
    file.close();

    Position pos = record.initialPosition;
    for (const auto& move : record.moveList) {
      auto sfen = pos.toStringSFEN();
      trainingData_.push_back({ std::move(sfen), move });

      Piece captured;
      if (!pos.doMove(move, captured)) {
        LOG(error) << "an illegal move is detected: " << move.toString(pos) << "\n"
                   << pos.toString();
        break;
      }
    }
  }

  return true;
}

void TrainingDataGenerator::shuffle(Random& random) {
  random.shuffle(trainingData_.begin(), trainingData_.end());
}

TrainingDataReader::~TrainingDataReader() {
  file_.close();
}

bool TrainingDataReader::open(const char* path) {
  file_.open(path, std::ios::in | std::ios::binary);
  return file_.operator bool();
}

bool TrainingDataReader::read(TrainingDataElement& elem) {
  char sfenSize;
  file_.read(&sfenSize, sizeof(sfenSize));
  if (file_.eof()) {
    return false;
  }

  char sfen[sfenSize+1];
  memset(sfen, 0, sizeof(sfen));
  file_.read(sfen, sfenSize);

  uint16_t move;
  file_.read(reinterpret_cast<char*>(&move), sizeof(move));

  elem.sfen = sfen;
  elem.move = Move::deserialize(move);

  return true;
}

} // namespace sunfish
<commit_msg>Fix TrainingDataReader<commit_after>/* TrainingData.cpp
 *
 * Kubo Ryosuke
 */

#include "learn/training_data/TrainingData.hpp"
#include "core/record/Record.hpp"
#include "core/record/CsaReader.hpp"
#include "common/file_system/Directory.hpp"
#include <cstring>

namespace sunfish {

bool TrainingDataGenerator::writeToFile(const char* path) const {
  std::ofstream file(path, std::ios::out | std::ios::binary);
  if (!file) {
    LOG(error) << "could not open a file: " << path;
    return false;
  }

  for (auto ite = trainingData_.begin(); ite != trainingData_.end(); ite++) {
    char sfenSize = static_cast<char>(ite->sfen.size());
    file.write(&sfenSize, sizeof(sfenSize));
    file.write(ite->sfen.c_str(), ite->sfen.size());
    uint16_t move = ite->move.serialize16();
    file.write(reinterpret_cast<char*>(&move), sizeof(move));
  }
  file.close();

  return true;
}

bool TrainingDataGenerator::loadCsaFiles(const char* dir) {
  Directory directory(dir);
  auto files = directory.files("*.csa");

  if (files.size() == 0) {
    LOG(error) << ".csa files not found";
    return false;
  }

  for (auto ite = files.begin(); ite != files.end(); ite++) {
    std::ifstream file(*ite);
    if (!file) {
      LOG(error) << "could not open a file: " << *ite;
      continue;
    }
    Record record;
    CsaReader::read(file, record);
    file.close();

    Position pos = record.initialPosition;
    for (const auto& move : record.moveList) {
      auto sfen = pos.toStringSFEN();
      trainingData_.push_back({ std::move(sfen), move });

      Piece captured;
      if (!pos.doMove(move, captured)) {
        LOG(error) << "an illegal move is detected: " << move.toString(pos) << "\n"
                   << pos.toString();
        break;
      }
    }
  }

  return true;
}

void TrainingDataGenerator::shuffle(Random& random) {
  random.shuffle(trainingData_.begin(), trainingData_.end());
}

TrainingDataReader::~TrainingDataReader() {
  if (file_.is_open()) {
    file_.close();
  }
}

bool TrainingDataReader::open(const char* path) {
  file_.open(path, std::ios::in | std::ios::binary);
  return !file_.fail();
}

bool TrainingDataReader::read(TrainingDataElement& elem) {
  char sfenSize;
  file_.read(&sfenSize, sizeof(sfenSize));
  if (file_.eof()) {
    return false;
  }

  char sfen[sfenSize+1];
  memset(sfen, 0, sizeof(sfen));
  file_.read(sfen, sfenSize);

  uint16_t move;
  file_.read(reinterpret_cast<char*>(&move), sizeof(move));

  elem.sfen = sfen;
  elem.move = Move::deserialize(move);

  return true;
}

} // namespace sunfish
<|endoftext|>


<commit_before>
//@HEADER
// ************************************************************************
//
//               HPCG: Simple Conjugate Gradient Benchmark Code
// Questions? Contact Michael A. Heroux (maherou@sandia.gov)
//
// ************************************************************************
//@HEADER

#ifndef SPARSEMATRIX_HPP
#define SPARSEMATRIX_HPP

#include <map>
#include <vector>
#include "Geometry.hpp"
#ifdef DETAILEDDEBUG
#include <iostream>
#endif

struct SparseMatrix_STRUCT {
  char   *title;
  global_int_t totalNumberOfRows;
  global_int_t totalNumberOfNonzeros;
  local_int_t localNumberOfRows;
  local_int_t localNumberOfColumns;  // Must be defined in make_local_matrix
  global_int_t localNumberOfNonzeros;  //Make this a globlal since it can get big
  char  * nonzerosInRow;  // The number of nonzeros in a row will always be 27 or fewer
  global_int_t ** mtxIndG;
  local_int_t ** mtxIndL;
  double ** matrixValues;
  double ** matrixDiagonal;
  std::map< global_int_t, local_int_t > globalToLocalMap;
  std::vector< global_int_t > localToGlobalMap;

#ifndef HPCG_NOMPI
  local_int_t numberOfExternalValues;
  int numberOfSendNeighbors;
  local_int_t totalToBeSent;
  local_int_t *elementsToSend;
  int *neighbors;
  local_int_t *receiveLength;
  local_int_t *sendLength;
  double *sendBuffer;
#endif
};
typedef struct SparseMatrix_STRUCT SparseMatrix;

inline void initializeMatrix(SparseMatrix & A) {
	A.title = 0;
	A.totalNumberOfRows = 0;
	A.totalNumberOfNonzeros = 0;
	A.localNumberOfRows = 0;
	A.localNumberOfColumns = 0;
	A.localNumberOfNonzeros = 0;
	A.nonzerosInRow = 0;
	A.mtxIndG = 0;
	A.mtxIndL = 0;
	A.matrixValues = 0;
	A.matrixDiagonal = 0;

	#ifndef HPCG_NOMPI
	A.numberOfExternalValues = 0;
	A.numberOfSendNeighbors = 0;
	A.totalToBeSent = 0;
	A.elementsToSend = 0;
	A.neighbors = 0;
	A.receiveLength = 0;
	A.sendLength = 0;
	A.sendBuffer = 0;
	#endif
	return;
}

inline void destroyMatrix(SparseMatrix & A) {

	for (int i = 0; i< A.localNumberOfRows; ++i) {
		delete [] A.matrixValues[i];
		delete [] A.mtxIndG[i];
		delete [] A.mtxIndL[i];
	}
	if(A.title)                  delete [] A.title;
	if(A.nonzerosInRow)             delete [] A.nonzerosInRow;
	if(A.mtxIndG) delete [] A.mtxIndG;
	if(A.mtxIndL) delete [] A.mtxIndL;
	if(A.matrixValues) delete [] A.matrixValues;
	if(A.matrixDiagonal)           delete [] A.matrixDiagonal;

#ifndef HPCG_NOMPI
	if(A.elementsToSend)       delete [] A.elementsToSend;
	if(A.neighbors)              delete [] A.neighbors;
	if(A.receiveLength)            delete [] A.receiveLength;
	if(A.sendLength)            delete [] A.sendLength;
	if(A.sendBuffer)            delete [] A.sendBuffer;
#endif
	initializeMatrix(A);
	return;
}

inline int getRankOfMatrixRow(const Geometry & geom, const SparseMatrix & A, global_int_t index) {
	// For the global row id given in the argument index, return the MPI process rank that is assigned that row
	int gnx = geom.nx*geom.npx;
	int gny = geom.ny*geom.npy;

	int iz = index/(gny*gnx);
	int iy = (index-iz*gny*gnx)/gnx;
	int ix = index%gnx;
	int ipz = iz/geom.nz;
	int ipy = iy/geom.ny;
	int ipx = ix/geom.nx;
	int rank = ipx+ipy*geom.npx+ipz*geom.npy*geom.npx;
#ifdef DETAILEDDEBUG
	//std::cout << "In getRank, rank = " << geom.rank << " index, gnx, gny, ipz, ipy, ipx, rank = " << index << " " << gnx << " "  << " " << gny << " " << ipz << " " << ipy << " " << ipx << " " << rank << std::endl;
#endif
	return(rank);

}

#endif // SPARSEMATRIX_HPP

<commit_msg>Added a member to store optimization data.<commit_after>
//@HEADER
// ************************************************************************
//
//               HPCG: Simple Conjugate Gradient Benchmark Code
// Questions? Contact Michael A. Heroux (maherou@sandia.gov)
//
// ************************************************************************
//@HEADER

#ifndef SPARSEMATRIX_HPP
#define SPARSEMATRIX_HPP

#include <map>
#include <vector>
#include "Geometry.hpp"
#ifdef DETAILEDDEBUG
#include <iostream>
#endif

struct SparseMatrix_STRUCT {
  char   *title;
  global_int_t totalNumberOfRows;
  global_int_t totalNumberOfNonzeros;
  local_int_t localNumberOfRows;
  local_int_t localNumberOfColumns;  // Must be defined in make_local_matrix
  global_int_t localNumberOfNonzeros;  //Make this a globlal since it can get big
  char  * nonzerosInRow;  // The number of nonzeros in a row will always be 27 or fewer
  global_int_t ** mtxIndG;
  local_int_t ** mtxIndL;
  double ** matrixValues;
  double ** matrixDiagonal;
  std::map< global_int_t, local_int_t > globalToLocalMap;
  std::vector< global_int_t > localToGlobalMap;

  /*
   This is for storing optimized data structres created in OptimizeProblem and
   used inside optimized spmv().
   */
  void *optimization_data;

#ifndef HPCG_NOMPI
  local_int_t numberOfExternalValues;
  int numberOfSendNeighbors;
  local_int_t totalToBeSent;
  local_int_t *elementsToSend;
  int *neighbors;
  local_int_t *receiveLength;
  local_int_t *sendLength;
  double *sendBuffer;
#endif
};
typedef struct SparseMatrix_STRUCT SparseMatrix;

inline void initializeMatrix(SparseMatrix & A) {
	A.title = 0;
	A.totalNumberOfRows = 0;
	A.totalNumberOfNonzeros = 0;
	A.localNumberOfRows = 0;
	A.localNumberOfColumns = 0;
	A.localNumberOfNonzeros = 0;
	A.nonzerosInRow = 0;
	A.mtxIndG = 0;
	A.mtxIndL = 0;
	A.matrixValues = 0;
	A.matrixDiagonal = 0;

	#ifndef HPCG_NOMPI
	A.numberOfExternalValues = 0;
	A.numberOfSendNeighbors = 0;
	A.totalToBeSent = 0;
	A.elementsToSend = 0;
	A.neighbors = 0;
	A.receiveLength = 0;
	A.sendLength = 0;
	A.sendBuffer = 0;
	#endif
	return;
}

inline void destroyMatrix(SparseMatrix & A) {

	for (int i = 0; i< A.localNumberOfRows; ++i) {
		delete [] A.matrixValues[i];
		delete [] A.mtxIndG[i];
		delete [] A.mtxIndL[i];
	}
	if(A.title)                  delete [] A.title;
	if(A.nonzerosInRow)             delete [] A.nonzerosInRow;
	if(A.mtxIndG) delete [] A.mtxIndG;
	if(A.mtxIndL) delete [] A.mtxIndL;
	if(A.matrixValues) delete [] A.matrixValues;
	if(A.matrixDiagonal)           delete [] A.matrixDiagonal;

#ifndef HPCG_NOMPI
	if(A.elementsToSend)       delete [] A.elementsToSend;
	if(A.neighbors)              delete [] A.neighbors;
	if(A.receiveLength)            delete [] A.receiveLength;
	if(A.sendLength)            delete [] A.sendLength;
	if(A.sendBuffer)            delete [] A.sendBuffer;
#endif
	initializeMatrix(A);
	return;
}

inline int getRankOfMatrixRow(const Geometry & geom, const SparseMatrix & A, global_int_t index) {
	// For the global row id given in the argument index, return the MPI process rank that is assigned that row
	int gnx = geom.nx*geom.npx;
	int gny = geom.ny*geom.npy;

	int iz = index/(gny*gnx);
	int iy = (index-iz*gny*gnx)/gnx;
	int ix = index%gnx;
	int ipz = iz/geom.nz;
	int ipy = iy/geom.ny;
	int ipx = ix/geom.nx;
	int rank = ipx+ipy*geom.npx+ipz*geom.npy*geom.npx;
#ifdef DETAILEDDEBUG
	//std::cout << "In getRank, rank = " << geom.rank << " index, gnx, gny, ipz, ipy, ipx, rank = " << index << " " << gnx << " "  << " " << gny << " " << ipz << " " << ipy << " " << ipx << " " << rank << std::endl;
#endif
	return(rank);

}

#endif // SPARSEMATRIX_HPP

<|endoftext|>


<commit_before>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE JPetCachedFunctionTest

#include "JPetCachedFunction/JPetCachedFunction.h"
#include "JPetLoggerInclude.h"
#include <boost/test/unit_test.hpp>

using namespace jpet_common_tools;
/// Returns Time-over-threshold for given deposited energy
/// the current parametrization is par1 + par2 * eDep
/// Returned value in ps, and eDep is given in keV.
double getToT1(double eDep, double  par1 = -91958., double par2 = 19341.)
{
  if (eDep < 0. ) return 0.;
  double value = par1 + eDep * par2;
  return value;
}

BOOST_AUTO_TEST_SUITE(JPetCachedFunctionTestSuite)

BOOST_AUTO_TEST_CASE(getTot_params)
{
  JPetCachedFunctionParams params("pol1", { -91958., 19341.});
  JPetCachedFunction1D func(params, Range(100, 0., 100.));
  BOOST_CHECK(func.getParams().fValidFunction);
  BOOST_CHECK_EQUAL(func.getParams().fParams.size(), 2);
  BOOST_CHECK_EQUAL(func.getParams().fParams[0], -91958.);
  BOOST_CHECK_EQUAL(func.getParams().fParams[1], 19341.);
  BOOST_CHECK_EQUAL(func.getValues().size(), 100);
  BOOST_CHECK_EQUAL(func.getRange().fBins, 100);
  BOOST_CHECK_EQUAL(func.getRange().fBins, 100);
  BOOST_CHECK_CLOSE(func.getRange().fMin, 0, 0.1);
  BOOST_CHECK_CLOSE(func.getRange().fMax, 100, 0.1);
  auto vals = func.getValues();
}

BOOST_AUTO_TEST_CASE(getTot_standardFunc)
{
  JPetCachedFunctionParams params("pol1", { -91958., 19341.});
  JPetCachedFunction1D func(params, Range( 10000, 0., 100.));
  BOOST_CHECK(func.getParams().fValidFunction);
  BOOST_CHECK_CLOSE(func(0.), getToT1(0.), 0.1);
  BOOST_CHECK_CLOSE(func(1.), getToT1(1.), 0.1);
  BOOST_CHECK_CLOSE(func(10.), getToT1(10.), 0.1);
  BOOST_CHECK_CLOSE(func(59.5), getToT1(59.5), 0.1);
  BOOST_CHECK_CLOSE(func(99.9), getToT1(99.9), 0.1);
  BOOST_CHECK_EQUAL(func.getRange().fBins, 10000);
  BOOST_CHECK_CLOSE(func.getRange().fMin, 0, 0.1);
  BOOST_CHECK_CLOSE(func.getRange().fMax, 100, 0.1);
}

BOOST_AUTO_TEST_CASE(getTot_quadratic)
{
  JPetCachedFunctionParams params("pol2", {1., 1., 1.}); /// 1 + x + x^2
  JPetCachedFunction1D func(params, Range(10000, 0., 100.));
  BOOST_CHECK(func.getParams().fValidFunction);
  BOOST_CHECK_CLOSE(func(0), 1., 0.1);
  BOOST_CHECK_CLOSE(func(1), 3., 0.1);
  BOOST_CHECK_CLOSE(func(2), 7., 0.1);
  BOOST_CHECK_CLOSE(func(3), 13., 0.1);
  BOOST_CHECK_EQUAL(func.getRange().fBins, 10000);
  BOOST_CHECK_CLOSE(func.getRange().fMin, 0, 0.1);
  BOOST_CHECK_CLOSE(func.getRange().fMax, 100, 0.1);
}

BOOST_AUTO_TEST_CASE(cached_2D)
{
  JPetCachedFunctionParams params("[0] + [1] * x  + [2] * y", {1., 1., 2.}); /// 1 + x + 2 * y
  JPetCachedFunction2D func(params, Range(100, 0., 100.), Range(100, 0., 100.));
  BOOST_CHECK(func.getParams().fValidFunction);
  BOOST_CHECK_CLOSE(func(0., 0.), 1., 0.1);
  BOOST_CHECK_CLOSE(func(1, 1.), 4., 0.1);
  BOOST_CHECK_CLOSE(func(0., 1.), 3., 0.1);
  BOOST_CHECK_CLOSE(func(1., 0.), 2., 0.1);
  BOOST_CHECK_EQUAL(func.getRange().first.fBins, 100);
  BOOST_CHECK_CLOSE(func.getRange().first.fMin, 0, 0.1);
  BOOST_CHECK_CLOSE(func.getRange().first.fMax, 100, 0.1);
  BOOST_CHECK_EQUAL(func.getRange().second.fBins, 100);
  BOOST_CHECK_CLOSE(func.getRange().second.fMin, 0, 0.1);
  BOOST_CHECK_CLOSE(func.getRange().second.fMax, 100, 0.1);
}

BOOST_AUTO_TEST_CASE(cached_log)
{
  JPetCachedFunctionParams params("[0] + [1] * TMath::Log(x)", {1., -2.}); /// 1 + -2 * log(x)
  JPetCachedFunction1D func(params, Range(10000, 2., 100.));
  BOOST_CHECK(func.getParams().fValidFunction);
  BOOST_CHECK_CLOSE(func(2.), -0.386294, 0.1);
  BOOST_CHECK_CLOSE(func(3.), -1.19696, 0.1);
  BOOST_CHECK_CLOSE(func(99.), -8.19005, 0.1);
  BOOST_CHECK_EQUAL(func.getRange().fBins, 10000);
  BOOST_CHECK_CLOSE(func.getRange().fMin, 2, 0.1);
  BOOST_CHECK_CLOSE(func.getRange().fMax, 100, 0.1);
}
BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Remove repated line in tests<commit_after>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE JPetCachedFunctionTest

#include "JPetCachedFunction/JPetCachedFunction.h"
#include "JPetLoggerInclude.h"
#include <boost/test/unit_test.hpp>

using namespace jpet_common_tools;
/// Returns Time-over-threshold for given deposited energy
/// the current parametrization is par1 + par2 * eDep
/// Returned value in ps, and eDep is given in keV.
double getToT1(double eDep, double  par1 = -91958., double par2 = 19341.)
{
  if (eDep < 0. ) return 0.;
  double value = par1 + eDep * par2;
  return value;
}

BOOST_AUTO_TEST_SUITE(JPetCachedFunctionTestSuite)

BOOST_AUTO_TEST_CASE(getTot_params)
{
  JPetCachedFunctionParams params("pol1", { -91958., 19341.});
  JPetCachedFunction1D func(params, Range(100, 0., 100.));
  BOOST_CHECK(func.getParams().fValidFunction);
  BOOST_CHECK_EQUAL(func.getParams().fParams.size(), 2);
  BOOST_CHECK_EQUAL(func.getParams().fParams[0], -91958.);
  BOOST_CHECK_EQUAL(func.getParams().fParams[1], 19341.);
  BOOST_CHECK_EQUAL(func.getValues().size(), 100);
  BOOST_CHECK_EQUAL(func.getRange().fBins, 100);
  BOOST_CHECK_CLOSE(func.getRange().fMin, 0, 0.1);
  BOOST_CHECK_CLOSE(func.getRange().fMax, 100, 0.1);
  auto vals = func.getValues();
}

BOOST_AUTO_TEST_CASE(getTot_standardFunc)
{
  JPetCachedFunctionParams params("pol1", { -91958., 19341.});
  JPetCachedFunction1D func(params, Range( 10000, 0., 100.));
  BOOST_CHECK(func.getParams().fValidFunction);
  BOOST_CHECK_CLOSE(func(0.), getToT1(0.), 0.1);
  BOOST_CHECK_CLOSE(func(1.), getToT1(1.), 0.1);
  BOOST_CHECK_CLOSE(func(10.), getToT1(10.), 0.1);
  BOOST_CHECK_CLOSE(func(59.5), getToT1(59.5), 0.1);
  BOOST_CHECK_CLOSE(func(99.9), getToT1(99.9), 0.1);
  BOOST_CHECK_EQUAL(func.getRange().fBins, 10000);
  BOOST_CHECK_CLOSE(func.getRange().fMin, 0, 0.1);
  BOOST_CHECK_CLOSE(func.getRange().fMax, 100, 0.1);
}

BOOST_AUTO_TEST_CASE(getTot_quadratic)
{
  JPetCachedFunctionParams params("pol2", {1., 1., 1.}); /// 1 + x + x^2
  JPetCachedFunction1D func(params, Range(10000, 0., 100.));
  BOOST_CHECK(func.getParams().fValidFunction);
  BOOST_CHECK_CLOSE(func(0), 1., 0.1);
  BOOST_CHECK_CLOSE(func(1), 3., 0.1);
  BOOST_CHECK_CLOSE(func(2), 7., 0.1);
  BOOST_CHECK_CLOSE(func(3), 13., 0.1);
  BOOST_CHECK_EQUAL(func.getRange().fBins, 10000);
  BOOST_CHECK_CLOSE(func.getRange().fMin, 0, 0.1);
  BOOST_CHECK_CLOSE(func.getRange().fMax, 100, 0.1);
}

BOOST_AUTO_TEST_CASE(cached_2D)
{
  JPetCachedFunctionParams params("[0] + [1] * x  + [2] * y", {1., 1., 2.}); /// 1 + x + 2 * y
  JPetCachedFunction2D func(params, Range(100, 0., 100.), Range(100, 0., 100.));
  BOOST_CHECK(func.getParams().fValidFunction);
  BOOST_CHECK_CLOSE(func(0., 0.), 1., 0.1);
  BOOST_CHECK_CLOSE(func(1, 1.), 4., 0.1);
  BOOST_CHECK_CLOSE(func(0., 1.), 3., 0.1);
  BOOST_CHECK_CLOSE(func(1., 0.), 2., 0.1);
  BOOST_CHECK_EQUAL(func.getRange().first.fBins, 100);
  BOOST_CHECK_CLOSE(func.getRange().first.fMin, 0, 0.1);
  BOOST_CHECK_CLOSE(func.getRange().first.fMax, 100, 0.1);
  BOOST_CHECK_EQUAL(func.getRange().second.fBins, 100);
  BOOST_CHECK_CLOSE(func.getRange().second.fMin, 0, 0.1);
  BOOST_CHECK_CLOSE(func.getRange().second.fMax, 100, 0.1);
}

BOOST_AUTO_TEST_CASE(cached_log)
{
  JPetCachedFunctionParams params("[0] + [1] * TMath::Log(x)", {1., -2.}); /// 1 + -2 * log(x)
  JPetCachedFunction1D func(params, Range(10000, 2., 100.));
  BOOST_CHECK(func.getParams().fValidFunction);
  BOOST_CHECK_CLOSE(func(2.), -0.386294, 0.1);
  BOOST_CHECK_CLOSE(func(3.), -1.19696, 0.1);
  BOOST_CHECK_CLOSE(func(99.), -8.19005, 0.1);
  BOOST_CHECK_EQUAL(func.getRange().fBins, 10000);
  BOOST_CHECK_CLOSE(func.getRange().fMin, 2, 0.1);
  BOOST_CHECK_CLOSE(func.getRange().fMax, 100, 0.1);
}
BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>//===- SymbolTable.cpp ----------------------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Symbol table is a bag of all known symbols. We put all symbols of
// all input files to the symbol table. The symbol table is basically
// a hash table with the logic to resolve symbol name conflicts using
// the symbol types.
//
//===----------------------------------------------------------------------===//

#include "SymbolTable.h"
#include "Config.h"
#include "Error.h"
#include "Symbols.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Support/StringSaver.h"

using namespace llvm;
using namespace llvm::object;
using namespace llvm::ELF;

using namespace lld;
using namespace lld::elf;

// All input object files must be for the same architecture
// (e.g. it does not make sense to link x86 object files with
// MIPS object files.) This function checks for that error.
template <class ELFT> static bool isCompatible(InputFile *FileP) {
  auto *F = dyn_cast<ELFFileBase<ELFT>>(FileP);
  if (!F)
    return true;
  if (F->getELFKind() == Config->EKind && F->getEMachine() == Config->EMachine)
    return true;
  StringRef A = F->getName();
  StringRef B = Config->Emulation;
  if (B.empty())
    B = Config->FirstElf->getName();
  error(A + " is incompatible with " + B);
  return false;
}

// Returns "(internal)", "foo.a(bar.o)" or "baz.o".
static std::string getFilename(InputFile *F) {
  if (!F)
    return "(internal)";
  if (!F->ArchiveName.empty())
    return (F->ArchiveName + "(" + F->getName() + ")").str();
  return F->getName();
}

// Add symbols in File to the symbol table.
template <class ELFT>
void SymbolTable<ELFT>::addFile(std::unique_ptr<InputFile> File) {
  InputFile *FileP = File.get();
  if (!isCompatible<ELFT>(FileP))
    return;

  // .a file
  if (auto *F = dyn_cast<ArchiveFile>(FileP)) {
    ArchiveFiles.emplace_back(cast<ArchiveFile>(File.release()));
    F->parse();
    for (Lazy &Sym : F->getLazySymbols())
      addLazy(&Sym);
    return;
  }

  // Lazy object file
  if (auto *F = dyn_cast<LazyObjectFile>(FileP)) {
    LazyObjectFiles.emplace_back(cast<LazyObjectFile>(File.release()));
    F->parse();
    for (Lazy &Sym : F->getLazySymbols())
      addLazy(&Sym);
    return;
  }

  if (Config->Trace)
    llvm::outs() << getFilename(FileP) << "\n";

  // .so file
  if (auto *F = dyn_cast<SharedFile<ELFT>>(FileP)) {
    // DSOs are uniquified not by filename but by soname.
    F->parseSoName();
    if (!SoNames.insert(F->getSoName()).second)
      return;

    SharedFiles.emplace_back(cast<SharedFile<ELFT>>(File.release()));
    F->parseRest();
    for (SharedSymbol<ELFT> &B : F->getSharedSymbols())
      resolve(&B);
    return;
  }

  // LLVM bitcode file
  if (auto *F = dyn_cast<BitcodeFile>(FileP)) {
    BitcodeFiles.emplace_back(cast<BitcodeFile>(File.release()));
    F->parse(ComdatGroups);
    for (SymbolBody *B : F->getSymbols())
      if (B)
        resolve(B);
    return;
  }

  // Regular object file
  auto *F = cast<ObjectFile<ELFT>>(FileP);
  ObjectFiles.emplace_back(cast<ObjectFile<ELFT>>(File.release()));
  F->parse(ComdatGroups);
  for (SymbolBody *B : F->getNonLocalSymbols())
    resolve(B);
}

template <class ELFT> void SymbolTable<ELFT>::addCombinedLtoObject() {
  if (BitcodeFiles.empty())
    return;

  // Compile bitcode files.
  Lto.reset(new BitcodeCompiler);
  for (const std::unique_ptr<BitcodeFile> &F : BitcodeFiles)
    Lto->add(*F);
  std::vector<std::unique_ptr<InputFile>> IFs = Lto->compile();

  // Replace bitcode symbols.
  for (auto &IF : IFs) {
    ObjectFile<ELFT> *Obj = cast<ObjectFile<ELFT>>(IF.release());

    llvm::DenseSet<StringRef> DummyGroups;
    Obj->parse(DummyGroups);
    for (SymbolBody *Body : Obj->getNonLocalSymbols()) {
      Symbol *Sym = insert(Body);
      if (!Sym->Body->isUndefined() && Body->isUndefined())
        continue;
      Sym->Body = Body;
    }
    ObjectFiles.emplace_back(Obj);
  }
}

// Add an undefined symbol.
template <class ELFT>
SymbolBody *SymbolTable<ELFT>::addUndefined(StringRef Name) {
  auto *Sym = new (Alloc)
      UndefinedElf<ELFT>(Name, STB_GLOBAL, STV_DEFAULT, /*Type*/ 0, false);
  resolve(Sym);
  return Sym;
}

// Add an undefined symbol. Unlike addUndefined, that symbol
// doesn't have to be resolved, thus "opt" (optional).
template <class ELFT>
SymbolBody *SymbolTable<ELFT>::addUndefinedOpt(StringRef Name) {
  auto *Sym = new (Alloc)
      UndefinedElf<ELFT>(Name, STB_GLOBAL, STV_HIDDEN, /*Type*/ 0, true);
  resolve(Sym);
  return Sym;
}

template <class ELFT>
DefinedRegular<ELFT> *SymbolTable<ELFT>::addAbsolute(StringRef Name,
                                                     uint8_t Visibility) {
  // Pass nullptr because absolute symbols have no corresponding input sections.
  auto *Sym = new (Alloc) DefinedRegular<ELFT>(Name, STB_GLOBAL, Visibility);
  resolve(Sym);
  return Sym;
}

template <class ELFT>
SymbolBody *SymbolTable<ELFT>::addSynthetic(StringRef Name,
                                            OutputSectionBase<ELFT> &Sec,
                                            uintX_t Val) {
  auto *Sym = new (Alloc) DefinedSynthetic<ELFT>(Name, Val, Sec);
  resolve(Sym);
  return Sym;
}

// Add Name as an "ignored" symbol. An ignored symbol is a regular
// linker-synthesized defined symbol, but is only defined if needed.
template <class ELFT>
DefinedRegular<ELFT> *SymbolTable<ELFT>::addIgnored(StringRef Name,
                                                    uint8_t Visibility) {
  if (!find(Name))
    return nullptr;
  return addAbsolute(Name, Visibility);
}

// Rename SYM as __wrap_SYM. The original symbol is preserved as __real_SYM.
// Used to implement --wrap.
template <class ELFT> void SymbolTable<ELFT>::wrap(StringRef Name) {
  if (Symtab.count(Name) == 0)
    return;
  StringSaver Saver(Alloc);
  Symbol *Sym = addUndefined(Name)->Backref;
  Symbol *Real = addUndefined(Saver.save("__real_" + Name))->Backref;
  Symbol *Wrap = addUndefined(Saver.save("__wrap_" + Name))->Backref;
  Real->Body = Sym->Body;
  Sym->Body = Wrap->Body;
}

// Returns a file from which symbol B was created.
// If B does not belong to any file, returns a nullptr.
template <class ELFT> InputFile *SymbolTable<ELFT>::findFile(SymbolBody *B) {
  for (const std::unique_ptr<ObjectFile<ELFT>> &F : ObjectFiles) {
    ArrayRef<SymbolBody *> Syms = F->getSymbols();
    if (std::find(Syms.begin(), Syms.end(), B) != Syms.end())
      return F.get();
  }
  for (const std::unique_ptr<BitcodeFile> &F : BitcodeFiles) {
    ArrayRef<SymbolBody *> Syms = F->getSymbols();
    if (std::find(Syms.begin(), Syms.end(), B) != Syms.end())
      return F.get();
  }
  return nullptr;
}

// Construct a string in the form of "Sym in File1 and File2".
// Used to construct an error message.
template <class ELFT>
std::string SymbolTable<ELFT>::conflictMsg(SymbolBody *Old, SymbolBody *New) {
  InputFile *F1 = findFile(Old);
  InputFile *F2 = findFile(New);
  StringRef Sym = Old->getName();
  return demangle(Sym) + " in " + getFilename(F1) + " and " + getFilename(F2);
}

// This function resolves conflicts if there's an existing symbol with
// the same name. Decisions are made based on symbol type.
template <class ELFT> void SymbolTable<ELFT>::resolve(SymbolBody *New) {
  Symbol *Sym = insert(New);
  if (Sym->Body == New)
    return;

  SymbolBody *Existing = Sym->Body;

  if (auto *L = dyn_cast<Lazy>(Existing)) {
    if (New->isUndefined()) {
      addMemberFile(New, L);
      return;
    }
    // Found a definition for something also in an archive.
    // Ignore the archive definition.
    Sym->Body = New;
    return;
  }

  if (New->isTls() != Existing->isTls()) {
    error("TLS attribute mismatch for symbol: " + conflictMsg(Existing, New));
    return;
  }

  // compare() returns -1, 0, or 1 if the lhs symbol is less preferable,
  // equivalent (conflicting), or more preferable, respectively.
  int Comp = Existing->compare(New);
  if (Comp == 0) {
    std::string S = "duplicate symbol: " + conflictMsg(Existing, New);
    if (Config->AllowMultipleDefinition)
      warning(S);
    else
      error(S);
    return;
  }
  if (Comp < 0)
    Sym->Body = New;
}

static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) {
  if (VA == STV_DEFAULT)
    return VB;
  if (VB == STV_DEFAULT)
    return VA;
  return std::min(VA, VB);
}

static bool shouldExport(SymbolBody *B) {
  if (Config->Shared || Config->ExportDynamic) {
    // Export most symbols except for those that do not need to be exported.
    return !B->CanOmitFromDynSym;
  }
  // Make sure we preempt DSO symbols with default visibility.
  return B->isShared() && B->getVisibility() == STV_DEFAULT;
}

// Find an existing symbol or create and insert a new one.
template <class ELFT> Symbol *SymbolTable<ELFT>::insert(SymbolBody *New) {
  StringRef Name = New->getName();
  unsigned NumSyms = SymVector.size();
  auto P = Symtab.insert(std::make_pair(Name, NumSyms));
  Symbol *Sym;
  if (P.second) {
    Sym = new (Alloc) Symbol;
    Sym->Body = New;
    Sym->Visibility = STV_DEFAULT;
    Sym->IsUsedInRegularObj = false;
    Sym->ExportDynamic = false;
    Sym->VersionScriptGlobal = !Config->VersionScript;
    SymVector.push_back(Sym);
  } else {
    Sym = SymVector[P.first->second];
  }
  New->Backref = Sym;

  // Merge in the new symbol's visibility. DSO symbols do not affect visibility
  // in the output.
  if (!New->isShared())
    Sym->Visibility = getMinVisibility(Sym->Visibility, New->getVisibility());
  Sym->ExportDynamic = Sym->ExportDynamic || shouldExport(New);
  SymbolBody::Kind K = New->kind();
  if (K == SymbolBody::DefinedRegularKind ||
      K == SymbolBody::DefinedCommonKind ||
      K == SymbolBody::DefinedSyntheticKind ||
      K == SymbolBody::UndefinedElfKind)
    Sym->IsUsedInRegularObj = true;
  return Sym;
}

template <class ELFT> SymbolBody *SymbolTable<ELFT>::find(StringRef Name) {
  auto It = Symtab.find(Name);
  if (It == Symtab.end())
    return nullptr;
  return SymVector[It->second]->Body;
}

template <class ELFT> void SymbolTable<ELFT>::addLazy(Lazy *L) {
  Symbol *Sym = insert(L);
  SymbolBody *Cur = Sym->Body;
  if (Cur == L)
    return;
  if (Cur->isUndefined()) {
    Sym->Body = L;
    addMemberFile(Cur, L);
  }
}

template <class ELFT>
void SymbolTable<ELFT>::addMemberFile(SymbolBody *Undef, Lazy *L) {
  // Weak undefined symbols should not fetch members from archives.
  // If we were to keep old symbol we would not know that an archive member was
  // available if a strong undefined symbol shows up afterwards in the link.
  // If a strong undefined symbol never shows up, this lazy symbol will
  // get to the end of the link and must be treated as the weak undefined one.
  // We already marked this symbol as used when we added it to the symbol table,
  // but we also need to preserve its binding and type.
  if (Undef->isWeak()) {
    // FIXME: Consider moving these members to Symbol.
    L->Binding = Undef->Binding;
    L->Type = Undef->Type;
    return;
  }

  // Fetch a member file that has the definition for L.
  // getMember returns nullptr if the member was already read from the library.
  if (std::unique_ptr<InputFile> File = L->getFile())
    addFile(std::move(File));
}

// This function takes care of the case in which shared libraries depend on
// the user program (not the other way, which is usual). Shared libraries
// may have undefined symbols, expecting that the user program provides
// the definitions for them. An example is BSD's __progname symbol.
// We need to put such symbols to the main program's .dynsym so that
// shared libraries can find them.
// Except this, we ignore undefined symbols in DSOs.
template <class ELFT> void SymbolTable<ELFT>::scanShlibUndefined() {
  for (std::unique_ptr<SharedFile<ELFT>> &File : SharedFiles)
    for (StringRef U : File->getUndefinedSymbols())
      if (SymbolBody *Sym = find(U))
        if (Sym->isDefined())
          Sym->Backref->ExportDynamic = true;
}

// This function process the dynamic list option by marking all the symbols
// to be exported in the dynamic table.
template <class ELFT> void SymbolTable<ELFT>::scanDynamicList() {
  for (StringRef S : Config->DynamicList)
    if (SymbolBody *B = find(S))
      B->Backref->ExportDynamic = true;
}

// This function processes the --version-script option by marking all global
// symbols with the VersionScriptGlobal flag, which acts as a filter on the
// dynamic symbol table.
template <class ELFT> void SymbolTable<ELFT>::scanVersionScript() {
  for (StringRef S : Config->VersionScriptGlobals)
    if (SymbolBody *B = find(S))
      B->Backref->VersionScriptGlobal = true;
}

template class elf::SymbolTable<ELF32LE>;
template class elf::SymbolTable<ELF32BE>;
template class elf::SymbolTable<ELF64LE>;
template class elf::SymbolTable<ELF64BE>;
<commit_msg>Add comments.<commit_after>//===- SymbolTable.cpp ----------------------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Symbol table is a bag of all known symbols. We put all symbols of
// all input files to the symbol table. The symbol table is basically
// a hash table with the logic to resolve symbol name conflicts using
// the symbol types.
//
//===----------------------------------------------------------------------===//

#include "SymbolTable.h"
#include "Config.h"
#include "Error.h"
#include "Symbols.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Support/StringSaver.h"

using namespace llvm;
using namespace llvm::object;
using namespace llvm::ELF;

using namespace lld;
using namespace lld::elf;

// All input object files must be for the same architecture
// (e.g. it does not make sense to link x86 object files with
// MIPS object files.) This function checks for that error.
template <class ELFT> static bool isCompatible(InputFile *FileP) {
  auto *F = dyn_cast<ELFFileBase<ELFT>>(FileP);
  if (!F)
    return true;
  if (F->getELFKind() == Config->EKind && F->getEMachine() == Config->EMachine)
    return true;
  StringRef A = F->getName();
  StringRef B = Config->Emulation;
  if (B.empty())
    B = Config->FirstElf->getName();
  error(A + " is incompatible with " + B);
  return false;
}

// Returns "(internal)", "foo.a(bar.o)" or "baz.o".
static std::string getFilename(InputFile *F) {
  if (!F)
    return "(internal)";
  if (!F->ArchiveName.empty())
    return (F->ArchiveName + "(" + F->getName() + ")").str();
  return F->getName();
}

// Add symbols in File to the symbol table.
template <class ELFT>
void SymbolTable<ELFT>::addFile(std::unique_ptr<InputFile> File) {
  InputFile *FileP = File.get();
  if (!isCompatible<ELFT>(FileP))
    return;

  // .a file
  if (auto *F = dyn_cast<ArchiveFile>(FileP)) {
    ArchiveFiles.emplace_back(cast<ArchiveFile>(File.release()));
    F->parse();
    for (Lazy &Sym : F->getLazySymbols())
      addLazy(&Sym);
    return;
  }

  // Lazy object file
  if (auto *F = dyn_cast<LazyObjectFile>(FileP)) {
    LazyObjectFiles.emplace_back(cast<LazyObjectFile>(File.release()));
    F->parse();
    for (Lazy &Sym : F->getLazySymbols())
      addLazy(&Sym);
    return;
  }

  if (Config->Trace)
    llvm::outs() << getFilename(FileP) << "\n";

  // .so file
  if (auto *F = dyn_cast<SharedFile<ELFT>>(FileP)) {
    // DSOs are uniquified not by filename but by soname.
    F->parseSoName();
    if (!SoNames.insert(F->getSoName()).second)
      return;

    SharedFiles.emplace_back(cast<SharedFile<ELFT>>(File.release()));
    F->parseRest();
    for (SharedSymbol<ELFT> &B : F->getSharedSymbols())
      resolve(&B);
    return;
  }

  // LLVM bitcode file
  if (auto *F = dyn_cast<BitcodeFile>(FileP)) {
    BitcodeFiles.emplace_back(cast<BitcodeFile>(File.release()));
    F->parse(ComdatGroups);
    for (SymbolBody *B : F->getSymbols())
      if (B)
        resolve(B);
    return;
  }

  // Regular object file
  auto *F = cast<ObjectFile<ELFT>>(FileP);
  ObjectFiles.emplace_back(cast<ObjectFile<ELFT>>(File.release()));
  F->parse(ComdatGroups);
  for (SymbolBody *B : F->getNonLocalSymbols())
    resolve(B);
}

// This function is where all the optimizations of link-time
// optimization happens. When LTO is in use, some input files are
// not in native object file format but in the LLVM bitcode format.
// This function compiles bitcode files into a few big native files
// using LLVM functions and replaces bitcode symbols with the results.
// Because all bitcode files that consist of a program are passed
// to the compiler at once, it can do whole-program optimization.
template <class ELFT> void SymbolTable<ELFT>::addCombinedLtoObject() {
  if (BitcodeFiles.empty())
    return;

  // Compile bitcode files.
  Lto.reset(new BitcodeCompiler);
  for (const std::unique_ptr<BitcodeFile> &F : BitcodeFiles)
    Lto->add(*F);
  std::vector<std::unique_ptr<InputFile>> IFs = Lto->compile();

  // Replace bitcode symbols.
  for (auto &IF : IFs) {
    ObjectFile<ELFT> *Obj = cast<ObjectFile<ELFT>>(IF.release());

    llvm::DenseSet<StringRef> DummyGroups;
    Obj->parse(DummyGroups);
    for (SymbolBody *Body : Obj->getNonLocalSymbols()) {
      Symbol *Sym = insert(Body);
      if (!Sym->Body->isUndefined() && Body->isUndefined())
        continue;
      Sym->Body = Body;
    }
    ObjectFiles.emplace_back(Obj);
  }
}

// Add an undefined symbol.
template <class ELFT>
SymbolBody *SymbolTable<ELFT>::addUndefined(StringRef Name) {
  auto *Sym = new (Alloc)
      UndefinedElf<ELFT>(Name, STB_GLOBAL, STV_DEFAULT, /*Type*/ 0, false);
  resolve(Sym);
  return Sym;
}

// Add an undefined symbol. Unlike addUndefined, that symbol
// doesn't have to be resolved, thus "opt" (optional).
template <class ELFT>
SymbolBody *SymbolTable<ELFT>::addUndefinedOpt(StringRef Name) {
  auto *Sym = new (Alloc)
      UndefinedElf<ELFT>(Name, STB_GLOBAL, STV_HIDDEN, /*Type*/ 0, true);
  resolve(Sym);
  return Sym;
}

template <class ELFT>
DefinedRegular<ELFT> *SymbolTable<ELFT>::addAbsolute(StringRef Name,
                                                     uint8_t Visibility) {
  // Pass nullptr because absolute symbols have no corresponding input sections.
  auto *Sym = new (Alloc) DefinedRegular<ELFT>(Name, STB_GLOBAL, Visibility);
  resolve(Sym);
  return Sym;
}

template <class ELFT>
SymbolBody *SymbolTable<ELFT>::addSynthetic(StringRef Name,
                                            OutputSectionBase<ELFT> &Sec,
                                            uintX_t Val) {
  auto *Sym = new (Alloc) DefinedSynthetic<ELFT>(Name, Val, Sec);
  resolve(Sym);
  return Sym;
}

// Add Name as an "ignored" symbol. An ignored symbol is a regular
// linker-synthesized defined symbol, but is only defined if needed.
template <class ELFT>
DefinedRegular<ELFT> *SymbolTable<ELFT>::addIgnored(StringRef Name,
                                                    uint8_t Visibility) {
  if (!find(Name))
    return nullptr;
  return addAbsolute(Name, Visibility);
}

// Rename SYM as __wrap_SYM. The original symbol is preserved as __real_SYM.
// Used to implement --wrap.
template <class ELFT> void SymbolTable<ELFT>::wrap(StringRef Name) {
  if (Symtab.count(Name) == 0)
    return;
  StringSaver Saver(Alloc);
  Symbol *Sym = addUndefined(Name)->Backref;
  Symbol *Real = addUndefined(Saver.save("__real_" + Name))->Backref;
  Symbol *Wrap = addUndefined(Saver.save("__wrap_" + Name))->Backref;
  Real->Body = Sym->Body;
  Sym->Body = Wrap->Body;
}

// Returns a file from which symbol B was created.
// If B does not belong to any file, returns a nullptr.
template <class ELFT> InputFile *SymbolTable<ELFT>::findFile(SymbolBody *B) {
  for (const std::unique_ptr<ObjectFile<ELFT>> &F : ObjectFiles) {
    ArrayRef<SymbolBody *> Syms = F->getSymbols();
    if (std::find(Syms.begin(), Syms.end(), B) != Syms.end())
      return F.get();
  }
  for (const std::unique_ptr<BitcodeFile> &F : BitcodeFiles) {
    ArrayRef<SymbolBody *> Syms = F->getSymbols();
    if (std::find(Syms.begin(), Syms.end(), B) != Syms.end())
      return F.get();
  }
  return nullptr;
}

// Construct a string in the form of "Sym in File1 and File2".
// Used to construct an error message.
template <class ELFT>
std::string SymbolTable<ELFT>::conflictMsg(SymbolBody *Old, SymbolBody *New) {
  InputFile *F1 = findFile(Old);
  InputFile *F2 = findFile(New);
  StringRef Sym = Old->getName();
  return demangle(Sym) + " in " + getFilename(F1) + " and " + getFilename(F2);
}

// This function resolves conflicts if there's an existing symbol with
// the same name. Decisions are made based on symbol type.
template <class ELFT> void SymbolTable<ELFT>::resolve(SymbolBody *New) {
  Symbol *Sym = insert(New);
  if (Sym->Body == New)
    return;

  SymbolBody *Existing = Sym->Body;

  if (auto *L = dyn_cast<Lazy>(Existing)) {
    if (New->isUndefined()) {
      addMemberFile(New, L);
      return;
    }
    // Found a definition for something also in an archive.
    // Ignore the archive definition.
    Sym->Body = New;
    return;
  }

  if (New->isTls() != Existing->isTls()) {
    error("TLS attribute mismatch for symbol: " + conflictMsg(Existing, New));
    return;
  }

  // compare() returns -1, 0, or 1 if the lhs symbol is less preferable,
  // equivalent (conflicting), or more preferable, respectively.
  int Comp = Existing->compare(New);
  if (Comp == 0) {
    std::string S = "duplicate symbol: " + conflictMsg(Existing, New);
    if (Config->AllowMultipleDefinition)
      warning(S);
    else
      error(S);
    return;
  }
  if (Comp < 0)
    Sym->Body = New;
}

static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) {
  if (VA == STV_DEFAULT)
    return VB;
  if (VB == STV_DEFAULT)
    return VA;
  return std::min(VA, VB);
}

static bool shouldExport(SymbolBody *B) {
  if (Config->Shared || Config->ExportDynamic) {
    // Export most symbols except for those that do not need to be exported.
    return !B->CanOmitFromDynSym;
  }
  // Make sure we preempt DSO symbols with default visibility.
  return B->isShared() && B->getVisibility() == STV_DEFAULT;
}

// Find an existing symbol or create and insert a new one.
template <class ELFT> Symbol *SymbolTable<ELFT>::insert(SymbolBody *New) {
  StringRef Name = New->getName();
  unsigned NumSyms = SymVector.size();
  auto P = Symtab.insert(std::make_pair(Name, NumSyms));
  Symbol *Sym;
  if (P.second) {
    Sym = new (Alloc) Symbol;
    Sym->Body = New;
    Sym->Visibility = STV_DEFAULT;
    Sym->IsUsedInRegularObj = false;
    Sym->ExportDynamic = false;
    Sym->VersionScriptGlobal = !Config->VersionScript;
    SymVector.push_back(Sym);
  } else {
    Sym = SymVector[P.first->second];
  }
  New->Backref = Sym;

  // Merge in the new symbol's visibility. DSO symbols do not affect visibility
  // in the output.
  if (!New->isShared())
    Sym->Visibility = getMinVisibility(Sym->Visibility, New->getVisibility());
  Sym->ExportDynamic = Sym->ExportDynamic || shouldExport(New);
  SymbolBody::Kind K = New->kind();
  if (K == SymbolBody::DefinedRegularKind ||
      K == SymbolBody::DefinedCommonKind ||
      K == SymbolBody::DefinedSyntheticKind ||
      K == SymbolBody::UndefinedElfKind)
    Sym->IsUsedInRegularObj = true;
  return Sym;
}

template <class ELFT> SymbolBody *SymbolTable<ELFT>::find(StringRef Name) {
  auto It = Symtab.find(Name);
  if (It == Symtab.end())
    return nullptr;
  return SymVector[It->second]->Body;
}

template <class ELFT> void SymbolTable<ELFT>::addLazy(Lazy *L) {
  Symbol *Sym = insert(L);
  SymbolBody *Cur = Sym->Body;
  if (Cur == L)
    return;
  if (Cur->isUndefined()) {
    Sym->Body = L;
    addMemberFile(Cur, L);
  }
}

template <class ELFT>
void SymbolTable<ELFT>::addMemberFile(SymbolBody *Undef, Lazy *L) {
  // Weak undefined symbols should not fetch members from archives.
  // If we were to keep old symbol we would not know that an archive member was
  // available if a strong undefined symbol shows up afterwards in the link.
  // If a strong undefined symbol never shows up, this lazy symbol will
  // get to the end of the link and must be treated as the weak undefined one.
  // We already marked this symbol as used when we added it to the symbol table,
  // but we also need to preserve its binding and type.
  if (Undef->isWeak()) {
    // FIXME: Consider moving these members to Symbol.
    L->Binding = Undef->Binding;
    L->Type = Undef->Type;
    return;
  }

  // Fetch a member file that has the definition for L.
  // getMember returns nullptr if the member was already read from the library.
  if (std::unique_ptr<InputFile> File = L->getFile())
    addFile(std::move(File));
}

// This function takes care of the case in which shared libraries depend on
// the user program (not the other way, which is usual). Shared libraries
// may have undefined symbols, expecting that the user program provides
// the definitions for them. An example is BSD's __progname symbol.
// We need to put such symbols to the main program's .dynsym so that
// shared libraries can find them.
// Except this, we ignore undefined symbols in DSOs.
template <class ELFT> void SymbolTable<ELFT>::scanShlibUndefined() {
  for (std::unique_ptr<SharedFile<ELFT>> &File : SharedFiles)
    for (StringRef U : File->getUndefinedSymbols())
      if (SymbolBody *Sym = find(U))
        if (Sym->isDefined())
          Sym->Backref->ExportDynamic = true;
}

// This function process the dynamic list option by marking all the symbols
// to be exported in the dynamic table.
template <class ELFT> void SymbolTable<ELFT>::scanDynamicList() {
  for (StringRef S : Config->DynamicList)
    if (SymbolBody *B = find(S))
      B->Backref->ExportDynamic = true;
}

// This function processes the --version-script option by marking all global
// symbols with the VersionScriptGlobal flag, which acts as a filter on the
// dynamic symbol table.
template <class ELFT> void SymbolTable<ELFT>::scanVersionScript() {
  for (StringRef S : Config->VersionScriptGlobals)
    if (SymbolBody *B = find(S))
      B->Backref->VersionScriptGlobal = true;
}

template class elf::SymbolTable<ELF32LE>;
template class elf::SymbolTable<ELF32BE>;
template class elf::SymbolTable<ELF64LE>;
template class elf::SymbolTable<ELF64BE>;
<|endoftext|>


<commit_before>#include "StreamServer.hpp"

#include <chrono>
#include <vlc/libvlc_vlm.h>
#include <vlc/vlc.h>
#include <Ice/Ice.h>
#include <IceStorm/IceStorm.h>

StreamServer::StreamServer() {
	Ice::CommunicatorPtr ic;
	try {
		ic = Ice::initialize();
		Ice::ObjectPrx obj = ic->stringToProxy("IceStorm/TopicManager:tcp -h 80.240.129.188 -p 9999");
		IceStorm::TopicManagerPrx topicManager = IceStorm::TopicManagerPrx::checkedCast(obj);
		IceStorm::TopicPrx topic;
		while (!topic) {
			try {
				topic = topicManager->retrieve("StreamPlayerNotifs");
			} catch (const IceStorm::NoSuchTopic&) {
				try {
					topic = topicManager->create("StreamPlayerNotifs");
				} catch(const IceStorm::TopicExists&) {
				}
			}
		}
		Ice::ObjectPrx pub = topic->getPublisher()->ice_twoway();
		monitor = MonitorPrx::uncheckedCast(pub);
	} catch (const Ice::Exception& e) {
		std::cerr << e << '\n';
	}
	vlc = libvlc_new(0, NULL);
}

std::string StreamServer::selectSong(const Song& s, const Ice::Current& c) {
	std::cout << "Selecting song (" << s.artist << ", " << s.title << ")\n";
	if(vlc == nullptr)
		return "";
	Ice::IPConnectionInfo* ipCoInfo = dynamic_cast<Ice::IPConnectionInfo*>(c.con->getInfo().get());
	auto duration = std::chrono::system_clock::now().time_since_epoch();
	std::string token = ipCoInfo->remoteAddress.substr(7) + "." + std::to_string(ipCoInfo->remotePort) + "." + std::to_string(std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count());
	std::string ssout = "#transcode{acodec=mp3,ab=128,channels=2," \
						 "samplerate=44100}:http{dst=:8090/"+token+".mp3}";
	const char* sout = ssout.c_str();
	std::string path = "songs/"+s.path;
	libvlc_vlm_add_broadcast(vlc, token.c_str(), path.c_str(), sout, 0, nullptr, true, false);
	std::cout << "Selected song (" << token << ")\n";
	return token;
}

void StreamServer::playSong(const std::string& token, const Ice::Current&) {
	std::cout << "Playing song (" << token << ")\n";
	if(vlc == nullptr)
		return;
	libvlc_vlm_play_media(vlc, token.c_str());
}

void StreamServer::stopSong(const std::string& token, const Ice::Current&) {
	std::cout << "Stopping song (" << token << ")\n";
	if(vlc == nullptr)
		return;
	libvlc_vlm_stop_media(vlc, token.c_str());
}

void StreamServer::addSong(const Song& s, const Ice::Current&) {
	std::cout << "Adding song (" << s.artist << ", " << s.title << ")\n";
	songs.push_back(s);
	monitor->report("add", s);
}

void StreamServer::removeSong(const Song& s, const Ice::Current&) {
	std::cout << "Removing song (" << s.artist << ", " << s.title << ")\n";
	for(int i = 0; i < songs.size(); ++i) {
		if(songs[i].artist == s.artist && songs[i].title == s.title)
			songs.erase(songs.begin()+(i--));
	}
	monitor->report("del", s);
}

std::vector<Song> StreamServer::searchSong(const std::string& artist, const std::string& title, const Ice::Current&) {
	std::cout << "Searching song (" << artist << ", " << title << ")\n";
	std::vector<Song> output;
	for(int i = 0; i < songs.size(); ++i) {
		if(artist.empty() && title.empty()) {
			output.push_back(songs[i]);
			std::cout << "Found song (" << songs[i].artist << ", " << songs[i].title << ")\n";
		} else if(artist.empty() || title.empty()) {
			if((title.empty() && songs[i].artist == artist)
					|| (artist.empty() && songs[i].title == title)) {
				output.push_back(songs[i]);
				std::cout << "Found song (" << songs[i].artist << ", " << songs[i].title << ")\n";
			}
		} else if(songs[i].artist == artist && songs[i].title == title) {
			output.push_back(songs[i]);
			std::cout << "Found song (" << songs[i].artist << ", " << songs[i].title << ")\n";
		}
	}
	std::cout << "Search finished\n";
	return output;
}

void StreamServer::uploadFile(const std::string& name, const ByteSeq& data, const Ice::Current& c) {
	FILE* file;
	std::string path = "../songs/" + name;
	file = fopen(path.c_str(), "a+");
	fseek(file, 0, SEEK_END);
	fwrite(&data[0], 1, data.size(), file);
	fclose(file);
}
<commit_msg>fix file upload<commit_after>#include "StreamServer.hpp"

#include <chrono>
#include <vlc/libvlc_vlm.h>
#include <vlc/vlc.h>
#include <Ice/Ice.h>
#include <IceStorm/IceStorm.h>

StreamServer::StreamServer() {
	Ice::CommunicatorPtr ic;
	try {
		ic = Ice::initialize();
		Ice::ObjectPrx obj = ic->stringToProxy("IceStorm/TopicManager:tcp -h 80.240.129.188 -p 9999");
		IceStorm::TopicManagerPrx topicManager = IceStorm::TopicManagerPrx::checkedCast(obj);
		IceStorm::TopicPrx topic;
		while (!topic) {
			try {
				topic = topicManager->retrieve("StreamPlayerNotifs");
			} catch (const IceStorm::NoSuchTopic&) {
				try {
					topic = topicManager->create("StreamPlayerNotifs");
				} catch(const IceStorm::TopicExists&) {
				}
			}
		}
		Ice::ObjectPrx pub = topic->getPublisher()->ice_twoway();
		monitor = MonitorPrx::uncheckedCast(pub);
	} catch (const Ice::Exception& e) {
		std::cerr << e << '\n';
	}
	vlc = libvlc_new(0, NULL);
}

std::string StreamServer::selectSong(const Song& s, const Ice::Current& c) {
	std::cout << "Selecting song (" << s.artist << ", " << s.title << ")\n";
	if(vlc == nullptr)
		return "";
	Ice::IPConnectionInfo* ipCoInfo = dynamic_cast<Ice::IPConnectionInfo*>(c.con->getInfo().get());
	auto duration = std::chrono::system_clock::now().time_since_epoch();
	std::string token = ipCoInfo->remoteAddress.substr(7) + "." + std::to_string(ipCoInfo->remotePort) + "." + std::to_string(std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count());
	std::string ssout = "#transcode{acodec=mp3,ab=128,channels=2," \
						 "samplerate=44100}:http{dst=:8090/"+token+".mp3}";
	const char* sout = ssout.c_str();
	std::string path = "songs/"+s.path;
	libvlc_vlm_add_broadcast(vlc, token.c_str(), path.c_str(), sout, 0, nullptr, true, false);
	std::cout << "Selected song (" << token << ")\n";
	return token;
}

void StreamServer::playSong(const std::string& token, const Ice::Current&) {
	std::cout << "Playing song (" << token << ")\n";
	if(vlc == nullptr)
		return;
	libvlc_vlm_play_media(vlc, token.c_str());
}

void StreamServer::stopSong(const std::string& token, const Ice::Current&) {
	std::cout << "Stopping song (" << token << ")\n";
	if(vlc == nullptr)
		return;
	libvlc_vlm_stop_media(vlc, token.c_str());
}

void StreamServer::addSong(const Song& s, const Ice::Current&) {
	std::cout << "Adding song (" << s.artist << ", " << s.title << ")\n";
	songs.push_back(s);
	monitor->report("add", s);
}

void StreamServer::removeSong(const Song& s, const Ice::Current&) {
	std::cout << "Removing song (" << s.artist << ", " << s.title << ")\n";
	for(int i = 0; i < songs.size(); ++i) {
		if(songs[i].artist == s.artist && songs[i].title == s.title)
			songs.erase(songs.begin()+(i--));
	}
	monitor->report("del", s);
}

std::vector<Song> StreamServer::searchSong(const std::string& artist, const std::string& title, const Ice::Current&) {
	std::cout << "Searching song (" << artist << ", " << title << ")\n";
	std::vector<Song> output;
	for(int i = 0; i < songs.size(); ++i) {
		if(artist.empty() && title.empty()) {
			output.push_back(songs[i]);
			std::cout << "Found song (" << songs[i].artist << ", " << songs[i].title << ")\n";
		} else if(artist.empty() || title.empty()) {
			if((title.empty() && songs[i].artist == artist)
					|| (artist.empty() && songs[i].title == title)) {
				output.push_back(songs[i]);
				std::cout << "Found song (" << songs[i].artist << ", " << songs[i].title << ")\n";
			}
		} else if(songs[i].artist == artist && songs[i].title == title) {
			output.push_back(songs[i]);
			std::cout << "Found song (" << songs[i].artist << ", " << songs[i].title << ")\n";
		}
	}
	std::cout << "Search finished\n";
	return output;
}

void StreamServer::uploadFile(const std::string& name, const ByteSeq& data, const Ice::Current& c) {
	FILE* file;
	std::string path = "songs/" + name + ".mp3";
	std::cout << path << std::endl;
	file = fopen(path.c_str(), "a+");
	fseek(file, 0, SEEK_END);
	fwrite(&data[0], 1, data.size(), file);
	fclose(file);
}
<|endoftext|>