<commit_before>#include <exprtk/exprtk.hpp>

#include <memory>

#include <possumwood_sdk/node_implementation.h>
#include <possumwood_sdk/source_editor.h>

#include <QPainter>
#include <QPushButton>
#include <QMenu>

#include "datatypes/pixmap.h"
#include "expressions/datatypes/symbol_table.h"

namespace {

dependency_graph::InAttr<std::string> a_src;
dependency_graph::InAttr<possumwood::ExprSymbols> a_symbols;
dependency_graph::InAttr<std::shared_ptr<const QPixmap>> a_inPixmap;
dependency_graph::OutAttr<std::shared_ptr<const QPixmap>> a_outPixmap;

class Popup : public QMenu {
	public:
		Popup(QWidget* parent) : QMenu(parent) {
		}

		void addItem(const std::string& name) {
			addAction(name.c_str());
		}

	private:
};

class Editor : public possumwood::SourceEditor {
	public:
		Editor() : SourceEditor(a_src), m_popup(nullptr) {
			m_varsButton = new QPushButton("Variables");
			buttonsLayout()->insertWidget(0, m_varsButton);

			widget()->connect(m_varsButton, &QPushButton::pressed, [this]() {
				if(m_popup)
					m_popup->popup(
						m_varsButton->mapToGlobal(QPoint(0,-m_popup->sizeHint().height()))
					);
			});
		}

	protected:
		virtual void valueChanged(const dependency_graph::Attr& attr) override {
			if(attr == a_symbols) {
				m_popup->deleteLater();

				populateVariableList();
			}

			else
				SourceEditor::valueChanged(attr);
		}

		void populateVariableList() {
			if(!m_popup)
				m_popup->deleteLater();

			m_popup = new Popup(m_varsButton);

			m_popup->connect(m_popup, &Popup::triggered, [this](QAction* action) {
				QString text = action->text();
				while(!text.isEmpty() && !QChar(text[0]).isLetterOrNumber())
					text = text.mid(1, text.length()-1);
				if(text.indexOf('\t') >= 0)
					text = text.mid(0, text.indexOf('\t'));

				editorWidget()->insertPlainText(text);
			});

			// the external symbols
			unsigned ctr = 0;
			for(auto& s : values().get(a_symbols)) {
				m_popup->addItem(s.first + "\t(constant)");
				++ctr;
			}

			if(ctr > 0)
				m_popup->addSeparator();

			// hardwired symbols
			m_popup->addItem("x\t(constant)");
			m_popup->addItem("y\t(constant)");
			m_popup->addItem("width\t(constant)");
			m_popup->addItem("height\t(constant)");

			m_popup->addSeparator();

			m_popup->addItem("r\t(variable)");
			m_popup->addItem("g\t(variable)");
			m_popup->addItem("b\t(variable)");
		}

	private:
		QPushButton* m_varsButton;

		Popup* m_popup;
};

dependency_graph::State compute(dependency_graph::Values& data) {
	dependency_graph::State result;

	std::shared_ptr<const QPixmap> input = data.get(a_inPixmap);

	if(input == nullptr) {
		result.addError("No input pixmap");
		data.set(a_outPixmap, input);
	}

	else {
		float x = 0.0f;
		float y = 0.0f;

		float r = 0.0f;
		float g = 0.0f;
		float b = 0.0f;

		const possumwood::ExprSymbols& symbols = data.get(a_symbols);

		exprtk::symbol_table<float> symbol_table;

		for(auto& s : symbols)
			symbol_table.add_constant(s.first, s.second);

		symbol_table.add_variable("x", x);
		symbol_table.add_variable("y", y);

		symbol_table.add_variable("r", r);
		symbol_table.add_variable("g", g);
		symbol_table.add_variable("b", b);

		symbol_table.add_constant("width", input->width());
		symbol_table.add_constant("height", input->height());

		symbol_table.add_constants();

		exprtk::expression<float> expression;
		expression.register_symbol_table(symbol_table);

		std::string err;
		bool success = false;
		{
			exprtk::parser<float> parser;
			success = parser.compile(data.get(a_src), expression);

			if(!success)
				err = parser.error();
		}

		auto cexpr = (const exprtk::expression<float>)expression;

		// compilation failed
		if(!success) {
			result.addError(err);

			// output nothing
			data.set(a_outPixmap, std::shared_ptr<const QPixmap>());
		}

		// compilation success
		else {
			// make a QImage, so we can set pixels
			QImage image = input->toImage();

			// iterate over pixels
			for(int yi = 0; yi < input->height(); ++yi)
				for(int xi = 0; xi < input->width(); ++xi) {
					x = xi;
					y = yi;

					// r, g, b variables are changeable from the expression
					QColor color = image.pixelColor(xi, yi);
					r = color.redF();
					g = color.greenF();
					b = color.blueF();

					// evaluate the expression, ignoring its output
					cexpr.value();

					color.setRedF(r);
					color.setGreenF(g);
					color.setBlueF(b);
					image.setPixelColor(xi, yi, color.rgb());
				}

			std::unique_ptr<QPixmap> out(new QPixmap());
			*out = QPixmap::fromImage(std::move(image));

			data.set(a_outPixmap, std::shared_ptr<const QPixmap>(out.release()));
		}
	}

	return result;
}

void init(possumwood::Metadata& meta) {
	meta.addAttribute(a_src, "source", std::string("r := x / width;\ng := y / height;\nb := max(0, 1-r-g);"));
	meta.addAttribute(a_symbols, "symbols");
	meta.addAttribute(a_inPixmap, "in_image");
	meta.addAttribute(a_outPixmap, "out_image");

	meta.addInfluence(a_src, a_outPixmap);
	meta.addInfluence(a_symbols, a_outPixmap);
	meta.addInfluence(a_inPixmap, a_outPixmap);

	meta.setCompute(&compute);
	meta.setEditor<Editor>();
}

possumwood::NodeImplementation s_impl("images/per_pixel_expr", init);

}
<commit_msg>setPixelColor -> setPixel for Qt 5.5.1 in Ubuntu Xenial<commit_after>#include <exprtk/exprtk.hpp>

#include <memory>

#include <possumwood_sdk/node_implementation.h>
#include <possumwood_sdk/source_editor.h>

#include <QPainter>
#include <QPushButton>
#include <QMenu>

#include "datatypes/pixmap.h"
#include "expressions/datatypes/symbol_table.h"

namespace {

dependency_graph::InAttr<std::string> a_src;
dependency_graph::InAttr<possumwood::ExprSymbols> a_symbols;
dependency_graph::InAttr<std::shared_ptr<const QPixmap>> a_inPixmap;
dependency_graph::OutAttr<std::shared_ptr<const QPixmap>> a_outPixmap;

class Popup : public QMenu {
	public:
		Popup(QWidget* parent) : QMenu(parent) {
		}

		void addItem(const std::string& name) {
			addAction(name.c_str());
		}

	private:
};

class Editor : public possumwood::SourceEditor {
	public:
		Editor() : SourceEditor(a_src), m_popup(nullptr) {
			m_varsButton = new QPushButton("Variables");
			buttonsLayout()->insertWidget(0, m_varsButton);

			widget()->connect(m_varsButton, &QPushButton::pressed, [this]() {
				if(m_popup)
					m_popup->popup(
						m_varsButton->mapToGlobal(QPoint(0,-m_popup->sizeHint().height()))
					);
			});
		}

	protected:
		virtual void valueChanged(const dependency_graph::Attr& attr) override {
			if(attr == a_symbols) {
				m_popup->deleteLater();

				populateVariableList();
			}

			else
				SourceEditor::valueChanged(attr);
		}

		void populateVariableList() {
			if(!m_popup)
				m_popup->deleteLater();

			m_popup = new Popup(m_varsButton);

			m_popup->connect(m_popup, &Popup::triggered, [this](QAction* action) {
				QString text = action->text();
				while(!text.isEmpty() && !QChar(text[0]).isLetterOrNumber())
					text = text.mid(1, text.length()-1);
				if(text.indexOf('\t') >= 0)
					text = text.mid(0, text.indexOf('\t'));

				editorWidget()->insertPlainText(text);
			});

			// the external symbols
			unsigned ctr = 0;
			for(auto& s : values().get(a_symbols)) {
				m_popup->addItem(s.first + "\t(constant)");
				++ctr;
			}

			if(ctr > 0)
				m_popup->addSeparator();

			// hardwired symbols
			m_popup->addItem("x\t(constant)");
			m_popup->addItem("y\t(constant)");
			m_popup->addItem("width\t(constant)");
			m_popup->addItem("height\t(constant)");

			m_popup->addSeparator();

			m_popup->addItem("r\t(variable)");
			m_popup->addItem("g\t(variable)");
			m_popup->addItem("b\t(variable)");
		}

	private:
		QPushButton* m_varsButton;

		Popup* m_popup;
};

dependency_graph::State compute(dependency_graph::Values& data) {
	dependency_graph::State result;

	std::shared_ptr<const QPixmap> input = data.get(a_inPixmap);

	if(input == nullptr) {
		result.addError("No input pixmap");
		data.set(a_outPixmap, input);
	}

	else {
		float x = 0.0f;
		float y = 0.0f;

		float r = 0.0f;
		float g = 0.0f;
		float b = 0.0f;

		const possumwood::ExprSymbols& symbols = data.get(a_symbols);

		exprtk::symbol_table<float> symbol_table;

		for(auto& s : symbols)
			symbol_table.add_constant(s.first, s.second);

		symbol_table.add_variable("x", x);
		symbol_table.add_variable("y", y);

		symbol_table.add_variable("r", r);
		symbol_table.add_variable("g", g);
		symbol_table.add_variable("b", b);

		symbol_table.add_constant("width", input->width());
		symbol_table.add_constant("height", input->height());

		symbol_table.add_constants();

		exprtk::expression<float> expression;
		expression.register_symbol_table(symbol_table);

		std::string err;
		bool success = false;
		{
			exprtk::parser<float> parser;
			success = parser.compile(data.get(a_src), expression);

			if(!success)
				err = parser.error();
		}

		auto cexpr = (const exprtk::expression<float>)expression;

		// compilation failed
		if(!success) {
			result.addError(err);

			// output nothing
			data.set(a_outPixmap, std::shared_ptr<const QPixmap>());
		}

		// compilation success
		else {
			// make a QImage, so we can set pixels
			QImage image = input->toImage();

			// iterate over pixels
			for(int yi = 0; yi < input->height(); ++yi)
				for(int xi = 0; xi < input->width(); ++xi) {
					x = xi;
					y = yi;

					// r, g, b variables are changeable from the expression
					QColor color(image.pixel(xi, yi));
					r = color.redF();
					g = color.greenF();
					b = color.blueF();

					// evaluate the expression, ignoring its output
					cexpr.value();

					color.setRedF(r);
					color.setGreenF(g);
					color.setBlueF(b);
					image.setPixel(xi, yi, color.rgb());
				}

			std::unique_ptr<QPixmap> out(new QPixmap());
			*out = QPixmap::fromImage(std::move(image));

			data.set(a_outPixmap, std::shared_ptr<const QPixmap>(out.release()));
		}
	}

	return result;
}

void init(possumwood::Metadata& meta) {
	meta.addAttribute(a_src, "source", std::string("r := x / width;\ng := y / height;\nb := max(0, 1-r-g);"));
	meta.addAttribute(a_symbols, "symbols");
	meta.addAttribute(a_inPixmap, "in_image");
	meta.addAttribute(a_outPixmap, "out_image");

	meta.addInfluence(a_src, a_outPixmap);
	meta.addInfluence(a_symbols, a_outPixmap);
	meta.addInfluence(a_inPixmap, a_outPixmap);

	meta.setCompute(&compute);
	meta.setEditor<Editor>();
}

possumwood::NodeImplementation s_impl("images/per_pixel_expr", init);

}
<|endoftext|>


<commit_before>//! @author prozac@rottenboy.com

#include <unistd.h>
#include <getopt.h>
#include <stdlib.h>
#include <signal.h>
#include "znc.h"
#include "Modules.h"
#include "MD5.h"

static struct option g_LongOpts[] = {
	{ "help",				0,	NULL,	0 },
	{ "version",			0,	NULL,	0 },
	{ "makeconf",			0,	NULL,	0 },
	{ "makepass",			0,	NULL,	0 },
#ifdef HAVE_LIBSSL
	{ "makepem",			0,	NULL,	0 },
	{ "encrypt-pem",		0,	NULL, 	0 },
#endif /* HAVE_LIBSSL */
	{ NULL }
};

void GenerateHelp(const char *appname) {
	CUtils::PrintMessage("USAGE: " + CString(appname) + " [options] [config]");
	CUtils::PrintMessage("Options are:");
	CUtils::PrintMessage("\t--help)");
	CUtils::PrintMessage("\t--version      Output version information and exit");
	CUtils::PrintMessage("\t--makeconf     Interactively create a new config");
	CUtils::PrintMessage("\t--makepass     Generates a password for use in config");
#ifdef HAVE_LIBSSL
	CUtils::PrintMessage("\t--makepem      Generates a pemfile for use with SSL");
	CUtils::PrintMessage("\t--encrypt-pem  when used along with --makepem, encrypts the private key in the pemfile");
#endif /* HAVE_LIBSSL */
}

void die(int sig) {
	signal(SIGSEGV, SIG_DFL);
	signal(SIGABRT, SIG_DFL);
	signal(SIGPIPE, SIG_DFL);

#ifdef _DEBUG
	CUtils::PrintMessage("Exiting on SIG [" + CString(sig) + "]");
	if ((sig == SIGABRT) || (sig == SIGSEGV)) {
		abort();
	}
#endif /* _DEBUG */

	delete &CZNC::Get();
	exit(sig);
}

int main(int argc, char** argv, char** envp) {
	CString sConfig;

#ifdef HAVE_LIBSSL
	// initialize ssl, allow client to have compression enabled if desired
	InitSSL(CT_ZLIB);
#endif /* HAVE_LIBSSL */

	int iArg, iOptIndex = -1;
	bool bMakeConf = false;
	bool bMakePass = false;
#ifdef HAVE_LIBSSL
	bool bMakePem = false;
	bool bEncPem = false;
#endif /* HAVE_LIBSSL */
	while ((iArg = getopt_long(argc, argv, "c|h", g_LongOpts, &iOptIndex) != -1)) {
		switch (iArg) {
			case 1: { // long options
				if (iOptIndex >= 0) {
					CString sOption = Lower(g_LongOpts[iOptIndex].name);
					if (sOption == "version") {
						cout << CZNC::GetTag() << endl;
						return 0;
					} else if (sOption == "makeconf") {
						bMakeConf = true;
					} else if (sOption == "makepass") {
						bMakePass = true;
#ifdef HAVE_LIBSSL
					} else if (sOption == "makepem") {
						bMakePem = true;
					} else if (sOption == "encrypt-pem") {
						bEncPem = true;
#endif /* HAVE_LIBSSL */
					} else if (sOption == "help") {
						GenerateHelp(argv[0]);
						return 0;
					}
				} else {
					GenerateHelp(argv[0]);
					return 1;
				}
				break;
			}
			case 'h':
				GenerateHelp(argv[0]);
				return 0;
			default: {
				GenerateHelp(argv[0]);
				return 1;
			}
		}
	}

	if (optind < argc) {
		sConfig = argv[optind];
	} else {
		sConfig = "znc.conf";
	}

	if (bMakeConf) {
		CZNC& ZNC = CZNC::Get();
		ZNC.InitDirs("");
		if (ZNC.WriteNewConfig(sConfig)) {
			char* args[3];

			if (argc > 2) {
				args[0] = argv[0];
				args[1] = argv[optind];
				args[2] = NULL;
			} else if (argc > 1) {
				args[0] = argv[0];
				args[1] = NULL;
				args[2] = NULL;
			} else {
				CUtils::PrintError("Unable to launch znc [Try manually restarting]");
				return 1;
			}

			if (execve(*argv, args, envp) == -1) {
				CUtils::PrintError("Unable to launch znc [" + CString(strerror(errno)) + "]");
				return 1;
			}
		}

		return 0;
	}

#ifdef HAVE_LIBSSL
	if (bMakePem) {
		CZNC* pZNC = &CZNC::Get();
		pZNC->InitDirs("");
		pZNC->WritePemFile( bEncPem );

		delete pZNC;
		return 0;
	}
	if( bEncPem && !bMakePem ) {
		CUtils::PrintError("--encrypt-pem should be used along with --makepem.");
		return 1;
	}

#endif /* HAVE_LIBSSL */
	if (bMakePass) {
		CString sHash = CUtils::GetHashPass();
		CUtils::PrintMessage("Use this in the <User> section of your config:");
		CUtils::PrintMessage("Pass = " + sHash + " -");

		return 0;
	}

	CZNC* pZNC = &CZNC::Get();
	pZNC->InitDirs(((argc) ? argv[0] : ""));

	if (!pZNC->ParseConfig(sConfig)) {
		CUtils::PrintError("Unrecoverable config error.");
		delete pZNC;
		return 1;
	}

	if (!pZNC->GetListeners().size()) {
		CUtils::PrintError("You must supply at least one Listen port in your config.");
		delete pZNC;
		return 1;
	}

	if (!pZNC->OnBoot()) {
		CUtils::PrintError("Exiting due to module boot errors.");
		delete pZNC;
		return 1;
	}

#ifdef _DEBUG
	CUtils::PrintMessage("Staying open for debugging");
#else
	CUtils::PrintAction("Forking into the background");

	int iPid = fork();

	if (iPid == -1) {
		CUtils::PrintStatus(false, strerror(errno));
		delete pZNC;
		exit(1);
	}

	if (iPid > 0) {
		CUtils::PrintStatus(true, "[pid: " + CString(iPid) + "]");

		pZNC->WritePidFile(iPid);
		CUtils::PrintMessage(CZNC::GetTag(false));
		exit(0);
	}

	// Redirect std in/out/err to /dev/null
	close(0); open("/dev/null", O_RDONLY);
	close(1); open("/dev/null", O_WRONLY);
	close(2); open("/dev/null", O_WRONLY);
#endif

	struct sigaction sa;
	sa.sa_flags = 0;
	sigemptyset(&sa.sa_mask);

	sa.sa_handler = SIG_IGN;
	sigaction(SIGPIPE, &sa, (struct sigaction*) NULL);

	sa.sa_handler = die;
	sigaction(SIGINT,  &sa, (struct sigaction*) NULL);
	sigaction(SIGILL,  &sa, (struct sigaction*) NULL);
	sigaction(SIGQUIT, &sa, (struct sigaction*) NULL);
	sigaction(SIGBUS,  &sa, (struct sigaction*) NULL);
	sigaction(SIGSEGV, &sa, (struct sigaction*) NULL);
	sigaction(SIGTERM, &sa, (struct sigaction*) NULL);

	int iRet = 0;

	try {
		iRet = pZNC->Loop();
	} catch (CException e) {
		// EX_Shutdown is thrown to exit
		switch (e.GetType()) {
			case CException::EX_Shutdown:
				iRet = 0;
			default:
				iRet = 1;
		}
	}

	delete pZNC;

	return iRet;
}
<commit_msg>remove compression initialization until standard has normalized a bit<commit_after>//! @author prozac@rottenboy.com

#include <unistd.h>
#include <getopt.h>
#include <stdlib.h>
#include <signal.h>
#include "znc.h"
#include "Modules.h"
#include "MD5.h"

static struct option g_LongOpts[] = {
	{ "help",				0,	NULL,	0 },
	{ "version",			0,	NULL,	0 },
	{ "makeconf",			0,	NULL,	0 },
	{ "makepass",			0,	NULL,	0 },
#ifdef HAVE_LIBSSL
	{ "makepem",			0,	NULL,	0 },
	{ "encrypt-pem",		0,	NULL, 	0 },
#endif /* HAVE_LIBSSL */
	{ NULL }
};

void GenerateHelp(const char *appname) {
	CUtils::PrintMessage("USAGE: " + CString(appname) + " [options] [config]");
	CUtils::PrintMessage("Options are:");
	CUtils::PrintMessage("\t--help)");
	CUtils::PrintMessage("\t--version      Output version information and exit");
	CUtils::PrintMessage("\t--makeconf     Interactively create a new config");
	CUtils::PrintMessage("\t--makepass     Generates a password for use in config");
#ifdef HAVE_LIBSSL
	CUtils::PrintMessage("\t--makepem      Generates a pemfile for use with SSL");
	CUtils::PrintMessage("\t--encrypt-pem  when used along with --makepem, encrypts the private key in the pemfile");
#endif /* HAVE_LIBSSL */
}

void die(int sig) {
	signal(SIGSEGV, SIG_DFL);
	signal(SIGABRT, SIG_DFL);
	signal(SIGPIPE, SIG_DFL);

#ifdef _DEBUG
	CUtils::PrintMessage("Exiting on SIG [" + CString(sig) + "]");
	if ((sig == SIGABRT) || (sig == SIGSEGV)) {
		abort();
	}
#endif /* _DEBUG */

	delete &CZNC::Get();
	exit(sig);
}

int main(int argc, char** argv, char** envp) {
	CString sConfig;

#ifdef HAVE_LIBSSL
	InitSSL();
#endif /* HAVE_LIBSSL */

	int iArg, iOptIndex = -1;
	bool bMakeConf = false;
	bool bMakePass = false;
#ifdef HAVE_LIBSSL
	bool bMakePem = false;
	bool bEncPem = false;
#endif /* HAVE_LIBSSL */
	while ((iArg = getopt_long(argc, argv, "c|h", g_LongOpts, &iOptIndex) != -1)) {
		switch (iArg) {
			case 1: { // long options
				if (iOptIndex >= 0) {
					CString sOption = Lower(g_LongOpts[iOptIndex].name);
					if (sOption == "version") {
						cout << CZNC::GetTag() << endl;
						return 0;
					} else if (sOption == "makeconf") {
						bMakeConf = true;
					} else if (sOption == "makepass") {
						bMakePass = true;
#ifdef HAVE_LIBSSL
					} else if (sOption == "makepem") {
						bMakePem = true;
					} else if (sOption == "encrypt-pem") {
						bEncPem = true;
#endif /* HAVE_LIBSSL */
					} else if (sOption == "help") {
						GenerateHelp(argv[0]);
						return 0;
					}
				} else {
					GenerateHelp(argv[0]);
					return 1;
				}
				break;
			}
			case 'h':
				GenerateHelp(argv[0]);
				return 0;
			default: {
				GenerateHelp(argv[0]);
				return 1;
			}
		}
	}

	if (optind < argc) {
		sConfig = argv[optind];
	} else {
		sConfig = "znc.conf";
	}

	if (bMakeConf) {
		CZNC& ZNC = CZNC::Get();
		ZNC.InitDirs("");
		if (ZNC.WriteNewConfig(sConfig)) {
			char* args[3];

			if (argc > 2) {
				args[0] = argv[0];
				args[1] = argv[optind];
				args[2] = NULL;
			} else if (argc > 1) {
				args[0] = argv[0];
				args[1] = NULL;
				args[2] = NULL;
			} else {
				CUtils::PrintError("Unable to launch znc [Try manually restarting]");
				return 1;
			}

			if (execve(*argv, args, envp) == -1) {
				CUtils::PrintError("Unable to launch znc [" + CString(strerror(errno)) + "]");
				return 1;
			}
		}

		return 0;
	}

#ifdef HAVE_LIBSSL
	if (bMakePem) {
		CZNC* pZNC = &CZNC::Get();
		pZNC->InitDirs("");
		pZNC->WritePemFile( bEncPem );

		delete pZNC;
		return 0;
	}
	if( bEncPem && !bMakePem ) {
		CUtils::PrintError("--encrypt-pem should be used along with --makepem.");
		return 1;
	}

#endif /* HAVE_LIBSSL */
	if (bMakePass) {
		CString sHash = CUtils::GetHashPass();
		CUtils::PrintMessage("Use this in the <User> section of your config:");
		CUtils::PrintMessage("Pass = " + sHash + " -");

		return 0;
	}

	CZNC* pZNC = &CZNC::Get();
	pZNC->InitDirs(((argc) ? argv[0] : ""));

	if (!pZNC->ParseConfig(sConfig)) {
		CUtils::PrintError("Unrecoverable config error.");
		delete pZNC;
		return 1;
	}

	if (!pZNC->GetListeners().size()) {
		CUtils::PrintError("You must supply at least one Listen port in your config.");
		delete pZNC;
		return 1;
	}

	if (!pZNC->OnBoot()) {
		CUtils::PrintError("Exiting due to module boot errors.");
		delete pZNC;
		return 1;
	}

#ifdef _DEBUG
	CUtils::PrintMessage("Staying open for debugging");
#else
	CUtils::PrintAction("Forking into the background");

	int iPid = fork();

	if (iPid == -1) {
		CUtils::PrintStatus(false, strerror(errno));
		delete pZNC;
		exit(1);
	}

	if (iPid > 0) {
		CUtils::PrintStatus(true, "[pid: " + CString(iPid) + "]");

		pZNC->WritePidFile(iPid);
		CUtils::PrintMessage(CZNC::GetTag(false));
		exit(0);
	}

	// Redirect std in/out/err to /dev/null
	close(0); open("/dev/null", O_RDONLY);
	close(1); open("/dev/null", O_WRONLY);
	close(2); open("/dev/null", O_WRONLY);
#endif

	struct sigaction sa;
	sa.sa_flags = 0;
	sigemptyset(&sa.sa_mask);

	sa.sa_handler = SIG_IGN;
	sigaction(SIGPIPE, &sa, (struct sigaction*) NULL);

	sa.sa_handler = die;
	sigaction(SIGINT,  &sa, (struct sigaction*) NULL);
	sigaction(SIGILL,  &sa, (struct sigaction*) NULL);
	sigaction(SIGQUIT, &sa, (struct sigaction*) NULL);
	sigaction(SIGBUS,  &sa, (struct sigaction*) NULL);
	sigaction(SIGSEGV, &sa, (struct sigaction*) NULL);
	sigaction(SIGTERM, &sa, (struct sigaction*) NULL);

	int iRet = 0;

	try {
		iRet = pZNC->Loop();
	} catch (CException e) {
		// EX_Shutdown is thrown to exit
		switch (e.GetType()) {
			case CException::EX_Shutdown:
				iRet = 0;
			default:
				iRet = 1;
		}
	}

	delete pZNC;

	return iRet;
}
<|endoftext|>


<commit_before>#include "fmt/color.h"

int main() {
    fmt::print(fg(fmt::terminal_color::cyan), "Hello!\n");
    return 1;
}<commit_msg>minor changes<commit_after>#include "fmt/color.h"

int main() {
    fmt::print(fg(fmt::terminal_color::cyan), "Hello!\n");
    return 0;
}<|endoftext|>


<commit_before>#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <cstdlib> //C standard library <stdlib.h>, /* atoi */
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h> //C standard library <stdlib.h>, /* atoi */
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/utsname.h>
#ifdef _WIN32
#include <windows.h>
#define chdir _chdir

#else
#include <unistd.h>
#endif

//INLCUDING COMMANDS
//#include "commands/cat.h"

using namespace std;

int executeCommand(vector<string>&);
vector<string> getTokens(string, char);
char** vectorToCharPP (vector<string> tokenized);
string PATH, CURR_DIR;

int main(int argc, char const *argv[]){
	CURR_DIR = getenv("PWD");
	PATH = CURR_DIR+"/commands/bin/";
	int status = 0;
	while(!status) {
		cout << "mi_sh> ";
		string line;
		getline(cin,line);
		vector<string> tokens = getTokens(line, ' ');
		status = executeCommand(tokens);
	};
	if(status != 1){
		cerr << "ERROR " << status << ": al ejecutar el comando" << endl;
	}
	return 0;
}

/*
ejecuta los comandos conocidos por el programa
retorna 0 cuando todo salio bien y continuar con el programa
retorna 1 para salir del programa sin errores
retorna cualquier otro valor con error
*/
int executeCommand(vector<string>& tokens){
	if(tokens.size() == 0){
		cerr << "No hay commando a ejecutar" << endl;
		return 0;
	}
	int childErr;
	if(tokens.size() > 0){
		int ppid, chpid;

		if(tokens[0] == "cd"){
			if(tokens.size()== 2){
				chdir(tokens[1].c_str());
			}
			return 0;

		}else{
			if((chpid=fork()) == 0){
				char** argvData = vectorToCharPP (tokens);
				int argcData = tokens.size();

				string commandPath = PATH + argvData[0];

				childErr = execvp(commandPath.c_str(), argvData);
				cout << "Comando " << argvData[0] <<": Fallido" << endl;

				return childErr;
			}else{
				wait(NULL);
				return 0;
			}
			return -1;
		}
	}

}

//retorna los tokens de la terminal
vector<string> getTokens(string toTokenize, char delimiter){
	vector<string> v;
	string::iterator stringIT = toTokenize.begin();
	for(string::iterator i = toTokenize.begin(); i != toTokenize.end(); i++){
		if(*i == delimiter){
			v.push_back(string(stringIT,i));
			stringIT=i+1;
		}
	}
	v.push_back(string(stringIT,toTokenize.end()));
	return v;
}
/*
retorna un char** al enviarle un vector<string>
vectorToCharPP = de vector a char puntero puntero
*/
char** vectorToCharPP (vector<string> tokenized){
	char** tokens;
	int tokenAmount = tokenized.size();
	tokens = new char*[tokenAmount+1];
	for(int i = 0; i < tokenAmount; i++){
		tokens[i] = new char[tokenized[i].length()];
		strcpy(tokens[i],tokenized[i].c_str());
	}
	tokens[tokenAmount] = NULL;
	return tokens;
}
<commit_msg>tratando de implementar pipe y redirect<commit_after>#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <cstdlib> //C standard library <stdlib.h>, /* atoi */
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h> //C standard library <stdlib.h>, /* atoi */
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/utsname.h>
#include <fcntl.h>
#ifdef _WIN32
#include <windows.h>
#define chdir _chdir

#else
#include <unistd.h>
#endif

//INLCUDING COMMANDS
//#include "commands/cat.h"

using namespace std;

enum TipoComando{PIPE, REDIRECT, NEITHER};

int executeCommand(vector<string>&);
vector<string> getTokens(string, char);
char** vectorToCharPP (vector<string> tokenized);
TipoComando identificarComando(int, char**, char**, char**);
void Pipe(string, char**, char**, char**);
void Redirect(string, char**, char**, char**);
void Neither(string, char**, char**, char**);

string PATH, CURR_DIR;

int main(int argc, char const *argv[]){
	CURR_DIR = getenv("PWD");
	PATH = CURR_DIR+"/commands/bin/";
	int status = 0;
	while(!status) {
		cout << "mi_sh> ";
		string line;
		getline(cin,line);
		vector<string> tokens = getTokens(line, ' ');
		status = executeCommand(tokens);
	};
	if(status != 1){
		cerr << "ERROR " << status << ": al ejecutar el comando" << endl;
	}
	return 0;
}

/*
ejecuta los comandos conocidos por el programa
retorna 0 cuando todo salio bien y continuar con el programa
retorna 1 para salir del programa sin errores
retorna cualquier otro valor con error
*/
int executeCommand(vector<string>& tokens){
	if(tokens.size() == 0){
		cerr << "No hay commando a ejecutar" << endl;
		return 0;
	}
	int childErr;

	if(tokens.size() > 0){
		if(tokens[0] == "cd"){
			if(tokens.size()== 2){
				chdir(tokens[1].c_str());
			}
			return 0;
		}else{

			char *comando1[50], *comando2[50];

			TipoComando tipo_comando;
			char** argvData = vectorToCharPP (tokens);
			int argcData = tokens.size();

			//string commandPath = PATH + argvData[0];

			tipo_comando = identificarComando(argcData, argvData, comando1, comando2);

			if(tipo_comando == PIPE){
				cout << "Entra a Pipe" << endl;

				Pipe(PATH, argvData, comando1, comando2);

			}else if(tipo_comando == REDIRECT){
				cout << "Entra a REDIRECT" << endl;

				Redirect(PATH, argvData, comando1, comando2);

			}else{
				cout << "entra a NEITHER" << endl;

				Neither(PATH, argvData, comando1, comando2);
			}
		}
		/*int ppid, chpid;

		if(tokens[0] == "cd"){
			if(tokens.size()== 2){
				chdir(tokens[1].c_str());
			}
			return 0;

		}else{
			if((chpid=fork()) == 0){
				char** argvData = vectorToCharPP (tokens);
				int argcData = tokens.size();

				string commandPath = PATH + argvData[0];

				childErr = execvp(commandPath.c_str(), argvData);
				cout << "Comando " << argvData[0] <<": Fallido" << endl;

				return childErr;
			}else{
				wait(NULL);
				return 0;
			}
			return -1;
		}*/

	}

}

//retorna los tokens de la terminal
vector<string> getTokens(string toTokenize, char delimiter){
	vector<string> v;
	string::iterator stringIT = toTokenize.begin();
	for(string::iterator i = toTokenize.begin(); i != toTokenize.end(); i++){
		if(*i == delimiter){
			v.push_back(string(stringIT,i));
			stringIT=i+1;
		}
	}
	v.push_back(string(stringIT,toTokenize.end()));
	return v;
}
/*
retorna un char** al enviarle un vector<string>
vectorToCharPP = de vector a char puntero puntero
*/
char** vectorToCharPP (vector<string> tokenized){
	char** tokens;
	int tokenAmount = tokenized.size();
	tokens = new char*[tokenAmount+1];
	for(int i = 0; i < tokenAmount; i++){
		tokens[i] = new char[tokenized[i].length()];
		strcpy(tokens[i],tokenized[i].c_str());
	}
	tokens[tokenAmount] = NULL;
	return tokens;
}

TipoComando identificarComando(int argcData, char** argvData, char** comando1, char** comando2){
	cout << "Entra a identificar" << endl;

	TipoComando tipo = NEITHER;
	int temp = -1;

	for(int i = 0; i < argcData; i++){
		if(strcmp(argvData[i], "|") == 0){
			tipo = PIPE;
			temp = i;

		}else if (strcmp(argvData[i], ">>") == 0){
			tipo = REDIRECT;
			temp = i;
		}
	}

	if(tipo != NEITHER){
		for(int i = 0; i < temp; i++){
			comando1[i] = argvData[i];
		}

		int count = 0;
		for(int i=temp+1; i<argcData; i++){
			comando2[count] = argvData[i];
			count++;
		}

		comando1[temp] = NULL;
		comando2[count] = NULL;
	}

	return tipo;
}

void Pipe(string PATH, char** argvData, char** comando1, char** comando2){

	int a[2];
	pid_t pid;

	pipe(a);

	if(fork() == 0){//PROCESO PADRE
		string commandPath = PATH + comando2[0];

		dup2(a[0], 0);
		close(a[1]);

		execvp(commandPath.c_str(), argvData);//No estoy segura de ese argvData en el execvp
		perror("Error en el execvp");
	}else if((pid == fork()) == 0){//PROCESO HIJO
		string commandPath = PATH + comando1[0];

		dup2(a[1], 1);
		close(a[0]);

		execvp(commandPath.c_str(), argvData);
		perror("Error en el execvp");
	} else {
		waitpid(pid, NULL, 0);
	}

}

void Redirect(string PATH, char** argvData, char** comando1, char** comando2){
	int contador;
	int file;
	int a[2];
	char caracter;
	pid_t pid;

	pipe(a);

	if(fork() == 0){
		string commandPath = PATH + comando2[0];

		file = open(commandPath.c_str(), O_RDWR | O_CREAT, 0666);

		if(file < 0){
			printf("Error: %s\n", strerror(errno));
		}

					//dup(a[0]);
		dup2(a[0], 0);
		close(a[1]);

		while((contador = read(0, &caracter, 1)) > 0){
			write(file, &caracter, 1);
		}

		execlp("echo", "echo", NULL);
	}else if((pid = fork()) == 0){
		string commandPath = PATH + comando1[0];

		dup2(a[1], 1);
		close(a[0]);

		execvp(commandPath.c_str(), comando1);//probar sin argvData
		perror("execvp error en el execvp");
	}else{
		waitpid(pid, NULL, 0);
		close(a[0]);
		close(a[1]);
	}
}

void Neither(string PATH, char** argvData, char** comando1, char** comando2){
	const char *amperson;
	pid_t pid;
	amperson = "&";
	bool encontro = false;

	if(strcmp(argvData[argcData-1], amperson) == 0){
		encontro = true;
	}

	pid = fork();

	if(pid < 0){
		perror("Hubo un error");

	}else if(pid == 0){

		if(encontro){
			argvData[argcData-1] = NULL;
			argcData--;
		}

		execvp(argvData[0], argvData);
		perror("Error en el execvp");

	}else if( !encontro){
		waitpid(pid, NULL, 0);
	}
}<|endoftext|>


<commit_before>#define __NO_STD_VECTOR // Use cl::vector instead of STL version
#define __CL_ENABLE_EXCEPTIONS

#include <CL/cl.hpp>
#include "openCLUtilities.hpp"
#include <iostream>
#include <string>
#include <fstream>
#include <utility>

#define MU = 0.05
#define ITERATIONS 500
#define FILENAME test.raw
#define SIZE_X 256
#define SIZE_Y 256
#define SIZE_Z 256

using namespace cl;

int main(void) {
   try {
        // Get available platforms
        vector<Platform> platforms;
        Platform::get(&platforms);

        // Select the default platform and create a context using this platform and the GPU
        cl_context_properties cps[] = {
            CL_CONTEXT_PLATFORM, (cl_context_properties)(platforms[0])(),
            0
        };
		Context context = Context( CL_DEVICE_TYPE_GPU, cps);

        // Get a list of devices on this platform
		vector<Device> devices = context.getInfo<CL_CONTEXT_DEVICES>();

        // Create a command queue and use the first device
        CommandQueue queue = CommandQueue(context, devices[0]);

        // Read source file
        std::ifstream sourceFile("kernels.cl");
        if(sourceFile.fail()) {
            std::cout << "Failed to open OpenCL source file" << std::endl;
            exit(-1);
        }
        std::string sourceCode(
            std::istreambuf_iterator<char>(sourceFile),
            (std::istreambuf_iterator<char>()));
        Program::Sources source(1, std::make_pair(sourceCode.c_str(), sourceCode.length()+1));

        // Make program of the source code in the context
        Program program = Program(context, source);

        // Build program for these specific devices
        try{
            program.build(devices);
        } catch(Error error) {
            if(error.err() == CL_BUILD_PROGRAM_FAILURE) {
                std::cout << "Build log:\t" << program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(devices[0]) << std::endl;
            }
            throw error;
        }

        // Create Kernels
        Kernel initKernel = Kernel(program, "GVFInit");
        Kernel iterationKernel = Kernel(program, "GVFIteration");

        // Load volume to GPU
        Image3D volume = Image3D(context, CL_MEM_READ, ImageFormat(CL_R, CL_FLOAT), SIZE_X, SIZE_Y, SIZE_Z);

        // Run initialization kernel
        Image3D initVectorField = Image3D(context, CL_MEM_READ_WRITE, ImageFormat(CL_RGBA, CLFLOAT), SIZE_X, SIZE_Y, SIZE_Z);
        initKernel.setArg(0, volume);
        initKernel.setArg(1, initVectorField);

        queue.enqueueNDRangeKernel(
                initKernel,
                NullRange,
                NDRange(SIZE_X,SIZE_Y,SIZE_Z),
                Nullrange
        );

        // Delete volume from device
        volume.release();

        // copy vector field and create double buffer
        Image3D vectorField = Image3D(context, CL_MEM_READ_WRITE, ImageFormat(CL_RGBA, CLFLOAT), SIZE_X, SIZE_Y, SIZE_Z);
        Image3D vectorField2 = Image3D(context, CL_MEM_READ_WRITE, ImageFormat(CL_RGBA, CLFLOAT), SIZE_X, SIZE_Y, SIZE_Z);
        queue.enqueueCopyImage(initVectorField, vectorField);

        // Run iterations
        iterationKernel.setArg(0, initVectorField);
        iterationKernel.setArg(3, MU);
        for(int i = 0; i < ITERATIONS; i++) {
            if(i % 2 == 0) {
                iterationKernel.setArg(1, vectorField);
                iterationKernel.setArg(2, vectorField2);
            } else {
                iterationKernel.setArg(1, vectorField2);
                iterationKernel.setArg(2, vectorField);
            }
            queue.enqueueNDRangeKernel(
                    iterationKernel,
                    NullRange,
                    NDRange(SIZE_X,SIZE_Y,SIZE_Z),
                    NullRange
            );
        }

        // Read the result in some way

    } catch(Error error) {
       std::cout << error.what() << "(" << error.err() << ")" << std::endl;
       std::cout << getCLErrorString(error.err()) << std::endl;
    }

   return 0;
}
<commit_msg>added the parse raw file function<commit_after>#define __NO_STD_VECTOR // Use cl::vector instead of STL version
#define __CL_ENABLE_EXCEPTIONS

#include <CL/cl.hpp>
#include "openCLUtilities.hpp"
#include <iostream>
#include <string>
#include <fstream>
#include <utility>

#define MU = 0.05
#define ITERATIONS 500
#define FILENAME test.raw
#define SIZE_X 256
#define SIZE_Y 256
#define SIZE_Z 256

using namespace cl;

int main(void) {
   try {
        // Get available platforms
        vector<Platform> platforms;
        Platform::get(&platforms);

        // Select the default platform and create a context using this platform and the GPU
        cl_context_properties cps[] = {
            CL_CONTEXT_PLATFORM, (cl_context_properties)(platforms[0])(),
            0
        };
		Context context = Context( CL_DEVICE_TYPE_GPU, cps);

        // Get a list of devices on this platform
		vector<Device> devices = context.getInfo<CL_CONTEXT_DEVICES>();

        // Create a command queue and use the first device
        CommandQueue queue = CommandQueue(context, devices[0]);

        // Read source file
        std::ifstream sourceFile("kernels.cl");
        if(sourceFile.fail()) {
            std::cout << "Failed to open OpenCL source file" << std::endl;
            exit(-1);
        }
        std::string sourceCode(
            std::istreambuf_iterator<char>(sourceFile),
            (std::istreambuf_iterator<char>()));
        Program::Sources source(1, std::make_pair(sourceCode.c_str(), sourceCode.length()+1));

        // Make program of the source code in the context
        Program program = Program(context, source);

        // Build program for these specific devices
        try{
            program.build(devices);
        } catch(Error error) {
            if(error.err() == CL_BUILD_PROGRAM_FAILURE) {
                std::cout << "Build log:\t" << program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(devices[0]) << std::endl;
            }
            throw error;
        }

        // Create Kernels
        Kernel initKernel = Kernel(program, "GVFInit");
        Kernel iterationKernel = Kernel(program, "GVFIteration");

        // Load volume to GPU
        float * voxels = parseRawFile(FILENAME);
        Image3D volume = Image3D(context, CL_MEM_READ | CL_MEM_COPY_HOST_PTR, ImageFormat(CL_R, CL_FLOAT), SIZE_X, SIZE_Y, SIZE_Z, 0, 0, voxels);
        delete[] voxels;

        // Run initialization kernel
        Image3D initVectorField = Image3D(context, CL_MEM_READ_WRITE, ImageFormat(CL_RGBA, CLFLOAT), SIZE_X, SIZE_Y, SIZE_Z);
        initKernel.setArg(0, volume);
        initKernel.setArg(1, initVectorField);

        queue.enqueueNDRangeKernel(
                initKernel,
                NullRange,
                NDRange(SIZE_X,SIZE_Y,SIZE_Z),
                Nullrange
        );

        // Delete volume from device
        volume.release();

        // copy vector field and create double buffer
        Image3D vectorField = Image3D(context, CL_MEM_READ_WRITE, ImageFormat(CL_RGBA, CLFLOAT), SIZE_X, SIZE_Y, SIZE_Z);
        Image3D vectorField2 = Image3D(context, CL_MEM_READ_WRITE, ImageFormat(CL_RGBA, CLFLOAT), SIZE_X, SIZE_Y, SIZE_Z);
        queue.enqueueCopyImage(initVectorField, vectorField);

        // Run iterations
        iterationKernel.setArg(0, initVectorField);
        iterationKernel.setArg(3, MU);
        for(int i = 0; i < ITERATIONS; i++) {
            if(i % 2 == 0) {
                iterationKernel.setArg(1, vectorField);
                iterationKernel.setArg(2, vectorField2);
            } else {
                iterationKernel.setArg(1, vectorField2);
                iterationKernel.setArg(2, vectorField);
            }
            queue.enqueueNDRangeKernel(
                    iterationKernel,
                    NullRange,
                    NDRange(SIZE_X,SIZE_Y,SIZE_Z),
                    NullRange
            );
        }

        // Read the result in some way

    } catch(Error error) {
       std::cout << error.what() << "(" << error.err() << ")" << std::endl;
       std::cout << getCLErrorString(error.err()) << std::endl;
    }

   return 0;
}

float * parseRawFile(char * filename, Image3D * volume) {
    // Parse the specified raw file and transfer it to the device
    int rawDataSize = SIZE_X*SIZE_Y*SIZE_Z;

    uchar * rawVoxels = new uchar[rawDataSize];
    FILE * file = fopen(filename, "rb");
    if(file == NULL) {
        printf("File not found: %s\n", filename);
        exit(-1);
    }

    fread(rawVoxels, sizeof(uchar), rawDataSize, file);

    // Find min and max
    int min = 256;
    int max = 0;
    for(int i = 0; i < rawDataSize; i++) {
        if(rawVoxels[i] > max)
            max = rawVoxels[i];

        if(rawVoxels[i] < min)
            min = rawVoxels[i];

    }

    // Normalize result
    float * voxels = new float[rawDataSize];
    for(int i = 0; i < rawDataSize; i++) {
        voxels[i] = (float)(rawVoxels[i] - min) / (max - min);
    }
    delete[] rawVoxels;

    return voxels;
}
<|endoftext|>


<commit_before>edc9664a-ad5b-11e7-96bf-ac87a332f658<commit_msg>( ͡° ͜ʖ ͡°)<commit_after>ee3cb99c-ad5b-11e7-afe2-ac87a332f658<|endoftext|>


<commit_before>2efe8594-2748-11e6-a670-e0f84713e7b8<commit_msg>Introduced random NullPointerException bug<commit_after>2f0a75fd-2748-11e6-a627-e0f84713e7b8<|endoftext|>


<commit_before>//===--- TaskLocal.cpp - Task Local Values --------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "../CompatibilityOverride/CompatibilityOverride.h"
#include "swift/Runtime/Atomic.h"
#include "swift/Runtime/Casting.h"
#include "swift/Runtime/Concurrency.h"
#include "swift/Threading/ThreadLocalStorage.h"
#include "swift/ABI/TaskLocal.h"
#include "swift/ABI/Task.h"
#include "swift/ABI/Actor.h"
#include "swift/ABI/Metadata.h"
#include "llvm/ADT/PointerIntPair.h"
#include "TaskPrivate.h"
#include <new>
#include <set>

#if SWIFT_STDLIB_HAS_ASL
#include <asl.h>
#elif defined(__ANDROID__)
#include <android/log.h>
#endif

#if HAVE_PTHREAD_H
#include <pthread.h>
#endif

#if defined(_WIN32)
#include <io.h>
#include <handleapi.h>
#include <processthreadsapi.h>
#endif

using namespace swift;

// =============================================================================

/// An extremely silly class which exists to make pointer
/// default-initialization constexpr.
template <class T> struct Pointer {
  T *Value;
  constexpr Pointer() : Value(nullptr) {}
  constexpr Pointer(T *value) : Value(value) {}
  operator T *() const { return Value; }
  T *operator->() const { return Value; }
};

/// THIS IS RUNTIME INTERNAL AND NOT ABI.
class FallbackTaskLocalStorage {
  static SWIFT_THREAD_LOCAL_TYPE(
      Pointer<TaskLocal::Storage>,
      SWIFT_CONCURRENCY_FALLBACK_TASK_LOCAL_STORAGE_KEY) Value;

public:
  static void set(TaskLocal::Storage *task) { Value.set(task); }
  static TaskLocal::Storage *get() { return Value.get(); }
};

/// Define the thread-locals.
SWIFT_THREAD_LOCAL_TYPE(
    Pointer<TaskLocal::Storage>,
    SWIFT_CONCURRENCY_FALLBACK_TASK_LOCAL_STORAGE_KEY)
FallbackTaskLocalStorage::Value;

// ==== ABI --------------------------------------------------------------------

SWIFT_CC(swift)
static void swift_task_localValuePushImpl(const HeapObject *key,
                                              /* +1 */ OpaqueValue *value,
                                              const Metadata *valueType) {
  if (AsyncTask *task = swift_task_getCurrent()) {
    task->localValuePush(key, value, valueType);
    return;
  }

  // no AsyncTask available so we must check the fallback
  TaskLocal::Storage *Local = nullptr;
  if (auto storage = FallbackTaskLocalStorage::get()) {
    Local = storage;
  } else {
    void *allocation = malloc(sizeof(TaskLocal::Storage));
    auto *freshStorage = new(allocation) TaskLocal::Storage();

    FallbackTaskLocalStorage::set(freshStorage);
    Local = freshStorage;
  }

  Local->pushValue(/*task=*/nullptr, key, value, valueType);
}

SWIFT_CC(swift)
static OpaqueValue* swift_task_localValueGetImpl(const HeapObject *key) {
  if (AsyncTask *task = swift_task_getCurrent()) {
    // we're in the context of a task and can use the task's storage
    return task->localValueGet(key);
  }

  // no AsyncTask available so we must check the fallback
  if (auto Local = FallbackTaskLocalStorage::get()) {
    return Local->getValue(/*task*/nullptr, key);
  }

  // no value found in task-local or fallback thread-local storage.
  return nullptr;
}

SWIFT_CC(swift)
static void swift_task_localValuePopImpl() {
  if (AsyncTask *task = swift_task_getCurrent()) {
    task->localValuePop();
    return;
  }

  if (TaskLocal::Storage *Local = FallbackTaskLocalStorage::get()) {
    bool hasRemainingBindings = Local->popValue(nullptr);
    if (!hasRemainingBindings) {
      // We clean up eagerly, it may be that this non-swift-concurrency thread
      // never again will use task-locals, and as such we better remove the storage.
      FallbackTaskLocalStorage::set(nullptr);
      free(Local);
    }
    return;
  }

  assert(false && "Attempted to pop value but no task or thread-local storage available!");
}

SWIFT_CC(swift)
static void swift_task_localsCopyToImpl(AsyncTask *task) {
  TaskLocal::Storage *Local = nullptr;

  if (AsyncTask *task = swift_task_getCurrent()) {
    Local = &task->_private().Local;
  } else if (auto *storage = FallbackTaskLocalStorage::get()) {
    Local = storage;
  } else {
    // bail out, there are no values to copy
    return;
  }

  Local->copyTo(task);
}

// =============================================================================
// ==== Initialization ---------------------------------------------------------

void TaskLocal::Storage::initializeLinkParent(AsyncTask* task,
                                              AsyncTask* parent) {
  assert(!head && "initial task local storage was already initialized");
  assert(parent && "parent must be provided to link to it");
  head = TaskLocal::Item::createParentLink(task, parent);
}

TaskLocal::Item*
TaskLocal::Item::createParentLink(AsyncTask *task, AsyncTask *parent) {
  size_t amountToAllocate = Item::itemSize(/*valueType*/nullptr);
  void *allocation = _swift_task_alloc_specific(task, amountToAllocate);
  Item *item = new(allocation) Item();

  auto parentHead = parent->_private().Local.head;
  if (parentHead) {
    if (parentHead->isEmpty()) {
      switch (parentHead->getNextLinkType()) {
        case NextLinkType::IsParent:
          // it has no values, and just points to its parent,
          // therefore skip also skip pointing to that parent and point
          // to whichever parent it was pointing to as well, it may be its
          // immediate parent, or some super-parent.
          item->next = reinterpret_cast<uintptr_t>(parentHead->getNext()) |
                       static_cast<uintptr_t>(NextLinkType::IsParent);
          break;
        case NextLinkType::IsNext:
          if (parentHead->getNext()) {
            assert(false && "empty taskValue head in parent task, yet parent's 'head' is `IsNext`, "
                            "this should not happen, as it implies the parent must have stored some value.");
          } else {
            // is terminal pointer
            item->next = reinterpret_cast<uintptr_t>(parentHead->getNext());
          }
          break;
      }
    } else {
      item->next = reinterpret_cast<uintptr_t>(parentHead) |
                   static_cast<uintptr_t>(NextLinkType::IsParent);
    }
  } else {
    item->next = reinterpret_cast<uintptr_t>(parentHead);
  }

  return item;
}

TaskLocal::Item*
TaskLocal::Item::createLink(AsyncTask *task,
                            const HeapObject *key,
                            const Metadata *valueType) {
  size_t amountToAllocate = Item::itemSize(valueType);
  void *allocation = task ? _swift_task_alloc_specific(task, amountToAllocate)
                          : malloc(amountToAllocate);
  Item *item = ::new (allocation) Item(key, valueType);

  auto next = task ? task->_private().Local.head
                   : FallbackTaskLocalStorage::get()->head;
  item->next = reinterpret_cast<uintptr_t>(next) |
      static_cast<uintptr_t>(NextLinkType::IsNext);

  return item;
}

void TaskLocal::Item::copyTo(AsyncTask *target) {
  assert(target && "TaskLocal item attempt to copy to null target task!");

  // 'parent' pointers are signified by null valueType.
  // We must not copy parent pointers, but rather perform a deep copy of all values,
  // as such, we skip parent pointers here entirely.
  if (isParentPointer())
    return;

  auto item = Item::createLink(target, key, valueType);
  valueType->vw_initializeWithCopy(item->getStoragePtr(), getStoragePtr());

  /// A `copyTo` may ONLY be invoked BEFORE the task is actually scheduled,
  /// so right now we can safely copy the value into the task without additional
  /// synchronization.
  target->_private().Local.head = item;
}

// =============================================================================
// ==== checks -----------------------------------------------------------------

SWIFT_CC(swift)
static void swift_task_reportIllegalTaskLocalBindingWithinWithTaskGroupImpl(
    const unsigned char *file, uintptr_t fileLength,
    bool fileIsASCII, uintptr_t line) {

  char *message;
  swift_asprintf(
      &message,
      "error: task-local: detected illegal task-local value binding at %.*s:%d.\n"
      "Task-local values must only be set in a structured-context, such as: "
      "around any (synchronous or asynchronous function invocation), "
      "around an 'async let' declaration, or around a 'with(Throwing)TaskGroup(...){ ... }' "
      "invocation. Notably, binding a task-local value is illegal *within the body* "
      "of a withTaskGroup invocation.\n"
      "\n"
      "The following example is illegal:\n\n"
      "    await withTaskGroup(...) { group in \n"
      "        await <task-local>.withValue(1234) {\n"
      "            group.spawn { ... }\n"
      "        }\n"
      "    }\n"
      "\n"
      "And should be replaced by, either: setting the value for the entire group:\n"
      "\n"
      "    // bind task-local for all tasks spawned within the group\n"
      "    await <task-local>.withValue(1234) {\n"
      "        await withTaskGroup(...) { group in\n"
      "            group.spawn { ... }\n"
      "        }\n"
      "    }\n"
      "\n"
      "or, inside the specific task-group child task:\n"
      "\n"
      "    // bind-task-local for only specific child-task\n"
      "    await withTaskGroup(...) { group in\n"
      "        group.spawn {\n"
      "            await <task-local>.withValue(1234) {\n"
      "                ... \n"
      "            }\n"
      "        }\n"
      "\n"
      "        group.spawn { ... }\n"
      "    }\n",
      (int)fileLength, file,
      (int)line);

  if (_swift_shouldReportFatalErrorsToDebugger()) {
    RuntimeErrorDetails details = {
        .version = RuntimeErrorDetails::currentVersion,
        .errorType = "task-local-violation",
        .currentStackDescription = "Task-local bound in illegal context",
        .framesToSkip = 1,
    };
    _swift_reportToDebugger(RuntimeErrorFlagFatal, message, &details);
  }

#if defined(_WIN32)
  #define STDERR_FILENO 2
  _write(STDERR_FILENO, message, strlen(message));
#else
  fputs(message, stderr);
  fflush(stderr);
#endif
#if SWIFT_STDLIB_HAS_ASL
  asl_log(nullptr, nullptr, ASL_LEVEL_ERR, "%s", message);
#elif defined(__ANDROID__)
  __android_log_print(ANDROID_LOG_FATAL, "SwiftRuntime", "%s", message);
#endif

  free(message);
  abort();
}

// =============================================================================
// ==== destroy ----------------------------------------------------------------

void TaskLocal::Item::destroy(AsyncTask *task) {
  // otherwise it was task-local allocated, so we can safely destroy it right away
  if (valueType) {
    valueType->vw_destroy(getStoragePtr());
  }

  // if task is available, we must have used the task allocator to allocate this item,
  // so we must deallocate it using the same. Otherwise, we must have used malloc.
  if (task) _swift_task_dealloc_specific(task, this);
  else free(this);
}

void TaskLocal::Storage::destroy(AsyncTask *task) {
  auto item = head;
  head = nullptr;
  TaskLocal::Item *next;
  while (item) {
    auto linkType = item->getNextLinkType();
    switch (linkType) {
    case TaskLocal::NextLinkType::IsNext:
        next = item->getNext();
        item->destroy(task);
        item = next;
        break;

      case TaskLocal::NextLinkType::IsParent:
        // we're done here; as we must not proceed into the parent owned values.
        // we do have to destroy the item pointing at the parent/edge itself though.
        item->destroy(task);
        return;
    }
  }
}

// =============================================================================
// ==== Task Local Storage: operations -----------------------------------------

void TaskLocal::Storage::pushValue(AsyncTask *task,
                                   const HeapObject *key,
                                   /* +1 */ OpaqueValue *value,
                                   const Metadata *valueType) {
  assert(value && "Task local value must not be nil");

  auto item = Item::createLink(task, key, valueType);
  valueType->vw_initializeWithTake(item->getStoragePtr(), value);
  head = item;
}

bool TaskLocal::Storage::popValue(AsyncTask *task) {
  assert(head && "attempted to pop value off empty task-local stack");
  auto old = head;
  head = head->getNext();
  old->destroy(task);

  /// if pointing at not-null next item, there are remaining bindings.
  return head != nullptr;
}

OpaqueValue* TaskLocal::Storage::getValue(AsyncTask *task,
                                          const HeapObject *key) {
  assert(key && "TaskLocal key must not be null.");

  auto item = head;
  while (item) {
    if (item->key == key) {
      return item->getStoragePtr();
    }

    item = item->getNext();
  }

  return nullptr;
}

void TaskLocal::Storage::copyTo(AsyncTask *target) {
  assert(target && "task must not be null when copying values into it");
  assert(!(target->_private().Local.head) &&
      "Task must not have any task-local values bound before copying into it");

  // Set of keys for which we already have copied to the new task.
  // We only ever need to copy the *first* encounter of any given key,
  // because it is the most "specific"/"recent" binding and any other binding
  // of a key does not matter for the target task as it will never be able to
  // observe it.
  std::set<const HeapObject*> copied = {};

  auto item = head;
  while (item) {
    // we only have to copy an item if it is the most recent binding of a key.
    // i.e. if we've already seen an item for this key, we can skip it.
    if (copied.emplace(item->key).second) {
      item->copyTo(target);
    }

    item = item->getNext();
  }
}

#define OVERRIDE_TASK_LOCAL COMPATIBILITY_OVERRIDE
#include COMPATIBILITY_OVERRIDE_INCLUDE_PATH
<commit_msg>[Concurrency][Windows] Remove unnecessary includes.<commit_after>//===--- TaskLocal.cpp - Task Local Values --------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "../CompatibilityOverride/CompatibilityOverride.h"
#include "swift/Runtime/Atomic.h"
#include "swift/Runtime/Casting.h"
#include "swift/Runtime/Concurrency.h"
#include "swift/Threading/ThreadLocalStorage.h"
#include "swift/ABI/TaskLocal.h"
#include "swift/ABI/Task.h"
#include "swift/ABI/Actor.h"
#include "swift/ABI/Metadata.h"
#include "llvm/ADT/PointerIntPair.h"
#include "TaskPrivate.h"
#include <new>
#include <set>

#if SWIFT_STDLIB_HAS_ASL
#include <asl.h>
#elif defined(__ANDROID__)
#include <android/log.h>
#endif

#if HAVE_PTHREAD_H
#include <pthread.h>
#endif

#if defined(_WIN32)
#include <io.h>
#endif

using namespace swift;

// =============================================================================

/// An extremely silly class which exists to make pointer
/// default-initialization constexpr.
template <class T> struct Pointer {
  T *Value;
  constexpr Pointer() : Value(nullptr) {}
  constexpr Pointer(T *value) : Value(value) {}
  operator T *() const { return Value; }
  T *operator->() const { return Value; }
};

/// THIS IS RUNTIME INTERNAL AND NOT ABI.
class FallbackTaskLocalStorage {
  static SWIFT_THREAD_LOCAL_TYPE(
      Pointer<TaskLocal::Storage>,
      SWIFT_CONCURRENCY_FALLBACK_TASK_LOCAL_STORAGE_KEY) Value;

public:
  static void set(TaskLocal::Storage *task) { Value.set(task); }
  static TaskLocal::Storage *get() { return Value.get(); }
};

/// Define the thread-locals.
SWIFT_THREAD_LOCAL_TYPE(
    Pointer<TaskLocal::Storage>,
    SWIFT_CONCURRENCY_FALLBACK_TASK_LOCAL_STORAGE_KEY)
FallbackTaskLocalStorage::Value;

// ==== ABI --------------------------------------------------------------------

SWIFT_CC(swift)
static void swift_task_localValuePushImpl(const HeapObject *key,
                                              /* +1 */ OpaqueValue *value,
                                              const Metadata *valueType) {
  if (AsyncTask *task = swift_task_getCurrent()) {
    task->localValuePush(key, value, valueType);
    return;
  }

  // no AsyncTask available so we must check the fallback
  TaskLocal::Storage *Local = nullptr;
  if (auto storage = FallbackTaskLocalStorage::get()) {
    Local = storage;
  } else {
    void *allocation = malloc(sizeof(TaskLocal::Storage));
    auto *freshStorage = new(allocation) TaskLocal::Storage();

    FallbackTaskLocalStorage::set(freshStorage);
    Local = freshStorage;
  }

  Local->pushValue(/*task=*/nullptr, key, value, valueType);
}

SWIFT_CC(swift)
static OpaqueValue* swift_task_localValueGetImpl(const HeapObject *key) {
  if (AsyncTask *task = swift_task_getCurrent()) {
    // we're in the context of a task and can use the task's storage
    return task->localValueGet(key);
  }

  // no AsyncTask available so we must check the fallback
  if (auto Local = FallbackTaskLocalStorage::get()) {
    return Local->getValue(/*task*/nullptr, key);
  }

  // no value found in task-local or fallback thread-local storage.
  return nullptr;
}

SWIFT_CC(swift)
static void swift_task_localValuePopImpl() {
  if (AsyncTask *task = swift_task_getCurrent()) {
    task->localValuePop();
    return;
  }

  if (TaskLocal::Storage *Local = FallbackTaskLocalStorage::get()) {
    bool hasRemainingBindings = Local->popValue(nullptr);
    if (!hasRemainingBindings) {
      // We clean up eagerly, it may be that this non-swift-concurrency thread
      // never again will use task-locals, and as such we better remove the storage.
      FallbackTaskLocalStorage::set(nullptr);
      free(Local);
    }
    return;
  }

  assert(false && "Attempted to pop value but no task or thread-local storage available!");
}

SWIFT_CC(swift)
static void swift_task_localsCopyToImpl(AsyncTask *task) {
  TaskLocal::Storage *Local = nullptr;

  if (AsyncTask *task = swift_task_getCurrent()) {
    Local = &task->_private().Local;
  } else if (auto *storage = FallbackTaskLocalStorage::get()) {
    Local = storage;
  } else {
    // bail out, there are no values to copy
    return;
  }

  Local->copyTo(task);
}

// =============================================================================
// ==== Initialization ---------------------------------------------------------

void TaskLocal::Storage::initializeLinkParent(AsyncTask* task,
                                              AsyncTask* parent) {
  assert(!head && "initial task local storage was already initialized");
  assert(parent && "parent must be provided to link to it");
  head = TaskLocal::Item::createParentLink(task, parent);
}

TaskLocal::Item*
TaskLocal::Item::createParentLink(AsyncTask *task, AsyncTask *parent) {
  size_t amountToAllocate = Item::itemSize(/*valueType*/nullptr);
  void *allocation = _swift_task_alloc_specific(task, amountToAllocate);
  Item *item = new(allocation) Item();

  auto parentHead = parent->_private().Local.head;
  if (parentHead) {
    if (parentHead->isEmpty()) {
      switch (parentHead->getNextLinkType()) {
        case NextLinkType::IsParent:
          // it has no values, and just points to its parent,
          // therefore skip also skip pointing to that parent and point
          // to whichever parent it was pointing to as well, it may be its
          // immediate parent, or some super-parent.
          item->next = reinterpret_cast<uintptr_t>(parentHead->getNext()) |
                       static_cast<uintptr_t>(NextLinkType::IsParent);
          break;
        case NextLinkType::IsNext:
          if (parentHead->getNext()) {
            assert(false && "empty taskValue head in parent task, yet parent's 'head' is `IsNext`, "
                            "this should not happen, as it implies the parent must have stored some value.");
          } else {
            // is terminal pointer
            item->next = reinterpret_cast<uintptr_t>(parentHead->getNext());
          }
          break;
      }
    } else {
      item->next = reinterpret_cast<uintptr_t>(parentHead) |
                   static_cast<uintptr_t>(NextLinkType::IsParent);
    }
  } else {
    item->next = reinterpret_cast<uintptr_t>(parentHead);
  }

  return item;
}

TaskLocal::Item*
TaskLocal::Item::createLink(AsyncTask *task,
                            const HeapObject *key,
                            const Metadata *valueType) {
  size_t amountToAllocate = Item::itemSize(valueType);
  void *allocation = task ? _swift_task_alloc_specific(task, amountToAllocate)
                          : malloc(amountToAllocate);
  Item *item = ::new (allocation) Item(key, valueType);

  auto next = task ? task->_private().Local.head
                   : FallbackTaskLocalStorage::get()->head;
  item->next = reinterpret_cast<uintptr_t>(next) |
      static_cast<uintptr_t>(NextLinkType::IsNext);

  return item;
}

void TaskLocal::Item::copyTo(AsyncTask *target) {
  assert(target && "TaskLocal item attempt to copy to null target task!");

  // 'parent' pointers are signified by null valueType.
  // We must not copy parent pointers, but rather perform a deep copy of all values,
  // as such, we skip parent pointers here entirely.
  if (isParentPointer())
    return;

  auto item = Item::createLink(target, key, valueType);
  valueType->vw_initializeWithCopy(item->getStoragePtr(), getStoragePtr());

  /// A `copyTo` may ONLY be invoked BEFORE the task is actually scheduled,
  /// so right now we can safely copy the value into the task without additional
  /// synchronization.
  target->_private().Local.head = item;
}

// =============================================================================
// ==== checks -----------------------------------------------------------------

SWIFT_CC(swift)
static void swift_task_reportIllegalTaskLocalBindingWithinWithTaskGroupImpl(
    const unsigned char *file, uintptr_t fileLength,
    bool fileIsASCII, uintptr_t line) {

  char *message;
  swift_asprintf(
      &message,
      "error: task-local: detected illegal task-local value binding at %.*s:%d.\n"
      "Task-local values must only be set in a structured-context, such as: "
      "around any (synchronous or asynchronous function invocation), "
      "around an 'async let' declaration, or around a 'with(Throwing)TaskGroup(...){ ... }' "
      "invocation. Notably, binding a task-local value is illegal *within the body* "
      "of a withTaskGroup invocation.\n"
      "\n"
      "The following example is illegal:\n\n"
      "    await withTaskGroup(...) { group in \n"
      "        await <task-local>.withValue(1234) {\n"
      "            group.spawn { ... }\n"
      "        }\n"
      "    }\n"
      "\n"
      "And should be replaced by, either: setting the value for the entire group:\n"
      "\n"
      "    // bind task-local for all tasks spawned within the group\n"
      "    await <task-local>.withValue(1234) {\n"
      "        await withTaskGroup(...) { group in\n"
      "            group.spawn { ... }\n"
      "        }\n"
      "    }\n"
      "\n"
      "or, inside the specific task-group child task:\n"
      "\n"
      "    // bind-task-local for only specific child-task\n"
      "    await withTaskGroup(...) { group in\n"
      "        group.spawn {\n"
      "            await <task-local>.withValue(1234) {\n"
      "                ... \n"
      "            }\n"
      "        }\n"
      "\n"
      "        group.spawn { ... }\n"
      "    }\n",
      (int)fileLength, file,
      (int)line);

  if (_swift_shouldReportFatalErrorsToDebugger()) {
    RuntimeErrorDetails details = {
        .version = RuntimeErrorDetails::currentVersion,
        .errorType = "task-local-violation",
        .currentStackDescription = "Task-local bound in illegal context",
        .framesToSkip = 1,
    };
    _swift_reportToDebugger(RuntimeErrorFlagFatal, message, &details);
  }

#if defined(_WIN32)
  #define STDERR_FILENO 2
  _write(STDERR_FILENO, message, strlen(message));
#else
  fputs(message, stderr);
  fflush(stderr);
#endif
#if SWIFT_STDLIB_HAS_ASL
  asl_log(nullptr, nullptr, ASL_LEVEL_ERR, "%s", message);
#elif defined(__ANDROID__)
  __android_log_print(ANDROID_LOG_FATAL, "SwiftRuntime", "%s", message);
#endif

  free(message);
  abort();
}

// =============================================================================
// ==== destroy ----------------------------------------------------------------

void TaskLocal::Item::destroy(AsyncTask *task) {
  // otherwise it was task-local allocated, so we can safely destroy it right away
  if (valueType) {
    valueType->vw_destroy(getStoragePtr());
  }

  // if task is available, we must have used the task allocator to allocate this item,
  // so we must deallocate it using the same. Otherwise, we must have used malloc.
  if (task) _swift_task_dealloc_specific(task, this);
  else free(this);
}

void TaskLocal::Storage::destroy(AsyncTask *task) {
  auto item = head;
  head = nullptr;
  TaskLocal::Item *next;
  while (item) {
    auto linkType = item->getNextLinkType();
    switch (linkType) {
    case TaskLocal::NextLinkType::IsNext:
        next = item->getNext();
        item->destroy(task);
        item = next;
        break;

      case TaskLocal::NextLinkType::IsParent:
        // we're done here; as we must not proceed into the parent owned values.
        // we do have to destroy the item pointing at the parent/edge itself though.
        item->destroy(task);
        return;
    }
  }
}

// =============================================================================
// ==== Task Local Storage: operations -----------------------------------------

void TaskLocal::Storage::pushValue(AsyncTask *task,
                                   const HeapObject *key,
                                   /* +1 */ OpaqueValue *value,
                                   const Metadata *valueType) {
  assert(value && "Task local value must not be nil");

  auto item = Item::createLink(task, key, valueType);
  valueType->vw_initializeWithTake(item->getStoragePtr(), value);
  head = item;
}

bool TaskLocal::Storage::popValue(AsyncTask *task) {
  assert(head && "attempted to pop value off empty task-local stack");
  auto old = head;
  head = head->getNext();
  old->destroy(task);

  /// if pointing at not-null next item, there are remaining bindings.
  return head != nullptr;
}

OpaqueValue* TaskLocal::Storage::getValue(AsyncTask *task,
                                          const HeapObject *key) {
  assert(key && "TaskLocal key must not be null.");

  auto item = head;
  while (item) {
    if (item->key == key) {
      return item->getStoragePtr();
    }

    item = item->getNext();
  }

  return nullptr;
}

void TaskLocal::Storage::copyTo(AsyncTask *target) {
  assert(target && "task must not be null when copying values into it");
  assert(!(target->_private().Local.head) &&
      "Task must not have any task-local values bound before copying into it");

  // Set of keys for which we already have copied to the new task.
  // We only ever need to copy the *first* encounter of any given key,
  // because it is the most "specific"/"recent" binding and any other binding
  // of a key does not matter for the target task as it will never be able to
  // observe it.
  std::set<const HeapObject*> copied = {};

  auto item = head;
  while (item) {
    // we only have to copy an item if it is the most recent binding of a key.
    // i.e. if we've already seen an item for this key, we can skip it.
    if (copied.emplace(item->key).second) {
      item->copyTo(target);
    }

    item = item->getNext();
  }
}

#define OVERRIDE_TASK_LOCAL COMPATIBILITY_OVERRIDE
#include COMPATIBILITY_OVERRIDE_INCLUDE_PATH
<|endoftext|>


<commit_before>c22c8187-ad5c-11e7-bf04-ac87a332f658<commit_msg>fixed bug<commit_after>c2ced14a-ad5c-11e7-aa2d-ac87a332f658<|endoftext|>


<commit_before>d9107519-2747-11e6-bf04-e0f84713e7b8<commit_msg>almost working<commit_after>d9203ba6-2747-11e6-8614-e0f84713e7b8<|endoftext|>


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

#include "config.h"

#include "flash-ipmi.hpp"
#include "host-ipmid/oemrouter.hpp"
#include "ipmi.hpp"

#include <memory>

#include "host-ipmid/ipmid-api.h"

static constexpr auto stagingPath = STAGING_PATH;
static constexpr auto hashPath = HASH_PATH;
static constexpr auto statusPath = STATUS_PATH;

/* TODO: Once OEM IPMI number placement is settled, point to that. */
namespace oem
{
namespace google
{
constexpr int number = 11129;
constexpr int flashOverBTCmd = 127;
} // namespace google
} // namespace oem

/* We have one instance of the FlashUpdate object tracking commands. */
std::unique_ptr<FlashUpdate> flashUpdateSingleton;

static ipmi_ret_t flashControl(ipmi_cmd_t cmd, const uint8_t* reqBuf,
                               uint8_t* replyCmdBuf, size_t* dataLen)
{
    size_t requestLength = (*dataLen);

    /* Verify it's at least as long as the shortest message. */
    if (requestLength < 1)
    {
        return IPMI_CC_INVALID;
    }

    auto subCmd = static_cast<FlashSubCmds>(reqBuf[0]);

    /* Validate the minimum request length for the command. */
    if (!validateRequestLength(subCmd, requestLength))
    {
        return IPMI_CC_INVALID;
    }

    auto handler = getCommandHandler(subCmd);
    if (handler)
    {
        return handler(flashUpdateSingleton.get(), reqBuf, replyCmdBuf,
                       dataLen);
    }

    return IPMI_CC_INVALID;
}

static ipmi_ret_t ipmiFlashControl(ipmi_netfn_t netFn, ipmi_cmd_t cmd,
                                   ipmi_request_t request,
                                   ipmi_response_t response,
                                   ipmi_data_len_t dataLen,
                                   ipmi_context_t context)
{
    /* request_t, response_t are void*. ipmi_data_len_t is a size_t* */
    auto reqBuf = static_cast<const uint8_t*>(request);
    auto replyCmdBuf = static_cast<uint8_t*>(response);

    return flashControl(cmd, reqBuf, replyCmdBuf, dataLen);
}

void setupGlobalOemFlashControl() __attribute__((constructor));

void setupGlobalOemFlashControl()
{
    flashUpdateSingleton = std::make_unique<FlashUpdate>(
        sdbusplus::bus::new_default(), stagingPath, statusPath, hashPath);

#ifdef ENABLE_GOOGLE
    oem::Router* router = oem::mutableRouter();

    fprintf(stderr, "Registering OEM:[%#08X], Cmd:[%#04X] for Flash Update\n",
            oem::google::number, oem::google::flashOverBTCmd);

    router->registerHandler(oem::google::number, oem::google::flashOverBTCmd,
                            flashControl);
#endif

    ipmi_register_callback(NETFUN_FIRMWARE, oem::google::flashOverBTCmd, NULL,
                           ipmiFlashControl, PRIVILEGE_USER);
}
<commit_msg>phosphor-ipmi-flash: main: move to iana header<commit_after>/*
 * Copyright 2018 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "config.h"

#include "flash-ipmi.hpp"
#include "ipmi.hpp"

#include <host-ipmid/ipmid-api.h>

#include <host-ipmid/iana.hpp>
#include <host-ipmid/oemrouter.hpp>
#include <memory>

static constexpr auto stagingPath = STAGING_PATH;
static constexpr auto hashPath = HASH_PATH;
static constexpr auto statusPath = STATUS_PATH;

/* TODO: Once OEM IPMI number placement is settled, point to that. */
namespace oem
{
namespace google
{
constexpr int flashOverBTCmd = 127;
} // namespace google
} // namespace oem

/* We have one instance of the FlashUpdate object tracking commands. */
std::unique_ptr<FlashUpdate> flashUpdateSingleton;

static ipmi_ret_t flashControl(ipmi_cmd_t cmd, const uint8_t* reqBuf,
                               uint8_t* replyCmdBuf, size_t* dataLen)
{
    size_t requestLength = (*dataLen);

    /* Verify it's at least as long as the shortest message. */
    if (requestLength < 1)
    {
        return IPMI_CC_INVALID;
    }

    auto subCmd = static_cast<FlashSubCmds>(reqBuf[0]);

    /* Validate the minimum request length for the command. */
    if (!validateRequestLength(subCmd, requestLength))
    {
        return IPMI_CC_INVALID;
    }

    auto handler = getCommandHandler(subCmd);
    if (handler)
    {
        return handler(flashUpdateSingleton.get(), reqBuf, replyCmdBuf,
                       dataLen);
    }

    return IPMI_CC_INVALID;
}

static ipmi_ret_t ipmiFlashControl(ipmi_netfn_t netFn, ipmi_cmd_t cmd,
                                   ipmi_request_t request,
                                   ipmi_response_t response,
                                   ipmi_data_len_t dataLen,
                                   ipmi_context_t context)
{
    /* request_t, response_t are void*. ipmi_data_len_t is a size_t* */
    auto reqBuf = static_cast<const uint8_t*>(request);
    auto replyCmdBuf = static_cast<uint8_t*>(response);

    return flashControl(cmd, reqBuf, replyCmdBuf, dataLen);
}

void setupGlobalOemFlashControl() __attribute__((constructor));

void setupGlobalOemFlashControl()
{
    flashUpdateSingleton = std::make_unique<FlashUpdate>(
        sdbusplus::bus::new_default(), stagingPath, statusPath, hashPath);

#ifdef ENABLE_GOOGLE
    oem::Router* router = oem::mutableRouter();

    fprintf(stderr, "Registering OEM:[%#08X], Cmd:[%#04X] for Flash Update\n",
            oem::googOemNumber, oem::google::flashOverBTCmd);

    router->registerHandler(oem::googOemNumber, oem::google::flashOverBTCmd,
                            flashControl);
#endif

    ipmi_register_callback(NETFUN_FIRMWARE, oem::google::flashOverBTCmd, NULL,
                           ipmiFlashControl, PRIVILEGE_USER);
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <mpi.h>
#include <regex>
#include <iostream>
#include <string>
#include <map>
#include <set>
#include <algorithm>

typedef std::map<std::string, std::set<std::string>> LinkMap;

int g_world_size;
int g_my_rank;
std::string g_filename = "enwiki-20160305-pages-articles.xml";

void parse_file(MPI_File *infile);
void regex_test();
void find_links(std::string section, std::string current_title, LinkMap &links);

int main(int argc, char** argv) {
  // Initialize the MPI environment
  MPI_Init(NULL, NULL);

  // Get the number of processes
  MPI_Comm_size(MPI_COMM_WORLD, &g_world_size);

  // Get the rank of the process
  MPI_Comm_rank(MPI_COMM_WORLD, &g_my_rank);

  // Print off a hello world message
  printf("Hello world from rank %d out of %d processors\n", g_my_rank, g_world_size);

  // Open up the wikipedia xml file
  MPI_File infile;
  MPI_File_open(MPI_COMM_WORLD, g_filename.c_str(), MPI_MODE_RDONLY, MPI_INFO_NULL, &infile);

  // Parse the file
  parse_file(&infile);

  if (g_my_rank == 0){
    //regex_test();
  }

  // Close the file
  MPI_File_close(&infile);

  // Finalize the MPI environment.
  MPI_Finalize();

  return 0;
}

// Parse the input file: pull out page titles and any links from a page to another
void parse_file(MPI_File *infile){
  //get file size
  MPI_Offset filesize;
  MPI_File_get_size(*infile, &filesize);

  // the size of each chunk that will be read in at a time
  //  TODO: find an optimal setting for this so that we aren't producing too many read reqeusts
  int chunk_size = 1000000;
  //get size of the chunk this rank will handle
  long long int max_size = filesize / g_world_size;
  // where this rank will stop reading the file (aka where the next rank will start reading)
  long long int stopping_point = max_size * (g_my_rank + 1);

  //get the start point for this rank in the file:
  //    subtract chunk_size from the 'logical' start point to make sure
  //    that each node has a title for the links that it finds
  MPI_Offset offset = std::max(max_size * g_my_rank, max_size * g_my_rank - chunk_size);

  printf("Rank %d ==> start point: %lld\n", g_my_rank, offset);

  // the regex to find a tile in the file
  std::regex title_regex("<title>(.+)</title>");

  // declare some variables
  char * chunk;
  std::string current_title = "";
  LinkMap links;

  // keep going until the offset is in the next ranks group
  int count = 0;
  while (offset < stopping_point && links.size() < 1000){
    std::cout << count << std::endl;
    count ++;
    // allocate a chunk to read in from the file
    chunk = (char *)malloc( (chunk_size + 1)*sizeof(char));
    // read it in
    MPI_File_read_at(*infile, offset, chunk, chunk_size, MPI_CHAR, MPI_STATUS_IGNORE);
    // end the string
    chunk[chunk_size] = '\0';
    // make it a c++ string for convenience
    std::string chunk_string(chunk);
    // free the allocated space
    free(chunk);

    std::smatch title_match;
    // keep looping while there is another title in the the current chunk
    while (std::regex_search(chunk_string, title_match, title_regex)){
      // if we've already found at least one title, search the first part of the chunk for any links
      if (current_title != ""){
        find_links(title_match.prefix(), current_title, links);
      }

      // overwrite current_title with the new one
      current_title = title_match[1].str();
      // initilize the new title's spot in the links map with an empty set
      links[current_title] = std::set<std::string>();

      //printf("title %lu: %s\n", links.size(), current_title.c_str());

      // set the chunk_string to be everything after the title
      chunk_string = title_match.suffix();
    }
    // do one last search through the remainder of the chunk for any links
    find_links(chunk_string, current_title, links);

    offset += chunk_size;
  }

  //output the contents of the links map after parsing
  /*for (const auto &key : links) {
    std::cout << g_my_rank << "  " << key.first << "  " << key.second.size() << std::endl;
    for (const auto &val: key.second){
      std::cout << "    " << val << std::endl;
    }
  }*/

}

void find_links(std::string section, std::string current_title, LinkMap &links){
  //links[current_title].push_back("test");
  //std::cout << section << std::endl;
  std::regex link_regex("\\[\\[([^ ]*)\\]\\]");
  std::smatch link_match;
  while (std::regex_search(section, link_match, link_regex)){
    std::ssub_match sub_match = link_match[1];
    std::string piece = sub_match.str();
    //std::cout << piece << '\n';
    links[current_title].insert(piece);
    //std::cout << current_title << " > " << piece << std::endl;
    section = link_match.suffix().str();
  }
}

void regex_test(){
  //std::regex link_regex("\\[\\[(.+)\\]\\]");

  std::string s ("this [[subject]] has a submarine as [[a]] subsequence");
  std::smatch m;
  std::regex e ("\\[\\[([^ ]*)\\]\\]");   // matches words beginning by "sub"

  std::cout << "The following matches and submatches were found:" << std::endl;

  while (std::regex_search (s,m,e)) {
    for (auto x:m) std::cout << x << "\n";
    std::cout << std::endl;
    s = m.suffix().str();
  }

}
<commit_msg>shorter runs<commit_after>#include <stdio.h>
#include <mpi.h>
#include <regex>
#include <iostream>
#include <string>
#include <map>
#include <set>
#include <algorithm>

typedef std::map<std::string, std::set<std::string>> LinkMap;

int g_world_size;
int g_my_rank;
std::string g_filename = "enwiki-20160305-pages-articles.xml";

void parse_file(MPI_File *infile);
void regex_test();
void find_links(std::string section, std::string current_title, LinkMap &links);

int main(int argc, char** argv) {
  // Initialize the MPI environment
  MPI_Init(NULL, NULL);

  // Get the number of processes
  MPI_Comm_size(MPI_COMM_WORLD, &g_world_size);

  // Get the rank of the process
  MPI_Comm_rank(MPI_COMM_WORLD, &g_my_rank);

  // Print off a hello world message
  printf("Hello world from rank %d out of %d processors\n", g_my_rank, g_world_size);

  // Open up the wikipedia xml file
  MPI_File infile;
  MPI_File_open(MPI_COMM_WORLD, g_filename.c_str(), MPI_MODE_RDONLY, MPI_INFO_NULL, &infile);

  // Parse the file
  parse_file(&infile);

  if (g_my_rank == 0){
    //regex_test();
  }

  // Close the file
  MPI_File_close(&infile);

  // Finalize the MPI environment.
  MPI_Finalize();

  return 0;
}

// Parse the input file: pull out page titles and any links from a page to another
void parse_file(MPI_File *infile){
  //get file size
  MPI_Offset filesize;
  MPI_File_get_size(*infile, &filesize);

  // the size of each chunk that will be read in at a time
  //  TODO: find an optimal setting for this so that we aren't producing too many read reqeusts
  int chunk_size = 1000000;
  //get size of the chunk this rank will handle
  long long int max_size = filesize / g_world_size;
  // where this rank will stop reading the file (aka where the next rank will start reading)
  long long int stopping_point = max_size * (g_my_rank + 1);

  //get the start point for this rank in the file:
  //    subtract chunk_size from the 'logical' start point to make sure
  //    that each node has a title for the links that it finds
  MPI_Offset offset = std::max(max_size * g_my_rank, max_size * g_my_rank - chunk_size);

  printf("Rank %d ==> start point: %lld\n", g_my_rank, offset);

  // the regex to find a tile in the file
  std::regex title_regex("<title>(.+)</title>");

  // declare some variables
  char * chunk;
  std::string current_title = "";
  LinkMap links;

  // keep going until the offset is in the next ranks group
  while (offset < stopping_point && links.size() < 100){
    // allocate a chunk to read in from the file
    chunk = (char *)malloc( (chunk_size + 1)*sizeof(char));
    // read it in
    MPI_File_read_at(*infile, offset, chunk, chunk_size, MPI_CHAR, MPI_STATUS_IGNORE);
    // end the string
    chunk[chunk_size] = '\0';
    // make it a c++ string for convenience
    std::string chunk_string(chunk);
    // free the allocated space
    free(chunk);

    std::smatch title_match;
    // keep looping while there is another title in the the current chunk
    while (std::regex_search(chunk_string, title_match, title_regex)){
      // if we've already found at least one title, search the first part of the chunk for any links
      if (current_title != ""){
        find_links(title_match.prefix(), current_title, links);
      }

      // overwrite current_title with the new one
      current_title = title_match[1].str();
      // initilize the new title's spot in the links map with an empty set
      links[current_title] = std::set<std::string>();

      //printf("title %lu: %s\n", links.size(), current_title.c_str());
      //std::cout << title_match[0] << std::endl;

      // set the chunk_string to be everything after the title
      chunk_string = title_match.suffix();
    }
    // do one last search through the remainder of the chunk for any links
    find_links(chunk_string, current_title, links);

    offset += chunk_size;
  }

  //output the contents of the links map after parsing
  std::cout << links.size() << std::endl;
  for (const auto &key : links) {
    std::cout << key.first << "  " << key.second.size() << std::endl;
    /*for (const auto &val: key.second){
      std::cout << "    " << val << std::endl;
    }*/
  }

}

void find_links(std::string section, std::string current_title, LinkMap &links){
  //links[current_title].push_back("test");
  //std::cout << section << std::endl;
  std::regex link_regex("\\[\\[([^\\[\\]]*)\\]\\]");
  std::smatch link_match;
  while (std::regex_search(section, link_match, link_regex)){
    std::ssub_match sub_match = link_match[1];
    std::string piece = sub_match.str();
    //std::cout << piece << '\n';
    links[current_title].insert(piece);
    //std::cout << current_title << " > " << piece << std::endl;
    section = link_match.suffix().str();
  }
}

void regex_test(){
  //std::regex link_regex("\\[\\[(.+)\\]\\]");

  std::string s ("this [[subject]] has a submarine as [[a]] subsequence");
  std::smatch m;
  std::regex e ("\\[\\[([^ ]*)\\]\\]");   // matches words beginning by "sub"

  std::cout << "The following matches and submatches were found:" << std::endl;

  while (std::regex_search (s,m,e)) {
    for (auto x:m) std::cout << x << "\n";
    std::cout << std::endl;
    s = m.suffix().str();
  }

}
<|endoftext|>


<commit_before>125f34a8-2748-11e6-a2ef-e0f84713e7b8<commit_msg>Typical bobby<commit_after>12687ae8-2748-11e6-aad4-e0f84713e7b8<|endoftext|>


<commit_before>85560f7d-4b02-11e5-b427-28cfe9171a43<commit_msg>lets try again<commit_after>85646f73-4b02-11e5-be12-28cfe9171a43<|endoftext|>


<commit_before>72b9f74a-ad5a-11e7-b88a-ac87a332f658<commit_msg>fixed bug<commit_after>735a2ccf-ad5a-11e7-9c16-ac87a332f658<|endoftext|>


<commit_before>108f220a-ad59-11e7-b9da-ac87a332f658<commit_msg>Added that feature we discussed on... Was it monday?<commit_after>1142e900-ad59-11e7-ab08-ac87a332f658<|endoftext|>


<commit_before>11133735-ad5a-11e7-974f-ac87a332f658<commit_msg>Introduced random NullPointerException bug<commit_after>118663c7-ad5a-11e7-b928-ac87a332f658<|endoftext|>


<commit_before>bf9a5df0-4b02-11e5-b932-28cfe9171a43<commit_msg>bug fix<commit_after>bfa86628-4b02-11e5-92fc-28cfe9171a43<|endoftext|>


<commit_before>e0695d8f-ad59-11e7-b7c4-ac87a332f658<commit_msg>My Life for Auir<commit_after>e0f46fab-ad59-11e7-84da-ac87a332f658<|endoftext|>


<commit_before>#include <iostream>
#include <vector>
#include <fstream>
using namespace std;

class Node {
    public:
        Node() {
            mContent = ' ';
            mMarker = false;
        }
        ~Node() {}
        char get() {
            return mContent;
        }
        void set(char c) {
            mContent = c;
        }
        bool isMarker() {
            return mMarker;
        }
        void setMarker() {
            mMarker = true;
        }
        void append(Node* child) {
            mChildren.push_back(child);
        }
        vector<Node*> children() {
            return mChildren;
        }
        Node* find(char c);

    private:
        char mContent;
        bool mMarker;
        vector<Node*> mChildren;
};

Node* Node::find(char c) {
    int l = mChildren.size();

    for (int i = 0; i < l; i++) {
        Node* tmp = mChildren.at(i);
        if (tmp->get() == c) {
            return tmp;
        }
    }

    return NULL;
};

class Trie {
    public:
        Trie();
        ~Trie();
        void add(string s);
        bool search(string s);
        void rem(string s);
    private:
        Node* root;
};

Trie::Trie() {
    root = new Node();
}

Trie::~Trie() {
    // Free memory
}

void Trie::add(string s) {
    Node* curr = root;
    int l = s.length();

    if (l == 0) {
        curr->setMarker(); // an empty word
        return;
    }

    for (int i = 0; i < l; i++) {
        Node* child = curr->find(s[i]);

        if (child != NULL) {
            curr = child;
        } else {
            Node* tmp = new Node();
            tmp->set(s[i]);
            curr->append(tmp);
            curr = tmp;
        }

        if (i == l - 1) {
            curr->setMarker();
        }
    }
}

bool Trie::search(string s) {
    Node* curr = root;
    int l = s.length();

    while (curr != NULL) {

        for (int i = 0; i < l; i++) {
            Node* tmp = curr->find(s[i]);
            if ( tmp == NULL ) {
                return false;
            }
            curr = tmp;
        }

        if (curr->isMarker()) {
            return true;
        } else {
            return false;
        }
    }

    return false;
}

class Corpus {
    public:
        Corpus() {
            cRoot = ' ';
        }
        void root(string r) {
            cRoot = r;
        }
        bool load(string s);
        Trie* get(string s);
        bool has(string s);

    private:
        string cRoot;
        typedef struct _Data {
            Trie t;
            string n;
        } Data ;
        vector<Data> stack;
};

bool Corpus::has(string s) {
    return false;
};

bool Corpus::load(string s) {
    ifstream file(cRoot+s);
    if (!file) {
        return false;
    }

    Trie* trie = new Trie();
    while(getline(*file, line)){
        trie->add(line)
    };
    return true;
};

Trie* Corpus::get(string s) {
    return NULL;
};

/*
    Main entry point

    Requires:
    - First argument: root of corpus files
*/
int main(int argc, char* argv[]) {

    Corpus* corpus = new Corpus();

    cout << "argc = " << argc << endl;
    for(int i = 0; i < argc; i++) {

    }
    cout << "argv[" << i << "] = " << argv[i] << endl;

    Trie* trie = new Trie();
    trie->add("Hello");
    trie->add("Balloon");
    trie->add("Ball");

    if ( trie->search("Hell") )
        cout << "Found Hell" << endl;

    if ( trie->search("Hello") )
        cout << "Found Hello" << endl;

    if ( trie->search("Helloo") )
        cout << "Found Helloo" << endl;

    if ( trie->search("Ball") )
        cout << "Found Ball" << endl;

    if ( trie->search("Balloon") )
        cout << "Found Balloon" << endl;

    delete trie;
}<commit_msg>Almost nothing<commit_after>#include <iostream>
#include <vector>
#include <fstream>
using namespace std;

class Node {
    public:
        Node() {
            mContent = ' ';
            mMarker = false;
        }
        ~Node() {}
        char get() {
            return mContent;
        }
        void set(char c) {
            mContent = c;
        }
        bool isMarker() {
            return mMarker;
        }
        void setMarker() {
            mMarker = true;
        }
        void append(Node* child) {
            mChildren.push_back(child);
        }
        vector<Node*> children() {
            return mChildren;
        }
        Node* find(char c);

    private:
        char mContent;
        bool mMarker;
        vector<Node*> mChildren;
};

Node* Node::find(char c) {
    int l = mChildren.size();

    for (int i = 0; i < l; i++) {
        Node* tmp = mChildren.at(i);
        if (tmp->get() == c) {
            return tmp;
        }
    }

    return NULL;
};

class Trie {
    public:
        Trie();
        ~Trie();
        void add(string s);
        bool search(string s);
        void rem(string s);
    private:
        Node* root;
};

Trie::Trie() {
    root = new Node();
}

Trie::~Trie() {
    // Free memory
}

void Trie::add(string s) {
    Node* curr = root;
    int l = s.length();

    if (l == 0) {
        curr->setMarker(); // an empty word
        return;
    }

    for (int i = 0; i < l; i++) {
        Node* child = curr->find(s[i]);

        if (child != NULL) {
            curr = child;
        } else {
            Node* tmp = new Node();
            tmp->set(s[i]);
            curr->append(tmp);
            curr = tmp;
        }

        if (i == l - 1) {
            curr->setMarker();
        }
    }
}

bool Trie::search(string s) {
    Node* curr = root;
    int l = s.length();

    while (curr != NULL) {

        for (int i = 0; i < l; i++) {
            Node* tmp = curr->find(s[i]);
            if ( tmp == NULL ) {
                return false;
            }
            curr = tmp;
        }

        if (curr->isMarker()) {
            return true;
        } else {
            return false;
        }
    }

    return false;
}

class Corpus {
    public:
        Corpus() {
            cRoot = ' ';
        }
        void root(string r) {
            cRoot = r;
        }
        bool load(string s);
        Trie* get(string s);
        bool has(string s);

    private:
        string cRoot;
        typedef struct _Data {
            Trie t;
            string n;
        } Data ;
        vector<Data> stack;
};

bool Corpus::has(string s) {
    return false;
};

bool Corpus::load(string s) {
    ifstream file(cRoot+s);
    if (!file) {
        return false;
    }

    Trie* trie = new Trie();
    while(getline(*file, line)){
        trie->add(line)
    };
    return true;
};

Trie* Corpus::get(string s) {
    return NULL;
};

/*
    Main entry point

    Requires:
    - First argument: root of corpus files
*/
int main(int argc, char* argv[]) {

    Corpus* corpus = new Corpus();

    cout << "argc = " << argc << endl;
    for(int i = 0; i < argc; i++) {

    }
    cout << "argv[" << i << "] = " << argv[i] << endl;

    Trie* trie = new Trie();
    trie->add("Hello");
    trie->add("Balloon");
    trie->add("Ball");

    if ( trie->search("Hell") )
        cout << "Found Hell" << endl;

    if ( trie->search("Hello") )
        cout << "Found Hello" << endl;

    if ( trie->search("Helloo") )
        cout << "Found Helloo" << endl;

    if ( trie->search("Ball") )
        cout << "Found Ball" << endl;

    if ( trie->search("Balloon") )
        cout << "Found Balloon" << endl;

    delete trie;
}<|endoftext|>