/*File Name: ReadValues.cpp
  Author: Bernd Oesterholz ; Date: 27.02.2006
  System: C++


  Copyright (C) 2006  Bernd Österholz

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2, June 1991, of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

*/

#include "ReadValues.h"

int ReadValues::charToInt(const char c)
/*makes the char c to a integer number c represents
pre: the char c
post: the integer number the char c represents (e.g. "1"=1) or -1 if it
	isn't a number*/
{
switch (c)
{
	case '0':return 0;
	case '1':return 1;
	case '2':return 2;
	case '3':return 3;
	case '4':return 4;
	case '5':return 5;
	case '6':return 6;
	case '7':return 7;
	case '8':return 8;
	case '9':return 9;
}
return -1;//error
}

char* ReadValues::readChar(ifstream &str)
/*reads a charstring from the given string str that is terminated with ':'
or ';'
pre: the input stream to read the char string from
post: the readed string terminated with 0;
	or 0 if a error occurs*/
{
unsigned int count=0;
char name[1000];
char c;
do{
	c=str.get();
	name[count]=c;
	count++;
}while ((count<1000)&&(c!=':')&&(c!=';'));
if (count>=1000){//error
	return 0;
}
char* ret=new char[count+1];
for (unsigned int i=0;i<(count-1);i++)
	{ret[i]=name[i];}
ret[count-1]=0;//last char in name is ';'
return ret;
}


char* ReadValues::readPath(ifstream &str, bool pathE)
/*reads a path from the given string str that is terminated with ':'
or ';'
if pathE is true the path will be terminated with '/' (the method insert
'/' at the end of the path if it needs to)
pre: the input stream to read the path from
post: the readed path terminated with 0;
	or 0 if a error occurs*/
{
unsigned int maxC=0;
char* path=readChar(str);
if (path==0){return 0;}
unsigned int count=0,blanks=0;
bool beg=true;
for (;(maxC<100000)&&(path[count+blanks]!=0);maxC++)
{//maxC= maximal chars to read; to avoid infinity loops
	if (beg){//delete begining blanks
		if (path[count+blanks]==' '){
			blanks++;
		}else{
			beg=false;
			path[count]=path[count+blanks];
			count++;
		}
	}else{
		path[count]=path[count+blanks];
		count++;
	}
}
path[count]=0;
if(pathE){
	if ((path[count-1]!='/')&&(path[count-1]!='\\')&&(count>1)){
		path[count]='/';
		path[count+1]=0;
		count++;
	}
}
for (unsigned int i=0;i<=count;i++){//change windows '\' to Linux '/'
	if (path[i]=='\\')
		{path[i]='/';}
}
if (maxC>=100000){//error
	delete path;
	return 0;
}
return path;
}

double ReadValues::readDouble(ifstream &str)
/*reads a double number from the given string str
pre: the input stream to read the double number from
post: the readed double number*/
{
unsigned int maxC=0;//maximal chars to read; to avoid infinity loops
double dnumb=0.0;
int count=0,exp=0;
bool sign=false;
char c;
do{//read till number
	str>>c;maxC++;
}while ((maxC<10000)&&(charToInt(c)==-1)&&(c!='-')&&(c!=';'));
maxC=0;
if (c=='-'){
	sign=true;
	str>>c;
}
if (charToInt(c)!=-1){
	dnumb=charToInt(c);
	for (;maxC<1000;maxC++){
		str>>c;
		if (charToInt(c)==-1){break;}
		dnumb=dnumb*10+charToInt(c);
	}
	if (c=='.'){
		for (;maxC<1000;maxC++){
			str>>c;
			if (charToInt(c)==-1){break;}
			dnumb=dnumb*10+charToInt(c);
			count++;
		}
	}
	if (sign){
		dnumb=-dnumb;
		sign=false;
	}
	if ((c=='e')||(c=='E')||(c=='^')){
		str>>c;
		if (c=='-'){
			sign=true;
		}else{
			sign=false;
			if (charToInt(c)!=-1){
				exp=charToInt(c);
			}
		}
		for (;(maxC<1000)&&(c!=';');maxC++){
			str>>c;
			if (charToInt(c)==-1){break;}
			exp=exp*10+charToInt(c);
		}
		if (sign){exp=-exp;}
	}
	exp-=count;
	if (exp>=0){
		for (;exp>0;exp--)
			{dnumb=dnumb*10;}
	}else{
		for (;exp<0;exp++)
			{dnumb=dnumb/10;}
	}
}
for (;(maxC<10000)&&(c!=';');str>>c,maxC++);//read till line end
return dnumb;
}

long ReadValues::readInt(ifstream &str)
/*reads a integer number from the given string str
pre: the input stream to read the integer number from
post: the readed integer number*/
{
unsigned int maxC=0;//maximal chars to read; to avoid infinity loops
long dnumb=0;
bool sign=false;
char c;
do{
	str>>c;maxC++;
}while((maxC<10000)&&(charToInt(c)==-1)&&(c!='-'));
maxC=0;
if (c=='-'){
	sign=true;
	str>>c;
}
if (charToInt(c)!=-1){
	dnumb=charToInt(c);
	for(;maxC<1000;maxC++){
		str>>c;
		if (charToInt(c)==-1){break;}
		dnumb=dnumb*10+charToInt(c);
	}
	if (sign){
		dnumb=-dnumb;
		sign=false;
	}
}
for(;(maxC<10000)&&(c!='.')&&(c!=';')&&(c!=':');str>>c,maxC++);//read till line end
return dnumb;
}


bool ReadValues::readBool(ifstream &str)
/*reads a truth value from the given string str
strings for true are: t, true, y, yes, w, wahr, j, ja, 1
all other strings are readed as false;
all strings can be writen in upper cases, just the first char of the words
are checked
pre: the input stream to read the truth value from
post: the readed truth value*/
{
char c;
unsigned int maxC=0;//maximal chars to read; to avoid infinity loops
bool value=false;
do{
	str>>c;maxC++;
}while((maxC<10000)&&(c!=';')&&(c!='t')&&(c!='y')&&(c!='w')&&(c!='j')&&(c!='1'));
if ((c=='t')||(c=='y')||(c=='w')||(c=='j')||(c=='1'))
	{value=true;}
for(;(maxC<10000)&&(c!=';');str>>c,maxC++);//read till line end
return value;
}


bool ReadValues::checkPath(char* path)
/*checks if the given Path or file exists
pre: a string for the path to be cheked
post: true if the path exists, else false*/
{
ifstream test(path);
if(test){test.close();return true;}
return false;
}

void ReadValues::cratePath(char* path)
/*if the path folders are not existing, creats them
pre: the string of the path that should be existing
post: the path now exists*/
{
unsigned int maxC=0,count=0,count2=0;//maxC= maximal chars to read; to avoid infinity loops
if (path==0){return;}
//begin with the first folder, check if the folder exists and if not creat it
char folder[1000],mkDir[1020];
for (;(maxC<100000)&&(path[count]!=0);maxC++)//check next folder
{
	for (;(maxC<100000)&&(path[count]!=0);maxC++)//reaad folder from path
	{
		if (path[count]=='/')
		{
			folder[count2]='/';
			count++;count2++;
			break;
		}else{
			folder[count2]=path[count];
			count++;count2++;
		}
	}
	folder[count2]=0;
	if ((count2!=0)&&
		!((count2==1)&&(folder[0]=='/'))&&
		!((count2==2)&&(folder[0]=='.')&&(folder[1]=='/'))
		&&!(checkPath(folder)))
	{
		sprintf(mkDir,"mkdir %s ",folder);
		system(mkDir);
	}
	if (path[count]==0){return;}
}
}

bool ReadValues::searchForLine(fstream *str, long number, unsigned int rows)
/*searches in a tabel for the line with the given number in front and
lets the fstream point to the end of the line;
the rows in the tabel must end with a ";"
pre: the stream str to search in, the number to search for and the number
	of rows in the tabel in the stream
post: the stream output pointer pointing to the end of the line wich begins
with number*/
{
str->seekg(0);//set input position to file begin
unsigned int maxC=0,r;
long numb;
char c;
for(;(maxC<10000000)&&!(str->eof());maxC++)
{//read next line
	if (maxC){(*str)>>numb;}
	for (r=0;r<rows;)
	{//read the rest of the line
		c=0;for(;(c!=';')&&(maxC<10000000)&&!(str->eof());maxC++){(*str)>>c;}//read till next ';'
		r++;
	}
	if((numb==number)&&(maxC<10000000))
	{
		str->seekp(str->tellg());//set outpout position to input position
		return true;
	}
}
return false;
}





















