#ifndef myutilinc
#define myutilinc
#include <string>
#include <fstream>
#include <vector>
#include <cmath>
using namespace std;

int valueof(string input)
//Purpose: type-juggler from string to integer
//Input: a string containing a sequence of only digits
//Output: that sequence of digits in integer format
//Accesses: none
//Edits: none
//Notes: string is marked as negative ONLY if very first character is a dash.
//       processing of the string terminates upon end of string or first non-digit
//       character, whichever comes first.
//       function may become unstable if string contains a value larger than +/-2.1 billion.
{
	int index=0;
	int ret=0; 
	bool neg=false;
	if(input[index]=='-')
	{
		neg=true;
		index++;
	}
	while(index<input.length() && '0'<=input[index] && input[index]<='9')
	{
		ret=ret*10+(int)(input[index])-0x30;
		index++;
	}
	if(neg)
		ret*=-1;
	return ret;		
};

unsigned short valueof(char input)
//converts a character into an unsigned short between 0-255
{
	return ((unsigned)input)%256;
};

string binary(unsigned int input, int size)
{
	string reverse="";
	string forward="";

	while(input>0)	//build string in reverse order (little endian)
	{
		reverse+=(char)(0x30+input%2);
		input/=2;
	}
	
	while(reverse.length()<size)
		reverse+='0';
	reverse.resize(size);
	
	for(int i=reverse.length()-1; i>=0; i--)	//reverse the string
		forward+=reverse[i];			//to make it big-endian
	return forward;
};

string valueof(int input)
//Purpose: type-juggler that converts an integer to its string format equivalent.
//Input: an integer to convert. May be negative or positive.
//Output: string containing equivalent value
//Accesses: none
//Edits: none
//Notes: negative values will be preceded by "-" and there will be no leading zeroes.
{
	string reverse="";
	string forward="";
	bool neg=false;
	if(input<0)
	{
		forward="-";
		input*=-1;
	}
	else if(input==0)
		return "0";

	while(input>0)	//build string in reverse order (little endian)
	{
		reverse+=(char)(0x30+input%10);
		input/=10;
	}
	for(int i=reverse.length()-1; i>=0; i--)	//reverse the string
		forward+=reverse[i];			//to make it big-endian
	return forward;
};

string addslashes(const string &input)
//Purpose: make input string SQL-query safe by adding escape sequences for
//         "dangerous" characters, the tick, doubletick, and backtick
//Input: input: a string to possibly add escape sequences to
//Output: input string with backslashes in front of dangerous chars
//Accesses: none
//Edits: none
{
	string output="";
	for(int i=0; i<input.length(); i++)
	{
		if(input[i]=='\'' || 
		   input[i]=='\"' ||
		   input[i]=='\\')
			output+='\\';
		output+=input[i];
	}
	return output;
};

double getcurrenttime2()
//Purpose: acquire the current unix timestamp in seconds since 1/1/1970 00:00:00 UTC.
//Input: none
//Output: current unix timestamp with nanoseconds in the decimal
//Accesses: none
//Edits: temporarily stores result in a system file
{
//WINDOWS VERSION
   time_t t=clock();
 	double t1=t;
 	return t1/1000;

/* THIS IS THE UNIX VERSION, DO NOT USE
	system("date +%s%N | sed \"s/\\(.*\\)\\([0-9]\\{9\\}\\)/\\1.\\2/g\" > TEMP_TEMP");
	ifstream inf;
	inf.open("TEMP_TEMP");
	double timestamp;
	inf>>timestamp;
	inf.close();
	system("rm TEMP_TEMP");
	return timestamp;
*/
};


int getcurrenttime()
//Purpose: acquire the current unix timestamp in seconds since 1/1/1970 00:00:00 UTC.
//Input: none
//Output: current unix timestamp
//Accesses: none
//Edits: temporarily stores result in a system file
{
	return (int)getcurrenttime2();
};

//Function: hrconvert(int x6)
//Use: converts a standard time format (Year/Month/Day/Hour/Min/Sec) into
//     a relative number of hours passed since 1970/01/01 00:00:00.
//Args: Year (any), Month (1-12), Day (1-31), Hour (0-23), Min (0-59), Sec(0-60)
//Notes: Does not protect against bad input

double hrconvert(int year, int month, int day, int hour, int min, int sec)
{//converts sanepeople time into an absolute format, in number of whole hours
//since 1/1/70
	double baseyear=1970; //year  ///***BASE VALUES
	double basemonth=1; //month
	double baseday=1; //day
	double temp=0; //hour
	baseday+=temp/24.0; // day+=hours
	temp=0; //minute
 	baseday+=temp/1440.0; //day+=minutes

	double givenyear=year;       ////****GIVEN VALUES
	double givenmonth=month;
	double givenday=day;
	temp=hour;
	givenday+=temp/24.0;
	temp=min;
	givenday+=temp/1440.0;
   temp=sec;
   givenday+=temp/86400;

	double tempwork,totaldays=0;
	if(givenyear>baseyear)
	{
		tempwork=baseyear;
		while(tempwork!=givenyear)
	   	{
			totaldays+=365;
			if(tempwork/4==int(tempwork/4) && tempwork/100!=int(tempwork/100) && basemonth<3)
	  			totaldays++;
			else if((tempwork+1)/4==int((tempwork+1)/4) && (tempwork+1)/100!=int((tempwork+1)/100) && basemonth>=3)
				totaldays++;
			else if(tempwork/400==int(tempwork/400) && basemonth<3)
				totaldays++;
			else if((tempwork+1)/400==int((tempwork+1)/400) && basemonth>=3)
				totaldays++;
			tempwork++;
		}
	}
	else if(givenyear<baseyear)
	{
		tempwork=baseyear;
		while(tempwork!=givenyear)
	   	{
			totaldays-=365;
			if(tempwork/4==int(tempwork/4) && tempwork/100!=int(tempwork/100) && givenmonth>=3)
				totaldays--;
			else if((tempwork-1)/4==int((tempwork-1)/4) && (tempwork-1)/100!=int((tempwork-1)/100) && givenmonth<3)
				totaldays--;
			else if(tempwork/400==int(tempwork/400) && givenmonth>=3)
				totaldays--;
			else if((tempwork-1)/400==int((tempwork-1)/400) && givenmonth<3)
				totaldays--;
			tempwork--;
		}
	}
	else
	{
		if(basemonth<=2 && givenmonth>2 && baseyear/4==int(baseyear/4) && baseyear/100!=int(baseyear/100))
			totaldays++;
		else if(baseyear/400==int(baseyear/400) && basemonth<=2 && givenmonth>2)
			totaldays++;
		else if(basemonth>2 && givenmonth<=2 && baseyear/4==int(baseyear/4) && baseyear/100!=int(baseyear/100))
			totaldays--;
		else if(baseyear/400==int(baseyear/400) && basemonth>2 && givenmonth<=2)
			totaldays--;
	}
	if(givenmonth==2) totaldays+=31;
	else if(givenmonth==3)	totaldays+=59;
	else if(givenmonth==4)	totaldays+=90;
	else if(givenmonth==5)	totaldays+=120;
	else if(givenmonth==6)	totaldays+=151;
	else if(givenmonth==7)	totaldays+=181;
	else if(givenmonth==8)	totaldays+=212;
	else if(givenmonth==9)	totaldays+=243;
	else if(givenmonth==10)totaldays+=273;
	else if(givenmonth==11)totaldays+=304;
	else if(givenmonth==12)totaldays+=334;
	if(basemonth==2)	totaldays-=31;
	else if(basemonth==3)	totaldays-=59;
	else if(basemonth==4)	totaldays-=90;
	else if(basemonth==5)	totaldays-=120;
	else if(basemonth==6)	totaldays-=151;
	else if(basemonth==7)	totaldays-=181;
	else if(basemonth==8)	totaldays-=212;
	else if(basemonth==9)	totaldays-=243;
	else if(basemonth==10) totaldays-=273;
	else if(basemonth==11)	totaldays-=304;
	else if(basemonth==12)	totaldays-=334;
	totaldays+=givenday-baseday;
	totaldays*=24; //days->hours
	return totaldays;
};

string getsysdate(const string &args)
//Purpose: acquire system time/date and return them to calling routing
//Input: string containing arguments to pass to system- empty string is acceptable
//Output: system's output for the current time
//Accesses: none
//Edits: none
{
	string temp;
	string result="";
	string query="date ";
	query+=args;
	query+=" > TIME_TIME";
	system(query.c_str());
	ifstream timez;
	timez.open("TIME_TIME");
	
	timez>>temp;
	while(!timez.eof())
	{
		temp+=' ';
		result+=temp;
		timez>>temp;
	}
	timez.close();
	system("rm TIME_TIME");
	return result;	
};

template <class T>
void push_back(vector <T> &ar, const T &item)
{
	ar.resize(ar.size()+1);
	ar[ar.size()-1]=item;
};

template <class T>
void push_front(vector <T>& ar, const T& item)
{
	ar.resize(ar.size()+1);
	for(int i=ar.size()-2; i>=0; i--)
		ar[i+1]=ar[i];
	ar[0]=item;
};

template <class T>
void push_all(vector <T> &ar, const vector <T> &ar2)
{
	for(int i=0; i<ar2.size(); i++)
		push_back(ar,ar2[i]);
};

template <class T>
T pop_back(vector <T> &ar)
{
	T temp=ar[ar.size()-1];
	ar.resize(ar.size()-1);
	return temp;
}

template <class T>
T pop_front(vector <T>& ar)
{
	T temp=ar[0];
	for(int i=0; i<ar.size()-1; i++)
		ar[i]=ar[i+1];
	ar.resize(ar.size()-1);
	return temp;
};

template <class T>
T v_max(vector <T> &ar)
//Find largest element of array
{
	if(ar.size()==0)
	{	T temp; return temp; }
	T temp=ar[0];
	for(int i=1; i<ar.size(); i++)
		if(temp<ar[i])
			temp=ar[i];
	return temp;
};

template <class T>
T v_min(vector <T> &ar)
//Find smallest element of array
{
	if(ar.size()==0)
	{	T temp; return temp; }
	T temp=ar[0];
	for(int i=1; i<ar.size(); i++)
		if(temp>ar[i])
			temp=ar[i];
	return temp;
};

vector <char> readfile(string filename)
{
	vector <char> ret(0);
	ifstream inf;
	char dummy;
	int begin, end, pos;
	
	inf.open(filename.c_str(),ios::binary);
	if(inf.fail())
		return ret;
	
	begin=inf.tellg();
	inf.seekg(0,ios::end);
	end=inf.tellg();
	inf.seekg(0,ios::beg);
	
	ret.resize(end-begin);
	
	pos=0;
	inf.get(dummy);
	while(!inf.eof())
	{
		ret[pos]=dummy;
		pos++;
		inf.get(dummy);
	}
	inf.close();
	return ret;	
};

#endif
