<commit_before>#include <cstdio>
#include <iostream>
#include <vector>

using namespace std;

int main() {
    //read strings a and b
    //|a| = |b| for now
    int string_size;

    // calculate submatrix dimension
    int submatrix_dim;

    // call submatrix calculator

    vector<vector<string > > final_columns;
    vector<vector<string > > final_rows;

    int subs_per_side = string_size/submatrix_dim;
    for (int submatrix_i=0; submatrix_i<subs_per_side; submatrix_i++) {
        vector<string> column;
        string temp_string;

        // assuming price for deletion is 1
        for (int string_index=0; string_index<submatrix_dim; string_index++)
            temp_string.push_back('1');

        column.push_back(temp_string);
        final_columns.push_back(column);
    }

    for (int submatrix_j=0; submatrix_j<subs_per_side; submatrix_j++) {
        vector<string> row;
        string temp_string;

        // assuming price for insertion is 1
        for (int string_index=0; string_index<submatrix_dim; string_index++)
            temp_string.push_back('1');

        row.push_back(temp_string);
        final_rows.push_back(row);
    }

    return 0;
}
<commit_msg>Edit distance calculation, missing string padding<commit_after>#include <cstdio>
#include <iostream>
#include <vector>
#include <cmath>

#define BLANK_CHAR ' '

using namespace std;

vector<vector<string > > final_columns;
vector<vector<string > > final_rows;

string string_a, string_b;

int submatrix_dim;
int row_num;
int column_num;

void pad_string()
{

}

void initialize_edit_matrix()
{
    string initial_string(submatrix_dim, '1');

    for (int submatrix_i=1; submatrix_i<=row_num; submatrix_i++)
        final_columns[submatrix_i][0] = initial_string;

    for (int submatrix_j=1; submatrix_j<=column_num; submatrix_j++)
        final_rows[0][submatrix_j] = initial_string;
}

void fill_edit_matrix()
{
    for (int submatrix_i=1; submatrix_i<=row_num; submatrix_i++) {
        for (int submatrix_j=1; submatrix_j<=column_num; submatrix_j++) {
            /*
            pair<string, string> final_steps = subm_calc.getFinalSteps(
                                    string_a.substr((submatrix_i-1)*submatrix_dim, submatrix_dim),
                                    string_b.substr((submatrix_j-1)*submatrix_dim, submatrix_dim),
                                    final_columns[submatrix_i][submatrix_j-1],
                                    final_rows[submatrix_i-1][submatrix_j]);

            final_columns[submatrix_i][submatrix_j] = final_steps.second;
            final_rows[submatrix[i][submatrix_j] = final_steps.first;
            */
        }
    }
}

int calc_edit_distance()
{
    int edit_distance = 0;

    for (int submatrix_i=1; submatrix_i<=row_num; submatrix_i++)
        //edit_distance += subm_calc.sumSteps(final_columns[submatrix_i][0]);

    for (int submatrix_j=1; submatrix_j<=column_num; submatrix_j++)
        //edit_distance += subm_calc.sumSteps(final_rows[subs_per_side][submatrix_j]);

    return edit_distance;
}

int main() {
    //read strings a and b
    string_a = "atcggatta";
    string_b = "atccattcc";

    submatrix_dim = ceil(log(string_a.size()) / log(12));

    // pad strings to fit dimension

    // call submatrix calculator

    int row_num = string_a.size() / submatrix_dim;
    int column_num = string_b.size() / submatrix_dim;
    final_columns.resize(row_num+1, vector<string>(row_num+1, ""));
    final_rows.resize(column_num+1, vector<string>(column_num+1, ""));

    initialize_edit_matrix();
    fill_edit_matrix();

    cout << calc_edit_distance();

    return 0;
}
<|endoftext|>


<commit_before>#include <chrono>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <unistd.h>
#include <signal.h>
#include <cstdio>
#include <fcntl.h>
#include <string>
#include <stdio.h>
#include <termios.h>
#include <mutex>
#include <thread>

#include <boost/asio.hpp>
#include <boost/filesystem.hpp>

#include "protocol/protocol.hpp"
#include "protocol/messages.hpp"
#include "protocol/decoder.hpp"

#include "reader.hpp"
#include "writer.hpp"

int pipeout;
int pipe_instrument;
int armed;

std::ofstream fileout;

template <std::size_t buffer_size>
void handle(const protocol::decoded_message_t<buffer_size>& decoded) {
	switch(decoded.id) {
	case protocol::message::heartbeat_message_t::ID: {
		//auto message = reinterpret_cast<const protocol::message::heartbeat_message_t&>(decoded.payload);
		//std::cout << "<heartbeat>: " << (int) message.seq << std::endl;
		//fileout << "<heartbeat>: " << (int) message.seq << std::endl;
		break;
	}
	case protocol::message::log_message_t::ID: {
		auto message = reinterpret_cast<const protocol::message::log_message_t&>(decoded.payload);
		std::cout << "<log>: " << message.data << std::endl;
		fileout << message.time << " <log>: " << message.data << std::endl;
		break;
    }

	case protocol::message::attitude_message_t::ID: {
		auto message = reinterpret_cast<const protocol::message::attitude_message_t&>(decoded.payload);
		std::ostringstream os;
		os << "attitude,";

		std::cout << "<attitude>: ";
		fileout << message.time << " <attitude>: ";
		for (int i = 0; i < 9; i++) {
			std::cout << std::fixed << std::setprecision(3) << message.dcm[i] << " ";
			fileout << std::fixed << std::setprecision(3) << message.dcm[i] << " ";
			os << message.dcm[i];
			if (i != 8)
				os << ",";
		}
		std::cout << std::endl;
		fileout << std::endl;

		if (pipe_instrument != -1) {
			const char* line = os.str().c_str();
			write(pipe_instrument, line, strlen(line));
		}
		break;
	}
	case protocol::message::motor_throttle_message_t::ID: {
		auto message = reinterpret_cast<const protocol::message::motor_throttle_message_t&>(decoded.payload);
		std::cout << "<throttle>: ";
		fileout << message.time << " <throttle>: ";
		for(int i = 0; i < 4; i++) {
			std::cout << std::fixed << std::setprecision(2) << message.throttles[i] << " ";
			fileout << std::fixed << std::setprecision(2) << message.throttles[i] << " ";
		}
		std::cout << std::endl;
		fileout << std::endl;
		break;
	}

	case protocol::message::location_message_t::ID: {
		auto message = reinterpret_cast<const protocol::message::location_message_t&>(decoded.payload);

		std::cout << "<location>: ";
		fileout << message.time << " <location>: ";
		std::cout << std::fixed << std::setprecision(6) << message.lat << ", " << message.lon << ", " << message.alt << std::endl;
		fileout << std::fixed << std::setprecision(6) << message.lat << ", " << message.lon << ", " << message.alt << std::endl;

		std::ostringstream os;
		os << message.lat << "," << message.lon << "," << message.alt << "\n";
		std::string temp = os.str();
		const char* line = temp.c_str();

		write(pipeout, line, strlen(line));
		break;
	}

	case protocol::message::system_message_t::ID: {
		auto message = reinterpret_cast<const protocol::message::system_message_t&>(decoded.payload);
		std::cout << "<system>: " << +message.state << ", " << std::fixed << std::setprecision(3) << message.motorDC << std::endl;
		fileout << message.time << " <system>: " << +message.state << ", " << std::fixed << std::setprecision(3) << message.motorDC << std::endl;

		armed = (int)message.state;
		if (armed == 1) {
			printf("\033[0m");
		}
		else {
			printf("\033[1;37;41m");
		}
		break;
	}

	case protocol::message::sensor_calibration_response_message_t::ID: {
		//auto message = reinterpret_cast<const protocol::message::sensor_calibration_response_message_t&>(decoded.payload);
		//std::cout << "<calibration>: <accel>: " << "<gyro>: " << "<mag>: " << std::endl;
		//fileout << "<calibration>: <accel>: " << "<gyro>: " << "<mag>: " << std::endl;
		break;
	}

	case protocol::message::raw_1000_message_t::ID: {
		auto message = reinterpret_cast<const protocol::message::raw_1000_message_t&>(decoded.payload);
		std::cout << "<1000>: <accel>: " << std::fixed << std::setprecision(3) << message.accel[0] << " " << message.accel[1] << " " << message.accel[2];
		fileout << "<1000>: <accel>: " << std::fixed << std::setprecision(3) << message.accel[0] << " " << message.accel[1] << " " << message.accel[2];
		std::cout << " <accelH>: " << message.accelH[0] << " " << message.accelH[1] << " " << message.accelH[2];
		fileout << " <accelH>: " << message.accelH[0] << " " << message.accelH[1] << " " << message.accelH[2];
		std::cout << " <gyro>: " << message.gyro[0] << " " << message.gyro[1] << " " << message.gyro[2] << std::endl;
		fileout << " <gyro>: " << message.gyro[0] << " " << message.gyro[1] << " " << message.gyro[2] << std::endl;
		break;
	}

	case protocol::message::raw_50_message_t::ID: {
		auto message = reinterpret_cast<const protocol::message::raw_50_message_t&>(decoded.payload);
		std::cout << "<temp> " << message.temp << std::endl;
		fileout << "<temp> " << message.temp << std::endl;
		break;
	}

	case protocol::message::fs_info_message_t::ID: {
		auto message = reinterpret_cast<const protocol::message::fs_info_message_t&>(decoded.payload);
		std::cout << "<filesystem>: Logging to " << +message.fname<< ", logged " << +message.fsize<< " bytes" << std::endl;
		fileout << message.time << "<filesystem>: Logging to " << +message.fname<< ", logged " << +message.fsize<< " bytes" << std::endl;

		break;
	}

	default:
		//std::cout << "<UNKNOWN>: " << std::hex << decoded.id << std::dec << std::endl;
		//fileout << "<UNKNOWN>: " << std::hex << decoded.id << std::dec << std::endl;
		break;
	}
}

int kbhit(void) {
	struct termios oldt, newt;
	int ch;
	int oldf;

	tcgetattr(STDIN_FILENO, &oldt);
	newt = oldt;
	newt.c_lflag &= ~(ICANON | ECHO);
	tcsetattr(STDIN_FILENO, F_GETFL, 0);
	oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
	fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);

	ch = getchar();

	tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
	fcntl(STDIN_FILENO, F_SETFL, oldf);

	if (ch != EOF) {
		ungetc(ch, stdin);
		return 1;
	}
	return 0;
}

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

	if(argc < 2) {
		std::cerr << "Usage: " << argv[0] << " <ttyUSB>" << std::endl;
		return EXIT_FAILURE;
	}

	std::string pre = "";
	if (strcmp(argv[1], "/dev/ttyUSB0") != 0) {
		pre = "avionics";
		pipeout = open("/tmp/rocket_avionics", O_WRONLY);
		pipe_instrument = -1;
	}
	else {
		pre = "payload";
		pipeout = open("/tmp/rocket_payload", O_WRONLY);
		pipe_instrument = open("/tmp/rocket_insturment", O_WRONLY);
	}

	//std::thread thread_kml(run_kml);

	//Create new numbered log file
	int i = 0;
	while (true) {
		std::ostringstream fo;
		fo << "./logs/" << pre << i << ".txt";
		if (boost::filesystem::exists(fo.str()))
			i++;
		else {
			std::cout << "opened file: " << fo.str() << "\n";
			fileout.open(fo.str());
			break;
		}
	}

	//serial read code begins
	boost::asio::io_service io;
	boost::asio::serial_port port(io, argv[1]);
	port.set_option(boost::asio::serial_port_base::baud_rate(38400));

	protocol::Decoder decoder;

	//Arm and disarm messages
	protocol::Encoder encoder;
	std::mutex write_msg_mutex;
	std::array<std::uint8_t, 255> buffer_out;
	armed = 0;

	protocol::message::set_arm_state_message_t armMsg {
		.armed = true
	};
	protocol::message::set_arm_state_message_t disarmMsg {
		.armed = false
	};

	while(true) {
		char buffer[1];
		boost::asio::read(port, boost::asio::buffer(buffer));

		if (kbhit()) {
			std::string temp;
			std::cin >> temp;
			if (temp.compare("arm") == 0) {
				std::cout << "ARMING ROCKET" << std::endl;
				std::uint16_t len = encoder.encode(armMsg, &buffer_out);
				boost::asio::write(port, boost::asio::buffer(buffer_out.data(), len));
				armed = 1;
			}
			else if (armed > 1) {
				std::cout << "DISARMING ROCKET" << std::endl;
				std::uint16_t len = encoder.encode(disarmMsg, &buffer_out);
				boost::asio::write(port, boost::asio::buffer(buffer_out.data(), len));
			}

			std::cin.clear();
			std::cin.ignore(INT_MAX, '\n');
		}

		protocol::decoded_message_t<255> decoded;
		if(decoder.process(buffer[0], &decoded)) {
			handle(decoded);
		}
	}
}
<commit_msg>Added pretty colors to the terminal<commit_after>#include <chrono>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <unistd.h>
#include <signal.h>
#include <cstdio>
#include <fcntl.h>
#include <string>
#include <stdio.h>
#include <termios.h>
#include <mutex>
#include <thread>

#include <boost/asio.hpp>
#include <boost/filesystem.hpp>

#include "protocol/protocol.hpp"
#include "protocol/messages.hpp"
#include "protocol/decoder.hpp"

#include "reader.hpp"
#include "writer.hpp"

int pipeout;
int pipe_instrument;
int armed;
int armed_count;

std::ofstream fileout;

template <std::size_t buffer_size>
void handle(const protocol::decoded_message_t<buffer_size>& decoded) {
	switch(decoded.id) {
	case protocol::message::heartbeat_message_t::ID: {
		//auto message = reinterpret_cast<const protocol::message::heartbeat_message_t&>(decoded.payload);
		//std::cout << "<heartbeat>: " << (int) message.seq << std::endl;
		//fileout << "<heartbeat>: " << (int) message.seq << std::endl;
		break;
	}
	case protocol::message::log_message_t::ID: {
		auto message = reinterpret_cast<const protocol::message::log_message_t&>(decoded.payload);
		std::cout << "<log>: " << message.data << std::endl;
		fileout << message.time << " <log>: " << message.data << std::endl;
		break;
    }

	case protocol::message::attitude_message_t::ID: {
		auto message = reinterpret_cast<const protocol::message::attitude_message_t&>(decoded.payload);
		std::ostringstream os;
		os << "attitude,";

		std::cout << "<attitude>: ";
		fileout << message.time << " <attitude>: ";
		for (int i = 0; i < 9; i++) {
			std::cout << std::fixed << std::setprecision(3) << message.dcm[i] << " ";
			fileout << std::fixed << std::setprecision(3) << message.dcm[i] << " ";
			os << message.dcm[i];
			if (i != 8)
				os << ",";
		}
		std::cout << std::endl;
		fileout << std::endl;
		os << std::endl;

		if (pipe_instrument != -1) {
			const char* line = os.str().c_str();
			write(pipe_instrument, line, strlen(line));
		}
		break;
	}
	case protocol::message::motor_throttle_message_t::ID: {
		auto message = reinterpret_cast<const protocol::message::motor_throttle_message_t&>(decoded.payload);
		std::cout << "<throttle>: ";
		fileout << message.time << " <throttle>: ";
		for(int i = 0; i < 4; i++) {
			std::cout << std::fixed << std::setprecision(2) << message.throttles[i] << " ";
			fileout << std::fixed << std::setprecision(2) << message.throttles[i] << " ";
		}
		std::cout << std::endl;
		fileout << std::endl;
		break;
	}

	case protocol::message::location_message_t::ID: {
		auto message = reinterpret_cast<const protocol::message::location_message_t&>(decoded.payload);

		std::cout << "<location>: ";
		fileout << message.time << " <location>: ";
		std::cout << std::fixed << std::setprecision(6) << message.lat << ", " << message.lon << ", " << message.alt << std::endl;
		fileout << std::fixed << std::setprecision(6) << message.lat << ", " << message.lon << ", " << message.alt << std::endl;

		std::ostringstream os;
		os << message.lat << "," << message.lon << "," << message.alt << "\n";
		std::string temp = os.str();
		const char* line = temp.c_str();

		write(pipeout, line, strlen(line));
		break;
	}

	case protocol::message::system_message_t::ID: {
		auto message = reinterpret_cast<const protocol::message::system_message_t&>(decoded.payload);
		std::cout << "<system>: " << +message.state << ", " << std::fixed << std::setprecision(3) << message.motorDC << std::endl;
		fileout << message.time << " <system>: " << +message.state << ", " << std::fixed << std::setprecision(3) << message.motorDC << std::endl;

		if (armed != (int)message.state) {
			armed = (int)message.state;
			armed_count = 0;
		}
		break;
	}

	case protocol::message::sensor_calibration_response_message_t::ID: {
		//auto message = reinterpret_cast<const protocol::message::sensor_calibration_response_message_t&>(decoded.payload);
		//std::cout << "<calibration>: <accel>: " << "<gyro>: " << "<mag>: " << std::endl;
		//fileout << "<calibration>: <accel>: " << "<gyro>: " << "<mag>: " << std::endl;
		break;
	}

	case protocol::message::raw_1000_message_t::ID: {
		auto message = reinterpret_cast<const protocol::message::raw_1000_message_t&>(decoded.payload);
		std::cout << "<1000>: <accel>: " << std::fixed << std::setprecision(3) << message.accel[0] << " " << message.accel[1] << " " << message.accel[2];
		fileout << "<1000>: <accel>: " << std::fixed << std::setprecision(3) << message.accel[0] << " " << message.accel[1] << " " << message.accel[2];
		std::cout << " <accelH>: " << message.accelH[0] << " " << message.accelH[1] << " " << message.accelH[2];
		fileout << " <accelH>: " << message.accelH[0] << " " << message.accelH[1] << " " << message.accelH[2];
		std::cout << " <gyro>: " << message.gyro[0] << " " << message.gyro[1] << " " << message.gyro[2] << std::endl;
		fileout << " <gyro>: " << message.gyro[0] << " " << message.gyro[1] << " " << message.gyro[2] << std::endl;
		break;
	}

	case protocol::message::raw_50_message_t::ID: {
		auto message = reinterpret_cast<const protocol::message::raw_50_message_t&>(decoded.payload);
		std::cout << "<temp> " << message.temp << std::endl;
		fileout << "<temp> " << message.temp << std::endl;
		break;
	}

	case protocol::message::fs_info_message_t::ID: {
		auto message = reinterpret_cast<const protocol::message::fs_info_message_t&>(decoded.payload);
		std::cout << "<filesystem>: Logging to " << +message.fname<< ", logged " << +message.fsize<< " bytes" << std::endl;
		fileout << message.time << "<filesystem>: Logging to " << +message.fname<< ", logged " << +message.fsize<< " bytes" << std::endl;

		break;
	}

	default:
		//std::cout << "<UNKNOWN>: " << std::hex << decoded.id << std::dec << std::endl;
		//fileout << "<UNKNOWN>: " << std::hex << decoded.id << std::dec << std::endl;
		break;
	}
}

int kbhit(void) {
	struct termios oldt, newt;
	int ch;
	int oldf;

	tcgetattr(STDIN_FILENO, &oldt);
	newt = oldt;
	newt.c_lflag &= ~(ICANON | ECHO);
	tcsetattr(STDIN_FILENO, F_GETFL, 0);
	oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
	fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);

	ch = getchar();

	tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
	fcntl(STDIN_FILENO, F_SETFL, oldf);

	if (ch != EOF) {
		ungetc(ch, stdin);
		return 1;
	}
	return 0;
}

//Flashes the terminal pretty colors
void update_color() {
	if (armed == 1) {
	}
	if (armed == 2) { //armed
		if (armed_count >= 20) {
			printf("\033[0m");
			armed_count = 0;
		}
		else if (armed_count > 10)
			printf("\033[1;37;41m");
		else
			printf("\033[0m");
		armed_count++;
	}
	if (armed == 3) { //flight, blue
		printf("\033[1;37;44m");
	}
	if (armed == 4) { //apogee, 2hz blue
		if (armed_count >= 20) {
			printf("\033[0m");
			armed_count = 0;
		}
		else if (armed_count > 10)
			printf("\033[1;37;44m");
		else
			printf("\033[0m");
		armed_count++;
	}
	if (armed == 5) { //zero g, 2hz rainbow
		if (armed_count > 50)    //magenta
			printf("\033[1;37;45m");
		else if (armed_count > 40)    //blue
			printf("\033[1;37;44m");
		else if (armed_count > 30)    //cyan
			printf("\033[1;37;46m");
		else if (armed_count > 20)    //green
			printf("\033[1;37;42m");
		else if (armed_count > 10)    //yellow
			printf("\033[1;37;43m");
		else                          //red
			printf("\033[1;37;41m");
		armed_count++;
	}
	if (armed == 6) { //descent, solid violet
		printf("\033[1;37;45m");
	}
	if (armed == 7) { //recovery, 2hz violet
		if (armed_count >= 20) {
			printf("\033[0m");
			armed_count = 0;
		}
		else if (armed_count > 10)
			printf("\033[1;37;45m");
		else
			printf("\033[0m");
		armed_count++;
	}
	else {
		printf("\033[0m");
	}
}

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

	if(argc < 2) {
		std::cerr << "Usage: " << argv[0] << " <ttyUSB>" << std::endl;
		return EXIT_FAILURE;
	}

	std::string pre = "";
	if (strcmp(argv[1], "/dev/ttyUSB0") != 0) {
		pre = "avionics";
		pipeout = open("/tmp/rocket_avionics", O_WRONLY);
		pipe_instrument = -1;
	}
	else {
		pre = "payload";
		pipeout = open("/tmp/rocket_payload", O_WRONLY);
		pipe_instrument = open("/tmp/rocket_insturment", O_WRONLY);
	}

	//std::thread thread_kml(run_kml);

	//Create new numbered log file
	int i = 0;
	while (true) {
		std::ostringstream fo;
		fo << "./logs/" << pre << i << ".txt";
		if (boost::filesystem::exists(fo.str()))
			i++;
		else {
			std::cout << "opened file: " << fo.str() << "\n";
			fileout.open(fo.str());
			break;
		}
	}

	//serial read code begins
	boost::asio::io_service io;
	boost::asio::serial_port port(io, argv[1]);
	port.set_option(boost::asio::serial_port_base::baud_rate(38400));

	protocol::Decoder decoder;

	//Arm and disarm messages
	protocol::Encoder encoder;
	std::mutex write_msg_mutex;
	std::array<std::uint8_t, 255> buffer_out;
	armed = armed_count = 0;

	protocol::message::set_arm_state_message_t armMsg {
		.armed = true
	};
	protocol::message::set_arm_state_message_t disarmMsg {
		.armed = false
	};

	while(true) {
		char buffer[1];
		boost::asio::read(port, boost::asio::buffer(buffer));

		if (kbhit()) {
			std::string temp;
			std::cin >> temp;
			if (temp.compare("arm") == 0) {
				std::cout << "ARMING ROCKET" << std::endl;
				std::uint16_t len = encoder.encode(armMsg, &buffer_out);
				boost::asio::write(port, boost::asio::buffer(buffer_out.data(), len));
				armed = 1;
			}
			else if (armed > 1) {
				std::cout << "DISARMING ROCKET" << std::endl;
				std::uint16_t len = encoder.encode(disarmMsg, &buffer_out);
				boost::asio::write(port, boost::asio::buffer(buffer_out.data(), len));
			}

			std::cin.clear();
			std::cin.ignore(INT_MAX, '\n');
		}

		protocol::decoded_message_t<255> decoded;
		if(decoder.process(buffer[0], &decoded)) {
			handle(decoded);
			update_color();
		}
	}
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2013-2014 Baptiste Wicht.
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <iostream>

#include "report.hpp"
#include "expenses.hpp"
#include "earnings.hpp"
#include "budget_exception.hpp"
#include "accounts.hpp"

using namespace budget;

namespace {

typedef std::vector<std::vector<std::string>> graph_type;

void render(graph_type& graph){
    std::reverse(graph.begin(), graph.end());

    for(auto& line : graph){
        for(auto& col : line){
            std::cout << col;
        }
        std::cout << std::endl;
    }
}

void write(graph_type& graph, int row, int col, const std::string& value){
    for(std::size_t i = 0; i < value.size(); ++i){
        graph[row][col + i] = value[i];
    }
}

void monthly_report(budget::year year){
    auto today = budget::local_day();

    budget::money max_expenses;
    budget::money max_earnings;
    budget::money max_balance;
    budget::money min_expenses;
    budget::money min_earnings;
    budget::money min_balance;

    auto sm = start_month(year);

    std::vector<int> expenses(13);
    std::vector<int> earnings(13);
    std::vector<int> balances(13);

    for(unsigned short i = sm + 1; i < today.month() + 1; ++i){
        budget::month month = i;

        budget::money total_expenses;
        budget::money total_earnings;
        budget::money total_balance;

        for(auto& account : all_accounts(year, month)){
            auto expenses = accumulate_amount_if(all_expenses(),
                [year,month,account](budget::expense& e){return e.account == account.id && e.date.year() == year && e.date.month() == month;});
            auto earnings = accumulate_amount_if(all_earnings(),
                [year,month,account](budget::earning& e){return e.account == account.id && e.date.year() == year && e.date.month() == month;});

            total_expenses += expenses;
            total_earnings += earnings;

            auto balance = account.amount;
            balance -= expenses;
            balance += earnings;

            total_balance += balance;
        }

        expenses[month] = total_expenses.dollars();
        earnings[month] = total_earnings.dollars();
        balances[month] = total_balance.dollars();

        max_expenses = std::max(max_expenses, total_expenses);
        max_earnings = std::max(max_earnings, total_earnings);
        max_balance = std::max(max_balance, total_balance);
        min_expenses = std::min(min_expenses, total_expenses);
        min_earnings = std::min(min_earnings, total_earnings);
        min_balance = std::min(min_balance, total_balance);
    }

    auto height = terminal_height() - 9;
    //auto width = terminal_width() - 6;

    //TODO compute the scale based on the data
    unsigned int scale = 1000;
    unsigned int scale_width = 5;

    int min = 0;
    if(min_expenses.negative() || min_earnings.negative() || min_balance.negative()){
        min = std::min(min_expenses, std::min(min_earnings, min_balance)).dollars();
        min = -1 * ((std::abs(min) / scale) + 1) * scale;
    }

    unsigned int max = std::max(max_earnings, std::max(max_expenses, max_balance)).dollars();
    max = ((max / scale) + 1) * scale;

    unsigned int levels = max / scale + std::abs(min) / scale;

    unsigned int step_height = height / levels;
    unsigned int precision = scale / step_height;

    auto graph_height = 9 + step_height * levels;
    auto graph_width = 6 + (13 - sm) * 8 + (13 - sm - 1) * 2;

    graph_type graph(graph_height, std::vector<std::string>(graph_width, " "));

    //Display graph title

    write(graph, graph_height - 2, 8, "Monthly report of " + to_string(year));

    //Display scale

    int first_step = min == 0 ? 0 : -1 * ((-min % scale) + 1) * scale;

    for(size_t i = 0; i <= levels; ++i){
        int level = first_step + i * scale;

        write(graph, 4 + step_height * i, 1, to_string(level));
    }

    //Display bar

    unsigned int min_index = 3;
    unsigned int zero_index = min_index + 1 + (std::abs(min) / scale) * step_height;

    auto first_bar = scale_width + 2;

    //TODO Choose bar width based on the terminal width

    for(unsigned short i = sm + 1; i < today.month() + 1; ++i){
        budget::month month = i;

        auto col_start = first_bar + 10 * (i - sm - 1);

        //Display month legend
        auto month_str = month.as_short_string();
        write(graph, 1, col_start + 2, month_str);

        for(std::size_t j = 0; j < expenses[month] / precision; ++j){
           graph[zero_index + j][col_start] = "\033[1;41m \033[0m";
           graph[zero_index + j][col_start + 1] = "\033[1;41m \033[0m";
        }

        col_start += 3;

        for(std::size_t j = 0; j < earnings[month] / precision; ++j){
           graph[zero_index + j][col_start] = "\033[1;42m \033[0m";
           graph[zero_index + j][col_start + 1] = "\033[1;42m \033[0m";
        }

        col_start += 3;

        if(balances[month] >= 0){
            for(std::size_t j = 0; j < balances[month] / precision; ++j){
                graph[zero_index + j][col_start] = "\033[1;44m \033[0m";
                graph[zero_index + j][col_start + 1] = "\033[1;44m \033[0m";
            }
        } else {
            for(std::size_t j = 0; j < std::abs(balances[month]) / precision; ++j){
                graph[zero_index - 1 - j][col_start] = "\033[1;44m \033[0m";
                graph[zero_index - 1 - j][col_start + 1] = "\033[1;44m \033[0m";
            }
        }
    }

    //Display legend

    int start_legend = first_bar + 10 * (today.month() - sm) + 4;

    graph[4][start_legend - 2] = "|";
    graph[3][start_legend - 2] = "|";
    graph[2][start_legend - 2] = "|";

    graph[4][start_legend] = "\033[1;41m \033[0m";
    graph[3][start_legend] = "\033[1;42m \033[0m";
    graph[2][start_legend] = "\033[1;44m \033[0m";

    write(graph, 6, start_legend - 2, " ____________ ");
    write(graph, 5, start_legend - 2, "|            |");
    write(graph, 4, start_legend + 2, "Expenses |");
    write(graph, 3, start_legend + 2, "Earnings |");
    write(graph, 2, start_legend + 2, "Balance  |");
    write(graph, 1, start_legend - 2, "|____________|");

    //Render the graph

    render(graph);
}

} //end of anonymous namespace

void budget::report_module::load(){
    load_accounts();
    load_expenses();
    load_earnings();
}

void budget::report_module::handle(const std::vector<std::string>& args){
    auto today = budget::local_day();

    if(args.size() == 1){
        monthly_report(today.year());
    } else {
        auto& subcommand = args[1];

        if(subcommand == "monthly"){
            monthly_report(today.year());
        } else {
            throw budget_exception("Invalid subcommand \"" + subcommand + "\"");
        }
    }
}
<commit_msg>Fix scale display<commit_after>//=======================================================================
// Copyright (c) 2013-2014 Baptiste Wicht.
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <iostream>

#include "report.hpp"
#include "expenses.hpp"
#include "earnings.hpp"
#include "budget_exception.hpp"
#include "accounts.hpp"

using namespace budget;

namespace {

typedef std::vector<std::vector<std::string>> graph_type;

void render(graph_type& graph){
    std::reverse(graph.begin(), graph.end());

    for(auto& line : graph){
        for(auto& col : line){
            std::cout << col;
        }
        std::cout << std::endl;
    }
}

void write(graph_type& graph, int row, int col, const std::string& value){
    for(std::size_t i = 0; i < value.size(); ++i){
        graph[row][col + i] = value[i];
    }
}

void monthly_report(budget::year year){
    auto today = budget::local_day();

    budget::money max_expenses;
    budget::money max_earnings;
    budget::money max_balance;
    budget::money min_expenses;
    budget::money min_earnings;
    budget::money min_balance;

    auto sm = start_month(year);

    std::vector<int> expenses(13);
    std::vector<int> earnings(13);
    std::vector<int> balances(13);

    for(unsigned short i = sm + 1; i < today.month() + 1; ++i){
        budget::month month = i;

        budget::money total_expenses;
        budget::money total_earnings;
        budget::money total_balance;

        for(auto& account : all_accounts(year, month)){
            auto expenses = accumulate_amount_if(all_expenses(),
                [year,month,account](budget::expense& e){return e.account == account.id && e.date.year() == year && e.date.month() == month;});
            auto earnings = accumulate_amount_if(all_earnings(),
                [year,month,account](budget::earning& e){return e.account == account.id && e.date.year() == year && e.date.month() == month;});

            total_expenses += expenses;
            total_earnings += earnings;

            auto balance = account.amount;
            balance -= expenses;
            balance += earnings;

            total_balance += balance;
        }

        expenses[month] = total_expenses.dollars();
        earnings[month] = total_earnings.dollars();
        balances[month] = total_balance.dollars();

        max_expenses = std::max(max_expenses, total_expenses);
        max_earnings = std::max(max_earnings, total_earnings);
        max_balance = std::max(max_balance, total_balance);
        min_expenses = std::min(min_expenses, total_expenses);
        min_earnings = std::min(min_earnings, total_earnings);
        min_balance = std::min(min_balance, total_balance);
    }

    auto height = terminal_height() - 9;
    //auto width = terminal_width() - 6;

    //TODO compute the scale based on the data
    unsigned int scale = 1000;
    unsigned int scale_width = 5;

    int min = 0;
    if(min_expenses.negative() || min_earnings.negative() || min_balance.negative()){
        min = std::min(min_expenses, std::min(min_earnings, min_balance)).dollars();
        min = -1 * ((std::abs(min) / scale) + 1) * scale;
    }

    unsigned int max = std::max(max_earnings, std::max(max_expenses, max_balance)).dollars();
    max = ((max / scale) + 1) * scale;

    unsigned int levels = max / scale + std::abs(min) / scale;

    unsigned int step_height = height / levels;
    unsigned int precision = scale / step_height;

    auto graph_height = 9 + step_height * levels;
    auto graph_width = 6 + (13 - sm) * 8 + (13 - sm - 1) * 2;

    graph_type graph(graph_height, std::vector<std::string>(graph_width, " "));

    //Display graph title

    write(graph, graph_height - 2, 8, "Monthly report of " + to_string(year));

    //Display scale

    for(size_t i = 0; i <= levels; ++i){
        int level = min + i * scale;

        write(graph, 4 + step_height * i, 1, to_string(level));
    }

    //Display bar

    unsigned int min_index = 3;
    unsigned int zero_index = min_index + 1 + (std::abs(min) / scale) * step_height;

    auto first_bar = scale_width + 2;

    //TODO Choose bar width based on the terminal width

    for(unsigned short i = sm + 1; i < today.month() + 1; ++i){
        budget::month month = i;

        auto col_start = first_bar + 10 * (i - sm - 1);

        //Display month legend
        auto month_str = month.as_short_string();
        write(graph, 1, col_start + 2, month_str);

        for(std::size_t j = 0; j < expenses[month] / precision; ++j){
           graph[zero_index + j][col_start] = "\033[1;41m \033[0m";
           graph[zero_index + j][col_start + 1] = "\033[1;41m \033[0m";
        }

        col_start += 3;

        for(std::size_t j = 0; j < earnings[month] / precision; ++j){
           graph[zero_index + j][col_start] = "\033[1;42m \033[0m";
           graph[zero_index + j][col_start + 1] = "\033[1;42m \033[0m";
        }

        col_start += 3;

        if(balances[month] >= 0){
            for(std::size_t j = 0; j < balances[month] / precision; ++j){
                graph[zero_index + j][col_start] = "\033[1;44m \033[0m";
                graph[zero_index + j][col_start + 1] = "\033[1;44m \033[0m";
            }
        } else {
            for(std::size_t j = 0; j < std::abs(balances[month]) / precision; ++j){
                graph[zero_index - 1 - j][col_start] = "\033[1;44m \033[0m";
                graph[zero_index - 1 - j][col_start + 1] = "\033[1;44m \033[0m";
            }
        }
    }

    //Display legend

    int start_legend = first_bar + 10 * (today.month() - sm) + 4;

    graph[4][start_legend - 2] = "|";
    graph[3][start_legend - 2] = "|";
    graph[2][start_legend - 2] = "|";

    graph[4][start_legend] = "\033[1;41m \033[0m";
    graph[3][start_legend] = "\033[1;42m \033[0m";
    graph[2][start_legend] = "\033[1;44m \033[0m";

    write(graph, 6, start_legend - 2, " ____________ ");
    write(graph, 5, start_legend - 2, "|            |");
    write(graph, 4, start_legend + 2, "Expenses |");
    write(graph, 3, start_legend + 2, "Earnings |");
    write(graph, 2, start_legend + 2, "Balance  |");
    write(graph, 1, start_legend - 2, "|____________|");

    //Render the graph

    render(graph);
}

} //end of anonymous namespace

void budget::report_module::load(){
    load_accounts();
    load_expenses();
    load_earnings();
}

void budget::report_module::handle(const std::vector<std::string>& args){
    auto today = budget::local_day();

    if(args.size() == 1){
        monthly_report(today.year());
    } else {
        auto& subcommand = args[1];

        if(subcommand == "monthly"){
            monthly_report(today.year());
        } else {
            throw budget_exception("Invalid subcommand \"" + subcommand + "\"");
        }
    }
}
<|endoftext|>


<commit_before>#pragma ident "$Id$"

/**
 * @file Vector.hpp
 * Classes for Vector, both constant and modifiable
 */

#ifndef GPSTK_VECTOR_HPP
#define GPSTK_VECTOR_HPP

//============================================================================
//
//  This file is part of GPSTk, the GPS Toolkit.
//
//  The GPSTk is free software; you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published
//  by the Free Software Foundation; either version 2.1 of the License, or
//  any later version.
//
//  The GPSTk is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with GPSTk; if not, write to the Free Software Foundation,
//  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Copyright 2004, The University of Texas at Austin
//
//============================================================================

#include "VectorBase.hpp"

namespace gpstk
{
 /** @addtogroup VectorGroup */
   //@{

// forward declaration
   template <class T> class VectorSlice;

/**
 * This class pretty much duplicates std::valarray<T> except it's fully
 * STL container compliant.  Remember that operators +=, -=, *= and /=
 * are provided by RefVectorBase.
 *
 * @sa matvectest.cpp for examples
 */
   template <class T>
   class Vector : public RefVectorBase<T, Vector<T> >
   {
   public:
         /// STL value type
      typedef T value_type;
         /// STL reference type
      typedef T& reference;
         /// STL const reference type
      typedef const T& const_reference;
         /// STL iterator type
      typedef T* iterator;
         /// STL const iterator type
      typedef const T* const_iterator;

         /// Default constructor
      Vector() : v(NULL), s(0) {}
         /// Constructor given an initial size.
      Vector(size_t siz) : s(siz)
            //: v(new T[siz]), s(siz)
         {
            v = new T[siz];
            if(!v) {
               VectorException e("Vector(size_t) failed to allocate");
               GPSTK_THROW(e);
            }
         }
         /**
          * Constructor given an initial size and default value for all elements.
          */
      Vector(size_t siz, const T defaultValue) : s(siz)
            //: v(new T[siz]), s(siz)
         {
            v = new T[siz];
            if(!v) {
               VectorException e("Vector<T>(size_t, const T) failed to allocate");
               GPSTK_THROW(e);
            }
            assignFrom(defaultValue);
         }
         /**
          * Copy constructor from a ConstVectorBase type.
          */
      template <class E>
      Vector(const ConstVectorBase<T, E>& r) : s(r.size())
            //: v(new T[r.size()]), s(r.size())
         {
            v = new T[r.size()];
            if(!v) {
               VectorException e("Vector<T>(ConstVectorBase) failed to allocate");
               GPSTK_THROW(e);
            }
            assignFrom(r);
         }
         /**
          * Copy constructor.
          */
      Vector(const Vector& r) : s(r.s)
            //: v(new T[r.s]), s(r.s)
         {
            v = new T[r.s];
            if(!v) {
               VectorException e("Vector(Vector) failed to allocate");
               GPSTK_THROW(e);
            }
            assignFrom(r);
         }
         /**
          * Valarray constructor
          */
      Vector(const std::valarray<T>& r) : s(r.size())
            //: v(new T[r.size()]), s(r.size())
         {
            v = new T[r.size()];
            if(!v) {
               VectorException e("Vector(valarray) failed to allocate");
               GPSTK_THROW(e);
            }
            assignFrom(r);
         }

         /// subvector constructor
      template <class E>
      Vector(const ConstVectorBase<T, E>& vec,
             size_t top,
             size_t num) : v(size_t(0)),s(0)
         {
               // sanity checks...
            if ( top >= vec.size() ||
                 top + num > vec.size())
            {
               VectorException e("Invalid dimensions or size for Vector(VectorBase)");
               GPSTK_THROW(e);
            }

            v = new T[num];
            if(!v) {
               VectorException e("Vector(subvector) failed to allocate");
               GPSTK_THROW(e);
            }
            size_t i;
            for(i = 0; i < num; i++)
               v[i] = vec(top+i);
            s = num;
         }

         /// Destructor
      ~Vector()
         { if (v) delete [] v; }

         /// STL iterator begin
      iterator begin() { return v; }
         /// STL const iterator begin
      const_iterator begin() const { return v; }
         /// STL iterator end
      iterator end() { return v + s; }
         /// STL const iterator end
      const_iterator end() const { return v + s; }
         /// STL front
      value_type front() { return v[s-1]; }
         /// STL const front
      const_reference front() const { return v[s-1];}
         /// STL empty
      bool empty() const { return size == 0; }
         /// STL size
      size_t size() const {return s; }
         /// STL max_size
      size_t max_size() const { return std::numeric_limits<size_t>().max(); }

         /// Non-const operator []
      T& operator[] (size_t i)
         { return v[i]; }
         /// Const operator []
      T operator[] (size_t i) const
         { return v[i]; }
         /// Non-const operator ()
      T& operator() (size_t i)
         { return v[i]; }
         /// Const operator ()
      T operator() (size_t i) const
         { return v[i]; }

         /// Like valarray, lets you do vec[slice] to get a VectorSlice.
      VectorSlice<T> operator[] (const std::slice& sli)
         { return VectorSlice<T>(*this, sli); }

         /// *this will be resized if it isn't as large as x.
      Vector& operator=(const Vector& x)
         { resize(x.s); return assignFrom(x); }

         /// *this will be resized if it isn't as large as x.
      template <class E>
      Vector& operator=(const ConstVectorBase<T, E>& x)
         { resize(x.size()); return assignFrom(x); }

         /// *this will be resized if it isn't as large as x.
      Vector& operator=(const std::valarray<T>& x)
         { resize(x.size()); return assignFrom(x); }
         /// Only (*this).size() elements will be assigned.
      Vector& operator=(const T x)
         { return assignFrom(x); }
         /// Only (*this).size() elements will be assigned.
      Vector& operator=(const T* x)
         { return assignFrom(x); }

         /// Resizes the vector.  if index > size, the vector will be
         /// erased and the contents destroyed.
      Vector& resize(const size_t index)
         {
            if (index > s)
            {
               if (v)
                  delete [] v;
               v = new T[index];
               if(!v) {
                  VectorException e("Vector.resize(size_t) failed to allocate");
                  GPSTK_THROW(e);
               }
            }
            s = index;
            return *this;
         }

         /// resize with new default value
      Vector& resize(const size_t index, const T defaultValue)
         {
            resize(index);
            size_t i;
            for(i = 0; i < s; i++)
               v[i] = defaultValue;
            return *this;
         }

   private:

         // a good optimizer will remove this function call
         // if RANGECHECK isn't defined.  remember that
         // range checking affects EVERY operation
      inline bool rangeCheck(const size_t index) const
         {
#ifdef RANGECHECK
            return (index < s);
#else
            return true;
#endif
         }

         /// The vector
      T* v;
         /// The size of the vector.
      size_t s;
   };
   // end class Vector<T>

/**
 * A slice of Vector<T> that can be modified.
 * @warning Remember that (VectorSlice = VectorSlice) will
 * assign elements to the VectorSlice, not copy the VectorSlice internal data!
 */
   template <class T>
   class VectorSlice : public RefVectorSliceBase<T, VectorSlice<T> >
   {
   public:
         /// Default constructor
      VectorSlice()
            : v(NULL), s(std::slice(0,0,0))
         { }

         /// Makes a slice of the whole vector
      VectorSlice(Vector<T>& vv)
            : v(&vv), s(std::slice(0,vv.size(),1))
         { }

         /// Makes a slice of the vector with the given std::slice.
      VectorSlice(Vector<T>& vv, const std::slice& ss)
            : v(&vv), s(ss)
         { vecSliceCheck(vv.size()); }

         /// Assign the elements of this slice from another vector.
      template <class V>
      VectorSlice& operator=(const ConstVectorBase<T, V>& x)
         { return assignFrom(x); }

         /// Assign the elements of this slice from a valarray.
      VectorSlice& operator=(const std::valarray<T>& x)
         { return assignFrom(x); }

         /// Assign all the elements of this slice to x.
      VectorSlice& operator=(const T x)
         { return assignFrom(x); }

         /// Assign (*this).size() elements from x to (*this).
      VectorSlice& operator=(const T* x)
         { return assignFrom(x); }

         /// Returns the modifiable i'th element of the slice.
      T& operator[] (size_t i)
         { return (*v)[start() + i * stride()]; }
         /// Returns the const i'th element of the slice.
      T operator[] (size_t i) const
         { return (*v)[start() + i * stride()]; }
         /// Returns the modifiable i'th element of the slice.
      T& operator() (size_t i)
         { return (*v)[start() + i * stride()]; }
         /// Returns the const i'th element of the slice.
      T operator() (size_t i) const
         { return (*v)[start() + i * stride()]; }

         /// returns the number of elements in the slice
      inline size_t size() const { return s.size(); }
         /// returns the index in the vector of the first element.
      inline size_t start() const { return s.start(); }
         /// returns the number of elements to skip between (*this)[i] and
         /// (*this)[i+1]
      inline size_t stride() const { return s.stride(); }
   private:
         /// the vector used as a source for the slice
      Vector<T>* v;
         /// the slice specification.
      std::slice s;
   };

/**
 * A Vector<T> slice that doesn't allow modification.
 */
   template <class T>
   class ConstVectorSlice : public ConstVectorSliceBase<T, ConstVectorSlice<T> >
   {
   public:
         /// default constructor
      ConstVectorSlice()
            : v(NULL), s(std::slice(0,0,0))
         { }

         /// Makes a slice of the whole vector
      ConstVectorSlice(const Vector<T>& vv)
            : v(&vv), s(std::slice(0,vv.size(),1))
         { }

         /// Uses the given slice and vector.
      ConstVectorSlice(const Vector<T>& vv, const std::slice& ss)
            : v(&vv), s(ss)
         { vecSliceCheck(vv.size()); }

         /// Returns a const version of the i'th slice element.
      T operator[] (size_t i) const
         { return (*v)[start() + i * stride()]; }
         /// Returns a const version of the i'th slice element.
      T operator() (size_t i) const
         { return (*v)[start() + i * stride()]; }

         /// returns the number of elements in the slice
      inline size_t size() const { return s.size(); }
         /// returns the index in the vector of the first element.
      inline size_t start() const { return s.start(); }
         /// returns the number of elements to skip between (*this)[i] and
         /// (*this)[i+1]
      inline size_t stride() const { return s.stride(); }

   private:
         /// Vectortor used as a source for this slice.
      const Vector<T>* v;
         /// the slice specification.
      std::slice s;
   };

   //@}

}  // namespace

#include "VectorOperators.hpp"

#endif
<commit_msg>src/Vector.hpp: Added method Vector& operator=(const std::vector<T>& x) and concatenation methods Vector operator&&(const Vector &b) and Vector operator&&(const T &b).<commit_after>#pragma ident "$Id$"

/**
 * @file Vector.hpp
 * Classes for Vector, both constant and modifiable
 */

#ifndef GPSTK_VECTOR_HPP
#define GPSTK_VECTOR_HPP

//============================================================================
//
//  This file is part of GPSTk, the GPS Toolkit.
//
//  The GPSTk is free software; you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published
//  by the Free Software Foundation; either version 2.1 of the License, or
//  any later version.
//
//  The GPSTk is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with GPSTk; if not, write to the Free Software Foundation,
//  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Copyright 2004, The University of Texas at Austin
//
//============================================================================

#include "VectorBase.hpp"

namespace gpstk
{
 /** @addtogroup VectorGroup */
   //@{

// forward declaration
   template <class T> class VectorSlice;

/**
 * This class pretty much duplicates std::valarray<T> except it's fully
 * STL container compliant.  Remember that operators +=, -=, *= and /=
 * are provided by RefVectorBase.
 *
 * @sa matvectest.cpp for examples
 */
   template <class T>
   class Vector : public RefVectorBase<T, Vector<T> >
   {
   public:
         /// STL value type
      typedef T value_type;
         /// STL reference type
      typedef T& reference;
         /// STL const reference type
      typedef const T& const_reference;
         /// STL iterator type
      typedef T* iterator;
         /// STL const iterator type
      typedef const T* const_iterator;

         /// Default constructor
      Vector() : v(NULL), s(0) {}
         /// Constructor given an initial size.
      Vector(size_t siz) : s(siz)
            //: v(new T[siz]), s(siz)
         {
            v = new T[siz];
            if(!v) {
               VectorException e("Vector(size_t) failed to allocate");
               GPSTK_THROW(e);
            }
         }
         /**
          * Constructor given an initial size and default value for all elements.
          */
      Vector(size_t siz, const T defaultValue) : s(siz)
            //: v(new T[siz]), s(siz)
         {
            v = new T[siz];
            if(!v) {
               VectorException e("Vector<T>(size_t, const T) failed to allocate");
               GPSTK_THROW(e);
            }
            assignFrom(defaultValue);
         }
         /**
          * Copy constructor from a ConstVectorBase type.
          */
      template <class E>
      Vector(const ConstVectorBase<T, E>& r) : s(r.size())
            //: v(new T[r.size()]), s(r.size())
         {
            v = new T[r.size()];
            if(!v) {
               VectorException e("Vector<T>(ConstVectorBase) failed to allocate");
               GPSTK_THROW(e);
            }
            assignFrom(r);
         }
         /**
          * Copy constructor.
          */
      Vector(const Vector& r) : s(r.s)
            //: v(new T[r.s]), s(r.s)
         {
            v = new T[r.s];
            if(!v) {
               VectorException e("Vector(Vector) failed to allocate");
               GPSTK_THROW(e);
            }
            assignFrom(r);
         }
         /**
          * Valarray constructor
          */
      Vector(const std::valarray<T>& r) : s(r.size())
            //: v(new T[r.size()]), s(r.size())
         {
            v = new T[r.size()];
            if(!v) {
               VectorException e("Vector(valarray) failed to allocate");
               GPSTK_THROW(e);
            }
            assignFrom(r);
         }

         /// subvector constructor
      template <class E>
      Vector(const ConstVectorBase<T, E>& vec,
             size_t top,
             size_t num) : v(size_t(0)),s(0)
         {
               // sanity checks...
            if ( top >= vec.size() ||
                 top + num > vec.size())
            {
               VectorException e("Invalid dimensions or size for Vector(VectorBase)");
               GPSTK_THROW(e);
            }

            v = new T[num];
            if(!v) {
               VectorException e("Vector(subvector) failed to allocate");
               GPSTK_THROW(e);
            }
            size_t i;
            for(i = 0; i < num; i++)
               v[i] = vec(top+i);
            s = num;
         }

         /// Destructor
      ~Vector()
         { if (v) delete [] v; }

         /// STL iterator begin
      iterator begin() { return v; }
         /// STL const iterator begin
      const_iterator begin() const { return v; }
         /// STL iterator end
      iterator end() { return v + s; }
         /// STL const iterator end
      const_iterator end() const { return v + s; }
         /// STL front
      value_type front() { return v[s-1]; }
         /// STL const front
      const_reference front() const { return v[s-1];}
         /// STL empty
      bool empty() const { return size == 0; }
         /// STL size
      size_t size() const {return s; }
         /// STL max_size
      size_t max_size() const { return std::numeric_limits<size_t>().max(); }

         /// Non-const operator []
      T& operator[] (size_t i)
         { return v[i]; }
         /// Const operator []
      T operator[] (size_t i) const
         { return v[i]; }
         /// Non-const operator ()
      T& operator() (size_t i)
         { return v[i]; }
         /// Const operator ()
      T operator() (size_t i) const
         { return v[i]; }

         /// Like valarray, lets you do vec[slice] to get a VectorSlice.
      VectorSlice<T> operator[] (const std::slice& sli)
         { return VectorSlice<T>(*this, sli); }

         /// *this will be resized if it isn't as large as x.
      Vector& operator=(const Vector& x)
         { resize(x.s); return assignFrom(x); }

         /// *this will be resized if it isn't as large as x.
      template <class E>
      Vector& operator=(const ConstVectorBase<T, E>& x)
         { resize(x.size()); return assignFrom(x); }

         /// *this will be resized if it isn't as large as x.
      Vector& operator=(const std::valarray<T>& x)
         { resize(x.size()); return assignFrom(x); }
         /// Only (*this).size() elements will be assigned.
      Vector& operator=(const T x)
         { return assignFrom(x); }
         /// Only (*this).size() elements will be assigned.
      Vector& operator=(const T* x)
         { return assignFrom(x); }

      /// *this will be cleared and resized as necessary
      inline Vector& operator=(const std::vector<T>& x)
      {
          size_t i;
          size_t vs = x.size();
          (*this).resize(vs);

          for (i = 0; i < vs; i++)
              (*this)[i] = x[i];

          return (*this);
      }

         /// Resizes the vector.  if index > size, the vector will be
         /// erased and the contents destroyed.
      Vector& resize(const size_t index)
         {
            if (index > s)
            {
               if (v)
                  delete [] v;
               v = new T[index];
               if(!v) {
                  VectorException e("Vector.resize(size_t) failed to allocate");
                  GPSTK_THROW(e);
               }
            }
            s = index;
            return *this;
         }

         /// resize with new default value
      Vector& resize(const size_t index, const T defaultValue)
         {
            resize(index);
            size_t i;
            for(i = 0; i < s; i++)
               v[i] = defaultValue;
            return *this;
         }

    /// Returns the concatenation of this Vector and Vector b
    inline Vector operator&&(const Vector &b)
    {
        size_t i;
        size_t vs = this->size();
        size_t bs = b.size();
        size_t rows = vs + bs;
        Vector<T> toReturn(rows);

        for (i = 0; i < vs; i++)
            toReturn[i] = (*this)[i];

        for (i = 0; i < bs; i++)
            toReturn[i+vs] = b[i];

        return toReturn;
    }

    /// Returns the concatenation of this Vector and a scalar of type T
    inline Vector operator&&(const T &b)
    {
        size_t i;
        size_t vs = this->size();
        size_t rows = vs + 1;
        Vector<T> toReturn(rows);

        for (i = 0; i < vs; i++)
            toReturn[i] = (*this)[i];

        toReturn[rows - 1] = b;

        return toReturn;
    }

   private:

         // a good optimizer will remove this function call
         // if RANGECHECK isn't defined.  remember that
         // range checking affects EVERY operation
      inline bool rangeCheck(const size_t index) const
         {
#ifdef RANGECHECK
            return (index < s);
#else
            return true;
#endif
         }

         /// The vector
      T* v;
         /// The size of the vector.
      size_t s;
   };
   // end class Vector<T>

/**
 * A slice of Vector<T> that can be modified.
 * @warning Remember that (VectorSlice = VectorSlice) will
 * assign elements to the VectorSlice, not copy the VectorSlice internal data!
 */
   template <class T>
   class VectorSlice : public RefVectorSliceBase<T, VectorSlice<T> >
   {
   public:
         /// Default constructor
      VectorSlice()
            : v(NULL), s(std::slice(0,0,0))
         { }

         /// Makes a slice of the whole vector
      VectorSlice(Vector<T>& vv)
            : v(&vv), s(std::slice(0,vv.size(),1))
         { }

         /// Makes a slice of the vector with the given std::slice.
      VectorSlice(Vector<T>& vv, const std::slice& ss)
            : v(&vv), s(ss)
         { vecSliceCheck(vv.size()); }

         /// Assign the elements of this slice from another vector.
      template <class V>
      VectorSlice& operator=(const ConstVectorBase<T, V>& x)
         { return assignFrom(x); }

         /// Assign the elements of this slice from a valarray.
      VectorSlice& operator=(const std::valarray<T>& x)
         { return assignFrom(x); }

         /// Assign all the elements of this slice to x.
      VectorSlice& operator=(const T x)
         { return assignFrom(x); }

         /// Assign (*this).size() elements from x to (*this).
      VectorSlice& operator=(const T* x)
         { return assignFrom(x); }

         /// Returns the modifiable i'th element of the slice.
      T& operator[] (size_t i)
         { return (*v)[start() + i * stride()]; }
         /// Returns the const i'th element of the slice.
      T operator[] (size_t i) const
         { return (*v)[start() + i * stride()]; }
         /// Returns the modifiable i'th element of the slice.
      T& operator() (size_t i)
         { return (*v)[start() + i * stride()]; }
         /// Returns the const i'th element of the slice.
      T operator() (size_t i) const
         { return (*v)[start() + i * stride()]; }

         /// returns the number of elements in the slice
      inline size_t size() const { return s.size(); }
         /// returns the index in the vector of the first element.
      inline size_t start() const { return s.start(); }
         /// returns the number of elements to skip between (*this)[i] and
         /// (*this)[i+1]
      inline size_t stride() const { return s.stride(); }
   private:
         /// the vector used as a source for the slice
      Vector<T>* v;
         /// the slice specification.
      std::slice s;
   };

/**
 * A Vector<T> slice that doesn't allow modification.
 */
   template <class T>
   class ConstVectorSlice : public ConstVectorSliceBase<T, ConstVectorSlice<T> >
   {
   public:
         /// default constructor
      ConstVectorSlice()
            : v(NULL), s(std::slice(0,0,0))
         { }

         /// Makes a slice of the whole vector
      ConstVectorSlice(const Vector<T>& vv)
            : v(&vv), s(std::slice(0,vv.size(),1))
         { }

         /// Uses the given slice and vector.
      ConstVectorSlice(const Vector<T>& vv, const std::slice& ss)
            : v(&vv), s(ss)
         { vecSliceCheck(vv.size()); }

         /// Returns a const version of the i'th slice element.
      T operator[] (size_t i) const
         { return (*v)[start() + i * stride()]; }
         /// Returns a const version of the i'th slice element.
      T operator() (size_t i) const
         { return (*v)[start() + i * stride()]; }

         /// returns the number of elements in the slice
      inline size_t size() const { return s.size(); }
         /// returns the index in the vector of the first element.
      inline size_t start() const { return s.start(); }
         /// returns the number of elements to skip between (*this)[i] and
         /// (*this)[i+1]
      inline size_t stride() const { return s.stride(); }

   private:
         /// Vectortor used as a source for this slice.
      const Vector<T>* v;
         /// the slice specification.
      std::slice s;
   };

   //@}

}  // namespace

#include "VectorOperators.hpp"

#endif
<|endoftext|>


<commit_before>#include <node.h>
#include <nan.h>
#include <v8.h>
#include <vector>
#include "mouse.h"
#include "deadbeef_rand.h"
#include "keypress.h"

using namespace v8;

/*
 __  __
|  \/  | ___  _   _ ___  ___
| |\/| |/ _ \| | | / __|/ _ \
| |  | | (_) | |_| \__ \  __/
|_|  |_|\___/ \__,_|___/\___|

 */

Handle<Value> moveMouse(const Arguments& args)
{
  HandleScope scope;
  if (args.Length() < 2)
  {
    ThrowException(Exception::TypeError(String::New("Wrong number of arguments")));
    return scope.Close(Undefined());
  }
  size_t x = args[0]->Int32Value();
  size_t y = args[1]->Int32Value();

  MMPoint point;
  point = MMPointMake(x, y);
  moveMouse(point);
  return scope.Close(String::New("1"));
}

Handle<Value> getMousePos(const Arguments& args)
{
  HandleScope scope;

  MMPoint pos = getMousePos();

  //Return object with .x and .y.
  Local<Object> obj = Object::New();
  obj->Set(String::NewSymbol("x"), Number::New(pos.x));
  obj->Set(String::NewSymbol("y"), Number::New(pos.y));
  return scope.Close(obj);
}

NAN_METHOD(mouseClick)
{
  NanScope();

  MMMouseButton button = LEFT_BUTTON;

  clickMouse(button);

  NanReturnValue(NanNew("1"));
}

/*
 _  __          _                         _
| |/ /___ _   _| |__   ___   __ _ _ __ __| |
| ' // _ \ | | | '_ \ / _ \ / _` | '__/ _` |
| . \  __/ |_| | |_) | (_) | (_| | | | (_| |
|_|\_\___|\__, |_.__/ \___/ \__,_|_|  \__,_|
          |___/
 */

char *get(v8::Local<v8::Value> value, const char *fallback = "")
{
    if (value->IsString())
    {
        v8::String::AsciiValue string(value);
        char *str = (char *) malloc(string.length() + 1);
        strcpy(str, *string);
        return str;
    }
    char *str = (char *) malloc(strlen(fallback) + 1);
    strcpy(str, fallback);
    return str;
}

Handle<Value> keyTap(const Arguments& args)
{
  HandleScope scope;

  MMKeyFlags flags = MOD_NONE;

  char c = get(args[0])[0];

  if (strlen(&c)==1)
  {
    tapKey(c, flags);
  }

  return scope.Close(String::New("1"));
}

Handle<Value> typeString(const Arguments& args)
{
  HandleScope scope;

  char *str = get(args[0]);

  typeString(str);

  return scope.Close(String::New("1"));
}

void init(Handle<Object> target)
{

  target->Set(NanNew<String>("moveMouse"),
    NanNew<FunctionTemplate>(moveMouse)->GetFunction());

  target->Set(NanNew<String>("getMousePos"),
    NanNew<FunctionTemplate>(getMousePos)->GetFunction());

  target->Set(NanNew<String>("mouseClick"),
    NanNew<FunctionTemplate>(mouseClick)->GetFunction());

  target->Set(NanNew<String>("keyTap"),
    NanNew<FunctionTemplate>(keyTap)->GetFunction());

  target->Set(NanNew<String>("typeString"),
    NanNew<FunctionTemplate>(typeString)->GetFunction());

}

NODE_MODULE(robotjs, init)
<commit_msg>Converted rest of code to nan.<commit_after>#include <node.h>
#include <nan.h>
#include <v8.h>
#include <vector>
#include "mouse.h"
#include "deadbeef_rand.h"
#include "keypress.h"

using namespace v8;

/*
 __  __
|  \/  | ___  _   _ ___  ___
| |\/| |/ _ \| | | / __|/ _ \
| |  | | (_) | |_| \__ \  __/
|_|  |_|\___/ \__,_|___/\___|

 */

NAN_METHOD(moveMouse)
{
  NanScope();
  if (args.Length() < 2)
  {
    return NanThrowError("Invalid number of arguments");
  }
  size_t x = args[0]->Int32Value();
  size_t y = args[1]->Int32Value();

  MMPoint point;
  point = MMPointMake(x, y);
  moveMouse(point);
  NanReturnValue(NanNew("1"));
}

NAN_METHOD(getMousePos)
{
  NanScope();

  MMPoint pos = getMousePos();

  //Return object with .x and .y.
  Local<Object> obj = NanNew<Object>();
  obj->Set(NanNew<String>("x"), NanNew<Number>(pos.x));
  obj->Set(NanNew<String>("y"), NanNew<Number>(pos.y));
  NanReturnValue(obj);
}

NAN_METHOD(mouseClick)
{
  NanScope();

  MMMouseButton button = LEFT_BUTTON;

  clickMouse(button);

  NanReturnValue(NanNew("1"));
}

/*
 _  __          _                         _
| |/ /___ _   _| |__   ___   __ _ _ __ __| |
| ' // _ \ | | | '_ \ / _ \ / _` | '__/ _` |
| . \  __/ |_| | |_) | (_) | (_| | | | (_| |
|_|\_\___|\__, |_.__/ \___/ \__,_|_|  \__,_|
          |___/
 */

char *get(v8::Local<v8::Value> value, const char *fallback = "")
{
    if (value->IsString())
    {
        v8::String::AsciiValue string(value);
        char *str = (char *) malloc(string.length() + 1);
        strcpy(str, *string);
        return str;
    }
    char *str = (char *) malloc(strlen(fallback) + 1);
    strcpy(str, fallback);
    return str;
}

NAN_METHOD (keyTap)
{
  NanScope();

  MMKeyFlags flags = MOD_NONE;

  const char c = (*v8::String::Utf8Value(args[0]->ToString()))[0];

  tapKey(c, flags);

  NanReturnValue(NanNew("1"));
}

NAN_METHOD (typeString)
{
  NanScope();

  char *str = get(args[0]->ToString());

  typeString(str);

  NanReturnValue(NanNew("1"));
}

void init(Handle<Object> target)
{

  target->Set(NanNew<String>("moveMouse"),
    NanNew<FunctionTemplate>(moveMouse)->GetFunction());

  target->Set(NanNew<String>("getMousePos"),
    NanNew<FunctionTemplate>(getMousePos)->GetFunction());

  target->Set(NanNew<String>("mouseClick"),
    NanNew<FunctionTemplate>(mouseClick)->GetFunction());

  target->Set(NanNew<String>("keyTap"),
    NanNew<FunctionTemplate>(keyTap)->GetFunction());

  target->Set(NanNew<String>("typeString"),
    NanNew<FunctionTemplate>(typeString)->GetFunction());

}

NODE_MODULE(robotjs, init)
<|endoftext|>


<commit_before>#include <iostream>
#include <vector>
#include <string>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <boost/tokenizer.hpp>

using namespace std;
using namespace boost;

int syntaxCheck(vector<string>&vect);
bool isConnector(string&);
bool validConnector(string&);
void executor(vector<string> &vect);
void commandParser(vector<string> &v, string str);

typedef tokenizer<char_separator<char> > toknizer;
int main()
{
	while(1)
	{
		//prints simple prompt, gets user input
		cout << "$ ";
		string userinput;
		getline(cin,userinput);

		//declares tokenizer and storage for tokens
		string cmd=""; //gathers entire command until connector or end
		string sym=""; //will hold collected symbol ('||' vs '|')
		vector<string> cmdvect;

		char_separator<char> delim("","<&|#;>");
		toknizer parser(userinput,delim);

		for(toknizer::iterator it=parser.begin();it!=parser.end();++it)
		{
			if(*it=="#") { break; } //finish reading input if comment
			if(*it=="&" || *it=="|" || *it==";" || *it==">" || *it=="<" ) //doesn't check validity/meaning of symbol yet
			{
				if(!cmd.empty()) //if there is currently a command recorded, push it onto vector and start reading in symbol
				{
					cmdvect.push_back(cmd);
					cmd.clear();
					sym+=(*it);
				}
				else if(cmd.empty() && !sym.empty())
				{
					sym+=(*it);
				}
			}
			//if none of cases above apply, can be assumed to be command
			else
			{
				if(!sym.empty())
				{
					cmdvect.push_back(sym);
					cmd+=(*it);
					sym.clear();
					//"empties" connector and resumes building command
				}
				else //otherwise, just keep building command
				{
					cmd+=(*it);
					cmd+=" "; //spaces out commands like "ls -a"
				}
			}

		} //end tokenizer loop

		if(!cmd.empty())
		{
			cmdvect.push_back(cmd); //adds last of input
		}
		if(!sym.empty())
		{
			cmdvect.push_back(sym);//and trailing connectors
		}
		for(unsigned n=0;n<cmdvect.size();++n)
		{
			cout << cmdvect.at(n) << endl;
		}
		/*int x=syntaxCheck(cmdvect);
		if(x==0)
		{
			executor(cmdvect);
		}*/
	}
	//end of while loop

	return 0;
} //end of main

void executor(vector<string> &vect)
{
	bool success=false;
	bool preArg=false;

	for(unsigned i=0;i<vect.size();++i)
	{
		if(vect.at(i)=="exit")
		{
			cout << "is exit" << endl;
		}
		//checks if current string is connector
		else if(isConnector(vect.at(i)))
		{
			if(vect.at(i)=="&&")
			{
				if(success==false || i==0 || preArg==false)
				{
					return;
				}
				else	{ preArg=false;  continue;	}
			}
			if(vect.at(i)=="||")
			{
				if(success==false && i!=0)
				{
					continue;
				}
				else if(success==true || i==0 || preArg==false)	{ return; }
			}
			if(vect.at(i)==";" && i!=0)
			{
				continue;
			}
		}
		else
		{
			preArg=true;
		}
		//otherwise can be assumed to be a command

		//parse vect.at(i) into smaller vector
		vector<string>argvect;
		commandParser(argvect,vect.at(i));

		//store vector size for array allocation
		const size_t sz=argvect.size();
		char**argv=new char*[sz+1]; //REMEMBER- delete at end

		for(unsigned j=0;j<sz+1;++j)
		{
			if(j<sz)//using strdup since it dynamically allocates on its own
			{
				argv[j]=strdup(argvect.at(j).c_str());
			}
			else if(j==sz) //adds null at end
			{
				argv[j]=NULL;
			}
		}

		//fork and attempt to execute using execvp
		pid_t pid=fork();
		if(pid==-1) //error with fork
		{
			perror("fork");
		}
		else if(pid==0) //child
		{

			if(execvp(argv[0],argv)==-1)
			{
				success=false;  //redundant maybe?
				perror("execvp");
				exit(1);
			}

			_exit(0);
		}
		else //parent
		{
			if(wait(0)==-1)
			{
				perror("wait");
				exit(1);
			}
			success=true;
		}

		//deallocates argv as well as strdup's dynamic memory
		for(unsigned i=0;i<sz+1;++i)
		{
			delete [] argv[i];
		}
		delete [] argv;
	}
	return;
}

void commandParser(vector<string> &v, string str)
{
	char_separator<char> delim(" ");
	toknizer parser(str,delim);
	for(toknizer::iterator it=parser.begin();it!=parser.end();++it)
	{
		if(*it=="exit")
		{
			exit(0);
		}
		v.push_back(*it);
	}

	return;
}

int syntaxCheck(vector<string> &vect)
{
	//checks input for invalid syntax in connectors
	for(unsigned i=0; i<vect.size();++i)
	{
		if(isConnector(vect.at(i)))
		{
			//ensures argument for && and || is complete
			if((i==0 || i+1==vect.size()) && vect.at(i)!=";")
			{
				cerr << "Connector syntax error: missing argument\n";
				return -1;
			}
			if(!validConnector(vect.at(i)))
			{
				cerr << "Connector syntax error: invalid connector\n";
				return -1;
			}
		}
	}
	return 0; //no syntax errors found
}

bool isConnector(string &s)
{
	//function just checks if token is supposed to be a connector
	size_t i=s.find("&");
	size_t j=s.find("|");
	size_t k=s.find(";");

	if(i==string::npos && j==string::npos && k==string::npos)
	{
		return false;
	}
	return true;
}

bool validConnector(string &str)
{
	//only supports few connectors now
	if(str=="&&") { return true; }
	else if(str=="||") { return true;}
	else if(str==";") { return true;}
	else if(str=="|") { return true;}
	else if(str=="<") { return true;}
	else if(str==">") { return true;}
	else if(str==">>") {return true;}
	//else if(str=="<<<") {return true;} //if time allows
	return false;
}
<commit_msg>Reworking syntaxCheck function<commit_after>#include <iostream>
#include <vector>
#include <string>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <boost/tokenizer.hpp>

using namespace std;
using namespace boost;

int syntaxCheck(vector<string>&vect);
bool isConnector(string&);
bool isSymbol(string&);
bool isSemiColon(string &s);
bool validSymbol(string&);
void executor(vector<string> &vect);
void commandParser(vector<string> &v, string str);

typedef tokenizer<char_separator<char> > toknizer;
int main()
{
	while(1)
	{
		//prints simple prompt, gets user input
		cout << "$ ";
		string userinput;
		getline(cin,userinput);

		//declares tokenizer and storage for tokens
		string cmd=""; //gathers entire command until connector or end
		string sym=""; //will hold collected symbol ('||' vs '|')
		vector<string> cmdvect;

		char_separator<char> delim("","<&|#;>");
		toknizer parser(userinput,delim);

		for(toknizer::iterator it=parser.begin();it!=parser.end();++it)
		{
			if(*it=="#") { break; } //finish reading input if comment
			if(*it=="&" || *it=="|" || *it==";" || *it==">" || *it=="<" ) //doesn't check validity/meaning of symbol yet
			{
				if(!cmd.empty()) //if there is currently a command recorded, push it onto vector and start reading in symbol
				{
					cmdvect.push_back(cmd);
					cmd.clear();
					sym+=(*it);
				}
				else if(cmd.empty() && !sym.empty())
				{
					sym+=(*it);
				}
			}
			//if none of cases above apply, can be assumed to be command
			else
			{
				if(!sym.empty())
				{
					cmdvect.push_back(sym);
					cmd+=(*it);
					sym.clear();
					//"empties" connector and resumes building command
				}
				else //otherwise, just keep building command
				{
					cmd+=(*it);
					cmd+=" "; //spaces out commands like "ls -a"
				}
			}

		} //end tokenizer loop

		if(!cmd.empty())
		{
			cmdvect.push_back(cmd); //adds last of input
		}
		if(!sym.empty())
		{
			cmdvect.push_back(sym);//and trailing connectors
		}
		for(unsigned n=0;n<cmdvect.size();++n)
		{
			cout << n << ": " << cmdvect.at(n) << endl;
		}
		int x=syntaxCheck(cmdvect);
		if(x==0)
		{
			cout << "All valid!\n";
			//executor(cmdvect);
		}
	}
	//end of while loop

	return 0;
} //end of main

void executor(vector<string> &vect)
{
	bool success=false;
	bool preArg=false;

	for(unsigned i=0;i<vect.size();++i)
	{
		if(vect.at(i)=="exit")
		{
			cout << "is exit" << endl;
		}
		//checks if current string is connector
		else if(isConnector(vect.at(i)))
		{
			if(vect.at(i)=="&&")
			{
				if(success==false || i==0 || preArg==false)
				{
					return;
				}
				else	{ preArg=false;  continue;	}
			}
			if(vect.at(i)=="||")
			{
				if(success==false && i!=0)
				{
					continue;
				}
				else if(success==true || i==0 || preArg==false)	{ return; }
			}
			if(vect.at(i)==";" && i!=0)
			{
				continue;
			}
		}
		else
		{
			preArg=true;
		}
		//otherwise can be assumed to be a command

		//parse vect.at(i) into smaller vector
		vector<string>argvect;
		commandParser(argvect,vect.at(i));

		//store vector size for array allocation
		const size_t sz=argvect.size();
		char**argv=new char*[sz+1]; //REMEMBER- delete at end

		for(unsigned j=0;j<sz+1;++j)
		{
			if(j<sz)//using strdup since it dynamically allocates on its own
			{
				argv[j]=strdup(argvect.at(j).c_str());
			}
			else if(j==sz) //adds null at end
			{
				argv[j]=NULL;
			}
		}

		//fork and attempt to execute using execvp
		pid_t pid=fork();
		if(pid==-1) //error with fork
		{
			perror("fork");
		}
		else if(pid==0) //child
		{

			if(execvp(argv[0],argv)==-1)
			{
				success=false;  //redundant maybe?
				perror("execvp");
				exit(1);
			}

			_exit(0);
		}
		else //parent
		{
			if(wait(0)==-1)
			{
				perror("wait");
				exit(1);
			}
			success=true;
		}

		//deallocates argv as well as strdup's dynamic memory
		for(unsigned i=0;i<sz+1;++i)
		{
			delete [] argv[i];
		}
		delete [] argv;
	}
	return;
}

void commandParser(vector<string> &v, string str)
{
	char_separator<char> delim(" ");
	toknizer parser(str,delim);
	for(toknizer::iterator it=parser.begin();it!=parser.end();++it)
	{
		if(*it=="exit")
		{
			exit(0);
		}
		v.push_back(*it);
	}

	return;
}

int syntaxCheck(vector<string> &vect)
{
	//checks input for invalid syntax in connectors
	for(unsigned i=0; i<vect.size();++i)
	{
		//after initial parsing, vector passed in should always have
		//commands in even indices, and any symbols in odd indices.
		if(i%2==0) //if even index...
		{
			if(isSymbol(vect.at(i))) //...and a symbol...
			{
				cerr << "Syntax error: missing argument.\n";
				return -1;  //...argument must be missing
			}
			else { continue; } //if not a symbol, assume to be intended command
		}
		else if(i%2!=0 && isSymbol(vect.at(i))) //if odd index a symbol
		{
			if(!validSymbol(vect.at(i))) //and symbol is not valid
			{
				cerr << "Syntax error: invalid operators.\n";
				return -1; //will return an error
			}
			else //if valid, just continue checking
			{
				continue;
			}
		}

	/*	if(isConnector(vect.at(i)))
		{
			//ensures argument for && and || is complete
			if((i==0 || i+1==vect.size()) && vect.at(i)!=";")
			{
				cerr << "Connector syntax error: missing argument\n";
				return -1;
			}
			if(!validConnector(vect.at(i)))
			{
				cerr << "Connector syntax error: invalid connector\n";
				return -1;
			}
		}
	}*/
	}
	return 0; //no syntax errors found
}

bool isSemiColon(string &s) //literally only to allow ";" as a valid command ending.
{
	size_t sc=s.find(";");
	if(sc==string::npos) { return false;}
	return true;
}

bool isConnector(string &s)
{
	//function just checks if token is supposed to be a connector
	size_t i=s.find("&");
	size_t j=s.find("|");
	size_t k=s.find(";");

	if(i==string::npos && j==string::npos && k==string::npos)
	{
		return false;
	}
	return true;
}

bool isSymbol(string &s)
{
	size_t a=s.find("&");
	size_t b=s.find("|");
	size_t c=s.find(";");
	size_t d=s.find(">");
	size_t e=s.find("<");
	size_t noSym = string::npos; //"no such symbol"
	//if no symbols are found in the string
	if(a==noSym && b==noSym && c==noSym && d==noSym && e==noSym)
	{
		return false; //assume it's not an attempt at connector/redirection symbol
	}
	return true;
}

bool validSymbol(string &str)
{
	//only supports few connectors now
	if(str=="&&") { return true; }
	else if(str=="||") { return true;}
	else if(str==";") { return true;}
	else if(str=="|") { return true;}
	else if(str=="<") { return true;}
	else if(str==">") { return true;}
	else if(str==">>") {return true;}
	//else if(str=="<<<") {return true;} //if time allows
	return false;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <boost/tokenizer.hpp> //Boost tokenizer
#include <unistd.h> // Fork()
#include <sys/types.h> // Wait()
#include <sys/wait.h> // Wait()
#include <vector>
#include <stdio.h> //Perror()
#include <errno.h> // Perror()
#include <algorithm>

using namespace std;
using namespace boost;

// Chose to write function comparing c-strings rather than copy to string then compare
// Used for checking exit command
bool cStringEqual(char* c1, char* c2)
{
	int i;
	for(i = 0; c1[i] != '\0' && c2[i] != '\0'; ++i)
	{
		if(c1[i] != c2[i])
		{
			return false;
		}
	}
	if(c1[i] != '\0' || c2[i] != '\0')
	{
		return false;
	}
	return true;
}

int main()
{
	while(true) //Shell runs until the exit command
	{
		cout << "$ "; // Prints command prompt
		string commandLine;
		getline(cin, commandLine);

		// Accounts for comments by removing parts that are comments
		if(commandLine.find(" #") != string::npos)
		{
			commandLine = commandLine.substr(commandLine.find(" #"));
		}

		// Finds locations of connectors; a && b, && has a location of 3
		vector<unsigned int> connectorLocs;
		unsigned int marker = 0; // Marks location to start find() from
		while(commandLine.find("&&", marker) != string::npos)//loc != string::npos)
		{
			connectorLocs.push_back(commandLine.find("&&", marker));
			marker = commandLine.find("&&", marker) + 2;//loc + 2; // Starts searching after "&&"
		}
		marker = 0;
		while(commandLine.find("||", marker) != string::npos)
		{
			connectorLocs.push_back(commandLine.find("||", marker));
			marker = commandLine.find("||", marker) + 2; // Starts searching after "||"
		}
		marker = 0;
		while(commandLine.find(";", marker) != string::npos)
		{
			connectorLocs.push_back(commandLine.find(";", marker));
			marker =  commandLine.find(";", marker)+ 1; // Starts searching after ";"
		}
		connectorLocs.push_back(0); // Will be sorted and put in beginning
		sort(connectorLocs.begin(), connectorLocs.end()); // Sorted to find each subcommand substring
		connectorLocs.push_back(commandLine.size()); // One past end index will act like connector

		// Runs through subcommands and runs each one
		// Works for connectors with nothing between them (tokenizer will have "" => syntax error, which is expected)
		// # of subcommands == # of connectors - 1 (including 0, one-past-end)
		for(unsigned int i = 0; i < connectorLocs.size() - 1; ++i)
		{
			int offset = 0; // Tells how much offset for connectors (&&, ||, ;)
			if(commandLine.at(connectorLocs.at(i)) == '&' || commandLine.at(connectorLocs.at(i)) == '|')
			{
				offset = 2;
			}
			else
			{
				if(commandLine.at(connectorLocs.at(i)) == ';')
				{
					offset = 1;
				}
			}

			//cout << commandLine.at(connectorLocs.at(i)) << endl; // DEBUGGING
			//cout << offset << endl; // DEBUGGING

			// For parsing line of commands; delimiter is whitespace, each token will be a command or an argument
			vector<string> strArgs;
			char_separator<char> sep(" ");
			// FOLLOWING LINE WILL BREAK IF USED DIRECTLY IN TOKENIZER
			string subcommand = commandLine.substr(connectorLocs.at(i) + offset, connectorLocs.at(i+1) - connectorLocs.at(i) - offset);
			//typedef tokenizer<char_separator<char>> tokenizer; // Used to use this
			//cout << "sub: " << subcommand << endl; // DEBUGGING
			tokenizer<char_separator<char>> tok(subcommand, sep);
			// First token is the command, other tokens are the arguments
			for(auto iter = tok.begin(); iter != tok.end(); ++iter)
			{
				//cout << "tok: " << *iter << endl; // DEBUGGING
				strArgs.push_back(*iter);
			}

			// Copy strArgs to vector of c-strings
			// NEED TO DO IT THIS WAY OR THERE'S ISSUES WITH POINTERS
			vector<char*> args;
			for(auto str : strArgs)
			{
				args.push_back(const_cast<char*> (str.c_str()));
			}
			args.push_back(NULL); // NULL terminating at the end of vector/array

			char* exitCString = const_cast<char*> ("exit");

			//cout << cStringEqual(args.at(0), exitCString) << endl; // DEBUGGING
			if(cStringEqual(args.at(0), exitCString)) // if command is exit, exit shell
			{
				exit(0);
			}

			// Executes commands/takes care of errors
			int pid = fork();
			if(pid == -1) // If fork fails
			{
				perror("Fork error");
				exit(1);
			}
			else
			{
				if(pid == 0) // Child process
				{
					execvp(args.at(0), &(args[0]));
					// Following don't run if execvp succeeds
					perror("Command execution error");
					_exit(1);
				}
				else // Parent process
				{
					int status; // Status isn't used but might use in future?
					int waitVar = wait(&status);
					if(waitVar == -1) // If child process has error
					{
						perror("Child process error");
						// exits if next connector is && or one-past-end element
						// continues if next connector is ; or ||

					}
					else
					{
						int exitStatus = WEXITSTATUS(status); // Checks whether returns 0/1 when exiting
						if(exitStatus == 1) // If unsuccessful command
						{
							if(connectorLocs.at(i+1) < commandLine.size() &&
								commandLine.at(connectorLocs.at(i+1)) == '&')
							{
								//cout << commandLine.at(connectorLocs.at(i+1)) << endl; // DEBUGGING
								break;
							}
						}
						else
						{
							if(connectorLocs.at(i+1) < commandLine.size() &&
								commandLine.at(connectorLocs.at(i+1)) == '|')
							{
								//cout << commandLine.at(connectorLocs.at(i+1)) << endl; // DEBUGGING
								break;
							}
						}
					}
				}
			}
		}
	}
	return 0;
}
<commit_msg>Bugfixes<commit_after>#include <iostream>
#include <string>
#include <boost/tokenizer.hpp> //Boost tokenizer
#include <unistd.h> // Fork()
#include <sys/types.h> // Wait()
#include <sys/wait.h> // Wait()
#include <vector>
#include <stdio.h> //Perror()
#include <errno.h> // Perror()
#include <algorithm>

using namespace std;
using namespace boost;

// Chose to write function comparing c-strings rather than copy to string then compare
// Used for checking exit command
bool cStringEqual(char* c1, char* c2)
{
	int i;
	for(i = 0; c1[i] != '\0' && c2[i] != '\0'; ++i)
	{
		if(c1[i] != c2[i])
		{
			return false;
		}
	}
	if(c1[i] != '\0' || c2[i] != '\0')
	{
		return false;
	}
	return true;
}

int main()
{
	while(true) //Shell runs until the exit command
	{
		cout << "$ "; // Prints command prompt
		string commandLine;
		getline(cin, commandLine);

		// Accounts for comments by removing parts that are comments
		if(commandLine.find(" #") != string::npos)
		{
			commandLine = commandLine.substr(commandLine.find(" #"));
		}

		// Finds locations of connectors; a && b, && has a location of 3
		vector<unsigned int> connectorLocs;
		unsigned int marker = 0; // Marks location to start find() from
		while(commandLine.find("&&", marker) != string::npos)//loc != string::npos)
		{
			connectorLocs.push_back(commandLine.find("&&", marker));
			marker = commandLine.find("&&", marker) + 2;//loc + 2; // Starts searching after "&&"
		}
		marker = 0;
		while(commandLine.find("||", marker) != string::npos)
		{
			connectorLocs.push_back(commandLine.find("||", marker));
			marker = commandLine.find("||", marker) + 2; // Starts searching after "||"
		}
		marker = 0;
		while(commandLine.find(";", marker) != string::npos)
		{
			connectorLocs.push_back(commandLine.find(";", marker));
			marker =  commandLine.find(";", marker)+ 1; // Starts searching after ";"
		}
		connectorLocs.push_back(0); // Will be sorted and put in beginning
		sort(connectorLocs.begin(), connectorLocs.end()); // Sorted to find each subcommand substring
		connectorLocs.push_back(commandLine.size()); // One past end index will act like connector

		// Runs through subcommands and runs each one
		// Works for connectors with nothing between them (tokenizer will have "" => syntax error, which is expected)
		// # of subcommands == # of connectors - 1 (including 0, one-past-end)
		for(unsigned int i = 0; i < connectorLocs.size() - 1; ++i)
		{
			int offset = 0; // Tells how much offset for connectors (&&, ||, ;)
			if(commandLine.at(connectorLocs.at(i)) == '&' || commandLine.at(connectorLocs.at(i)) == '|')
			{
				offset = 2;
			}
			else
			{
				if(commandLine.at(connectorLocs.at(i)) == ';')
				{
					offset = 1;
				}
			}

			//cout << commandLine.at(connectorLocs.at(i)) << endl; // DEBUGGING
			//cout << offset << endl; // DEBUGGING

			// For parsing line of commands; delimiter is whitespace, each token will be a command or an argument
			vector<string> strArgs;
			char_separator<char> sep(" ");
			// FOLLOWING LINE WILL BREAK IF USED DIRECTLY IN TOKENIZER
			string subcommand = commandLine.substr(connectorLocs.at(i) + offset, connectorLocs.at(i+1) - connectorLocs.at(i) - offset);
			//typedef tokenizer<char_separator<char>> tokenizer; // Used to use this
			//cout << "sub: " << subcommand << endl; // DEBUGGING
			tokenizer<char_separator<char>> tok(subcommand, sep);
			// First token is the command, other tokens are the arguments
			for(auto iter = tok.begin(); iter != tok.end(); ++iter)
			{
				//cout << "tok: " << *iter << endl; // DEBUGGING
				strArgs.push_back(*iter);
			}

			// Copy strArgs to vector of c-strings
			// NEED TO DO IT THIS WAY OR THERE'S ISSUES WITH POINTERS
			vector<char*> args;
			for(auto str : strArgs)
			{
				args.push_back(const_cast<char*> (str.c_str()));
			}
			args.push_back(NULL); // NULL terminating at the end of vector/array

			//Blank command or consecutive connectors
			if(args.size() == 1)
			{
				continue;
			}

			char* exitCString = const_cast<char*> ("exit");

			//cout << cStringEqual(args.at(0), exitCString) << endl; // DEBUGGING
			if(cStringEqual(args.at(0), exitCString)) // if command is exit, exit shell
			{
				exit(0);
			}

			// Executes commands/takes care of errors
			int pid = fork();
			if(pid == -1) // If fork fails
			{
				perror("Fork error");
				exit(1);
			}
			else
			{
				if(pid == 0) // Child process
				{
					execvp(args.at(0), &(args[0]));
					// Following don't run if execvp succeeds
					perror("Command execution error");
					_exit(1);
				}
				else // Parent process
				{
					int status; // Status isn't used but might use in future?
					int waitVar = wait(&status);
					if(waitVar == -1) // If child process has error
					{
						perror("Child process error");
						// exits if next connector is && or one-past-end element
						// continues if next connector is ; or ||

					}
					else
					{
						int exitStatus = WEXITSTATUS(status); // Checks whether returns 0/1 when exiting
						if(exitStatus == 1) // If unsuccessful command
						{
							if(connectorLocs.at(i+1) < commandLine.size() &&
								commandLine.at(connectorLocs.at(i+1)) == '&')
							{
								//cout << commandLine.at(connectorLocs.at(i+1)) << endl; // DEBUGGING
								break;
							}
						}
						else
						{
							if(connectorLocs.at(i+1) < commandLine.size() &&
								commandLine.at(connectorLocs.at(i+1)) == '|')
							{
								//cout << commandLine.at(connectorLocs.at(i+1)) << endl; // DEBUGGING
								break;
							}
						}
					}
				}
			}
		}
	}
	return 0;
}
<|endoftext|>