<commit_before>// Copyright (c) 2009-2012 Bitcoin Developers
// Copyright (c) 2011-2012 Litecoin Developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "net.h"
#include "bitcoinrpc.h"

#include <QString>
#include <QByteArray>
#include <QtNetwork/QNetworkAccessManager>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonValue>

using namespace json_spirit;
using namespace std;

Value getconnectioncount(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 0)
        throw runtime_error(
            "getconnectioncount\n"
            "Returns the number of connections to other nodes.");

    LOCK(cs_vNodes);
    return (int)vNodes.size();
}

static void CopyNodeStats(std::vector<CNodeStats>& vstats)
{
    vstats.clear();

    LOCK(cs_vNodes);
    vstats.reserve(vNodes.size());
    BOOST_FOREACH(CNode* pnode, vNodes) {
        CNodeStats stats;
        pnode->copyStats(stats);
        vstats.push_back(stats);
    }
}

Value getpeerinfo(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 0)
        throw runtime_error(
            "getpeerinfo\n"
            "Returns data about each connected network node.");

    vector<CNodeStats> vstats;
    CopyNodeStats(vstats);

    Array ret;

    BOOST_FOREACH(const CNodeStats& stats, vstats) {
        Object obj;

        obj.push_back(Pair("addr", stats.addrName));
        obj.push_back(Pair("services", strprintf("%08" PRI64x, stats.nServices)));
        obj.push_back(Pair("lastsend", (boost::int64_t)stats.nLastSend));
        obj.push_back(Pair("lastrecv", (boost::int64_t)stats.nLastRecv));
        obj.push_back(Pair("conntime", (boost::int64_t)stats.nTimeConnected));
        obj.push_back(Pair("version", stats.nVersion));
        obj.push_back(Pair("subver", stats.strSubVer));
        obj.push_back(Pair("inbound", stats.fInbound));
        obj.push_back(Pair("releasetime", (boost::int64_t)stats.nReleaseTime));
        obj.push_back(Pair("startingheight", stats.nStartingHeight));
        obj.push_back(Pair("banscore", stats.nMisbehavior));

        ret.push_back(obj);
    }

    return ret;
}

const char* NYAN_SPACE_SEEDS = "https://nyan.space/peers.php?json";

// vmp32k - experimental seeding method
Value connectnyandotspacepeers(const Array& params, bool fHelp)
{
    QNetworkAccessManager networkManager;
    QNetworkRequest req;
    req.setUrl(NYAN_SPACE_SEEDS);

    QNetworkReply *reply = networkManager.get(req);
    QString responseBody = QString(reply->readall());
	delete reply;

	if (responseBody.length() <= 1) {
		throw runtime_error("Unable to fetch peers from " NYAN_SPACE_SEEDS);
	}

	QJsonDocument doc = QJsonDocument::fromJson(responseBody.toUtf8());

	QJsonObject jsonObject = doc.object();
	QJsonArray peers = jsonObject['results'].toArray();

	Array ret;

	BOOST_FOREACH (const QJsonValue &value, jsonArray)
	{
		QJsonObject obj = value.toObject();
		QString addr = value['addr'].toString()

		Object obj;
        obj.push_back(Pair("addr", addr);
        ret.push_back(obj);
	}

    return ret;
}

<commit_msg>Well this is as far as I got for today.<commit_after>// Copyright (c) 2009-2012 Bitcoin Developers
// Copyright (c) 2011-2012 Litecoin Developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "net.h"
#include "bitcoinrpc.h"

#include <QEventLoop>
#include <QString>
#include <QByteArray>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkReply>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonValue>

using namespace json_spirit;
using namespace std;

Value getconnectioncount(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 0)
        throw runtime_error(
            "getconnectioncount\n"
            "Returns the number of connections to other nodes.");

    LOCK(cs_vNodes);
    return (int)vNodes.size();
}

static void CopyNodeStats(std::vector<CNodeStats>& vstats)
{
    vstats.clear();

    LOCK(cs_vNodes);
    vstats.reserve(vNodes.size());
    BOOST_FOREACH(CNode* pnode, vNodes) {
        CNodeStats stats;
        pnode->copyStats(stats);
        vstats.push_back(stats);
    }
}

Value getpeerinfo(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 0)
        throw runtime_error(
            "getpeerinfo\n"
            "Returns data about each connected network node.");

    vector<CNodeStats> vstats;
    CopyNodeStats(vstats);

    Array ret;

    BOOST_FOREACH(const CNodeStats& stats, vstats) {
        Object obj;

        obj.push_back(Pair("addr", stats.addrName));
        obj.push_back(Pair("services", strprintf("%08" PRI64x, stats.nServices)));
        obj.push_back(Pair("lastsend", (boost::int64_t)stats.nLastSend));
        obj.push_back(Pair("lastrecv", (boost::int64_t)stats.nLastRecv));
        obj.push_back(Pair("conntime", (boost::int64_t)stats.nTimeConnected));
        obj.push_back(Pair("version", stats.nVersion));
        obj.push_back(Pair("subver", stats.strSubVer));
        obj.push_back(Pair("inbound", stats.fInbound));
        obj.push_back(Pair("releasetime", (boost::int64_t)stats.nReleaseTime));
        obj.push_back(Pair("startingheight", stats.nStartingHeight));
        obj.push_back(Pair("banscore", stats.nMisbehavior));

        ret.push_back(obj);
    }

    return ret;
}

const static QString NYAN_SPACE_SEEDS("http://nyan.space/peers.php?json");
extern void AddOneShot(string strDest);

// vmp32k - experimental seeding method
Value connectnyandotspacepeers(const Array& params, bool fHelp)
{
	if (fHelp) {
		throw runtime_error(
			"connectnyandotspacepeers\n"
			"Fetch and connect to peers via the nyan.space peer list."
		);
	}

    QNetworkAccessManager networkManager;
	networkManager.setNetworkAccessible(QNetworkAccessManager::Accessible);
    QNetworkRequest req;
    req.setUrl(NYAN_SPACE_SEEDS);

    QNetworkReply *reply = networkManager.get(req);

	// Need to connect signal somehow and wait for positive response before going on. >.<

    QString responseBody = QString(reply->readAll());
	delete reply;

	if (responseBody.length() <= 1) {
		QString msg = QString("Unable to fetch peers from %1: %2").arg(NYAN_SPACE_SEEDS).arg(reply->errorString());
		throw runtime_error(msg.toStdString().c_str());
	}

	QJsonDocument doc = QJsonDocument::fromJson(responseBody.toUtf8());

	QJsonObject jsonObject = doc.object();
	QJsonArray peers = jsonObject["results"].toArray();

	Array ret;

	BOOST_FOREACH (const QJsonValue &value, peers)
	{
		QJsonObject jsonobj = value.toObject();
		QString addr = jsonobj["addr"].toString();

		Object obj;
        obj.push_back(Pair("addr", addr.toStdString().c_str()));
        ret.push_back(obj);

		AddOneShot(addr.toStdString().c_str());
	}

    return ret;
}

<|endoftext|>


<commit_before>/*mchen046
SID: 861108671
CS100 Spring 2015: hw0-rshell
https://www.github.com/mchen046/rshell/src/main.cpp
*/
/*
Worklist:
bug when running: ls -a; echo hello; mkdir test;
	the command exits when mkdir test finishes.
	concatenates an extra " e" after original command
fix memory leaks
*/
/*
Fixed:
problem when running ls -a multiple times
	ls -a breaks on the second execution "error in execvp: Bad address
*/
/*
README:
ex command?
parentheses and quotes
*/
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <wait.h>
#include <string.h>
#include <string>
#include <vector>
#include <cstdlib>
#include <stdlib.h>
#include <stdio.h>
#include <boost/tokenizer.hpp>
#include <boost/token_iterator.hpp>

using namespace std;
using namespace boost;

bool exitSeen = false;

void printcmd(vector<char*> cmd){ //debugging cmdC
	cout << "---------------\ncmd\n";
	for(unsigned int i = 0; i<cmd.size(); i++){
		cout << "cmd[" << i << "]: " << cmd[i] << endl;
	}
	cout << "---------------\n";
}

int sizeOfPart(char *cmdLine){ //finds size to allocate for execution
	string str = static_cast<string>(cmdLine);
	char_separator<char> delim(" ");
	tokenizer< char_separator<char> > mytok(str, delim);
	int size= 0;
	for(tokenizer<char_separator<char> >::iterator it = mytok.begin(); it!=mytok.end(); it++){
		size++;
	}
	return size;
}

bool hasText(char* cmdText, string text){
	unsigned int count = 0;
	int j = 0;
	for(unsigned int i = 0; cmdText[i]!='\0'; i++){
		if(cmdText[i]!=text[j]){
			count = 0;
			j = 0;
		}
		if(cmdText[i]==text[j]){
			count++;
			j++;
		}
		if(count == text.size()){
			return true;
		}
	}
	return false;
}

bool isText(char* cmdText, string text){
	if(!(cmdText[text.size()-1]==text[text.size()-1] && cmdText[text.size()]=='\0' && text[text.size()]=='\0')){
		return false;
	}
	for(unsigned int i = 0; cmdText[i]!='\0' && i<text.size(); i++){
		if(cmdText[i]!=text[i])
			return false;
	}
	return true;
}

bool isNumericOnly(const string &str){
	return all_of(str.begin(), str.end(), ::isdigit);
}

char** parseSpace(char *cmd){
	string str = static_cast<string>(cmd); //parsing " "
	char_separator<char> delim(" ");
	tokenizer< char_separator<char> > mytok(str, delim);

	int size = 0;
	for(tokenizer<char_separator<char> >::iterator it = mytok.begin(); it!=mytok.end(); it++){
		size++;
	}

	//creating cmdExec
	char **cmdExec = new char*[size+1];

	int i = 0;
	for(tokenizer<char_separator<char> >::iterator it = mytok.begin(); it!=mytok.end(); it++){
		string cmdString = static_cast<string>(*it);
		char *token = new char[cmdString.size()+1];
		for(unsigned int j = 0; j<cmdString.size(); j++){
			token[j] = cmdString[j];
			if(j+1==cmdString.size()){
				token[j+1] = '\0';
			}
		}
		cmdExec[i] = token;
		tokenizer<char_separator<char> >::iterator itA = it;
		if(++itA==mytok.end()){
			cmdExec[i+1] = NULL;
		}
		i++;
		//deallocate token?
	}
	if(isText(cmdExec[0], "exit") || isText(cmdExec[0], "exit;")){ //exit executable
		exitSeen = true;
		if(cmdExec[1]!=NULL && !isNumericOnly(static_cast<string>(cmdExec[1]))){
			cout << "rshell: exit: " << cmdExec[1] << ": numeric argument required" << endl;
			exit(0); //exit
		}
		else if(cmdExec[1]!=NULL && cmdExec[2]!=NULL){
			cout << "rshell: exit: too many arguments" << endl;
		}
		else{
			exit(0); //exit
		}
	}
	return cmdExec;
	//end creating cmdExec
	//deallocate cmdExec?
}

int execCmd(char** cmdD){ //process spawning
	if(exitSeen){
		return -1;
	}
	exitSeen = false;
	int pid = fork();
	int status = 0;
	//cout << "cmdD[0]: " << cmdD[0] << endl;
	if(pid == -1){ //error
		perror("fork() error");
		_exit(2);
	}
	else if(pid == 0){ //child process
		//cout << "cmdD[0]: " << cmdD[0] << endl;
		if(execvp(cmdD[0], cmdD) == -1){
			perror("error in execvp"); //status becomes 256/512
			_exit(2);
		}
	}
	else if(pid > 0){ //parent process
		if(wait(&status)==-1){
			perror("error in wait()");
			_exit(2);
		}
	}
	//cout << "status: " << status << endl;
	if(status!=0){ //command fails
		//cout << "command fails!\n";
		return -1;
	}
	return status; //status defaults to 0 if successful
}

void parseDelim(vector<char*> &cmdC, char *cmdB, char const * delim, char **ptr){
	char *token = strtok_r(cmdB, delim, &*ptr);
	cmdC.push_back(token);
	while(hasText(*ptr, delim)){
		token = strtok_r(NULL, delim, &*ptr);
		cmdC.push_back(token);
	}
	token = strtok_r(NULL, delim, *&ptr);
	cmdC.push_back(token);
	//delete[] ptr;
	//delete[] token;
}

int cAND(vector<char*> &cmdC, char *cmdB, char **ptr){ //parse and execute && command
	parseDelim(cmdC, cmdB, "&&", &*ptr);
	int success = 1;
	for(unsigned int i = 0; i<cmdC.size() && success; i++){
		if(execCmd(parseSpace(cmdC[i]))==-1){ //command fails
			success = -1;
		}
	}
	return success;
}

int cOR(vector<char*> &cmdC, char *cmdB, char **ptr){ //parse and execute || command
	parseDelim(cmdC, cmdB, "||", &*ptr);
	int success = -1;
	for(unsigned int i = 0; i<cmdC.size() && success==-1; i++){
		if(!execCmd(parseSpace(cmdC[i]))){ //command succeeds
			success = 1;
		}
	}
	return success;
}

void parseMaster(char* cmdB){
	char *ptr;
	vector <char*> cmdC;
	if((hasText(cmdB, "\"") || hasText(cmdB, "(") || hasText(cmdB, ")")) && !hasText(cmdB, "&&") && !hasText(cmdB, "||")){
		if(hasText(cmdB, "&") || hasText(cmdB, "|")){
			execCmd(parseSpace(cmdB));
		}
		else{
			//invalid command
			cout << "rshell: " << cmdB  <<": command not found\n";
		}
	}
	else if(!hasText(cmdB, "&&") && !hasText(cmdB, "||")){
		//execute
		execCmd(parseSpace(cmdB));
	}
	else if(hasText(cmdB, "&&") && !hasText(cmdB, "||")){ //only has &&
		cAND(cmdC, cmdB, &ptr);
	}
	else if(!hasText(cmdB, "&&") && hasText(cmdB, "||")){ //only has ||
		cOR(cmdC, cmdB, &ptr);
	}
	else if(hasText(cmdB, "&&") && hasText(cmdB, "||")){ //has both && and ||
		char* cmdBX = new char[strlen(cmdB)]; //backup cmdB
		strcpy(cmdBX, cmdB);

		bool succeed;
		char *ptrA;
		vector<char*> cmdD;
		parseDelim(cmdC, cmdB, "||", &ptr);
		if(hasText(cmdC[0], "&&")){ //vector of && commands separated by ||
			succeed = false;
			//printcmd(cmdC);
			for(unsigned int i = 0; i<cmdC.size() && !succeed; i++){
				if(hasText(cmdC[i], "&&")){
					if(cAND(cmdD, cmdC[i], &ptrA)!=-1){ //connectorAnd succeeds
						succeed	= true;
					}
				}
				else if(!execCmd(parseSpace(cmdC[i]))){
					succeed = true;
				}
			}
			cmdD.clear();
		}
		else{ //vector of || commands separated by &&
			succeed = true;
			cmdC.clear();
			cmdB = cmdBX; //restore cmdB
			parseDelim(cmdC, cmdB, "&&", &ptr);
			//printcmd(cmdC);
			for(unsigned int i = 0; i<cmdC.size() && succeed; i++){
				if(hasText(cmdC[i], "||")){
					if(cOR(cmdD, cmdC[i], &ptrA)==-1){
						succeed = false;
					}
				}
				else if(execCmd(parseSpace(cmdC[i]))==-1){
					succeed = false;
				}
				cmdD.clear();
			}
			delete[] cmdBX;
		}
	}
}
int main(){
	while(1){
		string cmd, cmd2;

		char host[64];	//prompt
		gethostname(host,64);
		cout << getlogin() << '@' << host << "$ ";
		getline(cin, cmd);

		//filter comments
		for(unsigned int i = 0; i<cmd.size(); i++){
			if(cmd.at(i)!='#'){
				cmd2.push_back(cmd.at(i));
			}
			else{
				i=cmd.size();
			}
		}

		if(cmd2!=""){ //if command is not empty
			//convert string to char*
			char *cmdA = new char[cmd2.size()+1];
			for(int i = 0; i<static_cast<int>(cmd2.size()); i++){
				cmdA[i] = cmd2.at(i);
				if(i+1==static_cast<int>(cmd.size())){
					cmdA[i+1] = '\0'; //null terminating
				}
			}

			char *cmdB = strtok(cmdA, ";"); //parsing ";"

			bool cmdBDone = false;
			while(!cmdBDone){
				//cout << "cmdB: " << cmdB << endl;
				parseMaster(cmdB);
				cmdB = strtok(NULL, ";");
				if(cmdB==NULL){
					cmdBDone = true;
				}
			}
			delete[] cmdA;
			delete[] cmdB;
		}
	}
	return 0;
}
<commit_msg>further connector checking<commit_after>/*
Michael Chen mchen046@ucr.edu
SID: 861108671
CS100 Spring 2015: hw0-rshell
https://www.github.com/mchen046/rshell/src/rshell.cpp
*/
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <wait.h>
#include <string.h>
#include <string>
#include <vector>
#include <cstdlib>
#include <stdlib.h>
#include <stdio.h>
#include <boost/tokenizer.hpp>
#include <boost/token_iterator.hpp>

using namespace std;
using namespace boost;

bool exitSeen = false;

void printcmd(vector<char*> cmd){ //debugging cmdC
	cout << "---------------\ncmd\n";
	for(unsigned int i = 0; i<cmd.size(); i++){
		cout << "cmd[" << i << "]: " << cmd[i] << endl;
	}
	cout << "---------------\n";
}

int sizeOfPart(char *cmdLine){ //finds size to allocate for execution
	string str = static_cast<string>(cmdLine);
	char_separator<char> delim(" ");
	tokenizer< char_separator<char> > mytok(str, delim);
	int size= 0;
	for(tokenizer<char_separator<char> >::iterator it = mytok.begin(); it!=mytok.end(); it++){
		size++;
	}
	return size;
}

bool hasText(char* cmdText, string text){
	unsigned int count = 0;
	int j = 0;
	for(unsigned int i = 0; cmdText[i]!='\0'; i++){
		if(cmdText[i]!=text[j]){
			count = 0;
			j = 0;
		}
		if(cmdText[i]==text[j]){
			count++;
			j++;
		}
		if(count == text.size()){
			return true;
		}
	}
	return false;
}

bool isText(char* cmdText, string text){
	if(!(cmdText[text.size()-1]==text[text.size()-1] && cmdText[text.size()]=='\0' && text[text.size()]=='\0')){
		return false;
	}
	for(unsigned int i = 0; cmdText[i]!='\0' && i<text.size(); i++){
		if(cmdText[i]!=text[i])
			return false;
	}
	return true;
}

bool isNumericOnly(const string &str){
	return all_of(str.begin(), str.end(), ::isdigit);
}

char** parseSpace(char *cmd){
	string str = static_cast<string>(cmd); //parsing " "
	char_separator<char> delim(" ");
	tokenizer< char_separator<char> > mytok(str, delim);

	int size = 0;
	for(tokenizer<char_separator<char> >::iterator it = mytok.begin(); it!=mytok.end(); it++){
		size++;
	}

	//creating cmdExec
	char **cmdExec = new char*[size+1];

	int i = 0;
	for(tokenizer<char_separator<char> >::iterator it = mytok.begin(); it!=mytok.end(); it++){
		string cmdString = static_cast<string>(*it);
		char *token = new char[cmdString.size()+1];
		for(unsigned int j = 0; j<cmdString.size(); j++){
			token[j] = cmdString[j];
			if(j+1==cmdString.size()){
				token[j+1] = '\0';
			}
		}
		cmdExec[i] = token;
		tokenizer<char_separator<char> >::iterator itA = it;
		if(++itA==mytok.end()){
			cmdExec[i+1] = NULL;
		}
		i++;
		//deallocate token?
	}
	if(isText(cmdExec[0], "exit") || isText(cmdExec[0], "exit;")){ //exit executable
		exitSeen = true;
		if(cmdExec[1]!=NULL && !isNumericOnly(static_cast<string>(cmdExec[1]))){
			cout << "rshell: exit: " << cmdExec[1] << ": numeric argument required" << endl;
			exit(0); //exit
		}
		else if(cmdExec[1]!=NULL && cmdExec[2]!=NULL){
			cout << "rshell: exit: too many arguments" << endl;
		}
		else{
			exit(0); //exit
		}
	}
	return cmdExec;
	//end creating cmdExec
	//deallocate cmdExec?
}

int execCmd(char** cmdD){ //process spawning
	if(exitSeen){
		return -1;
	}
	exitSeen = false;
	int pid = fork();
	int status = 0;
	//cout << "cmdD[0]: " << cmdD[0] << endl;
	if(pid == -1){ //error
		perror("fork() error");
		_exit(2);
	}
	else if(pid == 0){ //child process
		//cout << "cmdD[0]: " << cmdD[0] << endl;
		if(execvp(cmdD[0], cmdD) == -1){
			perror("error in execvp"); //status becomes 256/512
			_exit(2);
		}
	}
	else if(pid > 0){ //parent process
		if(wait(&status)==-1){
			perror("error in wait()");
			_exit(2);
		}
	}
	//cout << "status: " << status << endl;
	if(status!=0){ //command fails
		//cout << "command fails!\n";
		return -1;
	}
	return status; //status defaults to 0 if successful
}

void parseDelim(vector<char*> &cmdC, char *cmdB, char const * delim, char **ptr){
	char *token = strtok_r(cmdB, delim, &*ptr);
	cmdC.push_back(token);
	while(hasText(*ptr, delim)){
		token = strtok_r(NULL, delim, &*ptr);
		cmdC.push_back(token);
	}
	token = strtok_r(NULL, delim, *&ptr);
	cmdC.push_back(token);
	//delete[] ptr;
	//delete[] token;
}

int cAND(vector<char*> &cmdC, char *cmdB, char **ptr){ //parse and execute && command
	parseDelim(cmdC, cmdB, "&&", &*ptr);
	int success = 1;
	for(unsigned int i = 0; i<cmdC.size() && success; i++){
		if(execCmd(parseSpace(cmdC[i]))==-1){ //command fails
			success = -1;
		}
	}
	return success;
}

int cOR(vector<char*> &cmdC, char *cmdB, char **ptr){ //parse and execute || command
	parseDelim(cmdC, cmdB, "||", &*ptr);
	int success = -1;
	for(unsigned int i = 0; i<cmdC.size() && success==-1; i++){
		if(!execCmd(parseSpace(cmdC[i]))){ //command succeeds
			success = 1;
		}
	}
	return success;
}

bool checkConnector(string cmd, string &stringToken){
	//&& &&
	//|| ||
	//&&& or &&&&&&&&&&&&&
	//||| or |||||||||||||
	//&& &
	//|| |
	//&&||
	//||&&
	//&|
	//|&
	//& |
	//| &
	//&& |
	//|| &
	//& &
	//| |
	bool valid = true;
	bool space = false;
	for(unsigned int i = 0; i<cmd.size() && valid; i++){
		if(cmd.at(i)=='&'){
			for(unsigned int j = i+1; j<cmd.size() && valid; j++){
				if(cmd.at(j)=='|'){
					stringToken = "|";
					valid = false;
				}
				else if(cmd.at(j)=='&'){
					if(space){
						stringToken = "&";
						if(j+1<cmd.size() && cmd.at(j+1)=='&'){
							stringToken = "&&";
						}
						valid = false;
					}
					for(unsigned int k = j+1; k<cmd.size() && valid; k++){
						if(cmd.at(k)=='&'){
							stringToken = "&";
							if(space){
								stringToken = "&";
								if(k+1<cmd.size() && cmd.at(k+1)=='&'){
									stringToken = "&&";
								}
							}
							valid = false;
						}
						else if(cmd.at(k)=='|'){
							stringToken = "||";
							if(space){
								stringToken = "|";
							}
							valid = false;
						}
						else if(cmd.at(k)==' '){
							space = true;
						}
					}
				}
				else if(cmd.at(j)==' '){
					space = true;
				}
			}
		}
		else if(cmd.at(i)=='|'){
			for(unsigned int j = i+1; j<cmd.size() && valid; j++){
				if(cmd.at(j)=='&'){
					stringToken = "&";
					valid = false;
				}
				else if(cmd.at(j)=='|'){
					if(space){
						stringToken = "|";
						if(j+1<cmd.size() && cmd.at(j+1)=='|'){
							stringToken = "||";
						}
						valid = false;
					}
					for(unsigned int k = j+1; k<cmd.size() && valid; k++){
						if(cmd.at(k)=='|'){
							stringToken = "|";
							if(space){
								stringToken = "|";
								if(k+1<cmd.size() && cmd.at(k+1)=='|'){
									stringToken = "||";
								}
							}
							valid = false;
						}
						else if(cmd.at(k)=='&'){
							stringToken = "&&";
							if(space){
								stringToken = "&";
							}
							valid = false;
						}
						else if(cmd.at(k)==' '){
							space = true;
						}
					}
				}
				else if(cmd.at(j)==' '){
					space = true;
				}
			}
		}
	}
	return valid;
}

void parseMaster(char* cmdB){
	char *ptr;
	vector <char*> cmdC;
	if((hasText(cmdB, "\"") || hasText(cmdB, "(") || hasText(cmdB, ")")) && !hasText(cmdB, "&&") && !hasText(cmdB, "||")){
		if(hasText(cmdB, "&") || hasText(cmdB, "|")){
			execCmd(parseSpace(cmdB));
		}
		else{
			//invalid command
			cout << "rshell: " << cmdB  <<": command not found\n";
		}
	}
	else if(!hasText(cmdB, "&&") && !hasText(cmdB, "||")){
		//execute
		execCmd(parseSpace(cmdB));
	}
	else if(hasText(cmdB, "&&") && !hasText(cmdB, "||")){ //only has &&
		cAND(cmdC, cmdB, &ptr);
	}
	else if(!hasText(cmdB, "&&") && hasText(cmdB, "||")){ //only has ||
		cOR(cmdC, cmdB, &ptr);
	}
	else if(hasText(cmdB, "&&") && hasText(cmdB, "||")){ //has both && and ||
		char* cmdBX = new char[strlen(cmdB)]; //backup cmdB
		strcpy(cmdBX, cmdB);

		bool succeed;
		char *ptrA;
		vector<char*> cmdD;
		parseDelim(cmdC, cmdB, "||", &ptr);
		if(hasText(cmdC[0], "&&")){ //vector of && commands separated by ||
			succeed = false;
			//printcmd(cmdC);
			for(unsigned int i = 0; i<cmdC.size() && !succeed; i++){
				if(hasText(cmdC[i], "&&")){
					if(cAND(cmdD, cmdC[i], &ptrA)!=-1){ //connectorAnd succeeds
						succeed	= true;
					}
				}
				else if(!execCmd(parseSpace(cmdC[i]))){
					succeed = true;
				}
			}
			cmdD.clear();
		}
		else{ //vector of || commands separated by &&
			succeed = true;
			cmdC.clear();
			cmdB = cmdBX; //restore cmdB
			parseDelim(cmdC, cmdB, "&&", &ptr);
			//printcmd(cmdC);
			for(unsigned int i = 0; i<cmdC.size() && succeed; i++){
				if(hasText(cmdC[i], "||")){
					if(cOR(cmdD, cmdC[i], &ptrA)==-1){
						succeed = false;
					}
				}
				else if(execCmd(parseSpace(cmdC[i]))==-1){
					succeed = false;
				}
				cmdD.clear();
			}
			delete[] cmdBX;
		}
	}
}
int main(){
	while(1){
		string cmd, cmd2, stringToken;

		char host[64];	//prompt
		gethostname(host,64);
		cout << getlogin() << '@' << host << "$ ";
		getline(cin, cmd);

		//filter comments
		for(unsigned int i = 0; i<cmd.size(); i++){
			if(cmd.at(i)!='#'){
				cmd2.push_back(cmd.at(i));
			}
			else{
				i=cmd.size();
			}
		}

		//check for invalid instances of && and ||
		if(!checkConnector(cmd2, stringToken)){
			cout << "rshell: syntax error near unexpected token \'" << stringToken << "\'" << endl;
			cmd2 = "";
		}

		if(cmd2!=""){ //if command is not empty
			//convert string to char*
			char *cmdA = new char[cmd2.size()+1];
			for(int i = 0; i<static_cast<int>(cmd2.size()); i++){
				cmdA[i] = cmd2.at(i);
				if(i+1==static_cast<int>(cmd.size())){
					cmdA[i+1] = '\0'; //null terminating
				}
			}

			char *cmdB = strtok(cmdA, ";"); //parsing ";"

			bool cmdBDone = false;
			while(!cmdBDone){
				//cout << "cmdB: " << cmdB << endl;
				parseMaster(cmdB);
				cmdB = strtok(NULL, ";");
				if(cmdB==NULL){
					cmdBDone = true;
				}
			}
			delete[] cmdA;
			delete[] cmdB;
		}
	}
	return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <vector>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <limits>

using namespace std;

void displayPrompt(){
    char *user = getlogin(); //I assign the login name to a user pointer
    if(user == NULL){
        perror("getlogin");
        exit(1);
    }

    char hostname[100]; //I allocate space for the hostname
    if(gethostname(hostname, sizeof(hostname)) == -1){ //checking for errors withostname
        perror("gethostname");
        exit(1);
    }

    cout << user << '@' << hostname << '$' << ' '; //here I output the user and hostanme to the screen.

}

int extractCommands(string &commandLine, char **cmds){
    const char* args = commandLine.c_str(); //the user input is converted to a const char* as we need it for execvp
    char* args_Mutatable = const_cast<char*>(args); //it needs to be mutable for us to tokenize it
    char *single_command;
    single_command = strtok(args_Mutatable, " ;&|"); //execute strtok with delimeters

    int numOfArgs = 0; //when you add one --> argv[1]

    while(single_command != NULL){
        //cout << single_command << endl;
        cmds[numOfArgs] = strdup(single_command); //this processes each command into the command array for execution
        cout << "at position " << numOfArgs << ": " << cmds[numOfArgs];
        cout << endl;
        single_command = strtok(NULL, " ;&|");
        numOfArgs++;
    }

    cmds[numOfArgs] = NULL;
    return numOfArgs;
}

int executeCommand(int pos, char **args){
    int pid = fork();

    if(pid == -1){
        perror("There was some error with fork()");
        exit(1);
    }
    else if(pid == 0){
        if(-1 == execvp(/*args[0]*/ args[pos], args)){
            perror("There was an error with execvp");
            exit(1);
        }
    }
    else if(pid > 0){
        if(-1 == wait(0)){
            perror("There was an error with wait()");
        }
    }

    return 0; //if everything goes well, return 0
}

vector<string>  extractConnectors(string inputLine){
    vector<string> cnctors;
    for(unsigned int i = 0; i < inputLine.size(); ++i){
        if(inputLine.at(i)  == ';'){
            cnctors.push_back(";");
        }
        if((inputLine.at(i) == '&' && inputLine.at(i+1) == '&')){
            cnctors.push_back("&&");
        }
        if((inputLine.at(i) == '|' && inputLine.at(i+1) == '|')){
            cnctors.push_back("||");
        }
    }
    return cnctors;
}

int main(){
    string userInput; //command line in string format
    char *cmds[10000];
    do{
        displayPrompt(); //displays current user and hostname

        getline(cin, userInput); //get's input from user and stores it in a string

        /*gets all the delimeters and stores into a vector*/
        vector<string> connectors = extractConnectors(userInput);
        cout << "CONNECTORS: ";
        for(unsigned i = 0; i < connectors.size(); ++i){
            cout << connectors.at(i) << ' ';
        }
        cout << endl;

        //cout << userInput << endl; //NEED TO DELETE UPON COMPLETETION

        int numArgs = extractCommands(userInput, cmds); //retrieve number of arguments by parsing the string

        if(numArgs <= 0){continue;} //if there are no arguments, simply continue to the next iteration

        /*checks if first argument is exit and quits iff it's the only argument*/
        if( (strcmp(cmds[0], "exit") == 0) && (numArgs == 1) ) { break; }

        /*if(executeCommand(cmds) != 0){
            cout << "Error in executing commands" << endl;
        }*/

    }while(1);

    return 0;
}

<commit_msg>backup point<commit_after>#include <iostream>
#include <vector>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <limits>

using namespace std;

void displayPrompt(){
    char *user = getlogin(); //I assign the login name to a user pointer
    if(user == NULL){
        perror("getlogin");
        exit(1);
    }

    char hostname[100]; //I allocate space for the hostname
    if(gethostname(hostname, sizeof(hostname)) == -1){ //checking for errors withostname
        perror("gethostname");
        exit(1);
    }

    cout << user << '@' << hostname << '$' << ' '; //here I output the user and hostanme to the screen.

}

int executeCommand(char **args){
    int pid = fork();

    if(pid == -1){
        perror("There was some error with fork()");
        exit(1);
    }
    else if(pid == 0){
        if(-1 == execvp(args[0], args)){
            perror("There was an error with execvp");
            exit(1);
        }
    }
    else if(pid > 0){
        if(-1 == wait(0)){
            perror("There was an error with wait()");
        }
    }

    return 0; //if everything goes well, return 0
}

int extractCommands(string &commandLine, char **cmds){
    const char* args = commandLine.c_str(); //the user input is converted to a const char* as we need it for execvp
    char* args_Mutatable = const_cast<char*>(args); //it needs to be mutable for us to tokenize it
    char *single_command;
    single_command = strtok(args_Mutatable, " ;&|"); //execute strtok with delimeters

    int numOfArgs = 0; //when you add one --> argv[1]

    while(single_command != NULL){
        //cout << single_command << endl;
        cmds[numOfArgs] = strdup(single_command); //this processes each command into the command array for execution
        cout << "at position " << numOfArgs << ": " << cmds[numOfArgs];
        cout << endl;
        single_command = strtok(NULL, " ;&|");
        numOfArgs++;
    }

    cmds[numOfArgs] = NULL;
    return numOfArgs;
}

vector<string>  extractConnectors(string inputLine){
    vector<string> cnctors;
    for(unsigned int i = 0; i < inputLine.size(); ++i){
        if(inputLine.at(i)  == ';'){
            cnctors.push_back(";");
        }
        if((inputLine.at(i) == '&' && inputLine.at(i+1) == '&')){
            cnctors.push_back("&&");
        }
        if((inputLine.at(i) == '|' && inputLine.at(i+1) == '|')){
            cnctors.push_back("||");
        }
    }
    return cnctors;
}

void run(vector<string> &connectors, char **cmds){
    for(unsigned int i = 0; i < connectors.size(); ++i){
        if(connectors.at(i) == ";"){
            if(executeCommand(cmds) != 0){
                cout << "ERROR: couldn't execute command properly" << endl;
            }
        }
    }
}

int main(){
    string userInput; //command line in string format
    char *cmds[10000];
    do{
        displayPrompt(); //displays current user and hostname

        getline(cin, userInput); //get's input from user and stores it in a string

        /*gets all the delimeters and stores into a vector*/
        vector<string> connectors = extractConnectors(userInput);
        cout << "CONNECTORS: ";
        for(unsigned i = 0; i < connectors.size(); ++i){
            cout << connectors.at(i) << ' ';
        }
        cout << endl;

        //cout << userInput << endl; //NEED TO DELETE UPON COMPLETETION

        int numArgs = extractCommands(userInput, cmds); //retrieve number of arguments by parsing the string

        if(numArgs <= 0){continue;} //if there are no arguments, simply continue to the next iteration

        /*checks if first argument is exit and quits iff it's the only argument*/
        if( (strcmp(cmds[0], "exit") == 0) && (numArgs == 1) ) { break; }

        run(connectors, cmds);
        /*if(executeCommand(cmds) != 0){
            cout << "Error in executing commands" << endl;
        }*/

    }while(1);

    return 0;
}

<|endoftext|>


<commit_before>#include<iostream>
#include<string.h>
#include<string>
#include<vector>
#include<sys/types.h>
#include<sys/wait.h>
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<cstring>
#include<boost/tokenizer.hpp>
#include<algorithm>
#include<iterator>
#include<sstream>

using namespace std;
using namespace boost;

void parse_line(char c_line[], char *command_line[]);
void run_line(char *command_line[]);

 int main()
{
	string str;
	string arg = "";
	 while(1)
	{
		str = "";
		char userName[100] = "";
		if(getlogin_r(userName, sizeof(userName)-1) != 0) //Getting username, and returns null if cant be found
		{
			perror("Error getting username");
		}
		cout << '['  << userName << '@';
		char hostName[100] = "";
		if(gethostname(hostName, sizeof(hostName)-1) != 0) // Getting host name, returns numm if it cannot be found
		{
			perror("Error getting hostname");
		}
		cout << hostName << ']';
		cout << "$";
		getline(cin,str);  //Gets a command
		if(str == "exit")  //If the command is exit the program stops
		{
			 break;
		}
		if(str.size() != 0 && str.at(0) == '#')
		{
			str = "";
		}
		if(str != "")
		{
			for(unsigned i = 0; i < str.size(); i++)
			{
				if(str.at(i) == ';')  //Looks for semicolons and adds a space in order to make parsing easier
				{
					str.insert(i, " ");
					i++;
				}
				if(str.at(i) == '#')  //Removes all part of the command after the comment
				{
					str = str.substr(0,i);
				}
			}
			while(str.find("  ") != string::npos)
			{
				str.erase(str.find(" "));
			}
			if(str.at(str.size() - 1 ) == ' ')
			{
				str = str.substr(0,str.size()-1);
			}
			char c_line[64];
			char *command_line[64];
			strcpy(c_line,str.c_str());
			c_line[str.size()] = '\0';

			parse_line(c_line, command_line);
			run_line(command_line);
		}

	}
	  return 0;
}

int k = 0;

void parse_line(char c_line[], char *command_line[])
{
	while(*c_line != '\0')
	{
		while(*c_line == ' ' || *c_line == '\n' || *c_line == '\t')
		{
			*c_line++ = '\0';
		}
		if(*c_line == ';')
		{
			run_line(command_line);
			//for(int i = 0; i < 64; i++)
			//{
			//	command_line[i] = new char[16];
			//}
			//command_line = new char*[64];
			//for(int i = 0; i < 64; i++)
			//{
			//	delete [] command_line[i];
			//}
			//delete [] command_line;
			c_line++;
		}
		*command_line++ = c_line;
		while(*c_line != '\0' && *c_line != ' ' && *c_line != '\n' && *c_line != '\t')
		{
			c_line++;
		}
		*command_line = '\0';
	}
	return;
}

void run_line(char *command_line[])
{
	pid_t pid;
	int status;
	if((pid = fork()) < 0)
	{
		perror("forking failed");
	}
	else if(pid == 0)
	{
		if(execvp(*command_line,command_line) < 0)
		{
			perror("execvp failed");
			exit(1);
		}
	}
	else
	{
		while(wait(&status) != pid)
		;
	}
	return;
}
<commit_msg>solving spacing issue<commit_after>#include<iostream>
#include<string.h>
#include<string>
#include<vector>
#include<sys/types.h>
#include<sys/wait.h>
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<cstring>
#include<boost/tokenizer.hpp>
#include<algorithm>
#include<iterator>
#include<sstream>

using namespace std;
using namespace boost;

void parse_line(char c_line[], char *command_line[]);
void run_line(char *command_line[]);

 int main()
{
	string str;
	string arg = "";
	 while(1)
	{
		str = "";
		char userName[100] = "";
		if(getlogin_r(userName, sizeof(userName)-1) != 0) //Getting username, and returns null if cant be found
		{
			perror("Error getting username");
		}
		cout << '['  << userName << '@';
		char hostName[100] = "";
		if(gethostname(hostName, sizeof(hostName)-1) != 0) // Getting host name, returns numm if it cannot be found
		{
			perror("Error getting hostname");
		}
		cout << hostName << ']';
		cout << "$";
		getline(cin,str);  //Gets a command
		if(str == "exit")  //If the command is exit the program stops
		{
			 break;
		}
		if(str.size() != 0 && str.at(0) == '#')
		{
			str = "";
		}
		if(str != "")
		{
			for(unsigned i = 0; i < str.size(); i++)
			{
				if(str.at(i) == ';')  //Looks for semicolons and adds a space in order to make parsing easier
				{
					str.insert(i, " ");
					i++;
				}
				if(str.at(i) == '#')  //Removes all part of the command after the comment
				{
					str = str.substr(0,i);
				}
			}
			while(str.find("  ") != string::npos)
			{
				str.erase(str.find("  ") + 1);
			}
			if(str.at(str.size() - 1 ) == ' ')
			{
				str = str.substr(0,str.size()-1);
			}
			char c_line[64];
			char *command_line[64];
			strcpy(c_line,str.c_str());
			c_line[str.size()] = '\0';
			parse_line(c_line, command_line);
			run_line(command_line);
		}

	}
	  return 0;
}

void parse_line(char c_line[], char *command_line[])
{
	while(*c_line != '\0')
	{
		while(*c_line == ' ' || *c_line == '\n' || *c_line == '\t')
		{
			*c_line++ = '\0';
		}
		//if(*c_line == ';')
		//{
			//run_line(command_line);
			//for(int i = 0; i < 64; i++)
			//{
			//	command_line[i] = new char[16];
			//}
			//command_line = new char*[64];
			//for(int i = 0; i < 64; i++)
			//{
			//	delete [] command_line[i];
			//}
			//delete [] command_line;
			//c_line++;
		//}
		*command_line++ = c_line;
		while(*c_line != '\0' && *c_line != ' ' && *c_line != '\n' && *c_line != '\t')
		{
			c_line++;
		}
		*command_line = '\0';
	}
	return;
}

void run_line(char *command_line[])
{
	pid_t pid;
	int status;
	if((pid = fork()) < 0)
	{
		perror("forking failed");
	}
	else if(pid == 0)
	{
		if(execvp(*command_line,command_line) < 0)
		{
			perror("execvp failed");
			exit(1);
		}
	}
	else
	{
		while(wait(&status) != pid)
		;
	}
	return;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <unistd.h>
#include <string>
#include <memory>
#include <vector>
#include <list>
#include <sstream>
#include <algorithm>
#include <boost/tokenizer.hpp>

const std::vector<std::string>
DEFINED_OPERATORS =
{"&&", "||", ";"};

void CombineDefinedOps(std::list<std::string>& input);

//uses unix calls to get username and hostname
//returns 'shellish' formatted str ie usrname@host:~$
std::string UserHostInfo();

//output username@hostname$ and wait for command input
std::string Prompt();

//separates string by delimeters into vector elements
//if # is found it excludes it and anything beyond in the string
std::list<std::string> Split(const std::string& input);

void Parse(std::list<std::string>& input);

// takes the input list and an operator character and merges all repeating instances of that character within the list
// operators in shell can use the same symbol a different amount of times to represent different things
// ie bitwise & vs and &&
// the delimiter method I used to separate the arguments in the first place only had single character delimiting available
// since the function is general it will:
// avoid having to create new handcrafted parses when more features have to be added
// make bug checking general and simple (is & implemented? is &&& implemented? if not theyre bugs)
void RebuildOps(std::list<std::string>& input, std::string op);

int main() {
    while(true) {
        auto cmd = Prompt();
        auto input = Split(cmd);
        RebuildOps(input, "&");

        Parse(input);
    }

    //execvp(list.c_str(), args);

}
std::string UserHostInfo() {
    std::string loginname(getlogin());

    char *rawhost= new char[100];
    gethostname(rawhost,100);
    std::string hostname(rawhost);
    delete [] rawhost;

    std::string pwd(get_current_dir_name());

    //handles /home/username -> ~/ shortcut
    std::string target = "/home/"+loginname+"/";
    if (pwd.find(target) == 0) {
        pwd.erase(0,target.size());
        pwd = "~/"+pwd;
    }
    return loginname+"@"+hostname+":"+pwd+"$ ";
}
std::string Prompt() {
    std::cout << UserHostInfo();
    std::string input;
    std::getline(std::cin, input);
    return input;
}

std::list<std::string> Split(const std::string& input) {
    using namespace boost;
    using namespace std;
    list<string> input_split;
    char_separator<char> sep("", " #&|;");
    typedef tokenizer<char_separator<char>> tokener;

    tokener tokens(input, sep);

    //complexity increases if I handle # as bash does.
    for (const auto& t : tokens) {
        if (t == "#") break;
        input_split.push_back(t);
    }

    return input_split;
}

void Parse(std::list<std::string>& input) {
    using namespace std;
    for (const auto& e : input)
        cout << e << endl;

}
void RebuildOps(std::list<std::string>& input, std::string op) {
    using namespace std;
    auto front = input.begin();
    auto back = input.end();
    while (front != back) {
        auto element = find(front, back, op);
        int count = 0;
        while (element != back) {
            if (*element == op) {
                element = input.erase(element);
                count++;
            }
            else {
                break;
            }
        }
        std::string tempstr = "";
        while (count--) {
            tempstr += op;
        }
        front = input.insert(element, tempstr);
        front++;
    }
}
void CombineDefinedOps(std::list<std::string>& input) {
    for(const auto& op : DEFINED_OPERATORS) {
        auto single = op.substr(0,1);
        RebuildOps(input, single);
    }
}
<commit_msg>CombineDefinedOps slight change<commit_after>#include <iostream>
#include <unistd.h>
#include <string>
#include <memory>
#include <vector>
#include <list>
#include <sstream>
#include <map>
#include <algorithm>
#include <boost/tokenizer.hpp>

const std::multimap<std::string, int>
DEFINED_OPS = {
    std::make_pair("&",2),
    std::make_pair("|",2),
    std::make_pair(";",1)
};

const std::vector<std::string> DEFINED_ADJACENT_OPS = {};
void CombineDefinedOps(std::list<std::string>& input);

//uses unix calls to get username and hostname
//returns 'shellish' formatted str ie usrname@host:~$
std::string UserHostInfo();

//output username@hostname$ and wait for command input
std::string Prompt();

//separates string by delimeters into vector elements
//if # is found it excludes it and anything beyond in the string
std::list<std::string> Split(const std::string& input);

void Output(std::list<std::string>& input);

// takes the input list and an operator character and merges all repeating instances of that character within the list
// operators in shell can use the same symbol a different amount of times to represent different things
// ie bitwise & vs and &&
// the delimiter method I used to separate the arguments in the first place only had single character delimiting available
// since the function is general it will:
// avoid having to create new handcrafted parses when more features have to be added
// make bug checking general and simple (is & implemented? is &&& implemented? if not theyre bugs)
void RebuildOps(std::list<std::string>& input, std::string op);

int main() {
    while(true) {
        auto cmd = Prompt();
        auto input = Split(cmd);
        CombineDefinedOps(input);
        Output(input);
    }

    //execvp(list.c_str(), args);

}
std::string UserHostInfo() {
    std::string loginname(getlogin());

    char *rawhost= new char[100];
    gethostname(rawhost,100);
    std::string hostname(rawhost);
    delete [] rawhost;

    std::string pwd(get_current_dir_name());

    //handles /home/username -> ~/ shortcut
    std::string target = "/home/"+loginname+"/";
    if (pwd.find(target) == 0) {
        pwd.erase(0,target.size());
        pwd = "~/"+pwd;
    }
    return loginname+"@"+hostname+":"+pwd+"$ ";
}
std::string Prompt() {
    std::cout << UserHostInfo();
    std::string input;
    std::getline(std::cin, input);
    return input;
}

std::list<std::string> Split(const std::string& input) {
    using namespace boost;
    using namespace std;
    list<string> input_split;
    char_separator<char> sep("", " #&|;");
    typedef tokenizer<char_separator<char>> tokener;

    tokener tokens(input, sep);

    //complexity increases if I handle # as bash does.
    for (const auto& t : tokens) {
        if (t == "#") break;
        input_split.push_back(t);
    }

    return input_split;
}

void Output(std::list<std::string>& input) {
    using namespace std;
    for (const auto& e : input)
        cout << e << endl;

}
void RebuildOps(std::list<std::string>& input, std::string op) {
    using namespace std;
    auto front = input.begin();
    auto back = input.end();
    while (front != back) {
        auto element = find(front, back, op);
        int count = 0;
        while (element != back) {
            if (*element == op) {
                element = input.erase(element);
                count++;
            }
            else {
                break;
            }
        }
        std::string tempstr = "";
        while (count--) {
            tempstr += op;
        }
        front = input.insert(element, tempstr);
        front++;
    }
}
void CombineDefinedOps(std::list<std::string>& input) {
    for(const auto& op : DEFINED_OPS) {
        RebuildOps(input, op.first);
    }
}
<|endoftext|>


<commit_before>#include <tree_sitter/parser.h>
#include <vector>
#include <cwctype>
#include <cstring>
#include <cassert>
#include <stdio.h>
namespace {

using std::vector;
using std::iswspace;
using std::memcpy;

enum TokenType {
  NEWLINE,
  INDENT,
  DEDENT,
  STRING_START,
  STRING_CONTENT,
  STRING_END,
};

struct Delimiter {
  enum {
    SingleQuote = 1 << 0,
    DoubleQuote = 1 << 1,
    BackQuote = 1 << 2,
    Raw = 1 << 3,
    Format = 1 << 4,
    Triple = 1 << 5,
    Bytes = 1 << 6,
  };

  Delimiter() : flags(0) {}

  bool is_format() const {
    return flags & Format;
  }

  bool is_raw() const {
    return flags & Raw;
  }

  bool is_triple() const {
    return flags & Triple;
  }

  bool is_bytes() const {
    return flags & Bytes;
  }

  int32_t end_character() const {
    if (flags & SingleQuote) return '\'';
    if (flags & DoubleQuote) return '"';
    if (flags & BackQuote) return '`';
    return 0;
  }

  void set_format() {
    flags |= Format;
  }

  void set_raw() {
    flags |= Raw;
  }

  void set_triple() {
    flags |= Triple;
  }

  void set_bytes() {
    flags |= Bytes;
  }

  void set_end_character(int32_t character) {
    switch (character) {
      case '\'':
        flags |= SingleQuote;
        break;
      case '"':
        flags |= DoubleQuote;
        break;
      case '`':
        flags |= BackQuote;
        break;
      default:
        assert(false);
    }
  }

  char flags;
};

struct Scanner {
  Scanner() {
    assert(sizeof(Delimiter) == sizeof(char));
    deserialize(NULL, 0);
  }

  unsigned serialize(char *buffer) {
    size_t i = 0;

    size_t delimiter_count = delimiter_stack.size();
    if (delimiter_count > UINT8_MAX) delimiter_count = UINT8_MAX;
    buffer[i++] = delimiter_count;

    if (delimiter_count > 0) {
      memcpy(&buffer[i], delimiter_stack.data(), delimiter_count);
    }
    i += delimiter_count;

    vector<uint16_t>::iterator
      iter = indent_length_stack.begin() + 1,
      end = indent_length_stack.end();

    for (; iter != end && i < TREE_SITTER_SERIALIZATION_BUFFER_SIZE; ++iter) {
      buffer[i++] = *iter;
    }

    return i;
  }

  void deserialize(const char *buffer, unsigned length) {
    delimiter_stack.clear();
    indent_length_stack.clear();
    indent_length_stack.push_back(0);

    if (length > 0) {
      size_t i = 0;

      size_t delimiter_count = (uint8_t)buffer[i++];
      delimiter_stack.resize(delimiter_count);
      if (delimiter_count > 0) {
        memcpy(delimiter_stack.data(), &buffer[i], delimiter_count);
      }
      i += delimiter_count;

      for (; i < length; i++) {
        indent_length_stack.push_back(buffer[i]);
      }
    }
  }

  void advance(TSLexer *lexer) {
    lexer->advance(lexer, false);
  }

  void skip(TSLexer *lexer) {
    lexer->advance(lexer, true);
  }

  bool scan(TSLexer *lexer, const bool *valid_symbols) {
    bool error_recovery_mode = valid_symbols[STRING_CONTENT] && valid_symbols[INDENT];

    if (valid_symbols[STRING_CONTENT] && !delimiter_stack.empty() && !error_recovery_mode) {
      Delimiter delimiter = delimiter_stack.back();
      int32_t end_character = delimiter.end_character();
      bool has_content = false;
      while (lexer->lookahead) {
        if ((lexer->lookahead == '{' || lexer->lookahead == '}') && delimiter.is_format()) {
          lexer->mark_end(lexer);
          lexer->result_symbol = STRING_CONTENT;
          return has_content;
        } else if (lexer->lookahead == '\\') {
          if (delimiter.is_raw()) {
            lexer->advance(lexer, false);
          } else if (delimiter.is_bytes()) {
              lexer->mark_end(lexer);
              lexer->advance(lexer, false);
              if (lexer->lookahead == 'N' || lexer->lookahead == 'u' || lexer->lookahead == 'U') {
                // In bytes string, \N{...}, \uXXXX and \UXXXXXXXX are not escape sequences
                // https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals
                lexer->advance(lexer, false);
              } else {
                  lexer->result_symbol = STRING_CONTENT;
                  return has_content;
              }
          } else {
            lexer->mark_end(lexer);
            lexer->result_symbol = STRING_CONTENT;
            return has_content;
          }
        } else if (lexer->lookahead == end_character) {
          if (delimiter.is_triple()) {
            lexer->mark_end(lexer);
            lexer->advance(lexer, false);
            if (lexer->lookahead == end_character) {
              lexer->advance(lexer, false);
              if (lexer->lookahead == end_character) {
                if (has_content) {
                  lexer->result_symbol = STRING_CONTENT;
                } else {
                  lexer->advance(lexer, false);
                  lexer->mark_end(lexer);
                  delimiter_stack.pop_back();
                  lexer->result_symbol = STRING_END;
                }
                return true;
              } else {
                lexer->mark_end(lexer);
                lexer->result_symbol = STRING_CONTENT;
                return true;
              }
            } else {
              lexer->mark_end(lexer);
              lexer->result_symbol = STRING_CONTENT;
              return true;
            }
          } else {
            if (has_content) {
              lexer->result_symbol = STRING_CONTENT;
            } else {
              lexer->advance(lexer, false);
              delimiter_stack.pop_back();
              lexer->result_symbol = STRING_END;
            }
            lexer->mark_end(lexer);
            return true;
          }
        } else if (lexer->lookahead == '\n' && has_content && !delimiter.is_triple()) {
          return false;
        }
        advance(lexer);
        has_content = true;
      }
    }

    lexer->mark_end(lexer);

    bool found_end_of_line = false;
    uint32_t indent_length = 0;
    int32_t first_comment_indent_length = -1;
    for (;;) {
      if (lexer->lookahead == '\n') {
        found_end_of_line = true;
        indent_length = 0;
        skip(lexer);
      } else if (lexer->lookahead == ' ') {
        indent_length++;
        skip(lexer);
      } else if (lexer->lookahead == '\r') {
        indent_length = 0;
        skip(lexer);
      } else if (lexer->lookahead == '\t') {
        indent_length += 8;
        skip(lexer);
      } else if (lexer->lookahead == '#') {
        if (first_comment_indent_length == -1) {
          first_comment_indent_length = (int32_t)indent_length;
        }
        while (lexer->lookahead && lexer->lookahead != '\n') {
          skip(lexer);
        }
        skip(lexer);
        indent_length = 0;
      } else if (lexer->lookahead == '\\') {
        skip(lexer);
        if (lexer->lookahead == '\r') {
          skip(lexer);
        }
        if (lexer->lookahead == '\n') {
          skip(lexer);
        } else {
          return false;
        }
      } else if (lexer->lookahead == '\f') {
        indent_length = 0;
        skip(lexer);
      } else if (lexer->lookahead == 0) {
        indent_length = 0;
        found_end_of_line = true;
        break;
      } else {
        break;
      }
    }

    if (found_end_of_line && !error_recovery_mode) {
      if (!indent_length_stack.empty()) {
        uint16_t current_indent_length = indent_length_stack.back();

        if (
          valid_symbols[INDENT] &&
          indent_length > current_indent_length
        ) {
          indent_length_stack.push_back(indent_length);
          lexer->result_symbol = INDENT;
          return true;
        }

        if (
          valid_symbols[DEDENT] &&
          indent_length < current_indent_length &&

          // Wait to create a dedent token until we've consumed any comments
          // whose indentation matches the current block.
          first_comment_indent_length < (int32_t)current_indent_length
        ) {
          indent_length_stack.pop_back();
          lexer->result_symbol = DEDENT;
          return true;
        }
      }

      if (valid_symbols[NEWLINE]) {
        lexer->result_symbol = NEWLINE;
        return true;
      }
    }

    if (first_comment_indent_length == -1 && valid_symbols[STRING_START]) {
      Delimiter delimiter;

      bool has_flags = false;
      while (lexer->lookahead) {
        if (lexer->lookahead == 'f' || lexer->lookahead == 'F') {
          delimiter.set_format();
        } else if (lexer->lookahead == 'r' || lexer->lookahead == 'R') {
          delimiter.set_raw();
        } else if (lexer->lookahead == 'b' || lexer->lookahead == 'B') {
          delimiter.set_bytes();
        } else if (lexer->lookahead != 'u' && lexer->lookahead != 'U') {
          break;
        }
        has_flags = true;
        advance(lexer);
      }

      if (lexer->lookahead == '`') {
        delimiter.set_end_character('`');
        advance(lexer);
        lexer->mark_end(lexer);
      } else if (lexer->lookahead == '\'') {
        delimiter.set_end_character('\'');
        advance(lexer);
        lexer->mark_end(lexer);
        if (lexer->lookahead == '\'') {
          advance(lexer);
          if (lexer->lookahead == '\'') {
            advance(lexer);
            lexer->mark_end(lexer);
            delimiter.set_triple();
          }
        }
      } else if (lexer->lookahead == '"') {
        delimiter.set_end_character('"');
        advance(lexer);
        lexer->mark_end(lexer);
        if (lexer->lookahead == '"') {
          advance(lexer);
          if (lexer->lookahead == '"') {
            advance(lexer);
            lexer->mark_end(lexer);
            delimiter.set_triple();
          }
        }
      }

      if (delimiter.end_character()) {
        delimiter_stack.push_back(delimiter);
        lexer->result_symbol = STRING_START;
        return true;
      } else if (has_flags) {
        return false;
      }
    }

    return false;
  }

  vector<uint16_t> indent_length_stack;
  vector<Delimiter> delimiter_stack;
};

}

extern "C" {

void *tree_sitter_python_external_scanner_create() {
  return new Scanner();
}

bool tree_sitter_python_external_scanner_scan(void *payload, TSLexer *lexer,
                                            const bool *valid_symbols) {
  Scanner *scanner = static_cast<Scanner *>(payload);
  return scanner->scan(lexer, valid_symbols);
}

unsigned tree_sitter_python_external_scanner_serialize(void *payload, char *buffer) {
  Scanner *scanner = static_cast<Scanner *>(payload);
  return scanner->serialize(buffer);
}

void tree_sitter_python_external_scanner_deserialize(void *payload, const char *buffer, unsigned length) {
  Scanner *scanner = static_cast<Scanner *>(payload);
  scanner->deserialize(buffer, length);
}

void tree_sitter_python_external_scanner_destroy(void *payload) {
  Scanner *scanner = static_cast<Scanner *>(payload);
  delete scanner;
}

}
<commit_msg>Always allow dedents to be recognized during error recovery<commit_after>#include <tree_sitter/parser.h>
#include <vector>
#include <cwctype>
#include <cstring>
#include <cassert>
#include <stdio.h>
namespace {

using std::vector;
using std::iswspace;
using std::memcpy;

enum TokenType {
  NEWLINE,
  INDENT,
  DEDENT,
  STRING_START,
  STRING_CONTENT,
  STRING_END,
};

struct Delimiter {
  enum {
    SingleQuote = 1 << 0,
    DoubleQuote = 1 << 1,
    BackQuote = 1 << 2,
    Raw = 1 << 3,
    Format = 1 << 4,
    Triple = 1 << 5,
    Bytes = 1 << 6,
  };

  Delimiter() : flags(0) {}

  bool is_format() const {
    return flags & Format;
  }

  bool is_raw() const {
    return flags & Raw;
  }

  bool is_triple() const {
    return flags & Triple;
  }

  bool is_bytes() const {
    return flags & Bytes;
  }

  int32_t end_character() const {
    if (flags & SingleQuote) return '\'';
    if (flags & DoubleQuote) return '"';
    if (flags & BackQuote) return '`';
    return 0;
  }

  void set_format() {
    flags |= Format;
  }

  void set_raw() {
    flags |= Raw;
  }

  void set_triple() {
    flags |= Triple;
  }

  void set_bytes() {
    flags |= Bytes;
  }

  void set_end_character(int32_t character) {
    switch (character) {
      case '\'':
        flags |= SingleQuote;
        break;
      case '"':
        flags |= DoubleQuote;
        break;
      case '`':
        flags |= BackQuote;
        break;
      default:
        assert(false);
    }
  }

  char flags;
};

struct Scanner {
  Scanner() {
    assert(sizeof(Delimiter) == sizeof(char));
    deserialize(NULL, 0);
  }

  unsigned serialize(char *buffer) {
    size_t i = 0;

    size_t delimiter_count = delimiter_stack.size();
    if (delimiter_count > UINT8_MAX) delimiter_count = UINT8_MAX;
    buffer[i++] = delimiter_count;

    if (delimiter_count > 0) {
      memcpy(&buffer[i], delimiter_stack.data(), delimiter_count);
    }
    i += delimiter_count;

    vector<uint16_t>::iterator
      iter = indent_length_stack.begin() + 1,
      end = indent_length_stack.end();

    for (; iter != end && i < TREE_SITTER_SERIALIZATION_BUFFER_SIZE; ++iter) {
      buffer[i++] = *iter;
    }

    return i;
  }

  void deserialize(const char *buffer, unsigned length) {
    delimiter_stack.clear();
    indent_length_stack.clear();
    indent_length_stack.push_back(0);

    if (length > 0) {
      size_t i = 0;

      size_t delimiter_count = (uint8_t)buffer[i++];
      delimiter_stack.resize(delimiter_count);
      if (delimiter_count > 0) {
        memcpy(delimiter_stack.data(), &buffer[i], delimiter_count);
      }
      i += delimiter_count;

      for (; i < length; i++) {
        indent_length_stack.push_back(buffer[i]);
      }
    }
  }

  void advance(TSLexer *lexer) {
    lexer->advance(lexer, false);
  }

  void skip(TSLexer *lexer) {
    lexer->advance(lexer, true);
  }

  bool scan(TSLexer *lexer, const bool *valid_symbols) {
    bool error_recovery_mode = valid_symbols[STRING_CONTENT] && valid_symbols[INDENT];

    if (valid_symbols[STRING_CONTENT] && !delimiter_stack.empty() && !error_recovery_mode) {
      Delimiter delimiter = delimiter_stack.back();
      int32_t end_character = delimiter.end_character();
      bool has_content = false;
      while (lexer->lookahead) {
        if ((lexer->lookahead == '{' || lexer->lookahead == '}') && delimiter.is_format()) {
          lexer->mark_end(lexer);
          lexer->result_symbol = STRING_CONTENT;
          return has_content;
        } else if (lexer->lookahead == '\\') {
          if (delimiter.is_raw()) {
            lexer->advance(lexer, false);
          } else if (delimiter.is_bytes()) {
              lexer->mark_end(lexer);
              lexer->advance(lexer, false);
              if (lexer->lookahead == 'N' || lexer->lookahead == 'u' || lexer->lookahead == 'U') {
                // In bytes string, \N{...}, \uXXXX and \UXXXXXXXX are not escape sequences
                // https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals
                lexer->advance(lexer, false);
              } else {
                  lexer->result_symbol = STRING_CONTENT;
                  return has_content;
              }
          } else {
            lexer->mark_end(lexer);
            lexer->result_symbol = STRING_CONTENT;
            return has_content;
          }
        } else if (lexer->lookahead == end_character) {
          if (delimiter.is_triple()) {
            lexer->mark_end(lexer);
            lexer->advance(lexer, false);
            if (lexer->lookahead == end_character) {
              lexer->advance(lexer, false);
              if (lexer->lookahead == end_character) {
                if (has_content) {
                  lexer->result_symbol = STRING_CONTENT;
                } else {
                  lexer->advance(lexer, false);
                  lexer->mark_end(lexer);
                  delimiter_stack.pop_back();
                  lexer->result_symbol = STRING_END;
                }
                return true;
              } else {
                lexer->mark_end(lexer);
                lexer->result_symbol = STRING_CONTENT;
                return true;
              }
            } else {
              lexer->mark_end(lexer);
              lexer->result_symbol = STRING_CONTENT;
              return true;
            }
          } else {
            if (has_content) {
              lexer->result_symbol = STRING_CONTENT;
            } else {
              lexer->advance(lexer, false);
              delimiter_stack.pop_back();
              lexer->result_symbol = STRING_END;
            }
            lexer->mark_end(lexer);
            return true;
          }
        } else if (lexer->lookahead == '\n' && has_content && !delimiter.is_triple()) {
          return false;
        }
        advance(lexer);
        has_content = true;
      }
    }

    lexer->mark_end(lexer);

    bool found_end_of_line = false;
    uint32_t indent_length = 0;
    int32_t first_comment_indent_length = -1;
    for (;;) {
      if (lexer->lookahead == '\n') {
        found_end_of_line = true;
        indent_length = 0;
        skip(lexer);
      } else if (lexer->lookahead == ' ') {
        indent_length++;
        skip(lexer);
      } else if (lexer->lookahead == '\r') {
        indent_length = 0;
        skip(lexer);
      } else if (lexer->lookahead == '\t') {
        indent_length += 8;
        skip(lexer);
      } else if (lexer->lookahead == '#') {
        if (first_comment_indent_length == -1) {
          first_comment_indent_length = (int32_t)indent_length;
        }
        while (lexer->lookahead && lexer->lookahead != '\n') {
          skip(lexer);
        }
        skip(lexer);
        indent_length = 0;
      } else if (lexer->lookahead == '\\') {
        skip(lexer);
        if (lexer->lookahead == '\r') {
          skip(lexer);
        }
        if (lexer->lookahead == '\n') {
          skip(lexer);
        } else {
          return false;
        }
      } else if (lexer->lookahead == '\f') {
        indent_length = 0;
        skip(lexer);
      } else if (lexer->lookahead == 0) {
        indent_length = 0;
        found_end_of_line = true;
        break;
      } else {
        break;
      }
    }

    if (found_end_of_line) {
      if (!indent_length_stack.empty()) {
        uint16_t current_indent_length = indent_length_stack.back();

        if (
          valid_symbols[INDENT] &&
          indent_length > current_indent_length
        ) {
          indent_length_stack.push_back(indent_length);
          lexer->result_symbol = INDENT;
          return true;
        }

        if (
          valid_symbols[DEDENT] &&
          indent_length < current_indent_length &&

          // Wait to create a dedent token until we've consumed any comments
          // whose indentation matches the current block.
          first_comment_indent_length < (int32_t)current_indent_length
        ) {
          indent_length_stack.pop_back();
          lexer->result_symbol = DEDENT;
          return true;
        }
      }

      if (valid_symbols[NEWLINE] && !error_recovery_mode) {
        lexer->result_symbol = NEWLINE;
        return true;
      }
    }

    if (first_comment_indent_length == -1 && valid_symbols[STRING_START]) {
      Delimiter delimiter;

      bool has_flags = false;
      while (lexer->lookahead) {
        if (lexer->lookahead == 'f' || lexer->lookahead == 'F') {
          delimiter.set_format();
        } else if (lexer->lookahead == 'r' || lexer->lookahead == 'R') {
          delimiter.set_raw();
        } else if (lexer->lookahead == 'b' || lexer->lookahead == 'B') {
          delimiter.set_bytes();
        } else if (lexer->lookahead != 'u' && lexer->lookahead != 'U') {
          break;
        }
        has_flags = true;
        advance(lexer);
      }

      if (lexer->lookahead == '`') {
        delimiter.set_end_character('`');
        advance(lexer);
        lexer->mark_end(lexer);
      } else if (lexer->lookahead == '\'') {
        delimiter.set_end_character('\'');
        advance(lexer);
        lexer->mark_end(lexer);
        if (lexer->lookahead == '\'') {
          advance(lexer);
          if (lexer->lookahead == '\'') {
            advance(lexer);
            lexer->mark_end(lexer);
            delimiter.set_triple();
          }
        }
      } else if (lexer->lookahead == '"') {
        delimiter.set_end_character('"');
        advance(lexer);
        lexer->mark_end(lexer);
        if (lexer->lookahead == '"') {
          advance(lexer);
          if (lexer->lookahead == '"') {
            advance(lexer);
            lexer->mark_end(lexer);
            delimiter.set_triple();
          }
        }
      }

      if (delimiter.end_character()) {
        delimiter_stack.push_back(delimiter);
        lexer->result_symbol = STRING_START;
        return true;
      } else if (has_flags) {
        return false;
      }
    }

    return false;
  }

  vector<uint16_t> indent_length_stack;
  vector<Delimiter> delimiter_stack;
};

}

extern "C" {

void *tree_sitter_python_external_scanner_create() {
  return new Scanner();
}

bool tree_sitter_python_external_scanner_scan(void *payload, TSLexer *lexer,
                                            const bool *valid_symbols) {
  Scanner *scanner = static_cast<Scanner *>(payload);
  return scanner->scan(lexer, valid_symbols);
}

unsigned tree_sitter_python_external_scanner_serialize(void *payload, char *buffer) {
  Scanner *scanner = static_cast<Scanner *>(payload);
  return scanner->serialize(buffer);
}

void tree_sitter_python_external_scanner_deserialize(void *payload, const char *buffer, unsigned length) {
  Scanner *scanner = static_cast<Scanner *>(payload);
  scanner->deserialize(buffer, length);
}

void tree_sitter_python_external_scanner_destroy(void *payload) {
  Scanner *scanner = static_cast<Scanner *>(payload);
  delete scanner;
}

}
<|endoftext|>


<commit_before>/**************************************************************************

 The MIT License (MIT)

 Copyright (c) 2015 Dmitry Sovetov

 https://github.com/dmsovetov

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:
 The above copyright notice and this permission notice shall be included in all
 copies or substantial portions of the Software.
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.

 **************************************************************************/

#include "Particles.h"

#include "Renderers.h"
#include "Zones.h"
#include "Modules.h"

#define ScalarParam( name ) m_scalar[name] ? &m_scalar[name] : NULL
#define ColorParam( name )  m_color[name]  ? &m_color[name]  : NULL

DC_BEGIN_DREEMCHEST

namespace Fx {

// ----------------------------------------------- Particles ----------------------------------------------- //

// ** Particles::Particles
Particles::Particles( EmitterWPtr emitter ) : m_emitter( emitter ), m_count( 1 )
{
	setRenderingMode( RenderQuads );

	// Add default particle modules
	addModule( DC_NEW Life );
	addModule( DC_NEW Acceleration );
};

// ** Particles::createInstance
ParticlesInstancePtr Particles::createInstance( IMaterialFactoryWPtr materialFactory ) const
{
	return ParticlesInstancePtr( DC_NEW ParticlesInstance( materialFactory, const_cast<Particles*>( this ) ) );
}

// ** Particles::emitter
EmitterWPtr Particles::emitter( void ) const
{
	return m_emitter;
}

// ** Particles::count
s32 Particles::count( void ) const
{
	return m_count;
}

// ** Particles::setCount
void Particles::setCount( s32 value )
{
	m_count = value;
}

// ** Particles::name
const String& Particles::name( void ) const
{
	return m_name;
}

// ** Particles::setName
void Particles::setName( const String& value )
{
	m_name = value;
}

// ** Particles::material
const String& Particles::material( void ) const
{
	return m_material;
}

// ** Particles::setMaterial
void Particles::setMaterial( const String& value )
{
	m_material = value;
}

// ** Particles::renderingMode
RenderingMode Particles::renderingMode( void ) const
{
	return m_renderingMode;
}

// ** Particles::setRenderingMode
void Particles::setRenderingMode( RenderingMode value )
{
	m_renderingMode = value;
}

// ** Particles::addModule
void Particles::addModule( const ModulePtr& module )
{
	DC_BREAK_IF( !module.valid() );
	log::verbose( "%s particle module added\n", module->name().c_str() );
	m_modules.push_back( module );
}

// ** Particles::update
void Particles::update( Particle* particles, s32 first, s32 last, f32 dt ) const
{
	// Construct the simulation state.
	SimulationState state;
	state.m_direction = Vec3( 0.0f, 0.0f, 0.0f );
	state.m_dt		  = dt;
	state.m_time	  = 0.0f;

	// Run all life time modules
	for( s32 i = 0, n = ( s32 )m_modules.size(); i < n; i++ ) {
		m_modules[i]->update( particles, first, last, state );
	}
}

// ------------------------------------------------- ParticlesInstance ------------------------------------------------- //

// ** ParticlesInstance::ParticlesInstance
ParticlesInstance::ParticlesInstance( IMaterialFactoryWPtr materialFactory, ParticlesWPtr particles ) : m_particles( particles ), m_aliveCount( 0 )
{
	s32 count = m_particles->count();

	m_items.life			= new Particle::Life[count];
	m_items.position		= new Vec3[count];
	m_items.size			= new Particle::Scalar[count];
	m_items.indices			= new u32[count];
	m_items.transparency	= new Particle::Scalar[count];
	m_items.rotation		= new f32[count];
	m_items.angularVelocity	= new Particle::Scalar[count];
	m_items.force			= new Particle::Force[count];
	m_items.color			= new Particle::Color[count];

	if( materialFactory.valid() ) {
		m_material = materialFactory->createMaterial( particles->material() );
	}
}

// ** ParticlesInstance::aliveCount
s32 ParticlesInstance::aliveCount( void ) const
{
	return m_aliveCount;
}

// ** ParticlesInstance::addAliveCount
void ParticlesInstance::addAliveCount( s32 value )
{
	m_aliveCount += value;
}

// ** ParticlesInstance::maxCount
s32 ParticlesInstance::maxCount( void ) const
{
	return m_particles->count();
}

// ** ParticlesInstance::items
const Particle& ParticlesInstance::items( void ) const
{
	return m_items;
}

// ** ParticlesInstance::items
Particle& ParticlesInstance::items( void )
{
	return m_items;
}

// ** ParticlesInstance::renderingMode
RenderingMode ParticlesInstance::renderingMode( void ) const
{
	return m_particles->renderingMode();
}

// ** ParticlesInstance::material
IMaterialWPtr ParticlesInstance::material( void ) const
{
	return m_material;
}

// ** ParticlesInstance::setMaterial
void ParticlesInstance::setMaterial( const IMaterialWPtr& value )
{
	m_material = value;
}

// ** ParticlesInstance::bounds
const Bounds& ParticlesInstance::bounds( void ) const
{
	return m_bounds;
}

// ** ParticlesInstance::update
s32 ParticlesInstance::update( f32 dt )
{
	// Lock particles
	Particle* particles = &items();

	// Update particles
	m_particles->update( particles, 0, m_aliveCount, dt );

	// Calculate alive particles count.
	s32 count = m_aliveCount;

	for( s32 i = 0; i < count; i++ ) {
		// Particle is alive - skip it
		if( m_items.life[i].current >= 0.0f ) {
			continue;
		}

		// Decrease the alive particles counter
        count = count - 1;

		// Swap data
		particles->indices[i]			= particles->indices[count];
		particles->position[i]			= particles->position[count];
		particles->rotation[i]			= particles->rotation[count];
		particles->life[i]				= particles->life[count];
		particles->size[i]				= particles->size[count];
		particles->transparency[i]		= particles->transparency[count];
		particles->color[i]				= particles->color[count];
		particles->angularVelocity[i]	= particles->angularVelocity[count];
		particles->force[i]				= particles->force[count];

		// Decrease counter
        i = i - 1;
	}

	// Save alive count
	m_aliveCount = count;

	return m_aliveCount;
}

} // namespace Fx

DC_END_DREEMCHEST
<commit_msg>Fixed: particles bounding box calculation<commit_after>/**************************************************************************

 The MIT License (MIT)

 Copyright (c) 2015 Dmitry Sovetov

 https://github.com/dmsovetov

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:
 The above copyright notice and this permission notice shall be included in all
 copies or substantial portions of the Software.
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.

 **************************************************************************/

#include "Particles.h"

#include "Renderers.h"
#include "Zones.h"
#include "Modules.h"

#define ScalarParam( name ) m_scalar[name] ? &m_scalar[name] : NULL
#define ColorParam( name )  m_color[name]  ? &m_color[name]  : NULL

DC_BEGIN_DREEMCHEST

namespace Fx {

// ----------------------------------------------- Particles ----------------------------------------------- //

// ** Particles::Particles
Particles::Particles( EmitterWPtr emitter ) : m_emitter( emitter ), m_count( 1 )
{
	setRenderingMode( RenderQuads );

	// Add default particle modules
	addModule( DC_NEW Life );
	addModule( DC_NEW Acceleration );
};

// ** Particles::createInstance
ParticlesInstancePtr Particles::createInstance( IMaterialFactoryWPtr materialFactory ) const
{
	return ParticlesInstancePtr( DC_NEW ParticlesInstance( materialFactory, const_cast<Particles*>( this ) ) );
}

// ** Particles::emitter
EmitterWPtr Particles::emitter( void ) const
{
	return m_emitter;
}

// ** Particles::count
s32 Particles::count( void ) const
{
	return m_count;
}

// ** Particles::setCount
void Particles::setCount( s32 value )
{
	m_count = value;
}

// ** Particles::name
const String& Particles::name( void ) const
{
	return m_name;
}

// ** Particles::setName
void Particles::setName( const String& value )
{
	m_name = value;
}

// ** Particles::material
const String& Particles::material( void ) const
{
	return m_material;
}

// ** Particles::setMaterial
void Particles::setMaterial( const String& value )
{
	m_material = value;
}

// ** Particles::renderingMode
RenderingMode Particles::renderingMode( void ) const
{
	return m_renderingMode;
}

// ** Particles::setRenderingMode
void Particles::setRenderingMode( RenderingMode value )
{
	m_renderingMode = value;
}

// ** Particles::addModule
void Particles::addModule( const ModulePtr& module )
{
	DC_BREAK_IF( !module.valid() );
	log::verbose( "%s particle module added\n", module->name().c_str() );
	m_modules.push_back( module );
}

// ** Particles::update
void Particles::update( Particle* particles, s32 first, s32 last, f32 dt ) const
{
	// Construct the simulation state.
	SimulationState state;
	state.m_direction = Vec3( 0.0f, 0.0f, 0.0f );
	state.m_dt		  = dt;
	state.m_time	  = 0.0f;

	// Run all life time modules
	for( s32 i = 0, n = ( s32 )m_modules.size(); i < n; i++ ) {
		m_modules[i]->update( particles, first, last, state );
	}
}

// ------------------------------------------------- ParticlesInstance ------------------------------------------------- //

// ** ParticlesInstance::ParticlesInstance
ParticlesInstance::ParticlesInstance( IMaterialFactoryWPtr materialFactory, ParticlesWPtr particles ) : m_particles( particles ), m_aliveCount( 0 )
{
	s32 count = m_particles->count();

	m_items.life			= new Particle::Life[count];
	m_items.position		= new Vec3[count];
	m_items.size			= new Particle::Scalar[count];
	m_items.indices			= new u32[count];
	m_items.transparency	= new Particle::Scalar[count];
	m_items.rotation		= new f32[count];
	m_items.angularVelocity	= new Particle::Scalar[count];
	m_items.force			= new Particle::Force[count];
	m_items.color			= new Particle::Color[count];

	if( materialFactory.valid() ) {
		m_material = materialFactory->createMaterial( particles->material() );
	}
}

// ** ParticlesInstance::aliveCount
s32 ParticlesInstance::aliveCount( void ) const
{
	return m_aliveCount;
}

// ** ParticlesInstance::addAliveCount
void ParticlesInstance::addAliveCount( s32 value )
{
	m_aliveCount += value;
}

// ** ParticlesInstance::maxCount
s32 ParticlesInstance::maxCount( void ) const
{
	return m_particles->count();
}

// ** ParticlesInstance::items
const Particle& ParticlesInstance::items( void ) const
{
	return m_items;
}

// ** ParticlesInstance::items
Particle& ParticlesInstance::items( void )
{
	return m_items;
}

// ** ParticlesInstance::renderingMode
RenderingMode ParticlesInstance::renderingMode( void ) const
{
	return m_particles->renderingMode();
}

// ** ParticlesInstance::material
IMaterialWPtr ParticlesInstance::material( void ) const
{
	return m_material;
}

// ** ParticlesInstance::setMaterial
void ParticlesInstance::setMaterial( const IMaterialWPtr& value )
{
	m_material = value;
}

// ** ParticlesInstance::bounds
const Bounds& ParticlesInstance::bounds( void ) const
{
	return m_bounds;
}

// ** ParticlesInstance::update
s32 ParticlesInstance::update( f32 dt )
{
	// Lock particles
	Particle* particles = &items();

	// Update particles
	m_particles->update( particles, 0, m_aliveCount, dt );

	// Calculate alive particles count & particle bounding box.
	s32    count = m_aliveCount;
	Bounds bounds;

	for( s32 i = 0; i < count; i++ ) {
		// Particle is alive - skip it
		if( m_items.life[i].current >= 0.0f ) {
			f32 size = -particles->size[i].current;
			bounds << particles->position[i] - Vec3( size, size, size ) << particles->position[i] + Vec3( size, size, size );
			continue;
		}

		// Decrease the alive particles counter
        count = count - 1;

		// Swap data
		particles->indices[i]			= particles->indices[count];
		particles->position[i]			= particles->position[count];
		particles->rotation[i]			= particles->rotation[count];
		particles->life[i]				= particles->life[count];
		particles->size[i]				= particles->size[count];
		particles->transparency[i]		= particles->transparency[count];
		particles->color[i]				= particles->color[count];
		particles->angularVelocity[i]	= particles->angularVelocity[count];
		particles->force[i]				= particles->force[count];

		// Decrease counter
        i = i - 1;
	}

	// Save alive count
	m_aliveCount = count;

	// Save particle bounds
	m_bounds = bounds;

	return m_aliveCount;
}

} // namespace Fx

DC_END_DREEMCHEST
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright The University of North Carolina at Chapel Hill
 *  All rights reserved.
 *
 *  Licensed under the MADAI Software License. You may obtain a copy of
 *  this license at
 *
 *         https://madai-public.cs.unc.edu/software/license/
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

#include "Trace.h"

namespace madai {

Trace
::Trace()
{
  // Nothing to initialize
}

Trace
::~Trace()
{
}

bool
Trace
::Add( const TraceElement & element ) {
  if ( this->GetSize() > 0 ) {
    // Check for consistency with previous element in trace.
    const TraceElement & previousElement = m_TraceElements.back();
    if ( element.m_ParameterValues.size() != previousElement.m_ParameterValues.size() ) {
      return false;
    }
    if ( element.m_OutputValues.size() != previousElement.m_OutputValues.size() ) {
      return false;
    }
  }

  m_TraceElements.push_back( element );

  return true;
}

bool
Trace
::Add( const std::vector< double > & parameterValues,
       const std::vector< double > & outputValues,
       double logLikelihood )
{
  return this->Add( TraceElement( parameterValues, outputValues, logLikelihood ) );
}

bool
Trace
::Add( const std::vector< double > & parameterValues,
       const std::vector< double > & outputValues )
{
  return this->Add( TraceElement( parameterValues, outputValues ) );
}

bool
Trace
::Add( const std::vector< double > & parameterValues )
{
  return this->Add( TraceElement( parameterValues ) );
}

unsigned int
Trace
::GetSize() const
{
  return this->m_TraceElements.size();
}

void
Trace
::Clear()
{
  m_TraceElements.clear();
}

TraceElement &
Trace
::operator[]( unsigned int idx )
{
  return this->m_TraceElements[idx];
}

const TraceElement &
Trace
::operator[]( unsigned int idx ) const
{
  return this->m_TraceElements[idx];
}

template <class T>
void write_vector( std::ostream& o, std::vector< T > const & v, char delim ) {
  if ( !v.empty() ) {
    typename std::vector< T >::const_iterator itr = v.begin();
    o << *(itr++);
    while ( itr < v.end() ) {
      o << delim << *(itr++);
    }
  }
}

bool
Trace
::WriteCSVFile( const std::string & filename,
		const std::vector< Parameter > & parameters,
		const std::vector< std::string > & outputNames ) const
{
  try {
    std::ofstream file( filename.c_str() );
    this->WriteCSVOutput( file, parameters, outputNames );
    file.close();
  } catch ( ... ) {
    return false;
  }

  return true;
}

void
Trace
::WriteCSVOutput( std::ostream & os,
                  const std::vector< Parameter > & parameters,
                  const std::vector< std::string > & outputNames ) const
{
  this->WriteHead( os, parameters, outputNames );
  this->WriteData( os );
}

bool
Trace
::ImportCSVFile( const std::string & filename,
		 int numberOfParameters,
		 int numberOfOutputs )
{
  try {
    std::ifstream file( filename.c_str() );
    // Read in header
    for ( int i = 0; i < numberOfParameters; ++i ) {
      std::string parameterName;
      std::getline( file, parameterName, ',' );
      parameterName = parameterName.substr( 1, parameterName.size() - 2 );
    }

    for ( int i = 0; i < numberOfOutputs; ++i ) {
      std::string outputName;
      std::getline( file, outputName, ',' );
    }

    // Likelihood output
    std::string likelihoodName;
    std::getline( file, likelihoodName );
    likelihoodName = likelihoodName.substr( 1, likelihoodName.size() - 2 );

    // Now read data
    while ( !file.eof() ) {

      std::vector< double > parameterValues;
      for ( int i = 0; i < numberOfParameters; ++i ) {
	std::string parameterString;
	std::getline( file, parameterString, ',' );
	if ( file.eof() ) {
	  break;
	}
	double parameterValue = atof( parameterString.c_str() );

	parameterValues.push_back( parameterValue );
      }

      std::vector< double > outputValues;
      for ( int i = 0; i < numberOfOutputs; ++i ) {
	std::string outputString;
	std::getline( file, outputString, ',' );
	if ( file.eof() ) {
	  break;
	}
	double outputValue = atof( outputString.c_str() );
	outputValues.push_back( outputValue );
      }

      std::string logLikelihoodString;
      std::getline( file, logLikelihoodString );
      if ( file.eof() ) {
	break;
      }
      double logLikelihood = atof( logLikelihoodString.c_str() );

      this->Add( parameterValues, outputValues, logLikelihood );

    }

    file.close();
  } catch ( ... ) {
    // Writing failed
    return false;
  }

  // Writing succeeded
  return true;
}

/*
    Assert:
      FOR ALL i < this->m_TraceElements.size():
        this->m_TraceElements[i].m_ParameterValues.size() == params.size()
        this->m_TraceElements[i].m_OutputValues.size() == outputs.size()
  */
void
Trace
::WriteHead( std::ostream & o,
             const std::vector< Parameter > & params,
             const std::vector< std::string > & outputs) const
{
  if ( !params.empty() ) {
    std::vector< Parameter >::const_iterator itr = params.begin();
    o << '"' << itr->m_Name << '"';
    for ( itr++; itr < params.end(); itr++ ) {
      o << ',' << '"' << itr->m_Name << '"';
    }
    if ( !outputs.empty() ) {
      o << ',';
    }
  }
  if ( !outputs.empty() ) {
    std::vector<std::string>::const_iterator itr = outputs.begin();
    std::cout << "Output name: " << *itr << std::endl;
    o << '"' << *itr << '"';
    for ( itr++; itr < outputs.end(); itr++ ) {
      o << ',' << '"' << *itr << '"';
    }
  }
  o << ",\"LogLikelihood\"\n";
}

void
Trace
::WriteData( std::ostream & out ) const {
  unsigned int n = this->GetSize();
  for ( unsigned int i = 0; i < n; i++ ) {
    const TraceElement & element = (*this)[i];
    write_vector( out, element.m_ParameterValues, ',' );
    out << ',';

    if ( element.m_OutputValues.size() > 0 ) {
      write_vector( out, element.m_OutputValues, ',' );
      out << ',';
    }
    out << element.m_LogLikelihood;
    if ( element.m_Comments.size() > 0 ) {
      out << ",\"";
      write_vector( out, element.m_Comments, ';' );
      out << '"';
    }
    out << '\n';
  }
  out.flush();
}

} // end namespace madai
<commit_msg>Fixed comments<commit_after>/*=========================================================================
 *
 *  Copyright The University of North Carolina at Chapel Hill
 *  All rights reserved.
 *
 *  Licensed under the MADAI Software License. You may obtain a copy of
 *  this license at
 *
 *         https://madai-public.cs.unc.edu/software/license/
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

#include "Trace.h"

namespace madai {

Trace
::Trace()
{
  // Nothing to initialize
}

Trace
::~Trace()
{
}

bool
Trace
::Add( const TraceElement & element ) {
  if ( this->GetSize() > 0 ) {
    // Check for consistency with previous element in trace.
    const TraceElement & previousElement = m_TraceElements.back();
    if ( element.m_ParameterValues.size() != previousElement.m_ParameterValues.size() ) {
      return false;
    }
    if ( element.m_OutputValues.size() != previousElement.m_OutputValues.size() ) {
      return false;
    }
  }

  m_TraceElements.push_back( element );

  return true;
}

bool
Trace
::Add( const std::vector< double > & parameterValues,
       const std::vector< double > & outputValues,
       double logLikelihood )
{
  return this->Add( TraceElement( parameterValues, outputValues, logLikelihood ) );
}

bool
Trace
::Add( const std::vector< double > & parameterValues,
       const std::vector< double > & outputValues )
{
  return this->Add( TraceElement( parameterValues, outputValues ) );
}

bool
Trace
::Add( const std::vector< double > & parameterValues )
{
  return this->Add( TraceElement( parameterValues ) );
}

unsigned int
Trace
::GetSize() const
{
  return this->m_TraceElements.size();
}

void
Trace
::Clear()
{
  m_TraceElements.clear();
}

TraceElement &
Trace
::operator[]( unsigned int idx )
{
  return this->m_TraceElements[idx];
}

const TraceElement &
Trace
::operator[]( unsigned int idx ) const
{
  return this->m_TraceElements[idx];
}

template <class T>
void write_vector( std::ostream& o, std::vector< T > const & v, char delim ) {
  if ( !v.empty() ) {
    typename std::vector< T >::const_iterator itr = v.begin();
    o << *(itr++);
    while ( itr < v.end() ) {
      o << delim << *(itr++);
    }
  }
}

bool
Trace
::WriteCSVFile( const std::string & filename,
		const std::vector< Parameter > & parameters,
		const std::vector< std::string > & outputNames ) const
{
  try {
    std::ofstream file( filename.c_str() );
    this->WriteCSVOutput( file, parameters, outputNames );
    file.close();
  } catch ( ... ) {
    return false;
  }

  return true;
}

void
Trace
::WriteCSVOutput( std::ostream & os,
                  const std::vector< Parameter > & parameters,
                  const std::vector< std::string > & outputNames ) const
{
  this->WriteHead( os, parameters, outputNames );
  this->WriteData( os );
}

bool
Trace
::ImportCSVFile( const std::string & filename,
		 int numberOfParameters,
		 int numberOfOutputs )
{
  try {
    std::ifstream file( filename.c_str() );
    // Read in header
    for ( int i = 0; i < numberOfParameters; ++i ) {
      std::string parameterName;
      std::getline( file, parameterName, ',' );
      parameterName = parameterName.substr( 1, parameterName.size() - 2 );
    }

    for ( int i = 0; i < numberOfOutputs; ++i ) {
      std::string outputName;
      std::getline( file, outputName, ',' );
    }

    // Likelihood output
    std::string likelihoodName;
    std::getline( file, likelihoodName );
    likelihoodName = likelihoodName.substr( 1, likelihoodName.size() - 2 );

    // Now read data
    while ( !file.eof() ) {

      std::vector< double > parameterValues;
      for ( int i = 0; i < numberOfParameters; ++i ) {
	std::string parameterString;
	std::getline( file, parameterString, ',' );
	if ( file.eof() ) {
	  break;
	}
	double parameterValue = atof( parameterString.c_str() );

	parameterValues.push_back( parameterValue );
      }

      std::vector< double > outputValues;
      for ( int i = 0; i < numberOfOutputs; ++i ) {
	std::string outputString;
	std::getline( file, outputString, ',' );
	if ( file.eof() ) {
	  break;
	}
	double outputValue = atof( outputString.c_str() );
	outputValues.push_back( outputValue );
      }

      std::string logLikelihoodString;
      std::getline( file, logLikelihoodString );
      if ( file.eof() ) {
	break;
      }
      double logLikelihood = atof( logLikelihoodString.c_str() );

      this->Add( parameterValues, outputValues, logLikelihood );

    }

    file.close();
  } catch ( ... ) {
    // Reading failed
    return false;
  }

  // Reading succeeded
  return true;
}

/*
    Assert:
      FOR ALL i < this->m_TraceElements.size():
        this->m_TraceElements[i].m_ParameterValues.size() == params.size()
        this->m_TraceElements[i].m_OutputValues.size() == outputs.size()
  */
void
Trace
::WriteHead( std::ostream & o,
             const std::vector< Parameter > & params,
             const std::vector< std::string > & outputs) const
{
  if ( !params.empty() ) {
    std::vector< Parameter >::const_iterator itr = params.begin();
    o << '"' << itr->m_Name << '"';
    for ( itr++; itr < params.end(); itr++ ) {
      o << ',' << '"' << itr->m_Name << '"';
    }
    if ( !outputs.empty() ) {
      o << ',';
    }
  }
  if ( !outputs.empty() ) {
    std::vector<std::string>::const_iterator itr = outputs.begin();
    std::cout << "Output name: " << *itr << std::endl;
    o << '"' << *itr << '"';
    for ( itr++; itr < outputs.end(); itr++ ) {
      o << ',' << '"' << *itr << '"';
    }
  }
  o << ",\"LogLikelihood\"\n";
}

void
Trace
::WriteData( std::ostream & out ) const {
  unsigned int n = this->GetSize();
  for ( unsigned int i = 0; i < n; i++ ) {
    const TraceElement & element = (*this)[i];
    write_vector( out, element.m_ParameterValues, ',' );
    out << ',';

    if ( element.m_OutputValues.size() > 0 ) {
      write_vector( out, element.m_OutputValues, ',' );
      out << ',';
    }
    out << element.m_LogLikelihood;
    if ( element.m_Comments.size() > 0 ) {
      out << ",\"";
      write_vector( out, element.m_Comments, ';' );
      out << '"';
    }
    out << '\n';
  }
  out.flush();
}

} // end namespace madai
<|endoftext|>