<commit_before>#include <tansa/action.h>
#include <tansa/control.h>
#include <tansa/core.h>
#include <tansa/jocsParser.h>
#include <tansa/config.h>
#include <tansa/jocsPlayer.h>
#include <tansa/mocap.h>
#include <tansa/gazebo.h>
#include <tansa/osc.h>

#ifdef  __linux__
#include <sys/signal.h>
#endif
//TODO check if these work on OSX
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <iostream>

using namespace std;
using namespace tansa;

static bool running;
static bool killmode = false;
static bool pauseMode = false;
static bool stopMode = false;
static bool playMode = false;
static JocsPlayer* player;
static vector<Vehicle *> vehicles;
static std::vector<vehicle_config> vconfigs;
static vector<unsigned> jocsActiveIds;

void signal_sigint(int s) {
	// TODO: Prevent
	running = false;
}

/* For sending a system state update to the gui */
void send_status_message() {

	json j;

	j["type"] = "status";
	j["time"] = player->currentTime();

	json vehs = json::array();
	for(int i = 0; i < vehicles.size(); i++) {
		json v;
		v["id"] = vconfigs[i].net_id;
		v["role"] = i <= jocsActiveIds.size() - 1? jocsActiveIds[i] : -1;
		v["connected"] = vehicles[i]->connected;
		v["armed"] = vehicles[i]->armed;
		v["tracking"] = vehicles[i]->tracking;

		json pos = json::array();
		pos.push_back(vehicles[i]->state.position.x());
		pos.push_back(vehicles[i]->state.position.y());
		pos.push_back(vehicles[i]->state.position.z());
		v["position"] = pos;

		json bat = {
			{"voltage", vehicles[i]->battery.voltage},
			{"percent", vehicles[i]->battery.percent}
		};
		v["battery"] = bat;

		vehs.push_back(v);
	}
	j["vehicles"] = vehs;

	json global;
	global["playing"] = player->isPlaying();
	global["ready"] = player->isReady();
	j["global"] = global;

	tansa::send_message(j);
}

void send_file_list() {
	std::vector<std::string> jocsFilePaths;
	json j;

	j["type"] = "list_reply";
	json files = json::array();
	DIR *dir;
	struct dirent *ent;
	if ((dir = opendir ("data")) != NULL) {
		while ((ent = readdir (dir)) != NULL) {
			if(ent->d_type == DT_REG && std::string(ent->d_name).find(".jocs") != std::string::npos)
			files.push_back(std::string(ent->d_name));
		}
		closedir (dir);
	} else {
		/* could not open directory */
	}
	j["files"] = files;
	tansa::send_message(j);
//	sio::message::ptr obj = sio::object_message::create();
//	obj->get_map()["type"] = sio::string_message::create("status");
//	obj->get_map()["time"] = sio::double_message::create(t.seconds());

//	sio::message::list li(obj);
//	tansa::send_message(li);

}

void socket_on_message(const json &data) {

	string type = data["type"];

	if(type == "prepare") {
		printf("Preparing...\n");
		player->prepare();
	}
	else if(type == "play") {		printf("Playing...\n");
		playMode = true;
	}
	else if(type == "land") {
		player->land();
	}
	else if (type == "pause") {
		printf("Pausing...\n");
		pauseMode = true;
	} else if (type == "stop") {
		printf("Stopping...\n");
		stopMode = true;
	} else if (type == "reset") {
		printf("Resetting...\n");
	} else if (type == "list"){
		send_file_list();
	}
	else if(type == "kill") {
		bool enabled = data["enabled"];
		printf("Killing...\n");
		killmode = enabled;
	}
	else {
		// TODO: Send an error message back to the browser
		printf("Unexpected message type recieved!\n");
	}

}

void osc_on_message(OSCMessage &msg) {

	// Address will look something like: '/cue/0101/start'
	if(msg.address[0] == "cue") {

		int num = std::stoi(msg.address[1]);

		if(msg.address[2] == "load") {
			player->prepare();
		}
		else if(msg.address[2] == "start") {
			printf("Starting at cue #: %d\n", num);

			// Assert that it is already prepared at the given cue

			player->play();
		}

	}

	/*
	printf("Address:\n");
	for(auto str : msg.address)
		printf("- %s\n", str.c_str());

	printf("\nArgs:\n");
	for(auto str : msg.args)
		printf("- %s\n", str.c_str());
	*/

}

pthread_t console_handle;

void *console_thread(void *arg) {

	while(running) {

		// Read a command
		cout << "> ";
		string line;
		getline(cin, line);

		// Split into arguments
		vector<string> args;
		istringstream iss(line);
		while(!iss.eof()) {
			string a;
			iss >> a;

			if(iss.fail())
				break;

			args.push_back(a);
		}

		if(args.size() == 0)
			continue;

		if (args[0] == "prepare") {
			cout << "Preparing..." << endl;
			player->prepare();
		} else if (args[0] == "play") {
			cout << "Playing..." << endl;
			playMode = true;
		} else if (args[0] == "pause") {
			cout << "Pausing..." << endl;
			pauseMode = true;
		} else if (args[0] == "stop") {
			cout << "Stopping..." << endl;
			stopMode = true;
		} else if (args[0] == "land") {
			cout << "Landing..." << endl;
			player->land();
		} else if (args[0] == "kill") {
			killmode = args.size() <= 1 || !(args[1] == "off");
		}

	}

}

void console_start() {
	pthread_create(&console_handle, NULL, console_thread, NULL);
}

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

	assert(argc == 2);
	string configPath = argv[1];

	ifstream configStream(configPath);
	if (!configStream) throw "Unable to read config file!";

	/// Parse the config file
	std::string configData((std::istreambuf_iterator<char>(configStream)), std::istreambuf_iterator<char>());
	nlohmann::json rawJson = nlohmann::json::parse(configData);
	hardware_config config;
	string jocsPath = rawJson["jocsPath"];
	vector<unsigned> activeids = rawJson["jocsActiveIds"];
	jocsActiveIds = activeids;
	bool useMocap = rawJson["useMocap"];
	float scale = rawJson["theaterScale"];
	bool enableMessaging = rawJson["enableMessaging"];
	bool enableOSC = rawJson["enableOSC"];

	if (useMocap) {
		nlohmann::json hardwareConfig = rawJson["hardwareConfig"];
		config.clientAddress = hardwareConfig["clientAddress"];
		config.serverAddress = hardwareConfig["serverAddress"];
	}

	vconfigs.resize(rawJson["vehicles"].size());
	for(unsigned i = 0; i < rawJson["vehicles"].size(); i++) {
		vconfigs[i].net_id = rawJson["vehicles"][i]["net_id"];
		if(useMocap) {
			vconfigs[i].lport = 14550 + 10*vconfigs[i].net_id;
			vconfigs[i].rport = 14555;
		}
		else { // The simulated ones are zero-indexed and
			vconfigs[i].lport = 14550 + 10*(vconfigs[i].net_id - 1);
			vconfigs[i].rport = 14555 + 10*(vconfigs[i].net_id - 1);
		}
	}

	Jocs *jocs = Jocs::Parse(jocsPath, scale);

	auto homes = jocs->GetHomes();

	// Only pay attention to homes of active drones
	std::vector<Point> spawns;
	for (int i = 0; i < jocsActiveIds.size(); i++) {
		int chosenId = jocsActiveIds[i];
		// We assume the user only configured for valid IDs..
		spawns.push_back(homes[chosenId]);
		spawns[i].z() = 0;
	}

	tansa::init(enableMessaging);

	if(enableMessaging) {
		tansa::on_message(socket_on_message);
	}

	Mocap *mocap = nullptr;
	GazeboConnector *gazebo = nullptr;

	// Only pay attention to homes of active drones
	// TODO: Have a better check for mocap initialization/health
	if (useMocap) {
		mocap = new Mocap();
		mocap->connect(config.clientAddress, config.serverAddress);
	} else {
		gazebo = new GazeboConnector();
		gazebo->connect();
		gazebo->spawn(spawns);
	}

	int n = spawns.size();

	if (n > vconfigs.size()) {
		printf("Not enough drones on the network\n");
		return 1;
	}

	vehicles.resize(n);

	for(int i = 0; i < n; i++) {
		const vehicle_config &v = vconfigs[i];

		vehicles[i] = new Vehicle();

		// Load default parameters
		vehicles[i]->readParams("./config/params/default.json");
		// TODO: Also read in per-drone ones

		vehicles[i]->connect(v.lport, v.rport);
		if (useMocap) {
			mocap->track(vehicles[i], i+1);
		} else {
			gazebo->track(vehicles[i], i);
		}
	}

	if(enableOSC) {
		OSC *osc = new OSC();
		osc->start(53100);
		osc->set_listener(osc_on_message);
	}

	player = new JocsPlayer(vehicles, jocsActiveIds);
	player->loadJocs(jocs);

	running = true;
	signal(SIGINT, signal_sigint);

	int i = 0;

	/*
	// For sample lighting demo
	float level = 0;
	float dl = 0.005;
	*/

	signal(SIGINT, signal_sigint);
	printf("running...\n");
	running = true;

	console_start();

	Rate r(100);
	while(running) {

		// Regular status messages
		if(enableMessaging && i % 20 == 0) {
			send_status_message();
		}

		if (killmode) {
			for(Vehicle *v : vehicles)
				v->terminate();
		} else if (playMode) {
			playMode = false;
			player->play();
		} else if (pauseMode) {
			pauseMode = false;
			player->pause();
		} else if (stopMode) {
			stopMode = false;
			player->stop();
		} else {
			player->step();
		}

		r.sleep();
		i++;
	}

	/// Cleanup
	if (useMocap) {
		mocap->disconnect();
		delete mocap;
	} else {
		gazebo->disconnect();
		delete gazebo;
	}

	// Stop all vehicles
	for(int vi = 0; vi < n; vi++) {
		Vehicle *v = vehicles[vi];
		v->disconnect();
		delete v;
	}

	player->cleanup();

	printf("Done!\n");
}
<commit_msg>Cleaned up jocs file listing and some other related style issues<commit_after>#include <tansa/action.h>
#include <tansa/control.h>
#include <tansa/core.h>
#include <tansa/jocsParser.h>
#include <tansa/config.h>
#include <tansa/jocsPlayer.h>
#include <tansa/mocap.h>
#include <tansa/gazebo.h>
#include <tansa/osc.h>

#ifdef  __linux__
#include <sys/signal.h>
#endif
//TODO check if these work on OSX
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <iostream>

using namespace std;
using namespace tansa;

static bool running;
static bool killmode = false;
static bool pauseMode = false;
static bool stopMode = false;
static bool playMode = false;
static JocsPlayer* player;
static vector<Vehicle *> vehicles;
static std::vector<vehicle_config> vconfigs;
static vector<unsigned> jocsActiveIds;

void signal_sigint(int s) {
	// TODO: Prevent
	running = false;
}

/* For sending a system state update to the gui */
void send_status_message() {

	json j;

	j["type"] = "status";
	j["time"] = player->currentTime();

	json vehs = json::array();
	for(int i = 0; i < vehicles.size(); i++) {
		json v;
		v["id"] = vconfigs[i].net_id;
		v["role"] = i <= jocsActiveIds.size() - 1? jocsActiveIds[i] : -1;
		v["connected"] = vehicles[i]->connected;
		v["armed"] = vehicles[i]->armed;
		v["tracking"] = vehicles[i]->tracking;

		json pos = json::array();
		pos.push_back(vehicles[i]->state.position.x());
		pos.push_back(vehicles[i]->state.position.y());
		pos.push_back(vehicles[i]->state.position.z());
		v["position"] = pos;

		json bat = {
			{"voltage", vehicles[i]->battery.voltage},
			{"percent", vehicles[i]->battery.percent}
		};
		v["battery"] = bat;

		vehs.push_back(v);
	}
	j["vehicles"] = vehs;

	json global;
	global["playing"] = player->isPlaying();
	global["ready"] = player->isReady();
	j["global"] = global;

	tansa::send_message(j);
}

void send_file_list() {
	json j;

	j["type"] = "list_reply";
	json files = json::array();
	DIR *dir;
	struct dirent *ent;
	if ((dir = opendir ("data")) != NULL) {
		while ((ent = readdir (dir)) != NULL) {
			if(ent->d_type == DT_REG && std::string(ent->d_name).find(".jocs") != std::string::npos)
				files.push_back(std::string(ent->d_name));
		}
		closedir (dir);
	} else {
		/* could not open directory */
		//TODO Do something intelligent here
	}
	j["files"] = files;
	tansa::send_message(j);
}

void socket_on_message(const json &data) {

	string type = data["type"];

	if(type == "prepare") {
		printf("Preparing...\n");
		player->prepare();
	} else if(type == "play") {
		printf("Playing...\n");
		playMode = true;
	} else if(type == "land") {
		player->land();
	} else if (type == "pause") {
		printf("Pausing...\n");
		pauseMode = true;
	} else if (type == "stop") {
		printf("Stopping...\n");
		stopMode = true;
	} else if (type == "reset") {
		printf("Resetting...\n");
	} else if (type == "list"){
		printf("Sending file list...\n");
		send_file_list();
	} else if (type == "load"){
		printf("Loading jocs file...\n")
	} else if(type == "kill") {
		bool enabled = data["enabled"];
		printf("Killing...\n");
		killmode = enabled;
	} else {
		// TODO: Send an error message back to the browser
		printf("Unexpected message type recieved!\n");
	}
}

void osc_on_message(OSCMessage &msg) {

	// Address will look something like: '/cue/0101/start'
	if(msg.address[0] == "cue") {

		int num = std::stoi(msg.address[1]);

		if(msg.address[2] == "load") {
			player->prepare();
		}
		else if(msg.address[2] == "start") {
			printf("Starting at cue #: %d\n", num);

			// Assert that it is already prepared at the given cue

			player->play();
		}

	}

	/*
	printf("Address:\n");
	for(auto str : msg.address)
		printf("- %s\n", str.c_str());

	printf("\nArgs:\n");
	for(auto str : msg.args)
		printf("- %s\n", str.c_str());
	*/

}

pthread_t console_handle;

void *console_thread(void *arg) {

	while(running) {

		// Read a command
		cout << "> ";
		string line;
		getline(cin, line);

		// Split into arguments
		vector<string> args;
		istringstream iss(line);
		while(!iss.eof()) {
			string a;
			iss >> a;

			if(iss.fail())
				break;

			args.push_back(a);
		}

		if(args.size() == 0)
			continue;

		if (args[0] == "prepare") {
			cout << "Preparing..." << endl;
			player->prepare();
		} else if (args[0] == "play") {
			cout << "Playing..." << endl;
			playMode = true;
		} else if (args[0] == "pause") {
			cout << "Pausing..." << endl;
			pauseMode = true;
		} else if (args[0] == "stop") {
			cout << "Stopping..." << endl;
			stopMode = true;
		} else if (args[0] == "land") {
			cout << "Landing..." << endl;
			player->land();
		} else if (args[0] == "kill") {
			killmode = args.size() <= 1 || !(args[1] == "off");
		}

	}

}

void console_start() {
	pthread_create(&console_handle, NULL, console_thread, NULL);
}

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

	assert(argc == 2);
	string configPath = argv[1];

	ifstream configStream(configPath);
	if (!configStream) throw "Unable to read config file!";

	/// Parse the config file
	std::string configData((std::istreambuf_iterator<char>(configStream)), std::istreambuf_iterator<char>());
	nlohmann::json rawJson = nlohmann::json::parse(configData);
	hardware_config config;
	string jocsPath = rawJson["jocsPath"];
	vector<unsigned> activeids = rawJson["jocsActiveIds"];
	jocsActiveIds = activeids;
	bool useMocap = rawJson["useMocap"];
	float scale = rawJson["theaterScale"];
	bool enableMessaging = rawJson["enableMessaging"];
	bool enableOSC = rawJson["enableOSC"];

	if (useMocap) {
		nlohmann::json hardwareConfig = rawJson["hardwareConfig"];
		config.clientAddress = hardwareConfig["clientAddress"];
		config.serverAddress = hardwareConfig["serverAddress"];
	}

	vconfigs.resize(rawJson["vehicles"].size());
	for(unsigned i = 0; i < rawJson["vehicles"].size(); i++) {
		vconfigs[i].net_id = rawJson["vehicles"][i]["net_id"];
		if(useMocap) {
			vconfigs[i].lport = 14550 + 10*vconfigs[i].net_id;
			vconfigs[i].rport = 14555;
		}
		else { // The simulated ones are zero-indexed and
			vconfigs[i].lport = 14550 + 10*(vconfigs[i].net_id - 1);
			vconfigs[i].rport = 14555 + 10*(vconfigs[i].net_id - 1);
		}
	}

	Jocs *jocs = Jocs::Parse(jocsPath, scale);

	auto homes = jocs->GetHomes();

	// Only pay attention to homes of active drones
	std::vector<Point> spawns;
	for (int i = 0; i < jocsActiveIds.size(); i++) {
		int chosenId = jocsActiveIds[i];
		// We assume the user only configured for valid IDs..
		spawns.push_back(homes[chosenId]);
		spawns[i].z() = 0;
	}

	tansa::init(enableMessaging);

	if(enableMessaging) {
		tansa::on_message(socket_on_message);
	}

	Mocap *mocap = nullptr;
	GazeboConnector *gazebo = nullptr;

	// Only pay attention to homes of active drones
	// TODO: Have a better check for mocap initialization/health
	if (useMocap) {
		mocap = new Mocap();
		mocap->connect(config.clientAddress, config.serverAddress);
	} else {
		gazebo = new GazeboConnector();
		gazebo->connect();
		gazebo->spawn(spawns);
	}

	int n = spawns.size();

	if (n > vconfigs.size()) {
		printf("Not enough drones on the network\n");
		return 1;
	}

	vehicles.resize(n);

	for(int i = 0; i < n; i++) {
		const vehicle_config &v = vconfigs[i];

		vehicles[i] = new Vehicle();

		// Load default parameters
		vehicles[i]->readParams("./config/params/default.json");
		// TODO: Also read in per-drone ones

		vehicles[i]->connect(v.lport, v.rport);
		if (useMocap) {
			mocap->track(vehicles[i], i+1);
		} else {
			gazebo->track(vehicles[i], i);
		}
	}

	if(enableOSC) {
		OSC *osc = new OSC();
		osc->start(53100);
		osc->set_listener(osc_on_message);
	}

	player = new JocsPlayer(vehicles, jocsActiveIds);
	player->loadJocs(jocs);

	running = true;
	signal(SIGINT, signal_sigint);

	int i = 0;

	/*
	// For sample lighting demo
	float level = 0;
	float dl = 0.005;
	*/

	signal(SIGINT, signal_sigint);
	printf("running...\n");
	running = true;

	console_start();

	Rate r(100);
	while(running) {

		// Regular status messages
		if(enableMessaging && i % 20 == 0) {
			send_status_message();
		}

		if (killmode) {
			for(Vehicle *v : vehicles)
				v->terminate();
		} else if (playMode) {
			playMode = false;
			player->play();
		} else if (pauseMode) {
			pauseMode = false;
			player->pause();
		} else if (stopMode) {
			stopMode = false;
			player->stop();
		} else {
			player->step();
		}

		r.sleep();
		i++;
	}

	/// Cleanup
	if (useMocap) {
		mocap->disconnect();
		delete mocap;
	} else {
		gazebo->disconnect();
		delete gazebo;
	}

	// Stop all vehicles
	for(int vi = 0; vi < n; vi++) {
		Vehicle *v = vehicles[vi];
		v->disconnect();
		delete v;
	}

	player->cleanup();

	printf("Done!\n");
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) Jason White
 *
 * MIT License
 *
 * Description:
 * Globbing.
 */
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <unistd.h>

#include <string>
#include <set>

#include "lua.hpp"

#include "glob.h"
#include "path.h"

namespace {

/**
 * Compare a character with case sensitivity or not.
 */
template <bool CaseSensitive>
static int charCmp(char a, char b) {
    if (CaseSensitive)
        return (int)a - (int)b;
    else
        return (int)tolower(a) - (int)tolower(b);
}

/**
 * Returns true if the pattern matches the given filename, false otherwise.
 */
template <bool CaseSensitive>
bool globMatch(path::Path path, path::Path pattern) {

    size_t i = 0;

    for (size_t j = 0; j < pattern.length; ++j) {
        switch (pattern.path[j]) {
            case '?': {
                // Match any single character
                if (i == path.length)
                    return false;
                ++i;
                break;
            }

            case '*': {
                // Match 0 or more characters
                if (j+1 == pattern.length)
                    return true;

                // Consume characters while looking ahead for matches
                for (; i < path.length; ++i) {
                    if (globMatch<CaseSensitive>(
                                path::Path(path.path+i, path.length-i),
                                path::Path(pattern.path+j+1, pattern.length-j-1)))
                        return true;
                }

                return false;
            }

            case '[': {
                // Match any of the characters that appear in the square brackets
                if (i == path.length) return false;

                // Skip past the opening bracket
                if (++j == pattern.length) return false;

                // Invert the match?
                bool invert = false;
                if (pattern.path[j] == '!') {
                    invert = true;
                    if (++j == pattern.length)
                        return false;
                }

                // Find the closing bracket
                size_t end = j;
                while (end < pattern.length && pattern.path[end] != ']')
                    ++end;

                // No matching bracket?
                if (end == pattern.length) return false;

                // Check each character between the brackets for a match
                bool match = false;
                while (j < end) {
                    // Found a match
                    if (!match && charCmp<CaseSensitive>(path.path[i], pattern.path[j]) == 0) {
                        match = true;
                    }

                    ++j;
                }

                if (match == invert)
                    return false;

                ++i;
                break;
            }

            default: {
                // Match the next character in the pattern
                if (i == path.length || charCmp<CaseSensitive>(path.path[i], pattern.path[j]))
                    return false;
                ++i;
                break;
            }
        }
    }

    // If we ran out of pattern and out of path, then we have a complete match.
    return i == path.length;
}

bool globMatch(path::Path path, path::Path pattern) {
#ifdef _WIN32
    return globMatch<false>(path, pattern);
#else
    return globMatch<true>(path, pattern);
#endif
}

/**
 * Returns true if the given string contains a glob pattern.
 */
bool isGlobPattern(path::Path p) {
    for (size_t i = 0; i < p.length; ++i) {
        switch (p.path[i]) {
            case '?':
            case '*':
            case '[':
                return true;
        }
    }

    return false;
}

/**
 * Returns true if the given path element is a recursive glob pattern.
 */
bool isRecursiveGlob(path::Path p) {
    return p.length == 2 && p.path[0] == '*' && p.path[1] == '*';
}

/**
 * Returns true if the given path element is a hidden directory (i.e., "." or
 * "..").
 */
bool isHiddenDir(const char* s, size_t len) {
    switch (len) {
        case 1:
            return s[0] == '.';
        case 2:
            return s[0] == '.' && s[1] == '.';
        default:
            return false;
    }
}

typedef void (*GlobCallback)(path::Path path, bool isDir, void* data);

struct GlobClosure {
    path::Path pattern;

    // Next callback
    GlobCallback next;
    void* nextData;
};

/**
 * Helper function for listing a directory with the given pattern. If the
 * pattern is empty,
 */
void glob(path::Path path, path::Path pattern,
          GlobCallback callback, void* data) {

    std::string buf(path.path, path.length);

    if (pattern.length == 0) {
        path::join(buf, pattern);
        callback(path::Path(buf.data(), buf.size()), true, data);
        return;
    }

    struct dirent* entry;
    DIR* dir = opendir(path.length > 0 ? buf.c_str() : ".");
    if (!dir)
        return;

    // TODO: Implement this for windows, too.
    while ((entry = readdir(dir))) {
        const char* name = entry->d_name;
        size_t nameLength = strlen(entry->d_name);
        bool isDir = entry->d_type == DT_DIR;

        if (isHiddenDir(name, nameLength))
            continue;

        if (globMatch(path::Path(name, nameLength), pattern)) {
            path::join(buf, path::Path(entry->d_name, nameLength));

            callback(path::Path(buf.data(), buf.size()), isDir, data);

            buf.assign(path.path, path.length);
        }
    }

    closedir(dir);
}

/**
 * Helper function to recursively yield directories for the given path.
 */
void globRecursive(std::string& path, GlobCallback callback, void* data) {

    size_t len = path.size();

    struct dirent* entry;
    DIR* dir = opendir(len > 0 ? path.c_str() : ".");
    if (!dir)
        return;

    // "**" matches 0 or more directories and thus includes this one.
    callback(path::Path(path.data(), path.size()), true, data);

    // TODO: Implement this for windows, too.
    while ((entry = readdir(dir))) {
        const char* name = entry->d_name;
        size_t nameLength = strlen(entry->d_name);
        bool isDir = entry->d_type == DT_DIR;

        if (isHiddenDir(name, nameLength))
            continue;

        path::join(path, path::Path(entry->d_name, nameLength));

        callback(path::Path(path.data(), path.size()), isDir, data);

        if (isDir)
            globRecursive(path, callback, data);

        path.resize(len);
    }

    closedir(dir);
}

void globCallback(path::Path path, bool isDir, void* data) {
    if (isDir) {
        const GlobClosure* c = (const GlobClosure*)data;
        glob(path, c->pattern, c->next, c->nextData);
    }
}

/**
 * Glob a directory.
 */
void glob(path::Path path, GlobCallback callback, void* data = NULL) {

    path::Split s = path::split(path);

    if (isGlobPattern(s.head)) {
        // Directory name contains a glob pattern

        GlobClosure c;
        c.pattern = s.tail;
        c.next = callback;
        c.nextData = data;

        glob(s.head, &globCallback, &c);
    }
    else if (isRecursiveGlob(s.tail)) {
        std::string buf(s.head.path, s.head.length);
        globRecursive(buf, callback, data);
    }
    else if (isGlobPattern(s.tail)) {
        // Only base name contains a glob pattern.
        glob(s.head, s.tail, callback, data);
    }
    else {
        // No glob pattern in this path.
        if (s.tail.length) {
            // TODO: If file exists, then return it
            callback(path, false, data);
        }
        else {
            // TODO: If directory exists, then return it
            callback(s.head, true, data);
        }
    }
}

/**
 * Callback to put globbed items into a set.
 */
void fs_globcallback(path::Path path, bool isDir, void* data) {
    std::set<std::string>* paths = (std::set<std::string>*)data;
    paths->insert(std::string(path.path, path.length));
}

/**
 * Callback to remove globbed items from a set.
 */
void fs_globcallback_exclude(path::Path path, bool isDir, void* data) {
    std::set<std::string>* paths = (std::set<std::string>*)data;
    paths->erase(std::string(path.path, path.length));
}

/**
 * Lua wrapper to prepend the current script directory to the requested path.
 */
void glob(lua_State* L, path::Path path, GlobCallback callback, void* data) {

    // Join the SCRIPT_DIR with this path.
    lua_getglobal(L, "path");
    lua_getfield(L, -1, "join");
    lua_getglobal(L, "SCRIPT_DIR");
    lua_pushlstring(L, path.path, path.length);
    lua_call(L, 2, 1);

    size_t len;
    const char* scriptDir = lua_tolstring(L, -1, &len);

    if (scriptDir)
        glob(path::Path(scriptDir, len), callback, data);

    lua_pop(L, 2); // Pop new path and path table
}

} // anonymous namespace

int lua_glob_match(lua_State* L) {
    size_t len, patlen;
    const char* path = luaL_checklstring(L, 1, &len);
    const char* pattern = luaL_checklstring(L, 2, &patlen);
    lua_pushboolean(L, globMatch(path::Path(path, len), path::Path(pattern, patlen)));
    return 1;
}

int lua_glob(lua_State* L) {

    // TODO: Cache results of a directory listing and use that for further globs.

    std::set<std::string> paths;

    int argc = lua_gettop(L);

    size_t len;
    const char* path;

    for (int i = 1; i <= argc; ++i) {
        const int type = lua_type(L, i);

        if (type == LUA_TTABLE) {
            for (int j = 1; ; ++j) {
                if (lua_rawgeti(L, i, j) == LUA_TNIL) {
                    lua_pop(L, 1);
                    break;
                }

                path = lua_tolstring(L, -1, &len);
                if (path) {
                    if (len > 0 && path[0] == '!')
                        glob(L, path::Path(path+1, len-1), &fs_globcallback_exclude, &paths);
                    else
                        glob(L, path::Path(path, len), &fs_globcallback, &paths);
                }

                lua_pop(L, 1); // Pop path
            }
        }
        else if (type == LUA_TSTRING) {
            path = luaL_checklstring(L, i, &len);

            if (len > 0 && path[0] == '!')
                glob(L, path::Path(path+1, len-1), &fs_globcallback_exclude, &paths);
            else
                glob(L, path::Path(path, len), &fs_globcallback, &paths);
        }
    }

    // Construct the Lua table.
    lua_newtable(L);
    lua_Number n = 1;

    for (std::set<std::string>::iterator it = paths.begin(); it != paths.end(); ++it) {
        lua_pushlstring(L, it->data(), it->size());
        lua_seti(L, -2, n);
        ++n;
    }

    return 1;
}
<commit_msg>Fallback to stat() if DT_DIR is not available<commit_after>/**
 * Copyright (c) Jason White
 *
 * MIT License
 *
 * Description:
 * Globbing.
 */
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <dirent.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>

#include <string>
#include <set>

#include "lua.hpp"

#include "glob.h"
#include "path.h"

namespace {

/**
 * Compare a character with case sensitivity or not.
 */
template <bool CaseSensitive>
static int charCmp(char a, char b) {
    if (CaseSensitive)
        return (int)a - (int)b;
    else
        return (int)tolower(a) - (int)tolower(b);
}

/**
 * Returns true if the pattern matches the given filename, false otherwise.
 */
template <bool CaseSensitive>
bool globMatch(path::Path path, path::Path pattern) {

    size_t i = 0;

    for (size_t j = 0; j < pattern.length; ++j) {
        switch (pattern.path[j]) {
            case '?': {
                // Match any single character
                if (i == path.length)
                    return false;
                ++i;
                break;
            }

            case '*': {
                // Match 0 or more characters
                if (j+1 == pattern.length)
                    return true;

                // Consume characters while looking ahead for matches
                for (; i < path.length; ++i) {
                    if (globMatch<CaseSensitive>(
                                path::Path(path.path+i, path.length-i),
                                path::Path(pattern.path+j+1, pattern.length-j-1)))
                        return true;
                }

                return false;
            }

            case '[': {
                // Match any of the characters that appear in the square brackets
                if (i == path.length) return false;

                // Skip past the opening bracket
                if (++j == pattern.length) return false;

                // Invert the match?
                bool invert = false;
                if (pattern.path[j] == '!') {
                    invert = true;
                    if (++j == pattern.length)
                        return false;
                }

                // Find the closing bracket
                size_t end = j;
                while (end < pattern.length && pattern.path[end] != ']')
                    ++end;

                // No matching bracket?
                if (end == pattern.length) return false;

                // Check each character between the brackets for a match
                bool match = false;
                while (j < end) {
                    // Found a match
                    if (!match && charCmp<CaseSensitive>(path.path[i], pattern.path[j]) == 0) {
                        match = true;
                    }

                    ++j;
                }

                if (match == invert)
                    return false;

                ++i;
                break;
            }

            default: {
                // Match the next character in the pattern
                if (i == path.length || charCmp<CaseSensitive>(path.path[i], pattern.path[j]))
                    return false;
                ++i;
                break;
            }
        }
    }

    // If we ran out of pattern and out of path, then we have a complete match.
    return i == path.length;
}

bool globMatch(path::Path path, path::Path pattern) {
#ifdef _WIN32
    return globMatch<false>(path, pattern);
#else
    return globMatch<true>(path, pattern);
#endif
}

/**
 * Returns true if the given string contains a glob pattern.
 */
bool isGlobPattern(path::Path p) {
    for (size_t i = 0; i < p.length; ++i) {
        switch (p.path[i]) {
            case '?':
            case '*':
            case '[':
                return true;
        }
    }

    return false;
}

/**
 * Returns true if the given path element is a recursive glob pattern.
 */
bool isRecursiveGlob(path::Path p) {
    return p.length == 2 && p.path[0] == '*' && p.path[1] == '*';
}

/**
 * Returns true if the given path element is a hidden directory (i.e., "." or
 * "..").
 */
bool isHiddenDir(const char* s, size_t len) {
    switch (len) {
        case 1:
            return s[0] == '.';
        case 2:
            return s[0] == '.' && s[1] == '.';
        default:
            return false;
    }
}

typedef void (*GlobCallback)(path::Path path, bool isDir, void* data);

struct GlobClosure {
    path::Path pattern;

    // Next callback
    GlobCallback next;
    void* nextData;
};

/**
 * Helper function for listing a directory with the given pattern. If the
 * pattern is empty,
 */
void glob(path::Path path, path::Path pattern,
          GlobCallback callback, void* data) {

    std::string buf(path.path, path.length);

    if (pattern.length == 0) {
        path::join(buf, pattern);
        callback(path::Path(buf.data(), buf.size()), true, data);
        return;
    }

    struct dirent* entry;
    DIR* dir = opendir(path.length > 0 ? buf.c_str() : ".");
    if (!dir)
        return;

    // TODO: Implement this for windows, too.
    while ((entry = readdir(dir))) {
        const char* name = entry->d_name;
        size_t nameLength = strlen(entry->d_name);

        bool isDir;

        if (entry->d_type == DT_UNKNOWN) {
            struct stat statbuf;
            if (fstatat(dirfd(dir), entry->d_name, &statbuf, 0) == 0)
                isDir = (statbuf.st_mode & S_IFMT) == S_IFDIR;
            else
                isDir = false;
        }
        else {
            isDir = entry->d_type == DT_DIR;
        }

        if (isHiddenDir(name, nameLength))
            continue;

        if (globMatch(path::Path(name, nameLength), pattern)) {
            path::join(buf, path::Path(entry->d_name, nameLength));

            callback(path::Path(buf.data(), buf.size()), isDir, data);

            buf.assign(path.path, path.length);
        }
    }

    closedir(dir);
}

/**
 * Helper function to recursively yield directories for the given path.
 */
void globRecursive(std::string& path, GlobCallback callback, void* data) {

    size_t len = path.size();

    struct dirent* entry;
    DIR* dir = opendir(len > 0 ? path.c_str() : ".");
    if (!dir)
        return;

    // "**" matches 0 or more directories and thus includes this one.
    callback(path::Path(path.data(), path.size()), true, data);

    // TODO: Implement this for windows, too.
    while ((entry = readdir(dir))) {
        const char* name = entry->d_name;
        size_t nameLength = strlen(entry->d_name);

        bool isDir;

        if (entry->d_type == DT_UNKNOWN) {
            struct stat statbuf;
            if (fstatat(dirfd(dir), entry->d_name, &statbuf, 0) == 0)
                isDir = (statbuf.st_mode & S_IFMT) == S_IFDIR;
            else
                isDir = false;
        }
        else {
            isDir = entry->d_type == DT_DIR;
        }

        if (isHiddenDir(name, nameLength))
            continue;

        path::join(path, path::Path(entry->d_name, nameLength));

        callback(path::Path(path.data(), path.size()), isDir, data);

        if (isDir)
            globRecursive(path, callback, data);

        path.resize(len);
    }

    closedir(dir);
}

void globCallback(path::Path path, bool isDir, void* data) {
    if (isDir) {
        const GlobClosure* c = (const GlobClosure*)data;
        glob(path, c->pattern, c->next, c->nextData);
    }
}

/**
 * Glob a directory.
 */
void glob(path::Path path, GlobCallback callback, void* data = NULL) {

    path::Split s = path::split(path);

    if (isGlobPattern(s.head)) {
        // Directory name contains a glob pattern

        GlobClosure c;
        c.pattern = s.tail;
        c.next = callback;
        c.nextData = data;

        glob(s.head, &globCallback, &c);
    }
    else if (isRecursiveGlob(s.tail)) {
        std::string buf(s.head.path, s.head.length);
        globRecursive(buf, callback, data);
    }
    else if (isGlobPattern(s.tail)) {
        // Only base name contains a glob pattern.
        glob(s.head, s.tail, callback, data);
    }
    else {
        // No glob pattern in this path.
        if (s.tail.length) {
            // TODO: If file exists, then return it
            callback(path, false, data);
        }
        else {
            // TODO: If directory exists, then return it
            callback(s.head, true, data);
        }
    }
}

/**
 * Callback to put globbed items into a set.
 */
void fs_globcallback(path::Path path, bool isDir, void* data) {
    std::set<std::string>* paths = (std::set<std::string>*)data;
    paths->insert(std::string(path.path, path.length));
}

/**
 * Callback to remove globbed items from a set.
 */
void fs_globcallback_exclude(path::Path path, bool isDir, void* data) {
    std::set<std::string>* paths = (std::set<std::string>*)data;
    paths->erase(std::string(path.path, path.length));
}

/**
 * Lua wrapper to prepend the current script directory to the requested path.
 */
void glob(lua_State* L, path::Path path, GlobCallback callback, void* data) {

    // Join the SCRIPT_DIR with this path.
    lua_getglobal(L, "path");
    lua_getfield(L, -1, "join");
    lua_getglobal(L, "SCRIPT_DIR");
    lua_pushlstring(L, path.path, path.length);
    lua_call(L, 2, 1);

    size_t len;
    const char* scriptDir = lua_tolstring(L, -1, &len);

    if (scriptDir)
        glob(path::Path(scriptDir, len), callback, data);

    lua_pop(L, 2); // Pop new path and path table
}

} // anonymous namespace

int lua_glob_match(lua_State* L) {
    size_t len, patlen;
    const char* path = luaL_checklstring(L, 1, &len);
    const char* pattern = luaL_checklstring(L, 2, &patlen);
    lua_pushboolean(L, globMatch(path::Path(path, len), path::Path(pattern, patlen)));
    return 1;
}

int lua_glob(lua_State* L) {

    // TODO: Cache results of a directory listing and use that for further globs.

    std::set<std::string> paths;

    int argc = lua_gettop(L);

    size_t len;
    const char* path;

    for (int i = 1; i <= argc; ++i) {
        const int type = lua_type(L, i);

        if (type == LUA_TTABLE) {
            for (int j = 1; ; ++j) {
                if (lua_rawgeti(L, i, j) == LUA_TNIL) {
                    lua_pop(L, 1);
                    break;
                }

                path = lua_tolstring(L, -1, &len);
                if (path) {
                    if (len > 0 && path[0] == '!')
                        glob(L, path::Path(path+1, len-1), &fs_globcallback_exclude, &paths);
                    else
                        glob(L, path::Path(path, len), &fs_globcallback, &paths);
                }

                lua_pop(L, 1); // Pop path
            }
        }
        else if (type == LUA_TSTRING) {
            path = luaL_checklstring(L, i, &len);

            if (len > 0 && path[0] == '!')
                glob(L, path::Path(path+1, len-1), &fs_globcallback_exclude, &paths);
            else
                glob(L, path::Path(path, len), &fs_globcallback, &paths);
        }
    }

    // Construct the Lua table.
    lua_newtable(L);
    lua_Number n = 1;

    for (std::set<std::string>::iterator it = paths.begin(); it != paths.end(); ++it) {
        lua_pushlstring(L, it->data(), it->size());
        lua_seti(L, -2, n);
        ++n;
    }

    return 1;
}
<|endoftext|>


<commit_before>#ifndef GUI_HPP
#define GUI_HPP

#endif // GUI_HPP
<commit_msg>Delete useless files<commit_after><|endoftext|>


<commit_before>#include <iostream>
#include <stdio.h>
#include <ctype.h>
#include <cstring>
#include <vector>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/wait.h>
using namespace std;

void parse(char  x[], vector<string> &v){
    //cout << "parse executes" << endl;
    char* tmp;
    tmp = strtok(x, " ");
    while(tmp != NULL){
        v.push_back(tmp);
        //cout << "*" << tmp << "*" << endl;
        tmp = strtok(NULL, " ");
    }
}

bool isExit(char x[]){
    string tmp = x;
    string ext = "exit";
    int e = tmp.find('e');
    int t = tmp.find('t', e);
    if(e == -1 || t == -1){
        return false;
    }
    int k = 0;
    for(int i = e; i < t + 1; i++){
        if(tmp.at(i) != ext.at(k)){
            return false;
        }
        k++;
    }
    return true;
}

bool run(char str[]){
    char* pch;
    bool sucs = true;
    int status = 0;
    string ext = "exit";
    string connector;
    string strz = str;
    vector<string> cmd;
    pch = strtok(str, ";");
    if(pch==NULL){
        return true;
    }

    else if(pch != strz){
        connector = ";";
    }

    if(pch == strz){
        pch = strtok(str, "&&");
        if(pch == NULL){
            return true;
        }
        if(pch != strz){
            connector = "&&";
        }
    }

    if(pch == strz){
        pch = strtok(str, "||");
        if(pch == NULL){
            return true;
        }
        if(pch != strz){
            connector = "||";
        }
    }

    if(pch != NULL && isExit(pch)){
        exit(0);
    }
    while(pch != NULL){
        //cout << "execvp executes" << endl;
            int pid = fork();
            if(pid == -1){
                perror("fork");
                exit(1);
            }
            if(pid == 0){
                parse(pch, cmd);
                char* argc[cmd.size() + 1];
                 for(int i = 0 ; i < cmd.size(); i++ ){
                	 argc[i] = new char[cmd.at(i).size()];
                	 strcpy(argc[i], cmd.at(i).c_str());
                 }
                 argc[cmd.size()] = NULL;
                 if(-1 ==  execvp(argc[0], argc)){
                    perror("execvp");
                    exit(1);
                 }
            }
            else{
                waitpid(-1, &status, 0);
                //cout << status << endl;
                if(status > 0){
                    sucs = false;
                }
                else{
                    sucs = true;
                }
	            cmd.clear();
                if((connector=="&&" && sucs) || (connector=="||" && !sucs) || (connector==";")){
                    pch = strtok(NULL, connector.c_str());
                }
                else{
                    return true;
                }
                if(pch != NULL && isExit(pch)){
                        exit(0);
                }
            }
   }
   return true;
}

int main(){
   bool goon = true;
   while(goon){
       string input;
       cout << "$ ";
       getline(cin, input);
       char str[input.size()+1];
       strcpy(str, input.c_str());
       goon = run(str);
   }
   return 0;
}
<commit_msg>added comments<commit_after>#include <iostream>
#include <stdio.h>
#include <ctype.h>
#include <cstring>
#include <vector>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/wait.h>
using namespace std;

void parse(char  x[], vector<string> &v){
    //cout << "parse executes" << endl;
    char* tmp;
    tmp = strtok(x, " ");
    while(tmp != NULL){
        v.push_back(tmp);
        //cout << tmp << endl;
        tmp = strtok(NULL, " ");
    }
}

bool isExit(char x[]){
    string tmp = x;
    string ext = "exit";
    int e = tmp.find('e');
    int t = tmp.find('t', e);
    if(e == -1 || t == -1){
        return false;
    }
    int k = 0;
    for(int i = e; i < t + 1; i++){
        if(tmp.at(i) != ext.at(k)){
            return false;
        }
        k++;
    }
    return true;
}

string commentRemoval(string x){
    int comm = x.find('#');
    if(comm == -1){
        return x;
    }
    else if(comm == 0){
        return "";
    }
    else{
        return x.substr(0, comm);
    }
}

bool run(char str[]){
    char* pch;
    bool sucs = true;
    int status = 0;
    string ext = "exit";
    string connector;
    string strz = str;
    vector<string> cmd;
    pch = strtok(str, ";");
    if(pch==NULL){
        return true;
    }

    else if(pch != strz){
        connector = ";";
    }

    if(pch == strz){
        pch = strtok(str, "&&");
        if(pch == NULL){
            return true;
        }
        if(pch != strz){
            connector = "&&";
        }
    }

    if(pch == strz){
        pch = strtok(str, "||");
        if(pch == NULL){
            return true;
        }
        if(pch != strz){
            connector = "||";
        }
    }

    if(pch != NULL && isExit(pch)){
        exit(0);
    }
    while(pch != NULL){
        //cout << "execvp executes" << endl;
            int pid = fork();
            if(pid == -1){
                exit(1);
            }
            else if(pid == 0){
                parse(pch, cmd);
                char* argc[cmd.size() + 1];
                 for(int i = 0 ; i < cmd.size(); i++ ){
                	 argc[i] = new char[cmd.at(i).size()];
                	 strcpy(argc[i], cmd.at(i).c_str());
                 }
                 argc[cmd.size()] = NULL;
                 if(-1 ==  execvp(argc[0], argc)){
                    perror("execvp");
                    exit(1);
                 }
            }
            else{
                waitpid(-1, &status, 0);
                //cout << status << endl;
                if(status > 0){
                    sucs = false;
                }
                else{
                    sucs = true;
                }
	            cmd.clear();
                if((connector=="&&" && sucs) || (connector=="||" && !sucs) || (connector==";")){
                    pch = strtok(NULL, connector.c_str());
                }
                else{
                    return true;
                }
                if(pch != NULL && isExit(pch)){
                        exit(0);
                }
            }
   }
   return true;
}

int main(){
   bool goon = true;
   while(goon){
       string input;
       cout << "$ ";
       getline(cin, input);
       input = commentRemoval(input);
       char str[input.size()+1];
       strcpy(str, input.c_str());
       goon = run(str);
   }
   return 0;
}
<|endoftext|>


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

namespace nyx {

int Chunk::write(u8_t byte, int line) {
  codes_.push_back(byte);
  lines_.push_back(line);

  return static_cast<int>(codes_.size() - 1);
}

int Chunk::add_constant(const Value& v) {
  constants_.push_back(v);
  return static_cast<int>(constants_.size() - 1);
}

void Chunk::disassemble(const str_t& name) {
  std::cout << "=== " << name << " ===" << std::endl;
  for (int i = 0; i < static_cast<int>(codes_.size());)
    i = disassemble_instruction(i);
}

int Chunk::disassemble_instruction(int i) {
  static auto simple_instruction = [](const char* name) {
    std::cout << name << std::endl;
  };

  static auto simple_instructionN = [](const char* name, int n) {
    std::cout << name << n << std::endl;
  };

  static auto code_instruction = [](Chunk& c, int i, const char* name) -> int {
    u8_t slot = c.get_code(i++);
    fprintf(stdout, "%-16s %4d\n", name, slot);
    return i;
  };

  static auto const_instruction = [](Chunk& c, int i, const char* name) -> int {
    u8_t constant = c.get_code(i);
    fprintf(stdout, "%-16s %4d ", name, constant);
    std::cout << "`" << c.get_constant(constant) << "`" << std::endl;
    return i;
  };

  static auto const_instructionN = [](
      Chunk& c, int i, const char* name, int n) -> int {
    u8_t constant = c.get_code(i);
    fprintf(stdout, "%s%-*d %4d ",
        name, 15 - static_cast<int>(strlen(name)), n, constant);
    std::cout << "`" << c.get_constant(constant) << "`" << std::endl;
    return i;
  };

  static auto jump_instruction = [](
      Chunk& c, int i, const char* name, int sign = 1) -> int {
    u16_t offset = static_cast<u16_t>(c.get_code(i++) << 8);
    offset |= c.get_code(i++);
    fprintf(stdout, "%-16s %4d -> %d\n", name, offset, i + offset * sign);
    return i;
  };

  fprintf(stdout, "%04d ", i);
  if (i > 1 && lines_[i] == lines_[i - 1])
    std::cout << "   | ";
  else
    fprintf(stdout, "%4d ", lines_[i]);

  const u8_t* codes = codes_.data();
  switch (auto instruction = codes[i++]; instruction) {
  case OpCode::OP_CONSTANT:
    i = const_instruction(*this, i, "OP_CONSTANT"); break;
  case OpCode::OP_NIL: simple_instruction("OP_NIL"); break;
  case OpCode::OP_TRUE: simple_instruction("OP_TRUE"); break;
  case OpCode::OP_FALSE: simple_instruction("OP_FALSE"); break;
  case OpCode::OP_POP: simple_instruction("OP_POP"); break;
  case OpCode::OP_GET_LOCAL:
    i = code_instruction(*this, i, "OP_GET_LOCAL"); break;
  case OpCode::OP_SET_LOCAL:
    i = code_instruction(*this, i, "OP_SET_LOCAL"); break;
  case OpCode::OP_DEF_GLOBAL:
    i = const_instruction(*this, i, "OP_DEF_GLOBAL"); break;
  case OpCode::OP_GET_GLOBAL:
    i = const_instruction(*this, i, "OP_GET_GLOBAL"); break;
  case OpCode::OP_SET_GLOBAL:
    i = const_instruction(*this, i, "OP_SET_GLOBAL"); break;
  case OpCode::OP_GET_UPVALUE:
    i = code_instruction(*this, i, "OP_GET_UPVALUE"); break;
  case OpCode::OP_SET_UPVALUE:
    i = code_instruction(*this, i, "OP_SET_UPVALUE"); break;
  case OpCode::OP_GET_FIELD:
    i = const_instruction(*this, i, "OP_GET_FIELD"); break;
  case OpCode::OP_SET_FIELD:
    i = const_instruction(*this, i, "OP_SET_FIELD"); break;
  case OpCode::OP_GET_SUPER:
    i = const_instruction(*this, i, "OP_GET_SUPER"); break;
  case OpCode::OP_EQ: simple_instruction("OP_EQ"); break;
  case OpCode::OP_NE: simple_instruction("OP_NE"); break;
  case OpCode::OP_GT: simple_instruction("OP_GT"); break;
  case OpCode::OP_GE: simple_instruction("OP_GE"); break;
  case OpCode::OP_LT: simple_instruction("OP_LT"); break;
  case OpCode::OP_LE: simple_instruction("OP_LE"); break;
  case OpCode::OP_ADD: simple_instruction("OP_ADD"); break;
  case OpCode::OP_SUB: simple_instruction("OP_SUB"); break;
  case OpCode::OP_MUL: simple_instruction("OP_MUL"); break;
  case OpCode::OP_DIV: simple_instruction("OP_DIV"); break;
  case OpCode::OP_NOT: simple_instruction("OP_NOT"); break;
  case OpCode::OP_NEG: simple_instruction("OP_NEG"); break;
  case OpCode::OP_JUMP:
    i = jump_instruction(*this, i, "OP_JUMP"); break;
  case OpCode::OP_JUMP_IF_FALSE:
    i = jump_instruction(*this, i, "OP_JUMP_IF_FALSE"); break;
  case OpCode::OP_LOOP:
    i = jump_instruction(*this, i, "OP_LOOP", -1); break;
  case OpCode::OP_CALL_0:
  case OpCode::OP_CALL_1:
  case OpCode::OP_CALL_2:
  case OpCode::OP_CALL_3:
  case OpCode::OP_CALL_4:
  case OpCode::OP_CALL_5:
  case OpCode::OP_CALL_6:
  case OpCode::OP_CALL_7:
  case OpCode::OP_CALL_8:
    simple_instructionN("OP_CALL_", instruction - OpCode::OP_CALL_0); break;
  case OpCode::OP_INVOKE_0:
  case OpCode::OP_INVOKE_1:
  case OpCode::OP_INVOKE_2:
  case OpCode::OP_INVOKE_3:
  case OpCode::OP_INVOKE_4:
  case OpCode::OP_INVOKE_5:
  case OpCode::OP_INVOKE_6:
  case OpCode::OP_INVOKE_7:
  case OpCode::OP_INVOKE_8:
    i = const_instructionN(*this, i, "OP_INVOKE_", instruction - OpCode::OP_INVOKE_0);
    break;
  case OpCode::OP_SUPER_0:
  case OpCode::OP_SUPER_1:
  case OpCode::OP_SUPER_2:
  case OpCode::OP_SUPER_3:
  case OpCode::OP_SUPER_4:
  case OpCode::OP_SUPER_5:
  case OpCode::OP_SUPER_6:
  case OpCode::OP_SUPER_7:
  case OpCode::OP_SUPER_8:
    i = const_instructionN(*this, i, "OP_SUPER_", instruction - OpCode::OP_SUPER_0);
    break;
  case OpCode::OP_CLOSURE:
    {
      u8_t constant = codes[i++];
      fprintf(stdout, "%-16s %4d ", "OP_CLOSURE", constant);
      Value constant_val = constants_[constant];
      std::cout << "`" << constant_val << "`" << std::endl;

      FunctionObject* closed_fn = constant_val.as_function();
      for (int j = 0; j < closed_fn->upvalues_count(); ++j) {
        int is_local = codes[i++];
        int index = codes[i++];
        fprintf(stdout, "%04d   |                     %s %d\n",
            i - 2, is_local ? "local" : "upvalue", index);
      }
    } break;
  case OpCode::OP_CLOSE_UPVALUE: simple_instruction("OP_CLOSE_UPVALUE"); break;
  case OpCode::OP_RETURN: simple_instruction("OP_RETURN"); break;
  case OpCode::OP_CLASS:
    i = const_instruction(*this, i, "OP_CLASS"); break;
  case OpCode::OP_SUBCLASS:
    i = const_instruction(*this, i, "OP_SUBCLASS"); break;
  case OpCode::OP_METHOD:
    i = const_instruction(*this, i, "OP_METHOD"); break;
  }
  return i;
}

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

namespace nyx {

int Chunk::write(u8_t byte, int line) {
  codes_.push_back(byte);
  lines_.push_back(line);

  return static_cast<int>(codes_.size() - 1);
}

int Chunk::add_constant(const Value& v) {
  constants_.push_back(v);
  return static_cast<int>(constants_.size() - 1);
}

void Chunk::disassemble(const str_t& name) {
  std::cout << "=== " << name << " ===" << std::endl;
  for (int i = 0; i < static_cast<int>(codes_.size());)
    i = disassemble_instruction(i);
}

int Chunk::disassemble_instruction(int i) {
  static auto simple_instruction = [](int i, const char* name) -> int {
    std::cout << name << std::endl;
    return i;
  };

  static auto simple_instructionN = [](int i, const char* name, int n) -> int {
    std::cout << name << n << std::endl;
    return i;
  };

  static auto code_instruction = [](Chunk& c, int i, const char* name) -> int {
    u8_t slot = c.get_code(i);
    fprintf(stdout, "%-16s %4d\n", name, slot);
    return i + 1;
  };

  static auto const_instruction = [](Chunk& c, int i, const char* name) -> int {
    u8_t constant = c.get_code(i);
    fprintf(stdout, "%-16s %4d ", name, constant);
    std::cout << "`" << c.get_constant(constant) << "`" << std::endl;
    return i + 1;
  };

  static auto const_instructionN = [](
      Chunk& c, int i, const char* name, int n) -> int {
    u8_t constant = c.get_code(i);
    fprintf(stdout, "%s%-*d %4d ",
        name, 15 - static_cast<int>(strlen(name)), n, constant);
    std::cout << "`" << c.get_constant(constant) << "`" << std::endl;
    return i + 1;
  };

  static auto jump_instruction = [](
      Chunk& c, int i, const char* name, int sign = 1) -> int {
    u16_t offset = static_cast<u16_t>(c.get_code(i) << 8);
    offset |= c.get_code(i + 1);
    fprintf(stdout, "%-16s %4d -> %d\n", name, offset, i + offset * sign);
    return i + 2;
  };

  fprintf(stdout, "%04d ", i);
  if (i > 1 && lines_[i] == lines_[i - 1])
    std::cout << "   | ";
  else
    fprintf(stdout, "%4d ", lines_[i]);

  const u8_t* codes = codes_.data();
  switch (auto instruction = codes[i++]; instruction) {
  case OpCode::OP_CONSTANT: return const_instruction(*this, i, "OP_CONSTANT");
  case OpCode::OP_NIL: return simple_instruction(i, "OP_NIL");
  case OpCode::OP_TRUE: return simple_instruction(i, "OP_TRUE");
  case OpCode::OP_FALSE: return simple_instruction(i, "OP_FALSE");
  case OpCode::OP_POP: return simple_instruction(i, "OP_POP");
  case OpCode::OP_GET_LOCAL: return code_instruction(*this, i, "OP_GET_LOCAL");
  case OpCode::OP_SET_LOCAL: return code_instruction(*this, i, "OP_SET_LOCAL");
  case OpCode::OP_DEF_GLOBAL: return const_instruction(*this, i, "OP_DEF_GLOBAL");
  case OpCode::OP_GET_GLOBAL: return const_instruction(*this, i, "OP_GET_GLOBAL");
  case OpCode::OP_SET_GLOBAL: return const_instruction(*this, i, "OP_SET_GLOBAL");
  case OpCode::OP_GET_UPVALUE: return code_instruction(*this, i, "OP_GET_UPVALUE");
  case OpCode::OP_SET_UPVALUE: return code_instruction(*this, i, "OP_SET_UPVALUE");
  case OpCode::OP_GET_FIELD: return const_instruction(*this, i, "OP_GET_FIELD");
  case OpCode::OP_SET_FIELD: return const_instruction(*this, i, "OP_SET_FIELD");
  case OpCode::OP_GET_SUPER: return const_instruction(*this, i, "OP_GET_SUPER");
  case OpCode::OP_EQ: return simple_instruction(i, "OP_EQ");
  case OpCode::OP_NE: return simple_instruction(i, "OP_NE");
  case OpCode::OP_GT: return simple_instruction(i, "OP_GT");
  case OpCode::OP_GE: return simple_instruction(i, "OP_GE");
  case OpCode::OP_LT: return simple_instruction(i, "OP_LT");
  case OpCode::OP_LE: return simple_instruction(i, "OP_LE");
  case OpCode::OP_ADD: return simple_instruction(i, "OP_ADD");
  case OpCode::OP_SUB: return simple_instruction(i, "OP_SUB");
  case OpCode::OP_MUL: return simple_instruction(i, "OP_MUL");
  case OpCode::OP_DIV: return simple_instruction(i, "OP_DIV");
  case OpCode::OP_NOT: return simple_instruction(i, "OP_NOT");
  case OpCode::OP_NEG: return simple_instruction(i, "OP_NEG");
  case OpCode::OP_JUMP: return jump_instruction(*this, i, "OP_JUMP");
  case OpCode::OP_JUMP_IF_FALSE: return jump_instruction(*this, i, "OP_JUMP_IF_FALSE");
  case OpCode::OP_LOOP: return jump_instruction(*this, i, "OP_LOOP", -1);
  case OpCode::OP_CALL_0:
  case OpCode::OP_CALL_1:
  case OpCode::OP_CALL_2:
  case OpCode::OP_CALL_3:
  case OpCode::OP_CALL_4:
  case OpCode::OP_CALL_5:
  case OpCode::OP_CALL_6:
  case OpCode::OP_CALL_7:
  case OpCode::OP_CALL_8:
    return simple_instructionN(i, "OP_CALL_", instruction - OpCode::OP_CALL_0);
  case OpCode::OP_INVOKE_0:
  case OpCode::OP_INVOKE_1:
  case OpCode::OP_INVOKE_2:
  case OpCode::OP_INVOKE_3:
  case OpCode::OP_INVOKE_4:
  case OpCode::OP_INVOKE_5:
  case OpCode::OP_INVOKE_6:
  case OpCode::OP_INVOKE_7:
  case OpCode::OP_INVOKE_8:
    return const_instructionN(*this, i, "OP_INVOKE_", instruction - OpCode::OP_INVOKE_0);
  case OpCode::OP_SUPER_0:
  case OpCode::OP_SUPER_1:
  case OpCode::OP_SUPER_2:
  case OpCode::OP_SUPER_3:
  case OpCode::OP_SUPER_4:
  case OpCode::OP_SUPER_5:
  case OpCode::OP_SUPER_6:
  case OpCode::OP_SUPER_7:
  case OpCode::OP_SUPER_8:
    return const_instructionN(*this, i, "OP_SUPER_", instruction - OpCode::OP_SUPER_0);
  case OpCode::OP_CLOSURE:
    {
      u8_t constant = codes[i++];
      fprintf(stdout, "%-16s %4d ", "OP_CLOSURE", constant);
      Value constant_val = constants_[constant];
      std::cout << "`" << constant_val << "`" << std::endl;

      FunctionObject* closed_fn = constant_val.as_function();
      for (int j = 0; j < closed_fn->upvalues_count(); ++j) {
        int is_local = codes[i++];
        int index = codes[i++];
        fprintf(stdout, "%04d   |                     %s %d\n",
            i - 2, is_local ? "local" : "upvalue", index);
      }
    } break;
  case OpCode::OP_CLOSE_UPVALUE: return simple_instruction(i, "OP_CLOSE_UPVALUE");
  case OpCode::OP_RETURN: return simple_instruction(i, "OP_RETURN");
  case OpCode::OP_CLASS: return const_instruction(*this, i, "OP_CLASS");
  case OpCode::OP_SUBCLASS: return const_instruction(*this, i, "OP_SUBCLASS");
  case OpCode::OP_METHOD: return const_instruction(*this, i, "OP_METHOD");
  }
  return 0;
}

}
<|endoftext|>


<commit_before>#include <iostream>
#include <immintrin.h>
#include "ch_frb_io_internals.hpp"

using namespace std;

namespace ch_frb_io {
#if 0
};  // pacify emacs c-mode!
#endif

assembled_chunk::assembled_chunk(int beam_id_, int nupfreq_, int nt_per_packet_, int fpga_counts_per_sample_, uint64_t chunk_t0_)
    : beam_id(beam_id_),
      nupfreq(nupfreq_),
      nt_per_packet(nt_per_packet_),
      fpga_counts_per_sample(fpga_counts_per_sample_),
      chunk_t0(chunk_t0_),
      chunk_t1(chunk_t0_ + constants::nt_per_assembled_chunk)
{
    if ((beam_id < 0) || (beam_id > constants::max_allowed_beam_id))
	throw runtime_error("assembled_chunk constructor: bad beam_id argument");
    if ((nupfreq <= 0) || (nupfreq > constants::max_allowed_nupfreq))
	throw runtime_error("assembled_chunk constructor: bad nupfreq argument");
    if ((nt_per_packet <= 0) || !is_power_of_two(nt_per_packet) || (nt_per_packet > constants::nt_per_assembled_chunk))
	throw runtime_error("assembled_chunk constructor: bad nt_per_packet argument");
    if ((fpga_counts_per_sample <= 0) || (fpga_counts_per_sample > constants::max_allowed_fpga_counts_per_sample))
	throw runtime_error("assembled_chunk constructor: bad fpga_counts_per_sample argument");

    this->data = aligned_alloc<uint8_t> (constants::nfreq_coarse * nupfreq * constants::nt_per_assembled_chunk);

    this->nt_coarse = constants::nt_per_assembled_chunk / nt_per_packet;
    this->scales = aligned_alloc<float> (constants::nfreq_coarse * nt_coarse);
    this->offsets = aligned_alloc<float> (constants::nfreq_coarse * nt_coarse);
}

assembled_chunk::~assembled_chunk()
{
    free(data);
    free(scales);
    free(offsets);
}

void assembled_chunk::add_packet(const intensity_packet &packet)
{
    // Offset relative to beginning of packet
    int t0 = packet.fpga_count / uint64_t(fpga_counts_per_sample) - chunk_t0;

#if 1
    // FIXME remove later?
    bool bad = ((packet.nbeams != 1) ||
		(packet.nupfreq != this->nupfreq) ||
		(packet.ntsamp != this->nt_per_packet) ||
		(packet.fpga_counts_per_sample != this->fpga_counts_per_sample) ||
		(packet.fpga_count % (fpga_counts_per_sample * nt_per_packet)) ||
		(packet.beam_ids[0] != this->beam_id) ||
		(t0 < 0) ||
		(t0 + nt_per_packet > constants::nt_per_assembled_chunk));

    if (_unlikely(bad))
	throw runtime_error("ch_frb_io: internal error in assembled_chunk::add_packet()");
#endif

    for (int f = 0; f < packet.nfreq_coarse; f++) {
	int coarse_freq_id = packet.freq_ids[f];

	this->scales[coarse_freq_id*nt_coarse + (t0/nt_per_packet)] = packet.scales[f];
	this->offsets[coarse_freq_id*nt_coarse + (t0/nt_per_packet)] = packet.offsets[f];

	for (int u = 0; u < nupfreq; u++) {
	    memcpy(data + (coarse_freq_id*nupfreq + u) * constants::nt_per_assembled_chunk + t0,
		   packet.data + (f*nupfreq + u) * nt_per_packet,
		   nt_per_packet);
	}
    }
}

#if 0
void assembled_chunk::decode(float *intensity, float *weights, int stride) const
{
    if (stride < constants::nt_per_assembled_chunk)
	throw runtime_error("ch_frb_io: bad stride passed to assembled_chunk::decode()");

    for (int if_coarse = 0; if_coarse < constants::nfreq_coarse; if_coarse++) {
	const float *scales_f = this->scales + if_coarse * nt_coarse;
	const float *offsets_f = this->offsets + if_coarse * nt_coarse;

	for (int if_fine = if_coarse*nupfreq; if_fine < (if_coarse+1)*nupfreq; if_fine++) {
	    const uint8_t *src_f = this->data + if_fine * constants::nt_per_assembled_chunk;
	    float *int_f = intensity + if_fine * stride;
	    float *wt_f = weights + if_fine * stride;

	    for (int it_coarse = 0; it_coarse < nt_coarse; it_coarse++) {
		float scale = scales_f[it_coarse];
		float offset = offsets_f[it_coarse];

		for (int it_fine = it_coarse*nt_per_packet; it_fine < (it_coarse+1)*nt_per_packet; it_fine++) {
		    float x = float(src_f[it_fine]);
		    int_f[it_fine] = scale*x + offset;
		    wt_f[it_fine] = ((x*(255.-x)) > 0.5) ? 1.0 : 0.0;  // FIXME ugh
		}
	    }
	}
    }
}
#endif

inline void _unpack(__m256i &out0, __m256i &out1, __m256i &out2, __m256i &out3, __m256i x)
{
    // FIXME is there a better way to initialize this?
    static const __m256i ctl0 = _mm256_set_epi8(15,11,7,3,14,10,6,2,13,9,5,1,12,8,4,0,
						15,11,7,3,14,10,6,2,13,9,5,1,12,8,4,0);

    // 4-by-4 transpose within each 128-bit lane
    x = _mm256_shuffle_epi8(x, ctl0);

    __m256i y0 = _mm256_and_si256(x, _mm256_set1_epi32(0xff));
    __m256i y1 = _mm256_and_si256(x, _mm256_set1_epi32(0xff00));
    __m256i y2 = _mm256_and_si256(x, _mm256_set1_epi32(0xff0000));
    __m256i y3 = _mm256_and_si256(x, _mm256_set1_epi32(0xff000000));

    y1 = _mm256_srli_epi32(y1, 8);
    y2 = _mm256_srli_epi32(y2, 16);
    y3 = _mm256_srli_epi32(y3, 24);

    out0 = _mm256_permute2f128_ps(y0, y1, 0x20);
    out1 = _mm256_permute2f128_ps(y2, y3, 0x20);
    out2 = _mm256_permute2f128_ps(y0, y1, 0x31);
    out3 = _mm256_permute2f128_ps(y2, y3, 0x31);
}

inline void _kernel32(float *intp, float *wtp, __m256i data, __m256 scale0, __m256 scale1, __m256 offset0, __m256 offset1)
{
    __m256i in0, in1, in2, in3;
    _unpack(in0, in1, in2, in3, data);

    _mm256_storeu_ps(intp, scale0 * _mm256_cvtepi32_ps(in0) + offset0);
    _mm256_storeu_ps(intp+8, scale0 * _mm256_cvtepi32_ps(in1) + offset0);
    _mm256_storeu_ps(intp+16, scale1 * _mm256_cvtepi32_ps(in2) + offset1);
    _mm256_storeu_ps(intp+24, scale1 * _mm256_cvtepi32_ps(in3) + offset1);

    // XXX placeholder for weights
    __m256 w = _mm256_set1_ps(1.0);
    _mm256_storeu_ps(wtp, w);
    _mm256_storeu_ps(wtp+8, w);
    _mm256_storeu_ps(wtp+16, w);
    _mm256_storeu_ps(wtp+25, w);
}

inline void _kernel128(float *intp, float *wtp, const uint8_t *src, const float *scalep, const float *offsetp)
{
    __m256 scale = _mm256_loadu_ps(scalep);
    __m256 offset = _mm256_loadu_ps(offsetp);
    __m256 scale0, offset0;

    scale0 = _mm256_permute2f128_ps(scale, scale, 0x00);
    offset0 = _mm256_permute2f128_ps(offset, offset, 0x00);

    _kernel32(intp, wtp,
	      _mm256_loadu_si256((const __m256i *) (src)),
	      _mm256_shuffle_ps(scale0, scale0, 0x00),
	      _mm256_shuffle_ps(scale0, scale0, 0x55),
	      _mm256_shuffle_ps(offset0, offset0, 0x00),
	      _mm256_shuffle_ps(offset0, offset0, 0x55));

    _kernel32(intp + 32, wtp + 32,
	      _mm256_loadu_si256((const __m256i *) (src + 32)),
	      _mm256_shuffle_ps(scale0, scale0, 0xaa),
	      _mm256_shuffle_ps(scale0, scale0, 0xff),
	      _mm256_shuffle_ps(offset0, offset0, 0xaa),
	      _mm256_shuffle_ps(offset0, offset0, 0xff));

    scale0 = _mm256_permute2f128_ps(scale, scale, 0x11);
    offset0 = _mm256_permute2f128_ps(offset, offset, 0x11);

    _kernel32(intp + 64, wtp + 64,
	      _mm256_loadu_si256((const __m256i *) (src + 64)),
	      _mm256_shuffle_ps(scale0, scale0, 0x00),
	      _mm256_shuffle_ps(scale0, scale0, 0x55),
	      _mm256_shuffle_ps(offset0, offset0, 0x00),
	      _mm256_shuffle_ps(offset0, offset0, 0x55));

    _kernel32(intp + 96, wtp + 96,
	      _mm256_loadu_si256((const __m256i *) (src + 96)),
	      _mm256_shuffle_ps(scale0, scale0, 0xaa),
	      _mm256_shuffle_ps(scale0, scale0, 0xff),
	      _mm256_shuffle_ps(offset0, offset0, 0xaa),
	      _mm256_shuffle_ps(offset0, offset0, 0xff));
}

inline void _kernel(float *intp, float *wtp, const uint8_t *src, const float *scalep, const float *offsetp)
{
    constexpr int n = constants::nt_per_assembled_chunk / 128;

    for (int i = 0; i < n; i++)
	_kernel128(intp + i*128, wtp + i*128, src + i*128, scalep + i*8, offsetp + i*8);
}

void assembled_chunk::decode(float *intensity, float *weights, int stride) const
{
    if ((nt_per_packet != 16) || (constants::nt_per_assembled_chunk % 128))
	throw runtime_error("ch_frb_io: can't use this kernel");
    if (stride < constants::nt_per_assembled_chunk)
	throw runtime_error("ch_frb_io: bad stride passed to assembled_chunk::decode()");

    for (int if_coarse = 0; if_coarse < constants::nfreq_coarse; if_coarse++) {
	const float *scales_f = this->scales + if_coarse * nt_coarse;
	const float *offsets_f = this->offsets + if_coarse * nt_coarse;

	for (int if_fine = if_coarse*nupfreq; if_fine < (if_coarse+1)*nupfreq; if_fine++) {
	    const uint8_t *src_f = this->data + if_fine * constants::nt_per_assembled_chunk;
	    float *int_f = intensity + if_fine * stride;
	    float *wt_f = weights + if_fine * stride;

	    for (int it_coarse = 0; it_coarse < nt_coarse; it_coarse++)
		_kernel(int_f, wt_f, src_f, scales_f, offsets_f);
	}
    }
}

}  // namespace ch_frb_io
<commit_msg>fix some bugs in decode kernel (not fully tested yet)<commit_after>#include <iostream>
#include <immintrin.h>
#include "ch_frb_io_internals.hpp"

using namespace std;

namespace ch_frb_io {
#if 0
};  // pacify emacs c-mode!
#endif

assembled_chunk::assembled_chunk(int beam_id_, int nupfreq_, int nt_per_packet_, int fpga_counts_per_sample_, uint64_t chunk_t0_)
    : beam_id(beam_id_),
      nupfreq(nupfreq_),
      nt_per_packet(nt_per_packet_),
      fpga_counts_per_sample(fpga_counts_per_sample_),
      chunk_t0(chunk_t0_),
      chunk_t1(chunk_t0_ + constants::nt_per_assembled_chunk)
{
    if ((beam_id < 0) || (beam_id > constants::max_allowed_beam_id))
	throw runtime_error("assembled_chunk constructor: bad beam_id argument");
    if ((nupfreq <= 0) || (nupfreq > constants::max_allowed_nupfreq))
	throw runtime_error("assembled_chunk constructor: bad nupfreq argument");
    if ((nt_per_packet <= 0) || !is_power_of_two(nt_per_packet) || (nt_per_packet > constants::nt_per_assembled_chunk))
	throw runtime_error("assembled_chunk constructor: bad nt_per_packet argument");
    if ((fpga_counts_per_sample <= 0) || (fpga_counts_per_sample > constants::max_allowed_fpga_counts_per_sample))
	throw runtime_error("assembled_chunk constructor: bad fpga_counts_per_sample argument");

    this->data = aligned_alloc<uint8_t> (constants::nfreq_coarse * nupfreq * constants::nt_per_assembled_chunk);

    this->nt_coarse = constants::nt_per_assembled_chunk / nt_per_packet;
    this->scales = aligned_alloc<float> (constants::nfreq_coarse * nt_coarse);
    this->offsets = aligned_alloc<float> (constants::nfreq_coarse * nt_coarse);
}

assembled_chunk::~assembled_chunk()
{
    free(data);
    free(scales);
    free(offsets);
}

void assembled_chunk::add_packet(const intensity_packet &packet)
{
    // Offset relative to beginning of packet
    int t0 = packet.fpga_count / uint64_t(fpga_counts_per_sample) - chunk_t0;

#if 1
    // FIXME remove later?
    bool bad = ((packet.nbeams != 1) ||
		(packet.nupfreq != this->nupfreq) ||
		(packet.ntsamp != this->nt_per_packet) ||
		(packet.fpga_counts_per_sample != this->fpga_counts_per_sample) ||
		(packet.fpga_count % (fpga_counts_per_sample * nt_per_packet)) ||
		(packet.beam_ids[0] != this->beam_id) ||
		(t0 < 0) ||
		(t0 + nt_per_packet > constants::nt_per_assembled_chunk));

    if (_unlikely(bad))
	throw runtime_error("ch_frb_io: internal error in assembled_chunk::add_packet()");
#endif

    for (int f = 0; f < packet.nfreq_coarse; f++) {
	int coarse_freq_id = packet.freq_ids[f];

	this->scales[coarse_freq_id*nt_coarse + (t0/nt_per_packet)] = packet.scales[f];
	this->offsets[coarse_freq_id*nt_coarse + (t0/nt_per_packet)] = packet.offsets[f];

	for (int u = 0; u < nupfreq; u++) {
	    memcpy(data + (coarse_freq_id*nupfreq + u) * constants::nt_per_assembled_chunk + t0,
		   packet.data + (f*nupfreq + u) * nt_per_packet,
		   nt_per_packet);
	}
    }
}

#if 0
void assembled_chunk::decode(float *intensity, float *weights, int stride) const
{
    if (stride < constants::nt_per_assembled_chunk)
	throw runtime_error("ch_frb_io: bad stride passed to assembled_chunk::decode()");

    for (int if_coarse = 0; if_coarse < constants::nfreq_coarse; if_coarse++) {
	const float *scales_f = this->scales + if_coarse * nt_coarse;
	const float *offsets_f = this->offsets + if_coarse * nt_coarse;

	for (int if_fine = if_coarse*nupfreq; if_fine < (if_coarse+1)*nupfreq; if_fine++) {
	    const uint8_t *src_f = this->data + if_fine * constants::nt_per_assembled_chunk;
	    float *int_f = intensity + if_fine * stride;
	    float *wt_f = weights + if_fine * stride;

	    for (int it_coarse = 0; it_coarse < nt_coarse; it_coarse++) {
		float scale = scales_f[it_coarse];
		float offset = offsets_f[it_coarse];

		for (int it_fine = it_coarse*nt_per_packet; it_fine < (it_coarse+1)*nt_per_packet; it_fine++) {
		    float x = float(src_f[it_fine]);
		    int_f[it_fine] = scale*x + offset;
		    wt_f[it_fine] = ((x*(255.-x)) > 0.5) ? 1.0 : 0.0;  // FIXME ugh
		}
	    }
	}
    }
}
#endif

#if 1
inline void _unpack(__m256i &out0, __m256i &out1, __m256i &out2, __m256i &out3, __m256i x)
{
    // FIXME is there a better way to initialize this?
    static const __m256i ctl0 = _mm256_set_epi8(15,11,7,3,14,10,6,2,13,9,5,1,12,8,4,0,
						15,11,7,3,14,10,6,2,13,9,5,1,12,8,4,0);

    // 4-by-4 transpose within each 128-bit lane
    x = _mm256_shuffle_epi8(x, ctl0);

    __m256i y0 = _mm256_and_si256(x, _mm256_set1_epi32(0xff));
    __m256i y1 = _mm256_and_si256(x, _mm256_set1_epi32(0xff00));
    __m256i y2 = _mm256_and_si256(x, _mm256_set1_epi32(0xff0000));
    __m256i y3 = _mm256_and_si256(x, _mm256_set1_epi32(0xff000000));

    y1 = _mm256_srli_epi32(y1, 8);
    y2 = _mm256_srli_epi32(y2, 16);
    y3 = _mm256_srli_epi32(y3, 24);

    out0 = _mm256_permute2f128_si256(y0, y1, 0x20);
    out1 = _mm256_permute2f128_si256(y2, y3, 0x20);
    out2 = _mm256_permute2f128_si256(y0, y1, 0x31);
    out3 = _mm256_permute2f128_si256(y2, y3, 0x31);
}

inline void _kernel32(float *intp, float *wtp, __m256i data, __m256 scale0, __m256 scale1, __m256 offset0, __m256 offset1)
{
    __m256i in0, in1, in2, in3;
    _unpack(in0, in1, in2, in3, data);

    _mm256_storeu_ps(intp, scale0 * _mm256_cvtepi32_ps(in0) + offset0);
    _mm256_storeu_ps(intp+8, scale0 * _mm256_cvtepi32_ps(in1) + offset0);
    _mm256_storeu_ps(intp+16, scale1 * _mm256_cvtepi32_ps(in2) + offset1);
    _mm256_storeu_ps(intp+24, scale1 * _mm256_cvtepi32_ps(in3) + offset1);

    // XXX placeholder for weights
    __m256 w = _mm256_set1_ps(1.0);
    _mm256_storeu_ps(wtp, w);
    _mm256_storeu_ps(wtp+8, w);
    _mm256_storeu_ps(wtp+16, w);
    _mm256_storeu_ps(wtp+24, w);
}

inline void _kernel128(float *intp, float *wtp, const uint8_t *src, const float *scalep, const float *offsetp)
{
    __m256 scale = _mm256_loadu_ps(scalep);
    __m256 offset = _mm256_loadu_ps(offsetp);
    __m256 scale0, offset0;

    scale0 = _mm256_permute2f128_ps(scale, scale, 0x00);
    offset0 = _mm256_permute2f128_ps(offset, offset, 0x00);

    _kernel32(intp, wtp,
	      _mm256_loadu_si256((const __m256i *) (src)),
	      _mm256_shuffle_ps(scale0, scale0, 0x00),
	      _mm256_shuffle_ps(scale0, scale0, 0x55),
	      _mm256_shuffle_ps(offset0, offset0, 0x00),
	      _mm256_shuffle_ps(offset0, offset0, 0x55));

    _kernel32(intp + 32, wtp + 32,
	      _mm256_loadu_si256((const __m256i *) (src + 32)),
	      _mm256_shuffle_ps(scale0, scale0, 0xaa),
	      _mm256_shuffle_ps(scale0, scale0, 0xff),
	      _mm256_shuffle_ps(offset0, offset0, 0xaa),
	      _mm256_shuffle_ps(offset0, offset0, 0xff));

    scale0 = _mm256_permute2f128_ps(scale, scale, 0x11);
    offset0 = _mm256_permute2f128_ps(offset, offset, 0x11);

    _kernel32(intp + 64, wtp + 64,
	      _mm256_loadu_si256((const __m256i *) (src + 64)),
	      _mm256_shuffle_ps(scale0, scale0, 0x00),
	      _mm256_shuffle_ps(scale0, scale0, 0x55),
	      _mm256_shuffle_ps(offset0, offset0, 0x00),
	      _mm256_shuffle_ps(offset0, offset0, 0x55));

    _kernel32(intp + 96, wtp + 96,
	      _mm256_loadu_si256((const __m256i *) (src + 96)),
	      _mm256_shuffle_ps(scale0, scale0, 0xaa),
	      _mm256_shuffle_ps(scale0, scale0, 0xff),
	      _mm256_shuffle_ps(offset0, offset0, 0xaa),
	      _mm256_shuffle_ps(offset0, offset0, 0xff));
}

inline void _kernel(float *intp, float *wtp, const uint8_t *src, const float *scalep, const float *offsetp)
{
    constexpr int n = constants::nt_per_assembled_chunk / 128;

    for (int i = 0; i < n; i++)
	_kernel128(intp + i*128, wtp + i*128, src + i*128, scalep + i*8, offsetp + i*8);
}

void assembled_chunk::decode(float *intensity, float *weights, int stride) const
{
    if ((nt_per_packet != 16) || (constants::nt_per_assembled_chunk % 128))
	throw runtime_error("ch_frb_io: can't use this kernel");
    if (stride < constants::nt_per_assembled_chunk)
	throw runtime_error("ch_frb_io: bad stride passed to assembled_chunk::decode()");

    for (int if_coarse = 0; if_coarse < constants::nfreq_coarse; if_coarse++) {
	const float *scales_f = this->scales + if_coarse * nt_coarse;
	const float *offsets_f = this->offsets + if_coarse * nt_coarse;

	for (int if_fine = if_coarse*nupfreq; if_fine < (if_coarse+1)*nupfreq; if_fine++) {
	    const uint8_t *src_f = this->data + if_fine * constants::nt_per_assembled_chunk;
	    float *int_f = intensity + if_fine * stride;
	    float *wt_f = weights + if_fine * stride;

	    _kernel(int_f, wt_f, src_f, scales_f, offsets_f);
	}
    }
}
#endif

}  // namespace ch_frb_io
<|endoftext|>


<commit_before>#include "../config.h"
#include "horde3dwindow.h"
#include "cameranodeobject.h"

#include <Horde3DUtils.h>

#include <QtCore/QPropertyAnimation>
#include <QtCore/QCoreApplication>
#include <QtCore/QDir>
#include <QtGui/QOpenGLFunctions>
#include <QtGui/QOpenGLFramebufferObject>
#include <QtGui/QScreen>
#include <QtQuick/QQuickWindow>
#include <QtQuick/QSGSimpleTextureNode>

#include <GL/gl.h>

static const bool USE_SEPARATE_CONTEXT = false;

Horde3DWindow::Horde3DWindow(QWindow *parent) :
		QQuickWindow(parent),
		m_samples(0),
		m_initialized(false),
		m_dirtyView(false),
		m_animTime(0.0f),
		m_qtContext(NULL),
		m_h3dContext(NULL)
{
	connect(this, SIGNAL(beforeRendering()), this, SLOT(onBeforeRendering()), Qt::DirectConnection);
	connect(this, SIGNAL(initFinished()), this, SLOT(onInitFinished()), Qt::QueuedConnection);
} // end Horde3DWindow

Horde3DWindow::~Horde3DWindow()
{
	if(m_h3dContext)
	{
		m_h3dContext->deleteLater();
		m_h3dContext = NULL;
	} // end if
} // end ~Horde3DWindow

void Horde3DWindow::renderHorde()
{
	m_animTime += 0.4f;

	// Do animation blending
	h3dSetModelAnimParams(m_knight, 0, m_animTime, 0.5f);
	h3dSetModelAnimParams(m_knight, 1, m_animTime, 0.5f);
	h3dUpdateModel(m_knight, H3DModelUpdateFlags::Animation | H3DModelUpdateFlags::Geometry);

	if(m_camera)
	{
		if(!USE_SEPARATE_CONTEXT || (m_qtContext && m_h3dContext))
		{
			restoreH3DState();

			h3dRender(m_camera);
			h3dFinalizeFrame();

			saveH3DState();
		} // end if
	} // end if
} // end renderHorde

void Horde3DWindow::resizeEvent(QResizeEvent* event)
{
	qDebug() << "Horde3DWindow::resizeEvent(" << event->oldSize() << "->" << event->size() << "); devicePixelRatio:" << screen()->devicePixelRatio();

	if(event->size() != event->oldSize())
	{
		m_size = event->size() * screen()->devicePixelRatio();
		m_dirtyView = true;
	} // end if

	QQuickWindow::resizeEvent(event);
} // end geometryChanged

void Horde3DWindow::printHordeMessages()
{
	int msgLevel;
	float msgTime;
	const char* message;

	while((message = h3dGetMessage(&msgLevel, &msgTime)) && strlen(message) > 0)
	{
		qDebug() << msgLevel << "message from Horde3D at" << msgTime << ":" << message;
	} // end while
} // end printHordeMessages

void Horde3DWindow::restoreH3DState()
{
	if(USE_SEPARATE_CONTEXT)
	{
		m_qtContext->doneCurrent();
		m_h3dContext->makeCurrent(this);
	}
	else
	{
		glPushAttrib(GL_ALL_ATTRIB_BITS);
	} // end if

	QOpenGLFunctions glFunctions(QOpenGLContext::currentContext());
	glFunctions.glUseProgram(0);

	if(renderTarget())
	{
		renderTarget()->bind();
	} // end if
} // end restoreH3DState

void Horde3DWindow::saveH3DState()
{
	if(renderTarget())
	{
		renderTarget()->release();
	} // end if

	if(USE_SEPARATE_CONTEXT)
	{
		m_h3dContext->doneCurrent();
		m_qtContext->makeCurrent(this);
	}
	else
	{
		glPopAttrib();
	} // end if
} // end saveH3DState

void Horde3DWindow::updateView()
{
	if(m_initialized)
	{
		qDebug() << "Horde3DWindow::updateView()";

		int deviceWidth = m_size.width();
		int deviceHeight = m_size.height();

		// Resize viewport
		h3dSetNodeParamI(m_camera, H3DCamera::ViewportXI, 0);
		h3dSetNodeParamI(m_camera, H3DCamera::ViewportYI, 0);
		h3dSetNodeParamI(m_camera, H3DCamera::ViewportWidthI, deviceWidth);
		h3dSetNodeParamI(m_camera, H3DCamera::ViewportHeightI, deviceHeight);

		// Set virtual camera parameters
		float aspectRatio = static_cast<float>(deviceWidth) / deviceHeight;
		h3dSetupCameraView(m_camera, 45.0f, aspectRatio, 0.1f, 1000.0f);
		h3dSetNodeTransform(m_camera,
				0, 40, -40,
				//-40, 40, -70,
				23, -166, 180,
				1, 1, 1
				);

		H3DRes cameraPipeRes = h3dGetNodeParamI(m_camera, H3DCamera::PipeResI);
		h3dResizePipelineBuffers(cameraPipeRes, deviceWidth, deviceHeight);

		m_dirtyView = false;
	} // end if
} // end updateView

void Horde3DWindow::timerEvent(QTimerEvent *)
{
	update();
} // end timerEvent

void Horde3DWindow::onBeforeRendering()
{
	if(!m_initialized)
	{
		init();
	} // end if

	if(m_dirtyView)
	{
		updateView();
	} // end if

	if(USE_SEPARATE_CONTEXT)
	{
		if(m_h3dContext && (m_h3dContext->format() != m_qtContext->format()))
		{
			m_h3dContext->deleteLater();
			m_h3dContext = NULL;
		} // end if

		if(!m_h3dContext)
		{
			qDebug() << "Creating new OpenGL context.";
			// Create a new shared OpenGL context to be used exclusively by Horde3D
			m_h3dContext = new QOpenGLContext();
			m_h3dContext->setFormat(requestedFormat());
			m_h3dContext->setShareContext(m_qtContext);
			m_h3dContext->create();
		} // end if
	} // end if

	renderHorde();

	printHordeMessages();
} // end onBeforeRendering

void Horde3DWindow::onInitFinished()
{
	startTimer(16);
} // end onInitFinished

void Horde3DWindow::init()
{
	qDebug() << "Horde3DWindow::init()";

	m_qtContext = openglContext();
	m_samples = m_qtContext->format().samples();

	if(!h3dInit())
	{
		qCritical() << "h3dInit failed";
	} // end if

	int textureAnisotropy = 8;
	if(!h3dSetOption(H3DOptions::MaxAnisotropy, textureAnisotropy))
	{
		qDebug() << "Couldn't set texture anisotropy to" << textureAnisotropy << "!";
	} // end if

	if(!h3dSetOption(H3DOptions::SampleCount, m_samples))
	{
		qDebug() << "Couldn't set antialiasing samples to" << m_samples << "!";
	} // end if

	H3DRes pipeline = h3dAddResource(H3DResTypes::Pipeline, "pipelines/forward.pipeline.xml", 0);
	H3DRes knight = h3dAddResource(H3DResTypes::SceneGraph, "models/knight/knight.scene.xml", 0);
	H3DRes knightAnim1Res = h3dAddResource( H3DResTypes::Animation, "animations/knight_order.anim", 0 );
	H3DRes knightAnim2Res = h3dAddResource( H3DResTypes::Animation, "animations/knight_attack.anim", 0 );

	h3dutLoadResourcesFromDisk("Content");

	m_knight = h3dAddNodes(H3DRootNode, knight);
	h3dSetNodeTransform(m_knight,
			0, 0, 0,
			0, 0, 0,
			1, 1, 1
			);
	h3dSetupModelAnimStage(m_knight, 0, knightAnim1Res, 0, "", false);
	h3dSetupModelAnimStage(m_knight, 1, knightAnim2Res, 0, "", false);

	m_camera = h3dAddCameraNode(H3DRootNode, "cam", pipeline);
	h3dSetNodeParamF(m_camera, H3DCamera::FarPlaneF, 0, 100000);

	m_cameraObject = new CameraNodeObject(m_camera);
	m_cameraQObject = static_cast<QObject *>(m_cameraObject);

	setClearBeforeRendering(false);

	printHordeMessages();
	qDebug() << "--------- Initialization Finished ---------";

	m_initialized = true;
	emit initFinished();
} // end init
<commit_msg>Set m_size at initialization time, and schedule a view update. Should fix render sizing issues at startup.<commit_after>#include "../config.h"
#include "horde3dwindow.h"
#include "cameranodeobject.h"

#include <Horde3DUtils.h>

#include <QtCore/QPropertyAnimation>
#include <QtCore/QCoreApplication>
#include <QtCore/QDir>
#include <QtGui/QOpenGLFunctions>
#include <QtGui/QOpenGLFramebufferObject>
#include <QtGui/QScreen>
#include <QtQuick/QQuickWindow>
#include <QtQuick/QSGSimpleTextureNode>

#include <GL/gl.h>

static const bool USE_SEPARATE_CONTEXT = false;

Horde3DWindow::Horde3DWindow(QWindow *parent) :
		QQuickWindow(parent),
		m_samples(0),
		m_initialized(false),
		m_dirtyView(false),
		m_animTime(0.0f),
		m_qtContext(NULL),
		m_h3dContext(NULL)
{
	connect(this, SIGNAL(beforeRendering()), this, SLOT(onBeforeRendering()), Qt::DirectConnection);
	connect(this, SIGNAL(initFinished()), this, SLOT(onInitFinished()), Qt::QueuedConnection);
} // end Horde3DWindow

Horde3DWindow::~Horde3DWindow()
{
	if(m_h3dContext)
	{
		m_h3dContext->deleteLater();
		m_h3dContext = NULL;
	} // end if
} // end ~Horde3DWindow

void Horde3DWindow::renderHorde()
{
	m_animTime += 0.4f;

	// Do animation blending
	h3dSetModelAnimParams(m_knight, 0, m_animTime, 0.5f);
	h3dSetModelAnimParams(m_knight, 1, m_animTime, 0.5f);
	h3dUpdateModel(m_knight, H3DModelUpdateFlags::Animation | H3DModelUpdateFlags::Geometry);

	if(m_camera)
	{
		if(!USE_SEPARATE_CONTEXT || (m_qtContext && m_h3dContext))
		{
			restoreH3DState();

			h3dRender(m_camera);
			h3dFinalizeFrame();

			saveH3DState();
		} // end if
	} // end if
} // end renderHorde

void Horde3DWindow::resizeEvent(QResizeEvent* event)
{
	qDebug() << "Horde3DWindow::resizeEvent(" << event->oldSize() << "->" << event->size() << "); devicePixelRatio:" << screen()->devicePixelRatio();

	if(event->size() != event->oldSize())
	{
		m_size = event->size() * screen()->devicePixelRatio();
		m_dirtyView = true;
	} // end if

	QQuickWindow::resizeEvent(event);
} // end geometryChanged

void Horde3DWindow::printHordeMessages()
{
	int msgLevel;
	float msgTime;
	const char* message;

	while((message = h3dGetMessage(&msgLevel, &msgTime)) && strlen(message) > 0)
	{
		qDebug() << msgLevel << "message from Horde3D at" << msgTime << ":" << message;
	} // end while
} // end printHordeMessages

void Horde3DWindow::restoreH3DState()
{
	if(USE_SEPARATE_CONTEXT)
	{
		m_qtContext->doneCurrent();
		m_h3dContext->makeCurrent(this);
	}
	else
	{
		glPushAttrib(GL_ALL_ATTRIB_BITS);
	} // end if

	QOpenGLFunctions glFunctions(QOpenGLContext::currentContext());
	glFunctions.glUseProgram(0);

	if(renderTarget())
	{
		renderTarget()->bind();
	} // end if
} // end restoreH3DState

void Horde3DWindow::saveH3DState()
{
	if(renderTarget())
	{
		renderTarget()->release();
	} // end if

	if(USE_SEPARATE_CONTEXT)
	{
		m_h3dContext->doneCurrent();
		m_qtContext->makeCurrent(this);
	}
	else
	{
		glPopAttrib();
	} // end if
} // end saveH3DState

void Horde3DWindow::updateView()
{
	if(m_initialized)
	{
		qDebug() << "Horde3DWindow::updateView()";

		int deviceWidth = m_size.width();
		int deviceHeight = m_size.height();

		// Resize viewport
		h3dSetNodeParamI(m_camera, H3DCamera::ViewportXI, 0);
		h3dSetNodeParamI(m_camera, H3DCamera::ViewportYI, 0);
		h3dSetNodeParamI(m_camera, H3DCamera::ViewportWidthI, deviceWidth);
		h3dSetNodeParamI(m_camera, H3DCamera::ViewportHeightI, deviceHeight);

		// Set virtual camera parameters
		float aspectRatio = static_cast<float>(deviceWidth) / deviceHeight;
		h3dSetupCameraView(m_camera, 45.0f, aspectRatio, 0.1f, 1000.0f);
		h3dSetNodeTransform(m_camera,
				0, 40, -40,
				//-40, 40, -70,
				23, -166, 180,
				1, 1, 1
				);

		H3DRes cameraPipeRes = h3dGetNodeParamI(m_camera, H3DCamera::PipeResI);
		h3dResizePipelineBuffers(cameraPipeRes, deviceWidth, deviceHeight);

		m_dirtyView = false;
	} // end if
} // end updateView

void Horde3DWindow::timerEvent(QTimerEvent *)
{
	update();
} // end timerEvent

void Horde3DWindow::onBeforeRendering()
{
	if(!m_initialized)
	{
		init();
	} // end if

	if(m_dirtyView)
	{
		updateView();
	} // end if

	if(USE_SEPARATE_CONTEXT)
	{
		if(m_h3dContext && (m_h3dContext->format() != m_qtContext->format()))
		{
			m_h3dContext->deleteLater();
			m_h3dContext = NULL;
		} // end if

		if(!m_h3dContext)
		{
			qDebug() << "Creating new OpenGL context.";
			// Create a new shared OpenGL context to be used exclusively by Horde3D
			m_h3dContext = new QOpenGLContext();
			m_h3dContext->setFormat(requestedFormat());
			m_h3dContext->setShareContext(m_qtContext);
			m_h3dContext->create();
		} // end if
	} // end if

	renderHorde();

	printHordeMessages();
} // end onBeforeRendering

void Horde3DWindow::onInitFinished()
{
	startTimer(16);
} // end onInitFinished

void Horde3DWindow::init()
{
	qDebug() << "Horde3DWindow::init()";

	m_qtContext = openglContext();
	m_samples = m_qtContext->format().samples();

	if(!h3dInit())
	{
		qCritical() << "h3dInit failed";
	} // end if

	int textureAnisotropy = 8;
	if(!h3dSetOption(H3DOptions::MaxAnisotropy, textureAnisotropy))
	{
		qDebug() << "Couldn't set texture anisotropy to" << textureAnisotropy << "!";
	} // end if

	if(!h3dSetOption(H3DOptions::SampleCount, m_samples))
	{
		qDebug() << "Couldn't set antialiasing samples to" << m_samples << "!";
	} // end if

	H3DRes pipeline = h3dAddResource(H3DResTypes::Pipeline, "pipelines/forward.pipeline.xml", 0);
	H3DRes knight = h3dAddResource(H3DResTypes::SceneGraph, "models/knight/knight.scene.xml", 0);
	H3DRes knightAnim1Res = h3dAddResource( H3DResTypes::Animation, "animations/knight_order.anim", 0 );
	H3DRes knightAnim2Res = h3dAddResource( H3DResTypes::Animation, "animations/knight_attack.anim", 0 );

	h3dutLoadResourcesFromDisk("Content");

	m_knight = h3dAddNodes(H3DRootNode, knight);
	h3dSetNodeTransform(m_knight,
			0, 0, 0,
			0, 0, 0,
			1, 1, 1
			);
	h3dSetupModelAnimStage(m_knight, 0, knightAnim1Res, 0, "", false);
	h3dSetupModelAnimStage(m_knight, 1, knightAnim2Res, 0, "", false);

	m_camera = h3dAddCameraNode(H3DRootNode, "cam", pipeline);
	h3dSetNodeParamF(m_camera, H3DCamera::FarPlaneF, 0, 100000);

	m_cameraObject = new CameraNodeObject(m_camera);
	m_cameraQObject = static_cast<QObject *>(m_cameraObject);

	setClearBeforeRendering(false);

	printHordeMessages();
	qDebug() << "--------- Initialization Finished ---------";

	m_size = size() * screen()->devicePixelRatio();
	m_dirtyView = true;

	m_initialized = true;
	emit initFinished();
} // end init
<|endoftext|>