<commit_before>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Claire Xenia Wolf <claire@yosyshq.com>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/register.h"
#include "kernel/rtlil.h"
#include "kernel/log.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

static void rename_in_module(RTLIL::Module *module, std::string from_name, std::string to_name, bool flag_output)
{
	from_name = RTLIL::escape_id(from_name);
	to_name = RTLIL::escape_id(to_name);

	if (module->count_id(to_name))
		log_cmd_error("There is already an object `%s' in module `%s'.\n", to_name.c_str(), module->name.c_str());

	RTLIL::Wire *wire_to_rename = module->wire(from_name);
	RTLIL::Cell *cell_to_rename = module->cell(from_name);

	if (wire_to_rename != nullptr) {
		log("Renaming wire %s to %s in module %s.\n", log_id(wire_to_rename), log_id(to_name), log_id(module));
		module->rename(wire_to_rename, to_name);
		if (wire_to_rename->port_id || flag_output) {
			if (flag_output)
				wire_to_rename->port_output = true;
			module->fixup_ports();
		}
		return;
	}

	if (cell_to_rename != nullptr) {
		if (flag_output)
			log_cmd_error("Called with -output but the specified object is a cell.\n");
		log("Renaming cell %s to %s in module %s.\n", log_id(cell_to_rename), log_id(to_name), log_id(module));
		module->rename(cell_to_rename, to_name);
		return;
	}

	log_cmd_error("Object `%s' not found!\n", from_name.c_str());
}

static std::string derive_name_from_src(const std::string &src, int counter)
{
	std::string src_base = src.substr(0, src.find('|'));
	if (src_base.empty())
		return stringf("$%d", counter);
	else
		return stringf("\\%s$%d", src_base.c_str(), counter);
}

static IdString derive_name_from_cell_output_wire(const RTLIL::Cell *cell)
{
	// Find output
	const SigSpec *output = nullptr;
	int num_outputs = 0;
	for (auto &connection : cell->connections()) {
		if (cell->output(connection.first)) {
			output = &connection.second;
			num_outputs++;
		}
	}

	if (num_outputs != 1) // Skip cells thad drive multiple outputs
		return cell->name;

	std::string name = "";
	for (auto &chunk : output->chunks()) {
		// Skip cells that drive privately named wires
		if (!chunk.wire || chunk.wire->name.str()[0] == '$')
			return cell->name;

		if (name != "")
			name += "$";

		name += chunk.wire->name.str();
		if (chunk.wire->width != chunk.width) {
			name += "[";
			if (chunk.width != 1)
				name += std::to_string(chunk.offset + chunk.width) + ":";
			name += std::to_string(chunk.offset) + "]";
		}
	}

	return name + cell->type.str();
}

struct RenamePass : public Pass {
	RenamePass() : Pass("rename", "rename object in the design") { }
	void help() override
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    rename old_name new_name\n");
		log("\n");
		log("Rename the specified object. Note that selection patterns are not supported\n");
		log("by this command.\n");
		log("\n");
		log("\n");
		log("\n");
		log("    rename -output old_name new_name\n");
		log("\n");
		log("Like above, but also make the wire an output. This will fail if the object is\n");
		log("not a wire.\n");
		log("\n");
		log("\n");
		log("    rename -src [selection]\n");
		log("\n");
		log("Assign names auto-generated from the src attribute to all selected wires and\n");
		log("cells with private names.\n");
		log("\n");
		log("\n");
		log("    rename -wire [selection]\n");
		log("\n");
		log("Assign auto-generated names based on the wires they drive to all selected\n");
		log("cells with private names. Ignores cells driving privatly named wires.\n");
		log("\n");
		log("\n");
		log("    rename -enumerate [-pattern <pattern>] [selection]\n");
		log("\n");
		log("Assign short auto-generated names to all selected wires and cells with private\n");
		log("names. The -pattern option can be used to set the pattern for the new names.\n");
		log("The character %% in the pattern is replaced with a integer number. The default\n");
		log("pattern is '_%%_'.\n");
		log("\n");
		log("\n");
		log("    rename -hide [selection]\n");
		log("\n");
		log("Assign private names (the ones with $-prefix) to all selected wires and cells\n");
		log("with public names. This ignores all selected ports.\n");
		log("\n");
		log("\n");
		log("    rename -top new_name\n");
		log("\n");
		log("Rename top module.\n");
		log("\n");
	}
	void execute(std::vector<std::string> args, RTLIL::Design *design) override
	{
		std::string pattern_prefix = "_", pattern_suffix = "_";
		bool flag_src = false;
		bool flag_wire = false;
		bool flag_enumerate = false;
		bool flag_hide = false;
		bool flag_top = false;
		bool flag_output = false;
		bool got_mode = false;

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++)
		{
			std::string arg = args[argidx];
			if (arg == "-src" && !got_mode) {
				flag_src = true;
				got_mode = true;
				continue;
			}
			if (arg == "-output" && !got_mode) {
				flag_output = true;
				got_mode = true;
				continue;
			}
			if (arg == "-wire" && !got_mode) {
				flag_wire = true;
				got_mode = true;
				continue;
			}
			if (arg == "-enumerate" && !got_mode) {
				flag_enumerate = true;
				got_mode = true;
				continue;
			}
			if (arg == "-hide" && !got_mode) {
				flag_hide = true;
				got_mode = true;
				continue;
			}
			if (arg == "-top" && !got_mode) {
				flag_top = true;
				got_mode = true;
				continue;
			}
			if (arg == "-pattern" && argidx+1 < args.size() && args[argidx+1].find('%') != std::string::npos) {
				int pos = args[++argidx].find('%');
				pattern_prefix = args[argidx].substr(0, pos);
				pattern_suffix = args[argidx].substr(pos+1);
				continue;
			}
			break;
		}

		if (flag_src)
		{
			extra_args(args, argidx, design);

			for (auto module : design->selected_modules())
			{
				int counter = 0;
				dict<RTLIL::Wire *, IdString> new_wire_names;
				dict<RTLIL::Cell *, IdString> new_cell_names;

				for (auto wire : module->selected_wires())
					if (wire->name[0] == '$')
						new_wire_names.emplace(wire, derive_name_from_src(wire->get_src_attribute(), counter++));

				for (auto cell : module->selected_cells())
					if (cell->name[0] == '$')
						new_cell_names.emplace(cell, derive_name_from_src(cell->get_src_attribute(), counter++));

				for (auto &it : new_wire_names)
					module->rename(it.first, it.second);

				for (auto &it : new_cell_names)
					module->rename(it.first, it.second);
			}
		}
		else
		if (flag_wire)
		{
			extra_args(args, argidx, design);

			for (auto module : design->selected_modules()) {
				dict<RTLIL::Cell *, IdString> new_cell_names;
				for (auto cell : module->selected_cells())
					if (cell->name[0] == '$')
						new_cell_names[cell] = derive_name_from_cell_output_wire(cell);
				for (auto &it : new_cell_names)
					module->rename(it.first, it.second);
			}
		}
		else
		if (flag_enumerate)
		{
			extra_args(args, argidx, design);

			for (auto module : design->selected_modules())
			{
				int counter = 0;
				dict<RTLIL::Wire *, IdString> new_wire_names;
				dict<RTLIL::Cell *, IdString> new_cell_names;

				for (auto wire : module->selected_wires())
					if (wire->name[0] == '$') {
						RTLIL::IdString buf;
						do buf = stringf("\\%s%d%s", pattern_prefix.c_str(), counter++, pattern_suffix.c_str());
						while (module->wire(buf) != nullptr);
						new_wire_names[wire] = buf;
					}

				for (auto cell : module->selected_cells())
					if (cell->name[0] == '$') {
						RTLIL::IdString buf;
						do buf = stringf("\\%s%d%s", pattern_prefix.c_str(), counter++, pattern_suffix.c_str());
						while (module->cell(buf) != nullptr);
						new_cell_names[cell] = buf;
					}

				for (auto &it : new_wire_names)
					module->rename(it.first, it.second);

				for (auto &it : new_cell_names)
					module->rename(it.first, it.second);
			}
		}
		else
		if (flag_hide)
		{
			extra_args(args, argidx, design);

			for (auto module : design->selected_modules())
			{
				dict<RTLIL::Wire *, IdString> new_wire_names;
				dict<RTLIL::Cell *, IdString> new_cell_names;

				for (auto wire : module->selected_wires())
					if (wire->name.isPublic() && wire->port_id == 0)
						new_wire_names[wire] = NEW_ID;

				for (auto cell : module->selected_cells())
					if (cell->name.isPublic())
						new_cell_names[cell] = NEW_ID;

				for (auto &it : new_wire_names)
					module->rename(it.first, it.second);

				for (auto &it : new_cell_names)
					module->rename(it.first, it.second);
			}
		}
		else
		if (flag_top)
		{
			if (argidx+1 != args.size())
				log_cmd_error("Invalid number of arguments!\n");

			IdString new_name = RTLIL::escape_id(args[argidx]);
			RTLIL::Module *module = design->top_module();

			if (module == nullptr)
				log_cmd_error("No top module found!\n");

			log("Renaming module %s to %s.\n", log_id(module), log_id(new_name));
			design->rename(module, new_name);
		}
		else
		{
			if (argidx+2 != args.size())
				log_cmd_error("Invalid number of arguments!\n");

			std::string from_name = args[argidx++];
			std::string to_name = args[argidx++];

			if (!design->selected_active_module.empty())
			{
				if (design->module(design->selected_active_module) != nullptr)
					rename_in_module(design->module(design->selected_active_module), from_name, to_name, flag_output);
			}
			else
			{
				if (flag_output)
					log_cmd_error("Mode -output requires that there is an active module selected.\n");

				RTLIL::Module *module_to_rename = nullptr;
				for (auto module : design->modules())
					if (module->name == from_name || RTLIL::unescape_id(module->name) == from_name) {
						module_to_rename = module;
						break;
					}

				if (module_to_rename != nullptr) {
					to_name = RTLIL::escape_id(to_name);
					log("Renaming module %s to %s.\n", module_to_rename->name.c_str(), to_name.c_str());
					design->rename(module_to_rename, to_name);
				} else
					log_cmd_error("Object `%s' not found!\n", from_name.c_str());
			}
		}
	}
} RenamePass;

PRIVATE_NAMESPACE_END
<commit_msg>Add -suffix option to rename -wire.<commit_after>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Claire Xenia Wolf <claire@yosyshq.com>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/register.h"
#include "kernel/rtlil.h"
#include "kernel/log.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

static void rename_in_module(RTLIL::Module *module, std::string from_name, std::string to_name, bool flag_output)
{
	from_name = RTLIL::escape_id(from_name);
	to_name = RTLIL::escape_id(to_name);

	if (module->count_id(to_name))
		log_cmd_error("There is already an object `%s' in module `%s'.\n", to_name.c_str(), module->name.c_str());

	RTLIL::Wire *wire_to_rename = module->wire(from_name);
	RTLIL::Cell *cell_to_rename = module->cell(from_name);

	if (wire_to_rename != nullptr) {
		log("Renaming wire %s to %s in module %s.\n", log_id(wire_to_rename), log_id(to_name), log_id(module));
		module->rename(wire_to_rename, to_name);
		if (wire_to_rename->port_id || flag_output) {
			if (flag_output)
				wire_to_rename->port_output = true;
			module->fixup_ports();
		}
		return;
	}

	if (cell_to_rename != nullptr) {
		if (flag_output)
			log_cmd_error("Called with -output but the specified object is a cell.\n");
		log("Renaming cell %s to %s in module %s.\n", log_id(cell_to_rename), log_id(to_name), log_id(module));
		module->rename(cell_to_rename, to_name);
		return;
	}

	log_cmd_error("Object `%s' not found!\n", from_name.c_str());
}

static std::string derive_name_from_src(const std::string &src, int counter)
{
	std::string src_base = src.substr(0, src.find('|'));
	if (src_base.empty())
		return stringf("$%d", counter);
	else
		return stringf("\\%s$%d", src_base.c_str(), counter);
}

static IdString derive_name_from_cell_output_wire(const RTLIL::Cell *cell, string suffix)
{
	// Find output
	const SigSpec *output = nullptr;
	int num_outputs = 0;
	for (auto &connection : cell->connections()) {
		if (cell->output(connection.first)) {
			output = &connection.second;
			num_outputs++;
		}
	}

	if (num_outputs != 1) // Skip cells thad drive multiple outputs
		return cell->name;

	std::string name = "";
	for (auto &chunk : output->chunks()) {
		// Skip cells that drive privately named wires
		if (!chunk.wire || chunk.wire->name.str()[0] == '$')
			return cell->name;

		if (name != "")
			name += "$";

		name += chunk.wire->name.str();
		if (chunk.wire->width != chunk.width) {
			name += "[";
			if (chunk.width != 1)
				name += std::to_string(chunk.offset + chunk.width) + ":";
			name += std::to_string(chunk.offset) + "]";
		}
	}

	if (suffix.empty()) {
		suffix = cell->type.str();
	}
	return name + suffix;
}

struct RenamePass : public Pass {
	RenamePass() : Pass("rename", "rename object in the design") { }
	void help() override
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    rename old_name new_name\n");
		log("\n");
		log("Rename the specified object. Note that selection patterns are not supported\n");
		log("by this command.\n");
		log("\n");
		log("\n");
		log("\n");
		log("    rename -output old_name new_name\n");
		log("\n");
		log("Like above, but also make the wire an output. This will fail if the object is\n");
		log("not a wire.\n");
		log("\n");
		log("\n");
		log("    rename -src [selection]\n");
		log("\n");
		log("Assign names auto-generated from the src attribute to all selected wires and\n");
		log("cells with private names.\n");
		log("\n");
		log("\n");
		log("    rename -wire [selection] [-suffix <suffix>]\n");
		log("\n");
		log("Assign auto-generated names based on the wires they drive to all selected\n");
		log("cells with private names. Ignores cells driving privatly named wires.\n");
		log("The -suffix option can be used to set a suffix to the renamed cells.\n");
		log("The default suffix is the cell type.\n");
		log("\n");
		log("\n");
		log("    rename -enumerate [-pattern <pattern>] [selection]\n");
		log("\n");
		log("Assign short auto-generated names to all selected wires and cells with private\n");
		log("names. The -pattern option can be used to set the pattern for the new names.\n");
		log("The character %% in the pattern is replaced with a integer number. The default\n");
		log("pattern is '_%%_'.\n");
		log("\n");
		log("\n");
		log("    rename -hide [selection]\n");
		log("\n");
		log("Assign private names (the ones with $-prefix) to all selected wires and cells\n");
		log("with public names. This ignores all selected ports.\n");
		log("\n");
		log("\n");
		log("    rename -top new_name\n");
		log("\n");
		log("Rename top module.\n");
		log("\n");
	}
	void execute(std::vector<std::string> args, RTLIL::Design *design) override
	{
		std::string pattern_prefix = "_", pattern_suffix = "_";
		std::string cell_suffix = "";
		bool flag_src = false;
		bool flag_wire = false;
		bool flag_enumerate = false;
		bool flag_hide = false;
		bool flag_top = false;
		bool flag_output = false;
		bool got_mode = false;

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++)
		{
			std::string arg = args[argidx];
			if (arg == "-src" && !got_mode) {
				flag_src = true;
				got_mode = true;
				continue;
			}
			if (arg == "-output" && !got_mode) {
				flag_output = true;
				got_mode = true;
				continue;
			}
			if (arg == "-wire" && !got_mode) {
				flag_wire = true;
				got_mode = true;
				continue;
			}
			if (arg == "-enumerate" && !got_mode) {
				flag_enumerate = true;
				got_mode = true;
				continue;
			}
			if (arg == "-hide" && !got_mode) {
				flag_hide = true;
				got_mode = true;
				continue;
			}
			if (arg == "-top" && !got_mode) {
				flag_top = true;
				got_mode = true;
				continue;
			}
			if (arg == "-pattern" && argidx+1 < args.size() && args[argidx+1].find('%') != std::string::npos) {
				int pos = args[++argidx].find('%');
				pattern_prefix = args[argidx].substr(0, pos);
				pattern_suffix = args[argidx].substr(pos+1);
				continue;
			}
			if (arg == "-suffix" && argidx + 1 < args.size()) {
				cell_suffix = args[++argidx];
			}
			break;
		}

		if (flag_src)
		{
			extra_args(args, argidx, design);

			for (auto module : design->selected_modules())
			{
				int counter = 0;
				dict<RTLIL::Wire *, IdString> new_wire_names;
				dict<RTLIL::Cell *, IdString> new_cell_names;

				for (auto wire : module->selected_wires())
					if (wire->name[0] == '$')
						new_wire_names.emplace(wire, derive_name_from_src(wire->get_src_attribute(), counter++));

				for (auto cell : module->selected_cells())
					if (cell->name[0] == '$')
						new_cell_names.emplace(cell, derive_name_from_src(cell->get_src_attribute(), counter++));

				for (auto &it : new_wire_names)
					module->rename(it.first, it.second);

				for (auto &it : new_cell_names)
					module->rename(it.first, it.second);
			}
		}
		else
		if (flag_wire)
		{
			extra_args(args, argidx, design);

			for (auto module : design->selected_modules()) {
				dict<RTLIL::Cell *, IdString> new_cell_names;
				for (auto cell : module->selected_cells())
					if (cell->name[0] == '$')
						new_cell_names[cell] = derive_name_from_cell_output_wire(cell, cell_suffix);
				for (auto &it : new_cell_names)
					module->rename(it.first, it.second);
			}
		}
		else
		if (flag_enumerate)
		{
			extra_args(args, argidx, design);

			for (auto module : design->selected_modules())
			{
				int counter = 0;
				dict<RTLIL::Wire *, IdString> new_wire_names;
				dict<RTLIL::Cell *, IdString> new_cell_names;

				for (auto wire : module->selected_wires())
					if (wire->name[0] == '$') {
						RTLIL::IdString buf;
						do buf = stringf("\\%s%d%s", pattern_prefix.c_str(), counter++, pattern_suffix.c_str());
						while (module->wire(buf) != nullptr);
						new_wire_names[wire] = buf;
					}

				for (auto cell : module->selected_cells())
					if (cell->name[0] == '$') {
						RTLIL::IdString buf;
						do buf = stringf("\\%s%d%s", pattern_prefix.c_str(), counter++, pattern_suffix.c_str());
						while (module->cell(buf) != nullptr);
						new_cell_names[cell] = buf;
					}

				for (auto &it : new_wire_names)
					module->rename(it.first, it.second);

				for (auto &it : new_cell_names)
					module->rename(it.first, it.second);
			}
		}
		else
		if (flag_hide)
		{
			extra_args(args, argidx, design);

			for (auto module : design->selected_modules())
			{
				dict<RTLIL::Wire *, IdString> new_wire_names;
				dict<RTLIL::Cell *, IdString> new_cell_names;

				for (auto wire : module->selected_wires())
					if (wire->name.isPublic() && wire->port_id == 0)
						new_wire_names[wire] = NEW_ID;

				for (auto cell : module->selected_cells())
					if (cell->name.isPublic())
						new_cell_names[cell] = NEW_ID;

				for (auto &it : new_wire_names)
					module->rename(it.first, it.second);

				for (auto &it : new_cell_names)
					module->rename(it.first, it.second);
			}
		}
		else
		if (flag_top)
		{
			if (argidx+1 != args.size())
				log_cmd_error("Invalid number of arguments!\n");

			IdString new_name = RTLIL::escape_id(args[argidx]);
			RTLIL::Module *module = design->top_module();

			if (module == nullptr)
				log_cmd_error("No top module found!\n");

			log("Renaming module %s to %s.\n", log_id(module), log_id(new_name));
			design->rename(module, new_name);
		}
		else
		{
			if (argidx+2 != args.size())
				log_cmd_error("Invalid number of arguments!\n");

			std::string from_name = args[argidx++];
			std::string to_name = args[argidx++];

			if (!design->selected_active_module.empty())
			{
				if (design->module(design->selected_active_module) != nullptr)
					rename_in_module(design->module(design->selected_active_module), from_name, to_name, flag_output);
			}
			else
			{
				if (flag_output)
					log_cmd_error("Mode -output requires that there is an active module selected.\n");

				RTLIL::Module *module_to_rename = nullptr;
				for (auto module : design->modules())
					if (module->name == from_name || RTLIL::unescape_id(module->name) == from_name) {
						module_to_rename = module;
						break;
					}

				if (module_to_rename != nullptr) {
					to_name = RTLIL::escape_id(to_name);
					log("Renaming module %s to %s.\n", module_to_rename->name.c_str(), to_name.c_str());
					design->rename(module_to_rename, to_name);
				} else
					log_cmd_error("Object `%s' not found!\n", from_name.c_str());
			}
		}
	}
} RenamePass;

PRIVATE_NAMESPACE_END
<|endoftext|>


<commit_before>/******************************************************************************
* Copyright (c) 2015, Howard Butler (howard@hobu.co)
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following
* conditions are met:
*
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in
*       the documentation and/or other materials provided
*       with the distribution.
*     * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the
*       names of its contributors may be used to endorse or promote
*       products derived from this software without specific prior
*       written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
****************************************************************************/

#include <pdal/GEOSUtils.hpp>
#include <pdal/Log.hpp>

#include <functional>
#include <map>
#include <sstream>

#ifdef PDAL_COMPILER_MSVC
#  pragma warning(disable: 4127)  // conditional expression is constant
#endif

namespace pdal
{
namespace geos
{

ErrorHandler::ErrorHandler(bool isDebug, LogPtr log)
    : m_isDebug(isDebug)
    , m_log(log)

{
    setup(isDebug, log);
}

void ErrorHandler::setup(bool isDebug, LogPtr log)
{
    if (m_isDebug)
        m_geos_callback = std::bind(&ErrorHandler::log, this, std::placeholders::_1 );
    else
        m_geos_callback = std::bind(&ErrorHandler::error, this, std::placeholders::_1 );

    // GEOS 3.5+ provides error handling context, so we will
    // prefer to use that where possible. Otherwise, we will default to
    // output to std::clog
#ifndef GEOS_init_r
    ctx = initGEOS_r(NULL, NULL);
#else
    ctx = GEOS_init_r();
#endif

#ifdef GEOSContext_setErrorMessageHandler_r
    GEOSContext_setErrorMessageHandler_r(ctx, &ErrorHandler::error_trampoline, this);
#else
    GEOSContext_setErrorHandler_r(ctx, &ErrorHandler::error_trampoline);
#endif

    if (m_isDebug)
    {
#ifdef GEOSContext_setNoticeHandler_r
        GEOSContext_setNoticeHandler_r(ctx, &ErrorHandler::notice_trampoline, this);
#else
        GEOSContext_setErrorHandler_r(ctx, &ErrorHandler::notice_trampoline);
#endif
    }
}

ErrorHandler::ErrorHandler(const ErrorHandler& other )
{
    setup(other.m_isDebug, other.m_log);
}

void ErrorHandler::log(char const* msg)
{
    std::ostringstream oss;
    oss << "GEOS debug: " << msg;
    if (m_log)
        m_log->get(LogLevel::Debug) << oss.str() << std::endl;
}

void ErrorHandler::error(char const* msg)
{
    std::ostringstream oss;
    oss << "GEOS failure: '" << msg <<"'";
    throw pdal_error(oss.str());
}

ErrorHandler::~ErrorHandler()
{
    std::cout << "context is going away" <<std::endl;
#ifdef GEOS_finish_r
    GEOS_finish_r(ctx);
#else
    finishGEOS_r(ctx);
#endif
}

} // namespace geos
} // namespace pdal

<commit_msg>remove debug lint<commit_after>/******************************************************************************
* Copyright (c) 2015, Howard Butler (howard@hobu.co)
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following
* conditions are met:
*
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in
*       the documentation and/or other materials provided
*       with the distribution.
*     * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the
*       names of its contributors may be used to endorse or promote
*       products derived from this software without specific prior
*       written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
****************************************************************************/

#include <pdal/GEOSUtils.hpp>
#include <pdal/Log.hpp>

#include <functional>
#include <map>
#include <sstream>

#ifdef PDAL_COMPILER_MSVC
#  pragma warning(disable: 4127)  // conditional expression is constant
#endif

namespace pdal
{
namespace geos
{

ErrorHandler::ErrorHandler(bool isDebug, LogPtr log)
    : m_isDebug(isDebug)
    , m_log(log)

{
    setup(isDebug, log);
}

void ErrorHandler::setup(bool isDebug, LogPtr log)
{
    if (m_isDebug)
        m_geos_callback = std::bind(&ErrorHandler::log, this, std::placeholders::_1 );
    else
        m_geos_callback = std::bind(&ErrorHandler::error, this, std::placeholders::_1 );

    // GEOS 3.5+ provides error handling context, so we will
    // prefer to use that where possible. Otherwise, we will default to
    // output to std::clog
#ifndef GEOS_init_r
    ctx = initGEOS_r(NULL, NULL);
#else
    ctx = GEOS_init_r();
#endif

#ifdef GEOSContext_setErrorMessageHandler_r
    GEOSContext_setErrorMessageHandler_r(ctx, &ErrorHandler::error_trampoline, this);
#else
    GEOSContext_setErrorHandler_r(ctx, &ErrorHandler::error_trampoline);
#endif

    if (m_isDebug)
    {
#ifdef GEOSContext_setNoticeHandler_r
        GEOSContext_setNoticeHandler_r(ctx, &ErrorHandler::notice_trampoline, this);
#else
        GEOSContext_setErrorHandler_r(ctx, &ErrorHandler::notice_trampoline);
#endif
    }
}

ErrorHandler::ErrorHandler(const ErrorHandler& other )
{
    setup(other.m_isDebug, other.m_log);
}

void ErrorHandler::log(char const* msg)
{
    std::ostringstream oss;
    oss << "GEOS debug: " << msg;
    if (m_log)
        m_log->get(LogLevel::Debug) << oss.str() << std::endl;
}

void ErrorHandler::error(char const* msg)
{
    std::ostringstream oss;
    oss << "GEOS failure: '" << msg <<"'";
    throw pdal_error(oss.str());
}

ErrorHandler::~ErrorHandler()
{
#ifdef GEOS_finish_r
    GEOS_finish_r(ctx);
#else
    finishGEOS_r(ctx);
#endif
}

} // namespace geos
} // namespace pdal

<|endoftext|>


<commit_before>//include <tclap/CmdLine.h>
#include <algorithm>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/variables_map.hpp>
#include <fstream>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <vector>
#include "bin_file.hpp"
#include "prenexusrenderer.hpp"
#include "renderer.hpp"
#include "version.hpp"

using std::cerr;
using std::cout;
using std::endl;
using std::invalid_argument;
using std::string;
using std::stringstream;
using std::vector;
namespace po = boost::program_options;

typedef uint32_t event_t;

struct Config{
  bool byte_swap;
  bool show_data;
  bool show_line_num;
  bool multi_file;
  bool sum_data;
  bool sum_block;
  bool is_event;
  bool get_pix_range;
  vector<size_t> integrate;
};

static const size_t BLOCK_SIZE=1024;
static const event_t ERROR=0x80000000;
static const string DEFAULT_TYPE="char";

static string::size_type count_occur(const string &str, const string &ch){
  string::size_type count = 0;
  string::size_type index = 0;

  // infinite loop to make sure that the entire string is parsed.
  while(true)
    {
      index = str.find(ch,index+1);
      if(index==string::npos)
        {
          break;
        }
      count++;
    }
  return count;
}

static bool my_isnotdigit(char c){
  return !isdigit(c);
}

static int str_to_int(const string &str){
  if(str.substr(0,1)=="-")
    return -1*str_to_int(str.substr(1,str.size()));

  string::const_iterator it = str.begin();
  it = std::find_if(it,str.end(),my_isnotdigit);

  if(it!=str.end())
    throw invalid_argument("str_to_int(string) argument is not an integer");

  return atol(str.c_str());
}

extern vector<string> split(const string &source,const string &split)
{
  string::size_type number=count_occur(source,split);
  if(number==0)
    {
      vector<string> result;
      result.push_back(source);
      return result;
    }

  vector<string> result;
  string::size_type start=0;
  string::size_type stop=0;
  string inner;
  while(true)
    {
      stop=source.find(split,start);
      if(stop==string::npos)
        {
          result.push_back(source.substr(start));
          break;
        }
      else
        {
          result.push_back(source.substr(start,stop-start));
          start=stop+split.size();
        }
    }
  return result;
}

static vector<int> str_to_intArray(const string & array){
  vector<string> str_array = split(array, ",");
  vector<int> result(0);
  size_t length = str_array.size();
  for (size_t i = 0; i < length; ++i) {
    result.push_back(str_to_int(str_array[i]));
  }
  return result;
}

template <typename NumT>
string thing_to_str(const NumT thing) {
  std::stringstream s;
  s << thing;
  return s.str();
}

template <typename NumT>
string thing_to_str(const vector<NumT> &thing) {
  std::stringstream s;
  size_t length = thing.size();
  for ( size_t i = 0 ; i < length ; ++i ){
    s << thing[i] << " ";
  }
  return s.str();
}

string pixid_str(const size_t pixid, const vector<size_t> &bounds) {
  size_t rank = bounds.size();
  if (rank<=0) {
    return "";
  }
  size_t max_index=1;
  for (size_t i = 0 ; i<rank ; ++i ){
    max_index*=bounds[i];
  }
  if(pixid>max_index) {
    std::stringstream s;
    s << "Pixel id outside of known bounds: " << pixid << ">" << max_index;
    throw std::runtime_error(s.str());
  }
  size_t my_id = pixid;
  vector<size_t> indices(bounds.size());
  for (size_t i = 0 ; i < rank-1 ; ++i ) {
    indices[i] = my_id / bounds[i+1];
    my_id = my_id - indices[i] * bounds[i+1];
  }
  indices[rank-1] = my_id;

  return thing_to_str(indices);
}

/**
 * The main entry point for the program.
 */
int main(int argc, char** argv)
{
  // ---------- Declare the supported options.
  po::options_description generic_options("Generic options");
  generic_options.add_options()
    ("help,h", "Produce this help message.")
    ("version,v", "Print version string.")
    ;

  stringstream typesHelp;
  typesHelp << "Set the type of the data. Allowed values are: " << render::getKnownDataDescr() << ", " << prenexus::getKnownDataDescr();
  po::options_description config_options("Configuration");
  config_options.add_options()
    ("type,t", po::value<string>()->default_value(DEFAULT_TYPE), typesHelp.str().c_str())
    ("offset", po::value<size_t>()->default_value(0), "Skip to this position (in bytes) in the file.")
    ("length", po::value<size_t>()->default_value(0), "Number of items to read (NOT in bytes). Zero means read to end of file.")
    ("byteswap", "Perform byte swapping on the data")
    ("lines", "show line numbers")
    ;

  po::options_description hidden_options;
  hidden_options.add_options()
    ("filename", po::value< vector<string> >(), "input files")
    ;

  // all options available on the command line
  po::options_description cmdline_options;
  cmdline_options.add(generic_options).add(config_options).add(hidden_options);

  // all options visible to the user
  po::options_description visible_options("Allowed options");
  visible_options.add(generic_options).add(config_options);

  // ---------- parse the command line
  po::positional_options_description p;
  p.add("filename", -1);
  po::variables_map vm;
  po::store(po::command_line_parser(argc, argv).options(cmdline_options)
	    .positional(p).run(), vm);
  po::notify(vm);

  // ---------- get everything out of the options
  // work with generic options
  if (vm.count("help")) {
    cout << "Usage: " << argv[0] << " [options] <filenames>" << endl;
    cout << endl;
    cout << visible_options << endl;
    return 1;
  }
  if (vm.count("version")) {
    cout << "morebin version " << VERSION << " built " << DATE << endl;
    return 0;
  }

  // config options
  size_t offset = 0;
  if (vm.count("offset"))
    offset = vm["offset"].as<size_t>();
  size_t length = 0;
  if (vm.count("length"))
    length = vm["length"].as<size_t>();
  bool byteswap = (vm.count("byteswap") > 0);
  string dataType = DEFAULT_TYPE;
  if (vm.count("type"))
    dataType = vm["type"].as<string>();
  bool showLines = (vm.count("lines") > 0);

  // hidden options
  vector<string> files;
  if (vm.count("filename"))
  {
    files = vm["filename"].as< vector<string> >();
  }
  else
  {
    cerr << "ERROR: failed to supply <filename>" << endl;
    //cmd.getOutput()->usage(cmd);
    return -1;
  }

  // ---------- push through the list of files
  try {
    bool multiFile = (files.size() > 1);
    render::Renderer * renderer = NULL;
    try {
      renderer = new render::Renderer();
      renderer->setDataDescr(dataType);
    } catch (std::runtime_error &e) {
      // TODO should print a warning
      renderer = new prenexus::PrenexusRenderer();
      renderer->setDataDescr(dataType);
    }
    renderer->showLines(showLines);

    for (std::size_t i = 0; i < files.size(); i++) {
      BinFile file(files[i]);
      file.setByteSwap(byteswap);
      if (multiFile) {
	cout << "******************************" << endl;
	cout << "* " << files[i] << " size:" << file.size_in_bytes() << endl;
	cout << "******************************" << endl;
      }
      renderer->showData(file, offset, length);
    }

    delete renderer;
  } catch(std::runtime_error &e) {
    cerr << "RUNTIME ERROR:" << e.what() << endl;
    return -1;
  }

  return 0;
}
<commit_msg>Printing link to the source when asking for version information.<commit_after>//include <tclap/CmdLine.h>
#include <algorithm>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/variables_map.hpp>
#include <fstream>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <vector>
#include "bin_file.hpp"
#include "prenexusrenderer.hpp"
#include "renderer.hpp"
#include "version.hpp"

using std::cerr;
using std::cout;
using std::endl;
using std::invalid_argument;
using std::string;
using std::stringstream;
using std::vector;
namespace po = boost::program_options;

typedef uint32_t event_t;

struct Config{
  bool byte_swap;
  bool show_data;
  bool show_line_num;
  bool multi_file;
  bool sum_data;
  bool sum_block;
  bool is_event;
  bool get_pix_range;
  vector<size_t> integrate;
};

static const size_t BLOCK_SIZE=1024;
static const event_t ERROR=0x80000000;
static const string DEFAULT_TYPE="char";

static string::size_type count_occur(const string &str, const string &ch){
  string::size_type count = 0;
  string::size_type index = 0;

  // infinite loop to make sure that the entire string is parsed.
  while(true)
    {
      index = str.find(ch,index+1);
      if(index==string::npos)
        {
          break;
        }
      count++;
    }
  return count;
}

static bool my_isnotdigit(char c){
  return !isdigit(c);
}

static int str_to_int(const string &str){
  if(str.substr(0,1)=="-")
    return -1*str_to_int(str.substr(1,str.size()));

  string::const_iterator it = str.begin();
  it = std::find_if(it,str.end(),my_isnotdigit);

  if(it!=str.end())
    throw invalid_argument("str_to_int(string) argument is not an integer");

  return atol(str.c_str());
}

extern vector<string> split(const string &source,const string &split)
{
  string::size_type number=count_occur(source,split);
  if(number==0)
    {
      vector<string> result;
      result.push_back(source);
      return result;
    }

  vector<string> result;
  string::size_type start=0;
  string::size_type stop=0;
  string inner;
  while(true)
    {
      stop=source.find(split,start);
      if(stop==string::npos)
        {
          result.push_back(source.substr(start));
          break;
        }
      else
        {
          result.push_back(source.substr(start,stop-start));
          start=stop+split.size();
        }
    }
  return result;
}

static vector<int> str_to_intArray(const string & array){
  vector<string> str_array = split(array, ",");
  vector<int> result(0);
  size_t length = str_array.size();
  for (size_t i = 0; i < length; ++i) {
    result.push_back(str_to_int(str_array[i]));
  }
  return result;
}

template <typename NumT>
string thing_to_str(const NumT thing) {
  std::stringstream s;
  s << thing;
  return s.str();
}

template <typename NumT>
string thing_to_str(const vector<NumT> &thing) {
  std::stringstream s;
  size_t length = thing.size();
  for ( size_t i = 0 ; i < length ; ++i ){
    s << thing[i] << " ";
  }
  return s.str();
}

string pixid_str(const size_t pixid, const vector<size_t> &bounds) {
  size_t rank = bounds.size();
  if (rank<=0) {
    return "";
  }
  size_t max_index=1;
  for (size_t i = 0 ; i<rank ; ++i ){
    max_index*=bounds[i];
  }
  if(pixid>max_index) {
    std::stringstream s;
    s << "Pixel id outside of known bounds: " << pixid << ">" << max_index;
    throw std::runtime_error(s.str());
  }
  size_t my_id = pixid;
  vector<size_t> indices(bounds.size());
  for (size_t i = 0 ; i < rank-1 ; ++i ) {
    indices[i] = my_id / bounds[i+1];
    my_id = my_id - indices[i] * bounds[i+1];
  }
  indices[rank-1] = my_id;

  return thing_to_str(indices);
}

/**
 * The main entry point for the program.
 */
int main(int argc, char** argv)
{
  // ---------- Declare the supported options.
  po::options_description generic_options("Generic options");
  generic_options.add_options()
    ("help,h", "Produce this help message.")
    ("version,v", "Print version string.")
    ;

  stringstream typesHelp;
  typesHelp << "Set the type of the data. Allowed values are: " << render::getKnownDataDescr() << ", " << prenexus::getKnownDataDescr();
  po::options_description config_options("Configuration");
  config_options.add_options()
    ("type,t", po::value<string>()->default_value(DEFAULT_TYPE), typesHelp.str().c_str())
    ("offset", po::value<size_t>()->default_value(0), "Skip to this position (in bytes) in the file.")
    ("length", po::value<size_t>()->default_value(0), "Number of items to read (NOT in bytes). Zero means read to end of file.")
    ("byteswap", "Perform byte swapping on the data")
    ("lines", "show line numbers")
    ;

  po::options_description hidden_options;
  hidden_options.add_options()
    ("filename", po::value< vector<string> >(), "input files")
    ;

  // all options available on the command line
  po::options_description cmdline_options;
  cmdline_options.add(generic_options).add(config_options).add(hidden_options);

  // all options visible to the user
  po::options_description visible_options("Allowed options");
  visible_options.add(generic_options).add(config_options);

  // ---------- parse the command line
  po::positional_options_description p;
  p.add("filename", -1);
  po::variables_map vm;
  po::store(po::command_line_parser(argc, argv).options(cmdline_options)
	    .positional(p).run(), vm);
  po::notify(vm);

  // ---------- get everything out of the options
  // work with generic options
  if (vm.count("help")) {
    cout << "Usage: " << argv[0] << " [options] <filenames>" << endl;
    cout << endl;
    cout << visible_options << endl;
    return 1;
  }
  if (vm.count("version")) {
    cout << "morebin version " << VERSION << " built " << DATE << endl;
    cout << endl;
    cout << "http://github.com/peterfpeterson/morebin/";
    if (VERSION.find("SNAPSHOT") == string::npos)
      cout << "tree/v" << VERSION;
    cout << endl;
    return 0;
  }

  // config options
  size_t offset = 0;
  if (vm.count("offset"))
    offset = vm["offset"].as<size_t>();
  size_t length = 0;
  if (vm.count("length"))
    length = vm["length"].as<size_t>();
  bool byteswap = (vm.count("byteswap") > 0);
  string dataType = DEFAULT_TYPE;
  if (vm.count("type"))
    dataType = vm["type"].as<string>();
  bool showLines = (vm.count("lines") > 0);

  // hidden options
  vector<string> files;
  if (vm.count("filename"))
  {
    files = vm["filename"].as< vector<string> >();
  }
  else
  {
    cerr << "ERROR: failed to supply <filename>" << endl;
    //cmd.getOutput()->usage(cmd);
    return -1;
  }

  // ---------- push through the list of files
  try {
    bool multiFile = (files.size() > 1);
    render::Renderer * renderer = NULL;
    try {
      renderer = new render::Renderer();
      renderer->setDataDescr(dataType);
    } catch (std::runtime_error &e) {
      // TODO should print a warning
      renderer = new prenexus::PrenexusRenderer();
      renderer->setDataDescr(dataType);
    }
    renderer->showLines(showLines);

    for (std::size_t i = 0; i < files.size(); i++) {
      BinFile file(files[i]);
      file.setByteSwap(byteswap);
      if (multiFile) {
	cout << "******************************" << endl;
	cout << "* " << files[i] << " size:" << file.size_in_bytes() << endl;
	cout << "******************************" << endl;
      }
      renderer->showData(file, offset, length);
    }

    delete renderer;
  } catch(std::runtime_error &e) {
    cerr << "RUNTIME ERROR:" << e.what() << endl;
    return -1;
  }

  return 0;
}
<|endoftext|>


<commit_before>#include <GL/glut.h>
#include <stdio.h>
#include <vector>
#include <floppy.h>
using namespace std;

vector<char> inputKey;
double g,v,tmp2;
int cnt;

void gameoverAnimation()
{

	inputKey.push_back('U');
	v=1.2;

}

void movePhysics()
{
int ii;
g=10;
for(ii=0;ii<inputKey.size();ii++)
	{

		if(inputKey[ii]=='U')
			{
				if((movementY+(resY/2)+50)<resY)
				movementY+=4;
				cnt++;
			}
		if(cnt>=10)
			{
				cnt=0;
				inputKey.erase(inputKey.begin()+ii);
			}

	}
//...GRAVITY
if(inputKey.size()==0)
{
// 0.021125
if(gameover==0)
{
tmp2=resY/2;
v=0.65+(abs(movementY)/tmp2)/5;
}
else
{

	if( (inputKey.size()==0 ) && (movementY <- (resY/2) ) )
	{
		gameover=0;
		resetFunc();
	}
}
movementY-= v*v/2*g;
}

}

void processSpecialKeys(int key, int xx, int yy)
{
	switch (key)
	{
		case GLUT_KEY_UP :
			if(gameover==0)
			inputKey.push_back('U');
			break;
	}
}
<commit_msg>Delete movement.cpp<commit_after><|endoftext|>


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

#include <modules/animationqt/animationqtmodule.h>
#include <inviwo/core/properties/ordinalproperty.h>
#include <inviwo/core/common/inviwoapplication.h>

#include <modules/qtwidgets/inviwoqtutils.h>

#include <modules/animation/animationmodule.h>
#include <modules/animation/datastructures/keyframe.h>
#include <modules/animation/datastructures/valuekeyframe.h>
#include <modules/animation/datastructures/track.h>
#include <modules/animation/datastructures/propertytrack.h>
#include <modules/animation/datastructures/controltrack.h>
#include <modules/animation/datastructures/animation.h>
#include <modules/animation/animationcontroller.h>

#include <modules/animationqt/animationeditordockwidgetqt.h>
#include <modules/animationqt/demo/demonavigatordockwidgetqt.h>

#include <modules/animationqt/widgets/propertytrackwidgetqt.h>
#include <modules/animationqt/widgets/controltrackwidgetqt.h>

#include <modules/animationqt/sequenceeditor/propertysequenceeditor.h>
#include <modules/animationqt/sequenceeditor/controlsequenceeditor.h>

#include <inviwo/core/properties/boolproperty.h>
#include <inviwo/core/properties/fileproperty.h>
#include <inviwo/core/properties/minmaxproperty.h>
#include <inviwo/core/properties/optionproperty.h>
#include <inviwo/core/properties/ordinalproperty.h>
#include <inviwo/core/properties/stringproperty.h>

#include <warn/push>
#include <warn/ignore/all>
#include <QMenu>
#include <QMainWindow>
#include <QMenuBar>
#include <QAction>
#include <warn/pop>

namespace inviwo {

namespace {

template <typename PropertyType>
void registerTrackHelper(animation::AnimationQtSupplier& as) {
    using namespace animation;

    using ValueType = typename PropertyType::value_type;
    using TrackType = PropertyTrack<PropertyType, ValueKeyframe<ValueType>>;

    as.registerTrackToWidgetMap(TrackType::classIdentifier(),
                                PropertyTrackWidgetQt::classIdentifier());

    as.registerTrackToSequenceEditorMap(TrackType::classIdentifier(),
                                        PropertySequenceEditor::classIdentifier());
}

template <template <typename> class Prop>
struct Reghelper {
    template <typename T>
    auto operator()(animation::AnimationQtSupplier& as) {
        using namespace animation;
        registerTrackHelper<Prop<T>>(as);
    }
};

struct PropertyReghelper {
    template <typename Prop>
    auto operator()(animation::AnimationQtSupplier& as) {
        using namespace animation;
        registerTrackHelper<Prop>(as);
    }
};

}  // namespace

AnimationQtModule::AnimationQtModule(InviwoApplication* app)
    : InviwoModule(app, "AnimationQt")
    , animation::AnimationQtSupplier(*this)
    , trackWidgetQtFactory_{}
    , sequenceEditorFactory_{} {

    using namespace animation;

    if (auto win = utilqt::getApplicationMainWindow()) {
        QString animationMenuName("Animation");
        QMenu* menu = nullptr;
        // Find view menu
        auto menus = win->menuBar()->findChildren<QMenu*>();
        auto viewMenuIt = std::find_if(menus.begin(), menus.end(), [](auto& m) {
            return m->title().compare(QObject::tr("&View"), Qt::CaseInsensitive) == 0;
        });

        if (viewMenuIt != menus.end()) {
            // Add to view menu if found
            menu = (*viewMenuIt);
        } else {
            // Add new menu if not found
            // To be removed when module is destroyed
            menu_ = std::make_unique<QMenu>(animationMenuName);
            win->menuBar()->addMenu(menu_.get());
            menu = menu_.get();
            // Release pointer if destroyed by Qt before module is destroyed
            QObject::connect(menu_.get(), &QObject::destroyed, [&](QObject*) { menu_.release(); });
        }

        {
            auto action = menu->addAction("Animation Editor");
            action->setCheckable(true);
            win->connect(action, &QAction::triggered, [this, win, app]() {
                if (!editor_) {
                    auto animationModule = app->getModuleByType<AnimationModule>();
                    auto& manager = animationModule->getAnimationManager();
                    editor_ = std::make_unique<AnimationEditorDockWidgetQt>(
                        manager, "Animation Editor", getTrackWidgetQtFactory(),
                        getSequenceEditorFactory(), win);
                    win->addDockWidget(Qt::BottomDockWidgetArea, editor_.get());
                    editor_->hide();
                    editor_->loadState();
                    // Release pointer if destroyed by Qt before module is destroyed
                    QObject::connect(editor_.get(), &QObject::destroyed,
                                     [this](QObject*) { editor_.release(); });
                    editor_->setVisible(true);
                } else {
                    editor_->setVisible(!editor_->isVisible());
                }
            });
        }

        {
            auto action = menu->addAction("Demo Navigator");
            action->setCheckable(true);
            win->connect(action, &QAction::triggered, [this, win, app]() {
                if (!navigator_) {
                    auto animationModule = app->getModuleByType<AnimationModule>();
                    auto& demoController = animationModule->getDemoController();
                    navigator_ = std::make_unique<DemoNavigatorDockWidgetQt>(demoController,
                                                                             "Demo Navigator", win);
                    win->addDockWidget(Qt::RightDockWidgetArea, navigator_.get());
                    navigator_->hide();
                    navigator_->loadState();
                    // Release pointer if destroyed by Qt before module is destroyed
                    QObject::connect(navigator_.get(), &QObject::destroyed,
                                     [this](QObject*) { navigator_.release(); });
                    navigator_->setVisible(true);
                } else {
                    navigator_->setVisible(!navigator_->isVisible());
                }
            });
        }
    }

    // register widgets
    registerTrackWidgetQt<PropertyTrackWidgetQt>();
    registerTrackWidgetQt<ControlTrackWidgetQt>();

    registerSequenceEditor<PropertySequenceEditor>();
    registerSequenceEditor<ControlSequenceEditor>();

    // Map Ordinal properties
    using Types = std::tuple<float, vec2, vec3, vec4, mat2, mat3, mat4, double, dvec2, dvec3, dvec4,
                             dmat2, dmat3, dmat4, int, ivec2, ivec3, ivec4, unsigned int, uvec2,
                             uvec3, uvec4, size_t, size2_t, size3_t, size4_t>;
    util::for_each_type<Types>{}(Reghelper<OrdinalProperty>{}, *this);

    util::for_each_type<std::tuple<float, double, int, unsigned int, size_t>>{}(
        Reghelper<MinMaxProperty>{}, *this);

    util::for_each_type<std::tuple<float, double, int, unsigned int, size_t, std::string>>{}(
        Reghelper<TemplateOptionProperty>{}, *this);

    util::for_each_type<std::tuple<BoolProperty, FileProperty, StringProperty>>{}(
        PropertyReghelper{}, *this);

    registerTrackToWidgetMap(ControlTrack::classIdentifier(),
                             ControlTrackWidgetQt::classIdentifier());

    registerTrackToSequenceEditorMap(ControlTrack::classIdentifier(),
                                     ControlSequenceEditor::classIdentifier());
}

AnimationQtModule::~AnimationQtModule() {
    // Unregister everything from the factory since this module _owns_ the factory. This is
    // neccessary even though the base class destructor, i.e. animation::AnimationQtSupplier, takes
    // care of this. Otherwise the supplier will unregister the items _after_ the factory is
    // destroyed.
    //
    // Other modules do not have to do this!
    unRegisterAll();
}

animation::TrackWidgetQtFactory& AnimationQtModule::getTrackWidgetQtFactory() {
    return trackWidgetQtFactory_;
}
const animation::TrackWidgetQtFactory& AnimationQtModule::getTrackWidgetQtFactory() const {
    return trackWidgetQtFactory_;
}

animation::SequenceEditorFactory& AnimationQtModule::getSequenceEditorFactory() {
    return sequenceEditorFactory_;
}
const animation::SequenceEditorFactory& AnimationQtModule::getSequenceEditorFactory() const {
    return sequenceEditorFactory_;
}

}  // namespace inviwo
<commit_msg>AnimationQt: Added OrdinalRefProperty<commit_after>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2016-2020 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <modules/animationqt/animationqtmodule.h>
#include <inviwo/core/properties/ordinalproperty.h>
#include <inviwo/core/common/inviwoapplication.h>

#include <modules/qtwidgets/inviwoqtutils.h>

#include <modules/animation/animationmodule.h>
#include <modules/animation/datastructures/keyframe.h>
#include <modules/animation/datastructures/valuekeyframe.h>
#include <modules/animation/datastructures/track.h>
#include <modules/animation/datastructures/propertytrack.h>
#include <modules/animation/datastructures/controltrack.h>
#include <modules/animation/datastructures/animation.h>
#include <modules/animation/animationcontroller.h>

#include <modules/animationqt/animationeditordockwidgetqt.h>
#include <modules/animationqt/demo/demonavigatordockwidgetqt.h>

#include <modules/animationqt/widgets/propertytrackwidgetqt.h>
#include <modules/animationqt/widgets/controltrackwidgetqt.h>

#include <modules/animationqt/sequenceeditor/propertysequenceeditor.h>
#include <modules/animationqt/sequenceeditor/controlsequenceeditor.h>

#include <inviwo/core/properties/boolproperty.h>
#include <inviwo/core/properties/fileproperty.h>
#include <inviwo/core/properties/minmaxproperty.h>
#include <inviwo/core/properties/optionproperty.h>
#include <inviwo/core/properties/ordinalproperty.h>
#include <inviwo/core/properties/ordinalrefproperty.h>
#include <inviwo/core/properties/stringproperty.h>

#include <warn/push>
#include <warn/ignore/all>
#include <QMenu>
#include <QMainWindow>
#include <QMenuBar>
#include <QAction>
#include <warn/pop>

namespace inviwo {

namespace {

template <typename PropertyType>
void registerTrackHelper(animation::AnimationQtSupplier& as) {
    using namespace animation;

    using ValueType = typename PropertyType::value_type;
    using TrackType = PropertyTrack<PropertyType, ValueKeyframe<ValueType>>;

    as.registerTrackToWidgetMap(TrackType::classIdentifier(),
                                PropertyTrackWidgetQt::classIdentifier());

    as.registerTrackToSequenceEditorMap(TrackType::classIdentifier(),
                                        PropertySequenceEditor::classIdentifier());
}

template <template <typename> class Prop>
struct Reghelper {
    template <typename T>
    auto operator()(animation::AnimationQtSupplier& as) {
        using namespace animation;
        registerTrackHelper<Prop<T>>(as);
    }
};

struct PropertyReghelper {
    template <typename Prop>
    auto operator()(animation::AnimationQtSupplier& as) {
        using namespace animation;
        registerTrackHelper<Prop>(as);
    }
};

}  // namespace

AnimationQtModule::AnimationQtModule(InviwoApplication* app)
    : InviwoModule(app, "AnimationQt")
    , animation::AnimationQtSupplier(*this)
    , trackWidgetQtFactory_{}
    , sequenceEditorFactory_{} {

    using namespace animation;

    if (auto win = utilqt::getApplicationMainWindow()) {
        QString animationMenuName("Animation");
        QMenu* menu = nullptr;
        // Find view menu
        auto menus = win->menuBar()->findChildren<QMenu*>();
        auto viewMenuIt = std::find_if(menus.begin(), menus.end(), [](auto& m) {
            return m->title().compare(QObject::tr("&View"), Qt::CaseInsensitive) == 0;
        });

        if (viewMenuIt != menus.end()) {
            // Add to view menu if found
            menu = (*viewMenuIt);
        } else {
            // Add new menu if not found
            // To be removed when module is destroyed
            menu_ = std::make_unique<QMenu>(animationMenuName);
            win->menuBar()->addMenu(menu_.get());
            menu = menu_.get();
            // Release pointer if destroyed by Qt before module is destroyed
            QObject::connect(menu_.get(), &QObject::destroyed, [&](QObject*) { menu_.release(); });
        }

        {
            auto action = menu->addAction("Animation Editor");
            action->setCheckable(true);
            win->connect(action, &QAction::triggered, [this, win, app]() {
                if (!editor_) {
                    auto animationModule = app->getModuleByType<AnimationModule>();
                    auto& manager = animationModule->getAnimationManager();
                    editor_ = std::make_unique<AnimationEditorDockWidgetQt>(
                        manager, "Animation Editor", getTrackWidgetQtFactory(),
                        getSequenceEditorFactory(), win);
                    win->addDockWidget(Qt::BottomDockWidgetArea, editor_.get());
                    editor_->hide();
                    editor_->loadState();
                    // Release pointer if destroyed by Qt before module is destroyed
                    QObject::connect(editor_.get(), &QObject::destroyed,
                                     [this](QObject*) { editor_.release(); });
                    editor_->setVisible(true);
                } else {
                    editor_->setVisible(!editor_->isVisible());
                }
            });
        }

        {
            auto action = menu->addAction("Demo Navigator");
            action->setCheckable(true);
            win->connect(action, &QAction::triggered, [this, win, app]() {
                if (!navigator_) {
                    auto animationModule = app->getModuleByType<AnimationModule>();
                    auto& demoController = animationModule->getDemoController();
                    navigator_ = std::make_unique<DemoNavigatorDockWidgetQt>(demoController,
                                                                             "Demo Navigator", win);
                    win->addDockWidget(Qt::RightDockWidgetArea, navigator_.get());
                    navigator_->hide();
                    navigator_->loadState();
                    // Release pointer if destroyed by Qt before module is destroyed
                    QObject::connect(navigator_.get(), &QObject::destroyed,
                                     [this](QObject*) { navigator_.release(); });
                    navigator_->setVisible(true);
                } else {
                    navigator_->setVisible(!navigator_->isVisible());
                }
            });
        }
    }

    // register widgets
    registerTrackWidgetQt<PropertyTrackWidgetQt>();
    registerTrackWidgetQt<ControlTrackWidgetQt>();

    registerSequenceEditor<PropertySequenceEditor>();
    registerSequenceEditor<ControlSequenceEditor>();

    // Map Ordinal properties
    using Types = std::tuple<float, vec2, vec3, vec4, mat2, mat3, mat4, double, dvec2, dvec3, dvec4,
                             dmat2, dmat3, dmat4, int, ivec2, ivec3, ivec4, unsigned int, uvec2,
                             uvec3, uvec4, size_t, size2_t, size3_t, size4_t>;
    util::for_each_type<Types>{}(Reghelper<OrdinalProperty>{}, *this);
    util::for_each_type<Types>{}(Reghelper<OrdinalRefProperty>{}, *this);

    util::for_each_type<std::tuple<float, double, int, unsigned int, size_t>>{}(
        Reghelper<MinMaxProperty>{}, *this);

    util::for_each_type<std::tuple<float, double, int, unsigned int, size_t, std::string>>{}(
        Reghelper<TemplateOptionProperty>{}, *this);

    util::for_each_type<std::tuple<BoolProperty, FileProperty, StringProperty>>{}(
        PropertyReghelper{}, *this);

    registerTrackToWidgetMap(ControlTrack::classIdentifier(),
                             ControlTrackWidgetQt::classIdentifier());

    registerTrackToSequenceEditorMap(ControlTrack::classIdentifier(),
                                     ControlSequenceEditor::classIdentifier());
}

AnimationQtModule::~AnimationQtModule() {
    // Unregister everything from the factory since this module _owns_ the factory. This is
    // neccessary even though the base class destructor, i.e. animation::AnimationQtSupplier, takes
    // care of this. Otherwise the supplier will unregister the items _after_ the factory is
    // destroyed.
    //
    // Other modules do not have to do this!
    unRegisterAll();
}

animation::TrackWidgetQtFactory& AnimationQtModule::getTrackWidgetQtFactory() {
    return trackWidgetQtFactory_;
}
const animation::TrackWidgetQtFactory& AnimationQtModule::getTrackWidgetQtFactory() const {
    return trackWidgetQtFactory_;
}

animation::SequenceEditorFactory& AnimationQtModule::getSequenceEditorFactory() {
    return sequenceEditorFactory_;
}
const animation::SequenceEditorFactory& AnimationQtModule::getSequenceEditorFactory() const {
    return sequenceEditorFactory_;
}

}  // namespace inviwo
<|endoftext|>


<commit_before>/*******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 1       *
*                (c) 2006-2007 MGH, INRIA, USTL, UJF, CNRS                     *
*                                                                              *
* This library is free software; you can redistribute it and/or modify it      *
* under the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, or (at your     *
* option) any later version.                                                   *
*                                                                              *
* This library is distributed in the hope that it will be useful, but WITHOUT  *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or        *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License  *
* for more details.                                                            *
*                                                                              *
* You should have received a copy of the GNU Lesser General Public License     *
* along with this library; if not, write to the Free Software Foundation,      *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.           *
*                                                                              *
* Contact information: contact@sofa-framework.org                              *
*                                                                              *
* Authors: J. Allard, P-J. Bensoussan, S. Cotin, C. Duriez, H. Delingette,     *
* F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza, M. Nesme, P. Neumann,        *
* and F. Poyer                                                                 *
*******************************************************************************/
#include "PipelineImpl.h"
//#include <sofa/component/collision/DiscreteIntersection.h>
#include <sofa/simulation/tree/GNode.h>
#include <sofa/core/ObjectFactory.h>

namespace sofa
{

namespace simulation
{

namespace tree
{

using namespace sofa::core;
using namespace sofa::core::objectmodel;
using namespace sofa::core::componentmodel::behavior;
using namespace sofa::core::componentmodel::collision;

PipelineImpl::PipelineImpl()
{
}

PipelineImpl::~PipelineImpl()
{
}

void PipelineImpl::init()
{
    simulation::tree::GNode* root = dynamic_cast<simulation::tree::GNode*>(getContext());
    if(root == NULL) return;
    intersectionMethods.clear();
    root->getTreeObjects<Intersection>(&intersectionMethods);
    intersectionMethod = (intersectionMethods.empty() ? NULL : intersectionMethods[0]);
    broadPhaseDetections.clear();
    root->getTreeObjects<BroadPhaseDetection>(&broadPhaseDetections);
    broadPhaseDetection = (broadPhaseDetections.empty() ? NULL : broadPhaseDetections[0]);
    narrowPhaseDetections.clear();
    root->getTreeObjects<NarrowPhaseDetection>(&narrowPhaseDetections);
    narrowPhaseDetection = (narrowPhaseDetections.empty() ? NULL : narrowPhaseDetections[0]);
    contactManagers.clear();
    root->getTreeObjects<ContactManager>(&contactManagers);
    contactManager = (contactManagers.empty() ? NULL : contactManagers[0]);
    groupManagers.clear();
    root->getTreeObjects<CollisionGroupManager>(&groupManagers);
    groupManager = (groupManagers.empty() ? NULL : groupManagers[0]);

//	if (intersectionMethod==NULL)
    if (intersectionMethod==NULL)
    {
//		intersectionMethod = new sofa::component::collision::DiscreteIntersection;
        std::cerr << "WARNING(Pipeline): no intersectionMethod defined. Using DiscreteIntersection.\n";
        sofa::core::objectmodel::BaseObjectDescription discreteIntersectionDesc("Default Intersection","DiscreteIntersection");
        intersectionMethod = dynamic_cast<Intersection*>(sofa::core::ObjectFactory::CreateObject(getContext(), &discreteIntersectionDesc));
    }
}

void PipelineImpl::reset()
{
    computeCollisionReset();
}

void PipelineImpl::computeCollisionReset()
{
    simulation::tree::GNode* root = dynamic_cast<simulation::tree::GNode*>(getContext());
    if(root == NULL) return;
    if (broadPhaseDetection!=NULL && broadPhaseDetection->getIntersectionMethod()!=intersectionMethod)
        broadPhaseDetection->setIntersectionMethod(intersectionMethod);
    if (narrowPhaseDetection!=NULL && narrowPhaseDetection->getIntersectionMethod()!=intersectionMethod)
        narrowPhaseDetection->setIntersectionMethod(intersectionMethod);
    if (contactManager!=NULL && contactManager->getIntersectionMethod()!=intersectionMethod)
        contactManager->setIntersectionMethod(intersectionMethod);
    doCollisionReset();
}

void PipelineImpl::computeCollisionDetection()
{
    simulation::tree::GNode* root = dynamic_cast<simulation::tree::GNode*>(getContext());
    if(root == NULL) return;
    std::vector<CollisionModel*> collisionModels;
    root->getTreeObjects<CollisionModel>(&collisionModels);
    doCollisionDetection(collisionModels);
}

void PipelineImpl::computeCollisionResponse()
{
    simulation::tree::GNode* root = dynamic_cast<simulation::tree::GNode*>(getContext());
    if(root == NULL) return;
    doCollisionResponse();
}

} // namespace tree

} // namespace simulation

} // namespace sofa
<commit_msg>r1168/sofa-dev : BUG: Creating intersectionMethod using the Factory makes Sofa crash on Windows (Visual C++ 2005 express). FIX: create object using "new" instead of the factory.<commit_after>/*******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 1       *
*                (c) 2006-2007 MGH, INRIA, USTL, UJF, CNRS                     *
*                                                                              *
* This library is free software; you can redistribute it and/or modify it      *
* under the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, or (at your     *
* option) any later version.                                                   *
*                                                                              *
* This library is distributed in the hope that it will be useful, but WITHOUT  *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or        *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License  *
* for more details.                                                            *
*                                                                              *
* You should have received a copy of the GNU Lesser General Public License     *
* along with this library; if not, write to the Free Software Foundation,      *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.           *
*                                                                              *
* Contact information: contact@sofa-framework.org                              *
*                                                                              *
* Authors: J. Allard, P-J. Bensoussan, S. Cotin, C. Duriez, H. Delingette,     *
* F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza, M. Nesme, P. Neumann,        *
* and F. Poyer                                                                 *
*******************************************************************************/
#include "PipelineImpl.h"
#include <sofa/component/collision/DiscreteIntersection.h>
#include <sofa/simulation/tree/GNode.h>
#include <sofa/core/ObjectFactory.h>

namespace sofa
{

namespace simulation
{

namespace tree
{

using namespace sofa::core;
using namespace sofa::core::objectmodel;
using namespace sofa::core::componentmodel::behavior;
using namespace sofa::core::componentmodel::collision;

PipelineImpl::PipelineImpl()
{
}

PipelineImpl::~PipelineImpl()
{
}

void PipelineImpl::init()
{
    simulation::tree::GNode* root = dynamic_cast<simulation::tree::GNode*>(getContext());
    if(root == NULL) return;
    intersectionMethods.clear();
    root->getTreeObjects<Intersection>(&intersectionMethods);
    intersectionMethod = (intersectionMethods.empty() ? NULL : intersectionMethods[0]);
    broadPhaseDetections.clear();
    root->getTreeObjects<BroadPhaseDetection>(&broadPhaseDetections);
    broadPhaseDetection = (broadPhaseDetections.empty() ? NULL : broadPhaseDetections[0]);
    narrowPhaseDetections.clear();
    root->getTreeObjects<NarrowPhaseDetection>(&narrowPhaseDetections);
    narrowPhaseDetection = (narrowPhaseDetections.empty() ? NULL : narrowPhaseDetections[0]);
    contactManagers.clear();
    root->getTreeObjects<ContactManager>(&contactManagers);
    contactManager = (contactManagers.empty() ? NULL : contactManagers[0]);
    groupManagers.clear();
    root->getTreeObjects<CollisionGroupManager>(&groupManagers);
    groupManager = (groupManagers.empty() ? NULL : groupManagers[0]);

    if (intersectionMethod==NULL)
    {
        std::cerr << "WARNING(Pipeline): no intersectionMethod defined. Using DiscreteIntersection.\n";
        sofa::core::objectmodel::BaseObjectDescription discreteIntersectionDesc("Default Intersection","DiscreteIntersection");
        //intersectionMethod = dynamic_cast<Intersection*>(sofa::core::ObjectFactory::CreateObject(getContext(), &discreteIntersectionDesc));
        intersectionMethod = new sofa::component::collision::DiscreteIntersection;
    }
}

void PipelineImpl::reset()
{
    computeCollisionReset();
}

void PipelineImpl::computeCollisionReset()
{
    simulation::tree::GNode* root = dynamic_cast<simulation::tree::GNode*>(getContext());
    if(root == NULL) return;
    if (broadPhaseDetection!=NULL && broadPhaseDetection->getIntersectionMethod()!=intersectionMethod)
        broadPhaseDetection->setIntersectionMethod(intersectionMethod);
    if (narrowPhaseDetection!=NULL && narrowPhaseDetection->getIntersectionMethod()!=intersectionMethod)
        narrowPhaseDetection->setIntersectionMethod(intersectionMethod);
    if (contactManager!=NULL && contactManager->getIntersectionMethod()!=intersectionMethod)
        contactManager->setIntersectionMethod(intersectionMethod);
    doCollisionReset();
}

void PipelineImpl::computeCollisionDetection()
{
    simulation::tree::GNode* root = dynamic_cast<simulation::tree::GNode*>(getContext());
    if(root == NULL) return;
    std::vector<CollisionModel*> collisionModels;
    root->getTreeObjects<CollisionModel>(&collisionModels);
    doCollisionDetection(collisionModels);
}

void PipelineImpl::computeCollisionResponse()
{
    simulation::tree::GNode* root = dynamic_cast<simulation::tree::GNode*>(getContext());
    if(root == NULL) return;
    doCollisionResponse();
}

} // namespace tree

} // namespace simulation

} // namespace sofa
<|endoftext|>


<commit_before>/* Copyright (C) 2008 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; version 2 of the License.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

/*
  Utility program that encapsulates process creation, monitoring
  and bulletproof process cleanup

  Usage:
    safe_process [options to safe_process] -- progname arg1 ... argn

  To safeguard mysqld you would invoke safe_process with a few options
  for safe_process itself followed by a double dash to indicate start
  of the command line for the program you really want to start

  $> safe_process --output=output.log -- mysqld --datadir=var/data1 ...

  This would redirect output to output.log and then start mysqld,
  once it has done that it will continue to monitor the child as well
  as the parent.

  The safe_process then checks the follwing things:
  1. Child exits, propagate the childs return code to the parent
     by exiting with the same return code as the child.

  2. Parent dies, immediately kill the child and exit, thus the
     parent does not need to properly cleanup any child, it is handled
     automatically.

  3. Signal's recieced by the process will trigger same action as 2)

*/

#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <errno.h>

int verbose= 0;
int terminated= 0;
pid_t child_pid= -1;
char safe_process_name[32]= {0};

static void message(const char* fmt, ...)
{
  if (!verbose)
    return;
  va_list args;
  fprintf(stderr, "%s: ", safe_process_name);
  va_start(args, fmt);
  vfprintf(stderr, fmt, args);
  fprintf(stderr, "\n");
  va_end(args);
  fflush(stderr);
}

static void die(const char* fmt, ...)
{
  va_list args;
  fprintf(stderr, "%s: FATAL ERROR, ", safe_process_name);
  va_start(args, fmt);
  vfprintf(stderr, fmt, args);
  fprintf(stderr, "\n");
  va_end(args);
  if (int last_err= errno)
    fprintf(stderr, "error: %d, %s\n", last_err, strerror(last_err));
  exit(1);
}

static void kill_child(void)
{
  int status= 0;

  message("Killing child: %d", child_pid);
  // Terminate whole process group
  kill(-child_pid, SIGKILL);

  pid_t ret_pid= waitpid(child_pid, &status, 0);
  if (ret_pid == child_pid)
  {
    int exit_code= 1;
    if (WIFEXITED(status))
    {
      // Process has exited, collect return status
      exit_code= WEXITSTATUS(status);
      message("Child exit: %d", exit_code);
      // Exit with exit status of the child
      exit(exit_code);
    }

    if (WIFSIGNALED(status))
      message("Child killed by signal: %d", WTERMSIG(status));

    exit(exit_code);
  }
  exit(1);
}

extern "C" void handle_abort(int sig)
{
    message("Got signal %d, child_pid: %d, sending ABRT", sig, child_pid);

    if (child_pid > 0) {
	kill (-child_pid, SIGABRT);	// Don't wait for it to terminate
    }
}

extern "C" void handle_signal(int sig)
{
  message("Got signal %d, child_pid: %d", sig, child_pid);
  terminated= 1;

  if (child_pid > 0)
    kill_child();

  // Ignore further signals
  signal(SIGTERM, SIG_IGN);
  signal(SIGINT,  SIG_IGN);

  // Continune execution, allow the child to be started and
  // finally terminated by monitor loop
}

int main(int argc, char* const argv[] )
{
  char* const* child_argv= 0;
  pid_t own_pid= getpid();
  pid_t parent_pid= getppid();
  bool nocore = false;

  /* Install signal handlers */
  signal(SIGTERM, handle_signal);
  signal(SIGINT,  handle_signal);
  signal(SIGCHLD, handle_signal);
  signal(SIGABRT, handle_abort);

  sprintf(safe_process_name, "safe_process[%d]", (int) own_pid);

  message("Started");

  /* Parse arguments */
  for (int i= 1; i < argc; i++) {
    const char* arg= argv[i];
    if (strcmp(arg, "--") == 0 && strlen(arg) == 2) {
      /* Got the "--" delimiter */
      if (i >= argc)
        die("No real args -> nothing to do");
      child_argv= &argv[i+1];
      break;
    } else {
      if ( strcmp(arg, "--verbose") == 0 )
        verbose++;
      else if ( strncmp(arg, "--parent-pid", 10) == 0 )
      {
        /* Override parent_pid with a value provided by user */
        const char* start;
        if ((start= strstr(arg, "=")) == NULL)
          die("Could not find start of option value in '%s'", arg);
        start++; /* Step past = */
        if ((parent_pid= atoi(start)) == 0)
          die("Invalid value '%s' passed to --parent-id", start);
      } else if ( strcmp(arg, "--nocore") == 0 )
      {
        nocore = true;	// Don't allow the process to dump core
      }
      else
        die("Unknown option: %s", arg);
    }
  }
  if (!child_argv || *child_argv == 0)
    die("nothing to do");

  message("parent_pid: %d", parent_pid);
  if (parent_pid == own_pid)
    die("parent_pid is equal to own pid!");

  char buf;
  int pfd[2];
  if (pipe(pfd) == -1)
    die("Failed to create pipe");

  /* Create the child process */
  while((child_pid= fork()) == -1)
  {
    message("fork failed");
    sleep(1);
  }

  if (child_pid == 0)
  {
    close(pfd[0]); // Close unused read end

    // Use default signal handlers in child
    signal(SIGTERM, SIG_DFL);
    signal(SIGINT,  SIG_DFL);
    signal(SIGCHLD, SIG_DFL);

    // Make this process it's own process group to be able to kill
    // it and any childs(that hasn't changed group themself)
    setpgid(0, 0);

    if (nocore)
    {
      struct rlimit corelim = { 0, 0 };
      if (setrlimit (RLIMIT_CORE, &corelim) < 0)
      {
        message("setrlimit failed, errno=%d", errno);
      }
    }

    // Signal that child is ready
    buf= 37;
    if ((write(pfd[1], &buf, 1)) < 1)
      die("Failed to signal that child is ready");
    // Close write end
    close(pfd[1]);

    if (execvp(child_argv[0], child_argv) < 0)
      die("Failed to exec child");
  }

  close(pfd[1]); // Close unused write end

  // Wait for child to signal it's ready
  if ((read(pfd[0], &buf, 1)) < 1)
    die("Failed to read signal from child");

  if (buf != 37)
    die("Didn't get 37 from pipe");
  close(pfd[0]); // Close read end

  /* Monitor loop */
  message("Started child %d, terminated: %d", child_pid, terminated);

  while(!terminated)
  {
    // Check if parent is still alive
    if (kill(parent_pid, 0) != 0){
      message("Parent is not alive anymore");
      break;
    }

    // Check if child has exited, normally this will be
    // detected immediately with SIGCHLD handler
    int status= 0;
    pid_t ret_pid= waitpid(child_pid, &status, WNOHANG);
    if (ret_pid == child_pid)
    {
      int ret_code= 2;
      if (WIFEXITED(status))
      {
        // Process has exited, collect return status
        ret_code= WEXITSTATUS(status);
        message("Child exit: %d", ret_code);
        // Exit with exit status of the child
        exit(ret_code);
      }

      if (WIFSIGNALED(status))
        message("Child killed by signal: %d", WTERMSIG(status));

      exit(ret_code);
    }
    sleep(1);
  }
  kill_child();

  return 1;
}

<commit_msg>Fixed race condition in safe_process.cc which may have caused some mysqltests to be reported as failed even if they succeded.<commit_after>/* Copyright (C) 2008 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; version 2 of the License.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

/*
  Utility program that encapsulates process creation, monitoring
  and bulletproof process cleanup

  Usage:
    safe_process [options to safe_process] -- progname arg1 ... argn

  To safeguard mysqld you would invoke safe_process with a few options
  for safe_process itself followed by a double dash to indicate start
  of the command line for the program you really want to start

  $> safe_process --output=output.log -- mysqld --datadir=var/data1 ...

  This would redirect output to output.log and then start mysqld,
  once it has done that it will continue to monitor the child as well
  as the parent.

  The safe_process then checks the follwing things:
  1. Child exits, propagate the childs return code to the parent
     by exiting with the same return code as the child.

  2. Parent dies, immediately kill the child and exit, thus the
     parent does not need to properly cleanup any child, it is handled
     automatically.

  3. Signal's recieced by the process will trigger same action as 2)

*/

#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <errno.h>

int verbose= 0;
int terminated= 0;
pid_t child_pid= -1;
char safe_process_name[32]= {0};

static void message(const char* fmt, ...)
{
  if (!verbose)
    return;
  va_list args;
  fprintf(stderr, "%s: ", safe_process_name);
  va_start(args, fmt);
  vfprintf(stderr, fmt, args);
  fprintf(stderr, "\n");
  va_end(args);
  fflush(stderr);
}

static void die(const char* fmt, ...)
{
  va_list args;
  fprintf(stderr, "%s: FATAL ERROR, ", safe_process_name);
  va_start(args, fmt);
  vfprintf(stderr, fmt, args);
  fprintf(stderr, "\n");
  va_end(args);
  if (int last_err= errno)
    fprintf(stderr, "error: %d, %s\n", last_err, strerror(last_err));
  exit(6);
}

static void kill_child(bool was_killed)
{
  int status= 0;

  message("Killing child: %d", child_pid);
  // Terminate whole process group
  if (! was_killed)
    kill(-child_pid, SIGKILL);

  pid_t ret_pid= waitpid(child_pid, &status, 0);
  if (ret_pid == child_pid)
  {
    int exit_code= 1;
    if (WIFEXITED(status))
    {
      // Process has exited, collect return status
      exit_code= WEXITSTATUS(status);
      message("Child exit: %d", exit_code);
      // Exit with exit status of the child
      exit(exit_code);
    }

    if (WIFSIGNALED(status))
      message("Child killed by signal: %d", WTERMSIG(status));

    exit(exit_code);
  }
  exit(5);
}

extern "C" void handle_abort(int sig)
{
    message("Got signal %d, child_pid: %d, sending ABRT", sig, child_pid);

    if (child_pid > 0) {
	kill (-child_pid, SIGABRT);	// Don't wait for it to terminate
    }
}

extern "C" void handle_signal(int sig)
{
  message("Got signal %d, child_pid: %d", sig, child_pid);
  terminated= 1;

  if (child_pid > 0)
    kill_child(sig == SIGCHLD);

  // Ignore further signals
  signal(SIGTERM, SIG_IGN);
  signal(SIGINT,  SIG_IGN);

  // Continune execution, allow the child to be started and
  // finally terminated by monitor loop
}

int main(int argc, char* const argv[] )
{
  char* const* child_argv= 0;
  pid_t own_pid= getpid();
  pid_t parent_pid= getppid();
  bool nocore = false;

  /* Install signal handlers */
  signal(SIGTERM, handle_signal);
  signal(SIGINT,  handle_signal);
  signal(SIGCHLD, handle_signal);
  signal(SIGABRT, handle_abort);

  sprintf(safe_process_name, "safe_process[%d]", (int) own_pid);

  message("Started");

  /* Parse arguments */
  for (int i= 1; i < argc; i++) {
    const char* arg= argv[i];
    if (strcmp(arg, "--") == 0 && strlen(arg) == 2) {
      /* Got the "--" delimiter */
      if (i >= argc)
        die("No real args -> nothing to do");
      child_argv= &argv[i+1];
      break;
    } else {
      if ( strcmp(arg, "--verbose") == 0 )
        verbose++;
      else if ( strncmp(arg, "--parent-pid", 10) == 0 )
      {
        /* Override parent_pid with a value provided by user */
        const char* start;
        if ((start= strstr(arg, "=")) == NULL)
          die("Could not find start of option value in '%s'", arg);
        start++; /* Step past = */
        if ((parent_pid= atoi(start)) == 0)
          die("Invalid value '%s' passed to --parent-id", start);
      } else if ( strcmp(arg, "--nocore") == 0 )
      {
        nocore = true;	// Don't allow the process to dump core
      }
      else
        die("Unknown option: %s", arg);
    }
  }
  if (!child_argv || *child_argv == 0)
    die("nothing to do");

  message("parent_pid: %d", parent_pid);
  if (parent_pid == own_pid)
    die("parent_pid is equal to own pid!");

  char buf;
  int pfd[2];
  if (pipe(pfd) == -1)
    die("Failed to create pipe");

  /* Create the child process */
  while((child_pid= fork()) == -1)
  {
    message("fork failed");
    sleep(1);
  }

  if (child_pid == 0)
  {
    close(pfd[0]); // Close unused read end

    // Use default signal handlers in child
    signal(SIGTERM, SIG_DFL);
    signal(SIGINT,  SIG_DFL);
    signal(SIGCHLD, SIG_DFL);

    // Make this process it's own process group to be able to kill
    // it and any childs(that hasn't changed group themself)
    setpgid(0, 0);

    if (nocore)
    {
      struct rlimit corelim = { 0, 0 };
      if (setrlimit (RLIMIT_CORE, &corelim) < 0)
      {
        message("setrlimit failed, errno=%d", errno);
      }
    }

    // Signal that child is ready
    buf= 37;
    if ((write(pfd[1], &buf, 1)) < 1)
      die("Failed to signal that child is ready");
    // Close write end
    close(pfd[1]);

    execvp(child_argv[0], child_argv);
    die("Failed to exec child");
  }

  close(pfd[1]); // Close unused write end

  // Wait for child to signal it's ready
  if ((read(pfd[0], &buf, 1)) < 1)
    die("Failed to read signal from child");

  if (buf != 37)
    die("Didn't get 37 from pipe");
  close(pfd[0]); // Close read end

  /* Monitor loop */
  message("Started child %d, terminated: %d", child_pid, terminated);

  while (!terminated)
  {
    // Check if parent is still alive
    if (kill(parent_pid, 0) != 0)
    {
      message("Parent is not alive anymore");
      break;
    }
    /* Wait for parent or child to die */
    sleep(1);
  }
  kill_child(0);

  return 4;
}

<|endoftext|>