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

#include <string>

#include "Irccd.h"
#include "Logger.h"
#include "Luae.h"
#include "LuaThread.h"
#include "Plugin.h"
#include "Thread.h"

namespace irccd {

namespace {

/* ---------------------------------------------------------
 * Buffer management for loading threads
 * --------------------------------------------------------- */

struct Buffer {
	std::vector<char>	array;
	bool			given;

	Buffer()
		: given(false)
	{
	}
};

int writer(lua_State *, const char *data, size_t size, Buffer *buffer)
{
	for (size_t i = 0; i < size; ++i)
		buffer->array.push_back(data[i]);

	return 0;
}

const char *loader(lua_State *, Buffer *buffer, size_t *size)
{
	if (buffer->given) {
		*size = 0;
		return nullptr;
	}

	buffer->given = true;
	*size = buffer->array.size();

	return buffer->array.data();
}

/* ---------------------------------------------------------
 * Thread management
 * --------------------------------------------------------- */

const char *THREAD_TYPE = "Thread";

/* ---------------------------------------------------------
 * Functions and metamethods
 * --------------------------------------------------------- */

int l_threadNew(lua_State *L)
{
	Thread::Ptr thread = Thread::create();
	Buffer chunk;
	int np;

	luaL_checktype(L, 1, LUA_TFUNCTION);

	// Dump the function
	lua_pushvalue(L, 1);
	lua_dump(L, reinterpret_cast<lua_Writer>(writer), &chunk);
	lua_pop(L, 1);

	for (auto l : Process::luaLibs)
		Luae::require(*thread, l.first, l.second, true);
	for (auto l : Process::irccdLibs)
		Luae::preload(*thread, l.first, l.second);

	lua_load(*thread, reinterpret_cast<lua_Reader>(loader), &chunk, "thread", nullptr);

	np = 0;
	for (int i = 2; i <= lua_gettop(L); ++i) {
		LuaValue v = LuaValue::copy(L, i);
		LuaValue::push(*thread, v);
		++ np;
	}

	try {
		auto info = Process::info(L);
		auto process = thread->process();

		// Set home and name like the plugin
		Process::initialize(process, info);

		// Create the object to push as return value
		Thread::Ptr *ptr = new (L, THREAD_TYPE) Thread::Ptr(thread);
		Thread::start(*ptr, np);
	} catch (std::out_of_range) {
		Logger::fatal(1, "irccd: could not find plugin from Lua state %p", L);
	}

	return 1;
}<commit_msg>Add support for files as threads.<commit_after>/*
 * LuaThread.cpp -- Lua bindings for threads
 *
 * Copyright (c) 2013 <NAME> <<EMAIL>>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <string>

#include "Irccd.h"
#include "Logger.h"
#include "Luae.h"
#include "LuaThread.h"
#include "Plugin.h"
#include "Thread.h"

namespace irccd {

namespace {

/* ---------------------------------------------------------
 * Buffer management for loading threads
 * --------------------------------------------------------- */

struct Buffer {
	std::vector<char>	array;
	bool			given;

	Buffer()
		: given(false)
	{
	}
};

int writer(lua_State *, const char *data, size_t size, Buffer *buffer)
{
	for (size_t i = 0; i < size; ++i)
		buffer->array.push_back(data[i]);

	return 0;
}

const char *loader(lua_State *, Buffer *buffer, size_t *size)
{
	if (buffer->given) {
		*size = 0;
		return nullptr;
	}

	buffer->given = true;
	*size = buffer->array.size();

	return buffer->array.data();
}

void loadfunction(Thread::Ptr thread, lua_State *owner)
{
	Buffer chunk;

	lua_pushvalue(owner, 1);
	lua_dump(owner, reinterpret_cast<lua_Writer>(writer), &chunk);
	lua_pop(owner, 1);
	lua_load(*thread, reinterpret_cast<lua_Reader>(loader), &chunk, "thread", nullptr);
}

void loadfile(Thread::Ptr thread, const char *path)
{
	if (luaL_loadfile(*thread, path) != LUA_OK) {
		auto error = lua_tostring(*thread, -1);
		lua_pop(*thread, 1);

		throw std::runtime_error(error);
	}
}

/* ---------------------------------------------------------
 * Thread management
 * --------------------------------------------------------- */

const char *THREAD_TYPE = "Thread";

/* ---------------------------------------------------------
 * Functions and metamethods
 * --------------------------------------------------------- */

int l_threadNew(lua_State *L)
{
	Thread::Ptr thread = Thread::create();
	int np;

	for (auto l : Process::luaLibs)
		Luae::require(*thread, l.first, l.second, true);
	for (auto l : Process::irccdLibs)
		Luae::preload(*thread, l.first, l.second);

	try {
		if (lua_type(L, 1) == LUA_TFUNCTION)
			loadfunction(thread, L);
		else if (lua_type(L, 1) == LUA_TSTRING)
			loadfile(thread, lua_tostring(L, 1));
		else
			return luaL_error(L, "expected a function or a file path");
	} catch (std::runtime_error err) {
		lua_pushnil(L);
		lua_pushstring(L, err.what());

		return 2;
	}

	np = 0;
	for (int i = 2; i <= lua_gettop(L); ++i) {
		LuaValue v = LuaValue::copy(L, i);
		LuaValue::push(*thread, v);
		++ np;
	}

	try {
		auto info = Process::info(L);
		auto process = thread->process();

		// Set home and name like the plugin
		Process::initialize(process, info);

		// Create the object to push as return value
		Thread::Ptr *ptr = new (L, THREAD_TYPE) Thread::Ptr(thread);
		Thread::start(*ptr, np);
	} catch (std::out_of_range) {
		Logger::fatal(1, "irccd: could not find plugin from Lua state %p", L);
	}

	return 1;
}
{'fraction_non_alphanumeric': 0.22433973589435774, 'fraction_numerical': 0.004951980792316926, 'mean_word_length': 2.589122240172321, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1743834', 'n_tokens_mistral': 2221, 'n_tokens_neox': 2045, 'n_words': 665}